Mercurial > hg > octave-lojdl
changeset 16050:fc3cb570ac46 classdef
periodic merge of default to classdef.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Mon, 11 Feb 2013 15:45:26 -0500 |
parents | ebd2259c5df1 (current diff) a1e67cf915ba (diff) |
children | 0259254a3ccc |
files | libgui/languages/generic.qm libgui/languages/generic.ts libinterp/Makefile.am test/Makefile.am test/bc_overloads_expected test/bug-35448/test_bug_35448.m test/bug-36025/test_bug_36025.m test/build_bc_overload_tests.sh test/build_sparse_tests.sh test/class-concat/test_class_concat.m test/classdef/classdef.tst test/classdef/module.mk test/classdef/test_classdef.m test/classes/classes.tst test/classes/module.mk test/classes/test_classes.m test/ctor-vs-method/test_ctor_vs_method.m test/fcn-handle-derived-resolution/test_fcn_handle_derived_resolution.m test/nest/test_nest.m test/test_args.m test/test_bug_31371.m test/test_diag_perm.m test/test_error.m test/test_eval-catch.m test/test_for.m test/test_func.m test/test_global.m test/test_if.m test/test_index.m test/test_io.m test/test_line_continue.m test/test_logical_index.m test/test_null_assign.m test/test_parser.m test/test_prefer.m test/test_range.m test/test_recursion.m test/test_return.m test/test_slice.m test/test_struct.m test/test_switch.m test/test_system.m test/test_transpose.m test/test_try.m test/test_unwind.m test/test_while.m |
diffstat | 153 files changed, 2627 insertions(+), 1061 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgsubstate +++ b/.hgsubstate @@ -1,1 +1,1 @@ -e2f98cc246bdb12f2d35366042d4aab61c3d54fe gnulib-hg +0eef0a2a05e22ac8ef2aad06dda200f7def83396 gnulib-hg
--- a/.hgtags +++ b/.hgtags @@ -71,3 +71,6 @@ 2e8eb9ac43a5f8cfaf0423814a312ed47cb80485 rc-3-6-4-0 df1aceb8f0bc6b5b5062907931cc663467f57d93 ss-3-7-1 858cbf6fc2ec1c232f5cf1d75dc344439b39a89c rc-3-6-4-1 +faefa1bea8ddae3cab170afdeab68d3d15c4e623 ss-3-7-2 +0000000000000000000000000000000000000000 ss-3-7-2 +23a7661e529ae9bfc91693618f8c314c31f695ca ss-3-7-2
--- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,7 @@ README \ bootstrap \ bootstrap.conf \ + build-aux/find-files-with-tests.sh \ build-aux/mk-opts.pl \ build-aux/mkinstalldirs \ build-aux/move-if-change \
--- a/bootstrap.conf +++ b/bootstrap.conf @@ -44,6 +44,7 @@ gettimeofday glob isatty + largefile link lstat malloc-gnu
--- a/build-aux/common.mk +++ b/build-aux/common.mk @@ -156,21 +156,14 @@ NO_UNDEFINED_LDFLAG = @NO_UNDEFINED_LDFLAG@ +MKOCTFILE_AR = @MKOCTFILE_AR@ MKOCTFILE_CC = @MKOCTFILE_CC@ MKOCTFILE_CXX = @MKOCTFILE_CXX@ MKOCTFILE_DL_LD = @MKOCTFILE_DL_LD@ MKOCTFILE_DL_LDFLAGS = @MKOCTFILE_DL_LDFLAGS@ MKOCTFILE_F77 = @MKOCTFILE_F77@ MKOCTFILE_LD_CXX = @MKOCTFILE_LD_CXX@ - -# List of libraries and their special compilation flags - -MKOCTFILE_CC = @MKOCTFILE_CC@ -MKOCTFILE_CXX = @MKOCTFILE_CXX@ -MKOCTFILE_DL_LD = @MKOCTFILE_DL_LD@ -MKOCTFILE_DL_LDFLAGS = @MKOCTFILE_DL_LDFLAGS@ -MKOCTFILE_F77 = @MKOCTFILE_F77@ -MKOCTFILE_LD_CXX = @MKOCTFILE_LD_CXX@ +MKOCTFILE_RANLIB = @MKOCTFILE_RANLIB@ # List of libraries and their special compilation flags @@ -349,6 +342,9 @@ # Where to install and expect extra files like NEWS and doc-cache. octetcdir = @octetcdir@ +# Where to install and expect the language files for the gui. +octlocaledir = @octlocaledir@ + # Where to install and expect libraries like liboctave.a, liboctinterp.a, # and other architecture-dependent data. octlibdir = @octlibdir@ @@ -367,6 +363,9 @@ man1dir = @man1dir@ man1ext = @man1ext@ +# Where to install test files. +octtestsdir = @octtestsdir@ + # The full path to the default doc cache file. doc_cache_file = @doc_cache_file@ @@ -581,12 +580,14 @@ -e "s|%OCTAVE_CONF_MAGICK_CPPFLAGS%|\"${MAGICK_CPPFLAGS}\"|" \ -e "s|%OCTAVE_CONF_MAGICK_LDFLAGS%|\"${MAGICK_LDFLAGS}\"|" \ -e "s|%OCTAVE_CONF_MAGICK_LIBS%|\"${MAGICK_LIBS}\"|" \ + -e 's|%OCTAVE_CONF_MKOCTFILE_AR%|\"${MKOCTFILE_AR}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_CC%|\"${MKOCTFILE_CC}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_CXX%|\"${MKOCTFILE_CXX}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_DL_LD%|\"${MKOCTFILE_DL_LD}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%|\"${MKOCTFILE_DL_LDFLAGS}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_F77%|\"${MKOCTFILE_F77}\"|' \ -e 's|%OCTAVE_CONF_MKOCTFILE_LD_CXX%|\"${MKOCTFILE_LD_CXX}\"|' \ + -e 's|%OCTAVE_CONF_MKOCTFILE_RANLIB%|\"${MKOCTFILE_RANLIB}\"|' \ -e "s|%OCTAVE_CONF_OCTAVE_LINK_DEPS%|\"${OCTAVE_LINK_DEPS}\"|" \ -e "s|%OCTAVE_CONF_OCTAVE_LINK_OPTS%|\"${OCTAVE_LINK_OPTS}\"|" \ -e "s|%OCTAVE_CONF_OCTINCLUDEDIR%|\"${octincludedir}\"|" \ @@ -678,6 +679,8 @@ -e "s|%OCTAVE_OCTETCDIR%|\"${octetcdir}\"|" \ -e "s|%OCTAVE_OCTINCLUDEDIR%|\"${octincludedir}\"|" \ -e "s|%OCTAVE_OCTLIBDIR%|\"${octlibdir}\"|" \ + -e "s|%OCTAVE_OCTLOCALEDIR%|\"${octlocaledir}\"|" \ + -e "s|%OCTAVE_OCTTESTSDIR%|\"${octtestsdir}\"|" \ -e "s|%OCTAVE_STARTUPFILEDIR%|\"${startupfiledir}\"|" \ -e "s|%OCTAVE_PREFIX%|\"${prefix}\"|" \ -e "s|%OCTAVE_API_VERSION%|\"${api_version}\"|" \ @@ -726,3 +729,17 @@ rm -f $(DESTDIR)$(fcnfiledir)/$(script_sub_dir)/PKG_ADD -rmdir $(DESTDIR)$(fcnfiledir)/$(script_sub_dir) endef + +define test-file-commands +( echo "## DO NOT EDIT! Generated automatically from $(<F) by Make."; grep '^%!' $< ) > $@-t +mv $@-t $@ +endef + +%.cc-tst : %.cc + $(test-file-commands) + +%.yy-tst : %.yy + $(test-file-commands) + +%.ll-tst : %.ll + $(test-file-commands)
new file mode 100755 --- /dev/null +++ b/build-aux/find-files-with-tests.sh @@ -0,0 +1,19 @@ +#! /bin/sh + +set -e +SED=${SED:-sed} + +srcdir="$1" +shift + +for arg +do + if [ -f "$arg" ]; then + file="$arg" + else + file="$srcdir/$arg" + fi + if [ "`grep -l '^%!' $file`" ]; then + echo "$file" | $SED "s,\\$srcdir/,,"; + fi +done
--- a/configure.ac +++ b/configure.ac @@ -19,14 +19,14 @@ ### <http://www.gnu.org/licenses/>. AC_PREREQ([2.62]) -AC_INIT([GNU Octave], [3.7.1+], [http://octave.org/bugs.html], [octave]) +AC_INIT([GNU Octave], [3.7.2+], [http://octave.org/bugs.html], [octave]) dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg OCTAVE_VERSION="$PACKAGE_VERSION" OCTAVE_API_VERSION_NUMBER="48" OCTAVE_API_VERSION="api-v$OCTAVE_API_VERSION_NUMBER+" -OCTAVE_RELEASE_DATE="2013-01-02" -OCTAVE_COPYRIGHT="Copyright (C) 2012 John W. Eaton and others." +OCTAVE_RELEASE_DATE="2013-02-09" +OCTAVE_COPYRIGHT="Copyright (C) 2013 John W. Eaton and others." AC_SUBST(OCTAVE_VERSION) AC_SUBST(OCTAVE_API_VERSION_NUMBER) AC_SUBST(OCTAVE_API_VERSION) @@ -80,7 +80,9 @@ '$(datadir)/octave/site/$(api_version)/m') OCTAVE_SET_DEFAULT([localverfcnfiledir], '$(datadir)/octave/$(version)/site/m') OCTAVE_SET_DEFAULT([octetcdir], '$(datadir)/octave/$(version)/etc') +OCTAVE_SET_DEFAULT([octlocaledir], '$(datadir)/octave/$(version)/locale') OCTAVE_SET_DEFAULT([doc_cache_file], '$(octetcdir)/doc-cache') +OCTAVE_SET_DEFAULT([octtestsdir], '$(octetcdir)/tests') OCTAVE_SET_DEFAULT([texi_macros_file], '$(octetcdir)/macros.texi') OCTAVE_SET_DEFAULT([imagedir], '$(datadir)/octave/$(version)/imagelib') OCTAVE_SET_DEFAULT([man1dir], '$(mandir)/man1') @@ -812,6 +814,22 @@ [FFTW3F library not found. The slower FFTPACK library will be used instead.], [fftw3.h], [fftwf_plan_dft_1d]) +## Check for the multithreaded FFTW library. +## Fallback to singlethreaded if not found or disabled +build_fftw_threads=true +AC_ARG_ENABLE([fftw-threads], + [AS_HELP_STRING([--disable-fftw-threads], + [disable Multi-threaded FFTW])], + [if test "$enableval" = no; then + build_fftw_threads=false + fi], + []) + +if test $build_fftw_threads = true; then + OCTAVE_CHECK_FFTW_THREADS(fftw3, fftw_plan_with_nthreads) + OCTAVE_CHECK_FFTW_THREADS(fftw3f, fftwf_plan_with_nthreads) +fi + AM_CONDITIONAL([AMCOND_HAVE_FFTW], [test -n "$FFTW3_LIBS" && test -n "$FFTW3F_LIBS"]) @@ -1277,7 +1295,7 @@ OCTAVE_CHECK_LIB(camd, CAMD, [CAMD library not found. This will result in some lack of functionality for sparse matrices.], - [suitesparse/camd.h ufsparse/camd.h amd/camd.h camd.h], + [suitesparse/camd.h ufsparse/camd.h camd/camd.h camd.h], [camd_postorder], [], [don't use CAMD library, disable some sparse matrix functionality]) @@ -1285,7 +1303,7 @@ OCTAVE_CHECK_LIB(colamd, COLAMD, [COLAMD library not found. This will result in some lack of functionality for sparse matrices.], - [suitesparse/colamd.h ufsparse/colamd.h amd/colamd.h colamd.h], + [suitesparse/colamd.h ufsparse/colamd.h colamd/colamd.h colamd.h], [colamd], [], [don't use COLAMD library, disable some sparse matrix functionality]) @@ -1293,7 +1311,7 @@ OCTAVE_CHECK_LIB(ccolamd, CCOLAMD, [CCOLAMD library not found. This will result in some lack of functionality for sparse matrices.], - [suitesparse/ccolamd.h ufsparse/ccolamd.h amd/ccolamd.h ccolamd.h], + [suitesparse/ccolamd.h ufsparse/ccolamd.h ccolamd/ccolamd.h ccolamd.h], [ccolamd], [], [don't use CCOLAMD library, disable some sparse matrix functionality]) @@ -1314,7 +1332,7 @@ OCTAVE_CHECK_LIB(cxsparse, CXSparse, [CXSparse library not found. This will result in some lack of functionality for sparse matrices.], - [suitesparse/cs.h ufsparse/cs.h amd/cs.h cs.h], + [suitesparse/cs.h ufsparse/cs.h cxsparse/cs.h cs.h], [cs_di_sqr], [C++], [don't use CXSparse library, disable some sparse matrix functionality]) @@ -1814,33 +1832,38 @@ if test "$cross_compiling" = yes && test -n "$ac_tool_prefix"; then CROSS_TOOL_PREFIX="$ac_tool_prefix" + MKOCTFILE_AR='$(shell echo $(AR) | sed "s,$(CROSS_TOOL_PREFIX),,")' MKOCTFILE_CC='$(shell echo $(CC) | sed "s,$(CROSS_TOOL_PREFIX),,")' MKOCTFILE_CXX='$(shell echo $(CXX) | sed "s,$(CROSS_TOOL_PREFIX),,")' MKOCTFILE_DL_LD='$(shell echo $(DL_LD) | sed "s,$(CROSS_TOOL_PREFIX),,")' MKOCTFILE_F77='$(shell echo $(F77) | sed "s,$(CROSS_TOOL_PREFIX),,")' MKOCTFILE_LD_CXX='$(shell echo $(LD_CXX) | sed "s,$(CROSS_TOOL_PREFIX),,")' + MKOCTFILE_RANLIB='$(shell echo $(RANLIB) | sed "s,$(CROSS_TOOL_PREFIX),,")' else + MKOCTFILE_AR="$AR" MKOCTFILE_CC="$CC" MKOCTFILE_CXX="$CXX" MKOCTFILE_DL_LD="$DL_LD" MKOCTFILE_F77="$F77" MKOCTFILE_LD_CXX="$LD_CXX" + MKOCTFILE_RANLIB="$RANLIB" fi AC_MSG_NOTICE([defining CROSS_TOOL_PREFIX to be $CROSS_TOOL_PREFIX]) +AC_MSG_NOTICE([defining MKOCTFILE_AR to be $MKOCTFILE_AR]) AC_MSG_NOTICE([defining MKOCTFILE_CC to be $MKOCTFILE_CC]) AC_MSG_NOTICE([defining MKOCTFILE_CXX to be $MKOCTFILE_CXX]) AC_MSG_NOTICE([defining MKOCTFILE_DL_LD to be $MKOCTFILE_DL_LD]) AC_MSG_NOTICE([defining MKOCTFILE_F77 to be $MKOCTFILE_F77]) AC_MSG_NOTICE([defining MKOCTFILE_LD_CXX to be $MKOCTFILE_LD_CXX]) +AC_MSG_NOTICE([defining MKOCTFILE_RANLIB to be $MKOCTFILE_RANLIB]) AC_SUBST(CROSS_TOOL_PREFIX) +AC_SUBST(MKOCTFILE_AR) AC_SUBST(MKOCTFILE_CC) AC_SUBST(MKOCTFILE_CXX) AC_SUBST(MKOCTFILE_DL_LD) AC_SUBST(MKOCTFILE_F77) AC_SUBST(MKOCTFILE_LD_CXX) - -### Check for existence of various libraries - +AC_SUBST(MKOCTFILE_RANLIB) ### Check for existence of various libraries @@ -2163,13 +2186,21 @@ #endif ]]) -### Need to disable building documentation if gnuplot was not found, -### unless it was already disabled previously. - -if test -n "$DOCDIR" && test -n "$warn_gnuplot"; then - DOCDIR= - warn_docs="building documentation disabled because gnuplot was not found; make dist will fail" - OCTAVE_CONFIGURE_WARNING([warn_docs]) +### Need to disable building documentation if either gnuplot or +### makeinfo are missing. Skip this warning if building docs was +### disabled with a configure option. + +if test -n "$DOCDIR"; then + if test -n "$warn_gnuplot"; then + DOCDIR= + warn_docs_gnuplot="building documentation disabled because gnuplot was not found; make dist will fail" + OCTAVE_CONFIGURE_WARNING([warn_docs_gnuplot]) + fi + if test -n "$warn_makeinfo"; then + DOCDIR= + warn_docs_makeinfo="building documentation disabled because makeinfo was not found; make dist will fail" + OCTAVE_CONFIGURE_WARNING([warn_docs_makeinfo]) + fi fi AM_CONDITIONAL([AMCOND_BUILD_DOCS], [test -n "$DOCDIR"])
--- a/doc/interpreter/contributors.in +++ b/doc/interpreter/contributors.in @@ -81,6 +81,7 @@ Steffen Groot Etienne Grossmann David Grundberg +Kyle Guinn Peter Gustafson Kai Habel Patrick Häcker
--- a/doc/interpreter/mkoctfile.1 +++ b/doc/interpreter/mkoctfile.1 @@ -95,29 +95,29 @@ Print configuration variable \fIVAR\fP. Recognized variables are: .RS .Vb - ALL_CFLAGS FFTW3F_LIBS - ALL_CXXFLAGS FLIBS - ALL_FFLAGS FPICFLAG - ALL_LDFLAGS INCFLAGS + ALL_CFLAGS FFTW3F_LDFLAGS + ALL_CXXFLAGS FFTW3F_LIBS + ALL_FFLAGS FLIBS + ALL_LDFLAGS FPICFLAG + AR INCFLAGS BLAS_LIBS LAPACK_LIBS CC LDFLAGS CFLAGS LD_CXX CPICFLAG LD_STATIC_FLAG CPPFLAGS LFLAGS CXX LIBOCTAVE - CXXFLAGS LIBOCTINTERP - CXXPICFLAG LIBS - DEPEND_EXTRA_SED_PATTERN OCTAVE_LIBS + CXXFLAGS LIBOCTINTERP + CXXPICFLAG LIBS + DEPEND_EXTRA_SED_PATTERN OCTAVE_LIBS DEPEND_FLAGS OCTAVE_LINK_DEPS - DL_LD OCT_LINK_DEPS - DL_LDFLAGS RDYNAMIC_FLAG - EXEEXT READLINE_LIBS - F77 SED - F77_INTEGER_8_FLAG XTRA_CFLAGS - FFLAGS XTRA_CXXFLAGS - FFTW3_LDFLAGS - FFTW3_LIBS - FFTW3F_LDFLAGS + DL_LD OCT_LINK_DEPS + DL_LDFLAGS RANLIB + EXEEXT RDYNAMIC_FLAG + F77 READLINE_LIBS + F77_INTEGER_8_FLAG SED + FFLAGS XTRA_CFLAGS + FFTW3_LDFLAGS XTRA_CXXFLAGS + FFTW3_LIBS .Ve .RE .TP
--- a/doc/interpreter/oop.txi +++ b/doc/interpreter/oop.txi @@ -656,6 +656,8 @@ Octave types. So in fact marking our polynomial class higher than the "double" class is in fact not necessary. +When faced with two objects that have the same precedence, Octave will use the +method of the object that appears first on the list of arguments. @node Inheritance and Aggregation @section Inheritance and Aggregation
--- a/doc/interpreter/plot.txi +++ b/doc/interpreter/plot.txi @@ -136,6 +136,10 @@ @DOCSTRING(hist) +@DOCSTRING(stemleaf) + +@DOCSTRING(printd) + @DOCSTRING(stairs) @DOCSTRING(stem)
--- a/etc/HACKING +++ b/etc/HACKING @@ -228,7 +228,7 @@ icons icon files that will be compiled into the executable via a resource file. - qterminal subrepository for the qterminal Qt terminal widget. + qterminal Qt terminal widget languages translation files and list of translators.
--- a/libgui/Makefile.am +++ b/libgui/Makefile.am @@ -26,8 +26,16 @@ octlib_LTLIBRARIES = liboctgui.la -EXTRA_DIST = default-qt-settings +locales = \ + languages/be_BY.qm \ + languages/de_DE.qm \ + languages/en_US.qm \ + languages/es_ES.qm \ + languages/pt_BR.qm \ + languages/ru_RU.qm \ + languages/uk_UA.qm +EXTRA_DIST = default-qt-settings $(locales) CLEANFILES = BUILT_SOURCES = @@ -70,6 +78,8 @@ octetc_DATA = default-qt-settings +octlocale_DATA = $(locales) + moc-%.cc: %.h @MOC@ -o$@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(MOC_CPPFLAGS) $(liboctgui_la_CPPFLAGS) $<
--- a/libgui/languages/translators +++ b/libgui/languages/translators @@ -1,5 +1,7 @@ # Below Octave GUI translators are listed with their e-mails -# to be able inform them about generic translation file changes +# to be able to inform them about generic translation file changes. +# The gerenic file that can be used as a template for new +# translation files is en_US.ts be_BY Mihas Varantsou <meequz@gmail.com> de_DE Jacob Dawid <jacob.dawid@googlemail.com> en_US Jacob Dawid <jacob.dawid@googlemail.com>
--- a/libgui/src/m-editor/file-editor-interface.h +++ b/libgui/src/m-editor/file-editor-interface.h @@ -43,11 +43,13 @@ virtual ~file_editor_interface () { } + virtual QMenu *get_mru_menu ( ) = 0; virtual QMenu *debug_menu () = 0; virtual QToolBar *toolbar () = 0; virtual void handle_entered_debug_mode () = 0; virtual void handle_quit_debug_mode () = 0; + virtual void set_focus () = 0; public slots: virtual void request_new_file () = 0;
--- a/libgui/src/m-editor/file-editor-tab.cc +++ b/libgui/src/m-editor/file-editor-tab.cc @@ -142,8 +142,7 @@ { // ignore close event if file is not saved and user cancels // closing this window - if (check_file_modified ("Close File", - QMessageBox::Cancel) == QMessageBox::Cancel) + if (check_file_modified () == QMessageBox::Cancel) { e->ignore (); } @@ -259,6 +258,15 @@ _edit_area->setLexer (lexer); } +// slot for fetab_set_focus: sets the focus to the current edit area +void +file_editor_tab::set_focus (const QWidget* ID) +{ + if (ID != this) + return; + _edit_area->setFocus (); +} + void file_editor_tab::undo (const QWidget* ID) { @@ -615,6 +623,8 @@ } _find_dialog->activateWindow (); + _find_dialog->init_search_text (); + } void @@ -649,22 +659,27 @@ file_editor_tab::update_window_title (bool modified) { QString title (""); + QString tooltip (""); if (_file_name.isEmpty () || _file_name.at (_file_name.count () - 1) == '/') - title = UNNAMED_FILE; + title = tr("<unnamed>"); else - title = _file_name; - if ( !_long_title ) { - QFileInfo file(_file_name); - title = file.fileName(); + if ( _long_title ) + title = _file_name; + else + { + QFileInfo file(_file_name); + title = file.fileName(); + tooltip = _file_name; + } } if ( modified ) { - emit file_name_changed (title.prepend("* ")); + emit file_name_changed (title.prepend("* "), tooltip); } else - emit file_name_changed (title); + emit file_name_changed (title, tooltip); } void @@ -675,7 +690,7 @@ } int -file_editor_tab::check_file_modified (const QString&, int) +file_editor_tab::check_file_modified () { int decision = QMessageBox::Yes; if (_edit_area->isModified ()) @@ -684,9 +699,14 @@ // editor tab can't be made parent because it may be deleted depending // upon the response. Instead, change the _edit_area to read only. QMessageBox* msgBox = new QMessageBox ( - QMessageBox::Warning, tr ("Octave Editor"), - tr ("The file \'%1\' has been modified. Do you want to save the changes?"). - arg (_file_name), QMessageBox::Yes | QMessageBox::No, 0); + QMessageBox::Warning, tr ("Octave Editor"), + tr ("The file\n" + "%1\n" + "is about to be closed but has been modified.\n" + "Do you want to cancel closing, save or discard the changes?"). + arg (_file_name), + QMessageBox::Save | QMessageBox::Cancel | QMessageBox::Discard, 0); + msgBox->setDefaultButton (QMessageBox::Save); _edit_area->setReadOnly (true); connect (msgBox, SIGNAL (finished (int)), this, SLOT (handle_file_modified_answer (int))); @@ -707,12 +727,12 @@ void file_editor_tab::handle_file_modified_answer (int decision) { - if (decision == QMessageBox::Yes) + if (decision == QMessageBox::Save) { // Save file, then remove from editor. save_file (_file_name, true); } - else if (decision == QMessageBox::No) + else if (decision == QMessageBox::Discard) { // User doesn't want to save, just remove from editor. emit tab_remove_request (); @@ -854,7 +874,7 @@ fileDialog->setDirectory (_file_name); } } - fileDialog->setNameFilter (SAVE_FILE_FILTER); + fileDialog->setNameFilter (tr("Octave Files (*.m);;All Files (*.*)")); fileDialog->setDefaultSuffix ("m"); fileDialog->setAcceptMode (QFileDialog::AcceptSave); fileDialog->setViewMode (QFileDialog::Detail); @@ -885,7 +905,8 @@ // Create a NonModal message about error. QMessageBox* msgBox = new QMessageBox ( QMessageBox::Critical, tr ("Octave Editor"), - tr ("File not saved! You've selected a file name\n\n %1\n\nwhich is the same as the current file name. Use ""Save"" to overwrite. (Could allow overwriting, with message, if that is what folks want.)"). + tr ("File not saved! The selected file name\n%1\n" + "is the same as the current file name"). arg (saveFileName), QMessageBox::Ok, 0); msgBox->setWindowModality (Qt::NonModal); @@ -958,12 +979,20 @@ } else { - // Create a WindowModal message that blocks the edit area - // by making _edit_area parent. + QString modified = ""; + if (_edit_area->isModified ()) + modified = tr ("\n\nWarning: The contents in the editor is modified!"); + // Create a WindowModal message. The file editor tab can't be made + // parent because it may be deleted depending upon the response. + // Instead, change the _edit_area to read only. QMessageBox* msgBox = new QMessageBox ( QMessageBox::Warning, tr ("Octave Editor"), - tr ("It seems that \'%1\' has been deleted or renamed. Do you want to save it now?"). - arg (_file_name), QMessageBox::Save | QMessageBox::Close, this); + tr ("It seems that the file\n" + "%1\n" + "has been deleted or renamed. Do you want to save it now?%2"). + arg (_file_name).arg (modified), + QMessageBox::Save | QMessageBox::Close, 0); + _edit_area->setReadOnly (true); connect (msgBox, SIGNAL (finished (int)), this, SLOT (handle_file_resave_answer (int))); msgBox->setWindowModality (Qt::WindowModal); @@ -1073,21 +1102,21 @@ void file_editor_tab::handle_file_resave_answer (int decision) { + // check decision of user in dialog if (decision == QMessageBox::Save) { - save_file (_file_name); + save_file (_file_name); // readds file to watcher in set_file_name () + _edit_area->setReadOnly (false); // delete read only flag } else { - if (close ()) - { - emit tab_remove_request (); - return; // Don't touch member variables after removal - } + // Definitely close the file. + // Set modified to false to prevent the dialog box when the close event + // is posted. If the user cancels the close in this dialog the tab is + // left open with a non-existing file. + _edit_area->setModified (false); + close (); } - - // Start watching file once again. - _file_system_watcher.addPath (_file_name); } void
--- a/libgui/src/m-editor/file-editor-tab.h +++ b/libgui/src/m-editor/file-editor-tab.h @@ -52,6 +52,7 @@ /** Simply transmit file name. */ void file_name_query (const QWidget* ID); + void set_focus (const QWidget* ID); void undo (const QWidget* ID); void redo (const QWidget* ID); void copy (const QWidget* ID); @@ -85,7 +86,7 @@ void file_has_changed (const QString& fileName); signals: - void file_name_changed (const QString& fileName); + void file_name_changed (const QString& fileName, const QString& toolTip); void editor_state_changed (bool copy_available, const QString& fileName); void tab_remove_request (); void add_filename_to_list (const QString& fileName); @@ -132,7 +133,7 @@ void request_add_breakpoint (int line); void request_remove_breakpoint (int line); - int check_file_modified (const QString& msg, int cancelButton); + int check_file_modified (); void do_comment_selected_text (bool comment); void run_file_callback (void);
--- a/libgui/src/m-editor/file-editor.cc +++ b/libgui/src/m-editor/file-editor.cc @@ -62,6 +62,23 @@ } settings->setValue ("editor/savedSessionTabs", fetFileNames); settings->sync (); + + if (_mru_file_menu) + delete _mru_file_menu; +} + +// set focus to editor and its current tab +void +file_editor::set_focus () +{ + if (!isVisible ()) + setVisible (true); + setFocus (); + activateWindow (); + raise (); + QWidget *fileEditorTab = _tab_widget->currentWidget (); + if (fileEditorTab) + emit fetab_set_focus (fileEditorTab); } QMenu * @@ -98,8 +115,9 @@ file_editor_tab *fileEditorTab = new file_editor_tab (ced); if (fileEditorTab) { - add_file_editor_tab (fileEditorTab, UNNAMED_FILE); - fileEditorTab->new_file (); + add_file_editor_tab (fileEditorTab, ""); // new tab with empty title + fileEditorTab->new_file (); // title is updated here + set_focus (); // focus editor and new tab } } @@ -112,7 +130,7 @@ // Create a NonModal message. QFileDialog* fileDialog = new QFileDialog (this); - fileDialog->setNameFilter (SAVE_FILE_FILTER); + fileDialog->setNameFilter (tr("Octave Files (*.m);;All Files (*.*)")); fileDialog->setAcceptMode (QFileDialog::AcceptOpen); fileDialog->setViewMode (QFileDialog::Detail); fileDialog->setDirectory (ced); @@ -190,6 +208,7 @@ msgBox->show (); } } + set_focus (); // really show editor and the current editor tab } } @@ -411,7 +430,7 @@ } void -file_editor::handle_file_name_changed (const QString& fileName) +file_editor::handle_file_name_changed (const QString& fileName, const QString& toolTip) { QObject *fileEditorTab = sender(); if (fileEditorTab) @@ -421,6 +440,7 @@ if (_tab_widget->widget (i) == fileEditorTab) { _tab_widget->setTabText (i, fileName); + _tab_widget->setTabToolTip (i, toolTip); } } } @@ -631,12 +651,12 @@ fileMenu->addAction (save_action); fileMenu->addAction (save_as_action); fileMenu->addSeparator (); - QMenu *mru_file_menu = new QMenu (tr ("Open &Recent"), fileMenu); + _mru_file_menu = new QMenu (tr ("&Recent Editor Files"), fileMenu); for (int i = 0; i < MaxMRUFiles; ++i) { - mru_file_menu->addAction (_mru_file_actions[i]); + _mru_file_menu->addAction (_mru_file_actions[i]); } - fileMenu->addMenu (mru_file_menu); + fileMenu->addMenu (_mru_file_menu); _menu_bar->addMenu (fileMenu); QMenu *editMenu = new QMenu (tr ("&Edit"), _menu_bar); @@ -754,8 +774,8 @@ _tab_widget->addTab (f, fn); // Signals from the file editor_tab - connect (f, SIGNAL (file_name_changed (const QString&)), - this, SLOT (handle_file_name_changed (const QString&))); + connect (f, SIGNAL (file_name_changed (const QString&, const QString&)), + this, SLOT (handle_file_name_changed (const QString&, const QString&))); connect (f, SIGNAL (editor_state_changed (bool, const QString&)), this, SLOT (handle_editor_state_changed (bool, const QString&))); connect (f, SIGNAL (tab_remove_request ()), @@ -819,6 +839,8 @@ f, SLOT (uncomment_selected_text (const QWidget*))); connect (this, SIGNAL (fetab_find (const QWidget*)), f, SLOT (find (const QWidget*))); + connect (this, SIGNAL (fetab_set_focus (const QWidget*)), + f, SLOT (set_focus (const QWidget*))); _tab_widget->setCurrentWidget (f); }
--- a/libgui/src/m-editor/file-editor.h +++ b/libgui/src/m-editor/file-editor.h @@ -33,8 +33,6 @@ #include "file-editor-interface.h" #include "file-editor-tab.h" -const char UNNAMED_FILE[] = "<unnamed>"; -const char SAVE_FILE_FILTER[] = "Octave Files (*.m);;All Files (*.*)"; enum editor_markers { bookmark, @@ -51,9 +49,11 @@ ~file_editor (); void loadFile (const QString& fileName); + QMenu * get_mru_menu ( ) { return _mru_file_menu; } QMenu * debug_menu (); QToolBar * toolbar (); + void set_focus (); void handle_entered_debug_mode (); void handle_quit_debug_mode (); @@ -85,6 +85,7 @@ void fetab_comment_selected_text (const QWidget* ID); void fetab_uncomment_selected_text (const QWidget* ID); void fetab_find (const QWidget* ID); + void fetab_set_focus (const QWidget* ID); public slots: void request_new_file (); @@ -113,7 +114,7 @@ void request_uncomment_selected_text (); void request_find (); - void handle_file_name_changed (const QString& fileName); + void handle_file_name_changed (const QString& fileName, const QString& toolTip); void handle_tab_close_request (int index); void handle_tab_remove_request (); void handle_add_filename_to_list (const QString& fileName); @@ -150,6 +151,7 @@ int _marker_breakpoint; enum { MaxMRUFiles = 10 }; + QMenu *_mru_file_menu; QAction *_mru_file_actions[MaxMRUFiles]; QStringList _mru_files;
--- a/libgui/src/m-editor/find-dialog.cc +++ b/libgui/src/m-editor/find-dialog.cc @@ -130,6 +130,21 @@ _extension->hide (); } + +// initialize search text with selected text if this is in one single line +void +find_dialog::init_search_text () +{ + if (_edit_area->hasSelectedText ()) + { + int lbeg, lend, cbeg, cend; + _edit_area->getSelection(&lbeg,&cbeg,&lend,&cend); + if (lbeg == lend) + _search_line_edit->setText (_edit_area->selectedText ()); + } +} + + void find_dialog::search_next () {
--- a/libgui/src/m-editor/find-dialog.h +++ b/libgui/src/m-editor/find-dialog.h @@ -57,6 +57,7 @@ Q_OBJECT public: find_dialog (QsciScintilla* edit_area, QWidget *parent = 0); + void init_search_text (); private slots: void search_next ();
--- a/libgui/src/main-window.cc +++ b/libgui/src/main-window.cc @@ -100,7 +100,6 @@ { #ifdef HAVE_QSCINTILLA _file_editor->request_new_file (); - focus_editor (); #endif } @@ -109,7 +108,6 @@ { #ifdef HAVE_QSCINTILLA _file_editor->request_open_file (); - focus_editor (); #endif } @@ -118,7 +116,6 @@ { #ifdef HAVE_QSCINTILLA _file_editor->request_open_file (file_name); - focus_editor (); #endif } @@ -166,7 +163,13 @@ main_window::handle_command_double_clicked (const QString& command) { _terminal->sendText (command); - _terminal->setFocus (); + focus_command_window (); +} + +void +main_window::open_online_documentation_page () +{ + QDesktopServices::openUrl (QUrl ("http://gnu.org/software/octave/doc/interpreter")); } void @@ -176,18 +179,18 @@ } void +main_window::open_octave_forge_page () +{ + QDesktopServices::openUrl (QUrl ("http://octave.sourceforge.net/")); +} + +void main_window::open_agora_page () { QDesktopServices::openUrl (QUrl ("http://agora.octave.org/")); } void -main_window::open_octave_forge_page () -{ - QDesktopServices::openUrl (QUrl ("http://octave.sourceforge.net/")); -} - -void main_window::process_settings_dialog_request () { settings_dialog *settingsDialog = new settings_dialog (this); @@ -393,18 +396,13 @@ _workspace_view->raise (); } + void main_window::focus_editor () { #ifdef HAVE_QSCINTILLA - if (!_file_editor->isVisible ()) - { - _file_editor->setVisible (true); - } - - _file_editor->setFocus (); - _file_editor->activateWindow (); - _file_editor->raise (); + // call own function of editor in order to set focus to the current editor tab + _file_editor->set_focus (); #endif } @@ -422,6 +420,56 @@ } void +main_window::handle_command_window_visible (bool visible) +{ + // if widget is changed to visible and is not floating + if (visible && !_terminal_dock_widget->isFloating ()) + focus_command_window (); +} + +void +main_window::handle_command_history_visible (bool visible) +{ + // if changed to visible and widget is not floating + if (visible && !_history_dock_widget->isFloating ()) + focus_command_history (); +} + +void +main_window::handle_current_directory_visible (bool visible) +{ + // if changed to visible and widget is not floating + if (visible && !_files_dock_widget->isFloating ()) + focus_current_directory (); +} + +void +main_window::handle_workspace_visible (bool visible) +{ + // if changed to visible and widget is not floating + if (visible && !_workspace_view->isFloating ()) + focus_workspace (); +} + +void +main_window::handle_editor_visible (bool visible) +{ + // if changed to visible and widget is not floating +#ifdef HAVE_QSCINTILLA + if (visible && !_file_editor->isFloating ()) + focus_editor (); +#endif +} + +void +main_window::handle_documentation_visible (bool visible) +{ + // if changed to visible and widget is not floating + if (visible && !_documentation_dock_widget->isFloating ()) + focus_documentation (); +} + +void main_window::handle_entered_debug_mode () { setWindowTitle ("Octave (Debugging)"); @@ -567,6 +615,30 @@ settings->sync (); } + +// Connecting the signals emitted when the visibility of a widget changes. +// This has to be done after the window is shown (see octave-gui.cc) +void +main_window::connect_visibility_changed () +{ + connect (_terminal_dock_widget, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_command_window_visible (bool))); + connect (_workspace_view, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_workspace_visible (bool))); + connect (_history_dock_widget, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_command_history_visible (bool))); + connect (_files_dock_widget, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_current_directory_visible (bool))); +#ifdef HAVE_QSCINTILLA + connect (_file_editor, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_editor_visible (bool))); +#endif + connect (_documentation_dock_widget, SIGNAL (visibilityChanged (bool)), + this, SLOT (handle_documentation_visible (bool))); +} + + +// Main subroutine of the constructor void main_window::construct () { @@ -647,12 +719,15 @@ = file_menu->addAction (QIcon(":/actions/icons/fileopen.png"), tr ("Open...")); open_action->setShortcut (Qt::ControlModifier + Qt::Key_O); + file_menu->addMenu(_file_editor->get_mru_menu ()); + QAction *close_command_window_action = file_menu->addAction (tr ("Close Command Window")); close_command_window_action->setShortcut (Qt::ControlModifier + Qt::Key_W); close_command_window_action->setEnabled (false); // TODO: Make this work. - file_menu->addSeparator (); + file_menu->addSeparator (); ///// + QAction *import_data_action = file_menu->addAction (tr ("Import Data...")); import_data_action->setEnabled (false); // TODO: Make this work. @@ -660,12 +735,15 @@ QAction *save_workspace_action = file_menu->addAction (tr ("Save Workspace...")); save_workspace_action->setShortcut (Qt::ControlModifier + Qt::Key_S); - file_menu->addSeparator (); + + file_menu->addSeparator (); ///// QAction *preferences_action = file_menu->addAction (QIcon(":/actions/icons/configure.png"), tr ("Preferences...")); - file_menu->addSeparator (); + + file_menu->addSeparator (); ///// + QAction *page_setup_action = file_menu->addAction (tr ("Page Setup...")); page_setup_action->setEnabled (false); // TODO: Make this work. @@ -677,7 +755,8 @@ = file_menu->addAction (tr ("Print Selection...")); print_selection_action->setEnabled (false); // TODO: Make this work. - file_menu->addSeparator (); + file_menu->addSeparator (); ///// + QAction *exit_action = file_menu->addAction (tr ("Exit")); exit_action->setShortcut (Qt::ControlModifier + Qt::Key_Q); @@ -690,7 +769,8 @@ QAction *redo_action = edit_menu->addAction (QIcon(":/actions/icons/redo.png"), tr ("Redo")); redo_action->setShortcut (QKeySequence::Redo); - edit_menu->addSeparator (); + + edit_menu->addSeparator (); ///// QAction *cut_action = edit_menu->addAction (QIcon(":/actions/icons/editcut.png"), tr ("Cut")); @@ -707,7 +787,8 @@ QAction *paste_to_workspace_action = edit_menu->addAction (tr ("Paste To Workspace...")); paste_to_workspace_action->setEnabled (false); // TODO: Make this work. - edit_menu->addSeparator (); + + edit_menu->addSeparator (); ///// QAction *select_all_action = edit_menu->addAction (tr ("Select All")); @@ -716,7 +797,8 @@ = edit_menu->addAction (tr ("Delete")); delete_action->setShortcut (Qt::Key_Delete); delete_action->setEnabled (false); // TODO: Make this work. - edit_menu->addSeparator (); + + edit_menu->addSeparator (); ///// QAction *find_action = edit_menu->addAction (tr ("Find...")); @@ -726,7 +808,8 @@ find_files_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_F); find_files_action->setEnabled (false); // TODO: Make this work. - edit_menu->addSeparator (); + + edit_menu->addSeparator (); ///// QAction *clear_command_window_action = edit_menu->addAction (tr ("Clear Command Window")); @@ -770,9 +853,9 @@ #endif _debug_continue->setShortcut (Qt::Key_F5); - _debug_menu->addSeparator (); + _debug_menu->addSeparator (); ///// #ifdef HAVE_QSCINTILLA - _file_editor->debug_menu ()->addSeparator (); + _file_editor->debug_menu ()->addSeparator (); ///// #endif _debug_quit = _debug_menu->addAction (QIcon (":/actions/icons/db_stop.png"), tr ("Exit Debug Mode")); @@ -823,7 +906,7 @@ show_documentation_action->setCheckable (true); show_documentation_action->setShortcut (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_5); - window_menu->addSeparator (); + window_menu->addSeparator (); ///// QAction * command_window_action = window_menu->addAction (tr ("Command Window")); @@ -849,20 +932,31 @@ = window_menu->addAction (tr ("Documentation")); documentation_action->setShortcut (Qt::ControlModifier + Qt::Key_5); - window_menu->addSeparator (); + window_menu->addSeparator (); ///// + QAction * reset_windows_action = window_menu->addAction (tr ("Reset Windows")); reset_windows_action->setEnabled (false); // TODO: Make this work. // Help menu QMenu * help_menu = menuBar ()->addMenu (tr ("&Help")); + QMenu * documentation_menu + = help_menu->addMenu (tr ("Documentation")); + QAction * ondisk_documentation_action + = documentation_menu->addAction (tr ("On Disk")); + QAction * online_documentation_action + = documentation_menu->addAction (tr ("Online")); + + help_menu->addSeparator (); ///// + QAction * report_bug_action = help_menu->addAction (tr ("Report Bug")); + QAction * octave_forge_action + = help_menu->addAction (tr ("Visit Octave Forge")); QAction * agora_action = help_menu->addAction (tr ("Visit Agora")); - QAction * octave_forge_action - = help_menu->addAction (tr ("Visit Octave Forge")); - help_menu->addSeparator (); + + help_menu->addSeparator (); ///// QAction * about_octave_action = help_menu->addAction (tr ("About Octave")); @@ -872,13 +966,17 @@ main_tool_bar->setObjectName ("MainToolBar"); main_tool_bar->addAction (new_script_action); main_tool_bar->addAction (open_action); - main_tool_bar->addSeparator (); + + main_tool_bar->addSeparator (); ///// + main_tool_bar->addAction (cut_action); main_tool_bar->addAction (copy_action); main_tool_bar->addAction (paste_action); main_tool_bar->addAction (undo_action); main_tool_bar->addAction (redo_action); - main_tool_bar->addSeparator (); + + main_tool_bar->addSeparator (); ///// + // addWidget takes ownership of the objects so there is no // need to delete these upon destroying this main_window. main_tool_bar->addWidget (new QLabel (tr ("Current Directory:"))); @@ -896,12 +994,14 @@ this, SLOT (new_file ())); connect (open_action, SIGNAL (triggered ()), this, SLOT (open_file ())); + connect (online_documentation_action, SIGNAL (triggered ()), + this, SLOT (open_online_documentation_page ())); connect (report_bug_action, SIGNAL (triggered ()), this, SLOT (open_bug_tracker_page ())); + connect (octave_forge_action, SIGNAL (triggered ()), + this, SLOT (open_octave_forge_page ())); connect (agora_action, SIGNAL (triggered ()), this, SLOT (open_agora_page ())); - connect (octave_forge_action, SIGNAL (triggered ()), - this, SLOT (open_octave_forge_page ())); connect (about_octave_action, SIGNAL (triggered ()), this, SLOT (show_about_octave ())); connect (show_command_window_action, SIGNAL (toggled (bool)), @@ -943,6 +1043,8 @@ this, SLOT (focus_editor ())); connect (documentation_action, SIGNAL (triggered ()), this, SLOT (focus_documentation ())); + connect (ondisk_documentation_action, SIGNAL (triggered ()), + this, SLOT (focus_documentation ())); connect (reset_windows_action, SIGNAL (triggered ()), this, SLOT (reset_windows ()));
--- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -86,9 +86,10 @@ void new_file (); void open_file (); void open_file (const QString& file_name); + void open_online_documentation_page (); void open_bug_tracker_page (); + void open_octave_forge_page (); void open_agora_page (); - void open_octave_forge_page (); void process_settings_dialog_request (); void show_about_octave (); void notice_settings (); @@ -106,6 +107,12 @@ void focus_workspace (); void focus_editor (); void focus_documentation (); + void handle_command_window_visible (bool); + void handle_command_history_visible (bool); + void handle_current_directory_visible (bool); + void handle_workspace_visible (bool); + void handle_editor_visible (bool); + void handle_documentation_visible (bool); void handle_entered_debug_mode (); void handle_quit_debug_mode (); @@ -117,6 +124,7 @@ void read_settings (); void write_settings (); + void connect_visibility_changed (); protected: void closeEvent (QCloseEvent * closeEvent);
--- a/libgui/src/octave-adapter/octave-main-thread.cc +++ b/libgui/src/octave-adapter/octave-main-thread.cc @@ -24,6 +24,7 @@ #include <config.h> #endif +#include <clocale> #include <string> #include "octave.h"
--- a/libgui/src/octave-gui.cc +++ b/libgui/src/octave-gui.cc @@ -26,7 +26,6 @@ #include <QtGui/QApplication> #include <QTranslator> -#include <QSettings> #include <iostream> @@ -95,24 +94,23 @@ } else { - QSettings *settings = resource_manager::get_settings (); - - // FIXME -- what should happen if settings is 0? - - QString language = settings->value ("language").toString (); + // install translators for the gui and qt text + QTranslator gui_translator, qt_translator; + resource_manager::config_translators (&gui_translator,&qt_translator); + application.installTranslator (&qt_translator); + application.installTranslator (&gui_translator); - QString translatorFile = resource_manager::find_translator_file (language); - QTranslator translator; - translator.load (translatorFile); - application.installTranslator (&translator); - + // update network-settings resource_manager::update_network_settings (); + // create main window, read settings, and show window main_window w; - w.read_settings (); // Get the widget settings after construction and before showing + w.read_settings (); // get widget settings after construction + // but before showing w.show (); w.focus_command_window (); - + w.connect_visibility_changed (); // connect signals for changes in + // visibility not before w is shown return application.exec (); } }
--- a/libgui/src/resource-manager.cc +++ b/libgui/src/resource-manager.cc @@ -29,6 +29,7 @@ #include <QFile> #include <QDir> #include <QNetworkProxy> + #include <QLibraryInfo> #include "error.h" #include "file-ops.h" @@ -52,11 +53,31 @@ delete settings; } + QString -resource_manager::find_translator_file (const QString& language) +resource_manager::get_gui_translation_dir (void) { - // TODO: Quick hack to be able to test language files. - return QString ("libgui/languages/%1.qm").arg (language); + // get environment variable for the locale dir (e.g. from run-octave) + std::string dldir = octave_env::getenv ("OCTAVE_LOCALE_DIR"); + if (dldir.empty ()) + dldir = Voct_locale_dir; // env-var empty, load the default location + return QString::fromStdString (dldir); +} + +void +resource_manager::config_translators (QTranslator *qt_tr,QTranslator *gui_tr) +{ + QSettings *settings = resource_manager::get_settings (); + // FIXME -- what should happen if settings is 0? + // get the locale from the settings + QString language = settings->value ("language","SYSTEM").toString (); + if (language == "SYSTEM") + language = QLocale::system().name(); // get system wide locale + // load the translator file for qt strings + qt_tr->load("qt_" + language, + QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + // load the translator file for gui strings + gui_tr->load (language, get_gui_translation_dir ()); } bool
--- a/libgui/src/resource-manager.h +++ b/libgui/src/resource-manager.h @@ -27,7 +27,7 @@ #include <QIcon> #include <QMap> #include <QSettings> - +#include <QTranslator> class resource_manager { @@ -61,7 +61,9 @@ instance->do_set_settings (file); } - static QString find_translator_file (const QString& language); + static QString get_gui_translation_dir (void); + + static void config_translators (QTranslator*, QTranslator*); static void update_network_settings (void) {
--- a/libgui/src/settings-dialog.cc +++ b/libgui/src/settings-dialog.cc @@ -28,6 +28,8 @@ #include "settings-dialog.h" #include "ui-settings-dialog.h" #include <QSettings> +#include <QDir> +#include <QFileInfo> settings_dialog::settings_dialog (QWidget *p): QDialog (p), ui (new Ui::settings_dialog) @@ -35,9 +37,28 @@ ui->setupUi (this); QSettings *settings = resource_manager::get_settings (); - // FIXME -- what should happen if settings is 0? + // look for available language files and the actual settings + QString qm_dir_name = resource_manager::get_gui_translation_dir (); + QDir qm_dir (qm_dir_name); + QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"), + QDir::Files | QDir::Readable, + QDir::Name); + for (int i = 0; i < qm_files.length (); i++) // insert available languages + ui->comboBox_language->addItem (qm_files.at (i).baseName ()); + ui->comboBox_language->insertItem (0,tr("System setting")); // System at beginning + ui->comboBox_language->insertSeparator (1); // separator after System + QString language = settings->value ("language","SYSTEM").toString (); + if (language == "SYSTEM") + language = tr("System setting"); + int selected = ui->comboBox_language->findText (language); + if (selected >= 0) + ui->comboBox_language->setCurrentIndex (selected); + else + ui->comboBox_language->setCurrentIndex (0); // System is default + + // which icon has to be selected QString widget_icon_set = settings->value ("DockWidgets/widget_icon_set","NONE").toString (); ui->general_icon_octave-> setChecked (true); // the default (if invalid set) @@ -104,15 +125,23 @@ settings_dialog::write_changed_settings () { QSettings *settings = resource_manager::get_settings (); - // FIXME -- what should happen if settings is 0? + // the icon set QString widget_icon_set = "NONE"; if (ui->general_icon_letter->isChecked ()) widget_icon_set = "LETTER"; else if (ui->general_icon_graphic->isChecked ()) widget_icon_set = "GRAPHIC"; settings->setValue ("DockWidgets/widget_icon_set",widget_icon_set); + + // language + QString language = ui->comboBox_language->currentText (); + if (language == tr("System setting")) + language = "SYSTEM"; + settings->setValue ("language", language); + + // other settings settings->setValue ("useCustomFileEditor", ui->useCustomFileEditor->isChecked ()); settings->setValue ("customFileEditor", ui->customFileEditor->text ()); settings->setValue ("editor/showLineNumbers", ui->editor_showLineNumbers->isChecked ()); @@ -138,6 +167,7 @@ settings->setValue ("proxyPassword", ui->proxyPassword->text ()); settings->setValue ("terminal/cursorBlinking", ui->terminal_cursorBlinking->isChecked ()); + // the cursor QString cursorType; switch (ui->terminal_cursorType->currentIndex ()) {
--- a/libgui/src/settings-dialog.ui +++ b/libgui/src/settings-dialog.ui @@ -41,75 +41,112 @@ <attribute name="title"> <string>General</string> </attribute> - <widget class="QGroupBox" name="groupBox"> + <widget class="QWidget" name="verticalLayoutWidget"> <property name="geometry"> <rect> - <x>10</x> + <x>9</x> <y>10</y> - <width>551</width> - <height>81</height> + <width>561</width> + <height>131</height> </rect> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Icon set for dock widget</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - <property name="flat"> - <bool>false</bool> - </property> - <property name="checkable"> - <bool>false</bool> - </property> - <widget class="QRadioButton" name="general_icon_octave"> - <property name="geometry"> - <rect> - <x>0</x> - <y>20</y> - <width>151</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Octave logo only</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - <widget class="QRadioButton" name="general_icon_letter"> - <property name="geometry"> - <rect> - <x>0</x> - <y>40</y> - <width>151</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Letter icons</string> - </property> - </widget> - <widget class="QRadioButton" name="general_icon_graphic"> - <property name="geometry"> - <rect> - <x>0</x> - <y>60</y> - <width>151</width> - <height>21</height> - </rect> - </property> - <property name="text"> - <string>Graphic icons</string> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Language (requires restart)</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_language"> + <property name="insertPolicy"> + <enum>QComboBox::InsertAtBottom</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Icon set for dock widgets</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <widget class="QRadioButton" name="general_icon_octave"> + <property name="geometry"> + <rect> + <x>0</x> + <y>20</y> + <width>151</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Octave logo only</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" name="general_icon_letter"> + <property name="geometry"> + <rect> + <x>0</x> + <y>40</y> + <width>151</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Letter icons</string> + </property> + </widget> + <widget class="QRadioButton" name="general_icon_graphic"> + <property name="geometry"> + <rect> + <x>0</x> + <y>60</y> + <width>151</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Graphic icons</string> + </property> + </widget> + </widget> + </item> + </layout> </widget> </widget> <widget class="QWidget" name="tab">
--- a/libinterp/Makefile.am +++ b/libinterp/Makefile.am @@ -230,6 +230,16 @@ -DMAKE_BUILTINS $< | $(srcdir)/mkdefs $(srcdir) $< > $@-t mv $@-t $@ +## Rules to build test files + +TST_FILES_SRC := $(shell $(top_srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(DIST_SRC) $(DLDFCN_SRC)) + +TST_FILES := $(addsuffix -tst,$(TST_FILES_SRC)) + +libinterptestsdir := $(octtestsdir)/libinterp + +nobase_libinterptests_DATA = $(TST_FILES) + ## Override Automake's rule that forces a .hh extension on us even ## though we don't want it. It would be super awesome if automake ## would allow users to choose the header file extension.
--- a/libinterp/corefcn/cellfun.cc +++ b/libinterp/corefcn/cellfun.cc @@ -69,7 +69,14 @@ octave_value& func, octave_value& error_handler) { - octave_value_list tmp = func.do_multi_index_op (nargout, inputlist); + octave_value_list tmp; + try { + tmp = func.do_multi_index_op (nargout, inputlist); + } + catch (octave_execution_exception) { + if (error_handler.is_defined ()) + error_state = 1; + } if (error_state) { @@ -996,6 +1003,7 @@ %!assert (cellfun (@atan2, {1,1;1,1}, {1,2;1,2}), atan2 ([1,1;1,1],[1,2;1,2])) %!error cellfun (@factorial, {-1,3}) %!assert (cellfun (@factorial,{-1,3},"ErrorHandler",@(x,y) NaN), [NaN,6]) +%!assert (cellfun (@(x) x(2),{[1],[1,2]},"ErrorHandler",@(x,y) NaN), [NaN,2]) %!test %! [a,b,c] = cellfun (@fileparts, {fullfile("a","b","c.d"), fullfile("e","f","g.h")}, "UniformOutput", false); %! assert (a, {fullfile("a","b"), fullfile("e","f")}); @@ -1133,7 +1141,8 @@ if (nargin < 2) { - error ("arrayfun: function requires at least 2 arguments"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: function requires at least 2 arguments"); print_usage (); return retval; } @@ -1164,7 +1173,9 @@ func = symbol_table::find_function (name); if (func.is_undefined ()) - error ("arrayfun: invalid function NAME: %s", name.c_str ()); + error_with_id ("Octave:invalid-input-arg", + "arrayfun: invalid function NAME: %s", + name.c_str ()); symbol_table_lookup = true; } @@ -1242,7 +1253,8 @@ { if (mask[i] && inputs[i].dims () != fdims) { - error ("arrayfun: dimensions mismatch"); + error_with_id ("Octave:invalid-input-arg", + "arrayfun: dimensions mismatch"); return retval; } } @@ -1289,7 +1301,8 @@ if (nargout > 0 && tmp.length () < nargout) { - error ("arrayfun: function returned fewer than nargout values"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: function returned fewer than nargout values"); return retval; } @@ -1314,7 +1327,8 @@ retv[j] = val.resize (fdims); else { - error ("arrayfun: all values must be scalars when UniformOutput = true"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: all values must be scalars when UniformOutput = true"); break; } } @@ -1341,7 +1355,8 @@ } else { - error ("arrayfun: all values must be scalars when UniformOutput = true"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: all values must be scalars when UniformOutput = true"); break; } } @@ -1399,7 +1414,8 @@ if (nargout > 0 && tmp.length () < nargout) { - error ("arrayfun: function returned fewer than nargout values"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: function returned fewer than nargout values"); return retval; } @@ -1430,7 +1446,8 @@ } } else - error ("arrayfun: argument NAME must be a string or function handle"); + error_with_id ("Octave:invalid-fun-call", + "arrayfun: argument NAME must be a string or function handle"); return retval; }
--- a/libinterp/corefcn/kron.cc +++ b/libinterp/corefcn/kron.cc @@ -177,6 +177,13 @@ octave_value retval; if (a.is_perm_matrix () && b.is_perm_matrix ()) retval = do_kron<PermMatrix, PermMatrix> (a, b); + else if (a.is_sparse_type () || b.is_sparse_type ()) + { + if (a.is_complex_type () || b.is_complex_type ()) + retval = do_kron<SparseComplexMatrix, SparseComplexMatrix> (a, b); + else + retval = do_kron<SparseMatrix, SparseMatrix> (a, b); + } else if (a.is_diag_matrix ()) { if (b.is_diag_matrix () && a.rows () == a.columns () @@ -214,13 +221,6 @@ retval = do_kron<DiagMatrix, Matrix> (a, b); } } - else if (a.is_sparse_type () || b.is_sparse_type ()) - { - if (a.is_complex_type () || b.is_complex_type ()) - retval = do_kron<SparseComplexMatrix, SparseComplexMatrix> (a, b); - else - retval = do_kron<SparseMatrix, SparseMatrix> (a, b); - } else if (a.is_single_type () || b.is_single_type ()) { if (a.is_complex_type ())
--- a/libinterp/corefcn/quadcc.cc +++ b/libinterp/corefcn/quadcc.cc @@ -33,11 +33,12 @@ #include "oct-obj.h" #include "utils.h" -//#include "oct.h" -//#include "defun.h" -/* Define the size of the interval heap. */ -#define cquad_heapsize 200 +/* Extended debugging */ +#define DEBUG_QUADCC 0 + +/* Define the minimum size of the interval heap. */ +#define min_cquad_heapsize 200 /* Data of a single interval */ @@ -1551,14 +1552,10 @@ static const double w = M_SQRT2 / 2; static const int ndiv_max = 20; - /* The interval heap. */ - cquad_ival ivals[cquad_heapsize]; - int heap[cquad_heapsize]; - /* Arguments left and right */ int nargin = args.length (); octave_function *fcn; - double a, b, tol, iivals[cquad_heapsize], *sing; + double a, b, tol, *sing; /* Variables needed for transforming the integrand. */ bool wrap = false; @@ -1588,7 +1585,7 @@ fcn = args(0).function_value (); else { - std::string fcn_name = unique_symbol_name ("__quadcc_fcn_"); + std::string fcn_name = unique_symbol_name ("__quadcc_fcn__"); std::string fname = "function y = "; fname.append (fcn_name); fname.append ("(x) y = "); @@ -1596,7 +1593,7 @@ "; endfunction"); } - if (!args(1).is_real_scalar ()) + if (! args(1).is_real_scalar ()) { error ("quadcc: lower limit of integration (A) must be a single real scalar"); return retval; @@ -1604,7 +1601,7 @@ else a = args(1).double_value (); - if (!args(2).is_real_scalar ()) + if (! args(2).is_real_scalar ()) { error ("quadcc: upper limit of integration (B) must be a single real scalar"); return retval; @@ -1614,7 +1611,7 @@ if (nargin < 4 || args(3).is_empty ()) tol = 1.0e-6; - else if (!args(3).is_real_scalar () || args(3).double_value () <= 0) + else if (! args(3).is_real_scalar () || args(3).double_value () <= 0) { error ("quadcc: tolerance (TOL) must be a single real scalar > 0"); return retval; @@ -1625,8 +1622,6 @@ if (nargin < 5) { nivals = 1; - iivals[0] = a; - iivals[1] = b; } else if (!(args(4).is_real_scalar () || args(4).is_real_matrix ())) { @@ -1635,16 +1630,27 @@ } else { - nivals = 1 + args(4).length (); - if (nivals > cquad_heapsize) - { - error ("quadcc: maximum number of singular points is limited to %i", - cquad_heapsize-1); - return retval; - } + nivals = 1 + args(4).numel (); + } + + int cquad_heapsize = (nivals >= min_cquad_heapsize ? nivals + 1 + : min_cquad_heapsize); + /* The interval heap. */ + OCTAVE_LOCAL_BUFFER (cquad_ival, ivals, cquad_heapsize); + OCTAVE_LOCAL_BUFFER (double, iivals, cquad_heapsize); + OCTAVE_LOCAL_BUFFER (int, heap, cquad_heapsize); + + if (nivals == 1) + { + iivals[0] = a; + iivals[1] = b; + } + else + { + // Intervals around singularities sing = args(4).array_value ().fortran_vec (); iivals[0] = a; - for (i = 0; i < nivals - 2; i++) + for (i = 0; i < nivals - 1; i++) iivals[i + 1] = sing[i]; iivals[nivals] = b; } @@ -1653,7 +1659,7 @@ if (xisinf (a) || xisinf (b)) { wrap = true; - for (i = 0; i <= nivals; i++) + for (i = 0; i < nivals + 1; i++) if (xisinf (iivals[i])) iivals[i] = gnulib::copysign (1.0, iivals[i]); else @@ -1665,7 +1671,6 @@ for (i = 0; i < cquad_heapsize; i++) heap[i] = i; - /* Create the first interval(s). */ igral = 0.0; err = 0.0; @@ -1681,16 +1686,16 @@ if (wrap) { for (i = 0; i <= n[3]; i++) - ex (i) = tan (M_PI / 2 * (m + xi[i] * h)); + ex(i) = tan (M_PI / 2 * (m + xi[i] * h)); } else { for (i = 0; i <= n[3]; i++) - ex (i) = m + xi[i] * h; + ex(i) = m + xi[i] * h; } fargs(0) = ex; fvals = feval (fcn, fargs, 1); - if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) + if (fvals.length () != 1 || ! fvals(0).is_real_matrix ()) { error ("quadcc: integrand F must return a single, real-valued vector"); return retval; @@ -1703,14 +1708,14 @@ } for (i = 0; i <= n[3]; i++) { - iv->fx[i] = effex (i); + iv->fx[i] = effex(i); if (wrap) { xw = ex(i); iv->fx[i] *= (1.0 + xw * xw) * M_PI / 2; } neval++; - if (!xfinite (iv->fx[i])) + if (! xfinite (iv->fx[i])) { nans[nnans++] = i; iv->fx[i] = 0.0; @@ -1782,10 +1787,12 @@ m = (iv->a + iv->b) / 2; h = (iv->b - iv->a) / 2; -/* printf +#if (DEBUG_QUADCC) + printf ("quadcc: processing ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth); -*/ +#endif + /* Should we try to increase the degree? */ if (iv->depth < 3) { @@ -1799,17 +1806,16 @@ if (wrap) { for (i = 0; i < n[d] / 2; i++) - ex (i) = - tan (M_PI / 2 * (m + xi[(2 * i + 1) * skip[d]] * h)); + ex(i) = tan (M_PI / 2 * (m + xi[(2 * i + 1) * skip[d]] * h)); } else { for (i = 0; i < n[d] / 2; i++) - ex (i) = m + xi[(2 * i + 1) * skip[d]] * h; + ex(i) = m + xi[(2 * i + 1) * skip[d]] * h; } fargs(0) = ex; fvals = feval (fcn, fargs, 1); - if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) + if (fvals.length () != 1 || ! fvals(0).is_real_matrix ()) { error ("quadcc: integrand F must return a single, real-valued vector"); return retval; @@ -1824,7 +1830,7 @@ for (i = 0; i < n[d] / 2; i++) { j = (2 * i + 1) * skip[d]; - iv->fx[j] = effex (i); + iv->fx[j] = effex(i); if (wrap) { xw = ex(i); @@ -1835,7 +1841,7 @@ nnans = 0; for (i = 0; i <= 32; i += skip[d]) { - if (!xfinite (iv->fx[i])) + if (! xfinite (iv->fx[i])) { nans[nnans++] = i; iv->fx[i] = 0.0; @@ -1888,11 +1894,13 @@ || iv->err < fabs (iv->igral) * std::numeric_limits<double>::epsilon () * 10) { -/* printf +#if (DEBUG_QUADCC) + printf ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth); -*/ +#endif + /* Keep this interval's contribution */ err_final += iv->err; igral_final += iv->igral; @@ -1905,7 +1913,6 @@ i = 0; while (2 * i + 1 < nivals) { - /* Get the kids */ j = 2 * i + 1; /* If the j+1st entry exists and is larger than the jth, @@ -1948,16 +1955,16 @@ if (wrap) { for (i = 0; i < n[0] - 1; i++) - ex (i) = tan (M_PI / 2 * (ml + xi[(i + 1) * skip[0]] * hl)); + ex(i) = tan (M_PI / 2 * (ml + xi[(i + 1) * skip[0]] * hl)); } else { for (i = 0; i < n[0] - 1; i++) - ex (i) = ml + xi[(i + 1) * skip[0]] * hl; + ex(i) = ml + xi[(i + 1) * skip[0]] * hl; } fargs(0) = ex; fvals = feval (fcn, fargs, 1); - if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) + if (fvals.length () != 1 || ! fvals(0).is_real_matrix ()) { error ("quadcc: integrand F must return a single, real-valued vector"); return retval; @@ -1972,7 +1979,7 @@ for (i = 0; i < n[0] - 1; i++) { j = (i + 1) * skip[0]; - ivl->fx[j] = effex (i); + ivl->fx[j] = effex(i); if (wrap) { xw = ex(i); @@ -1983,7 +1990,7 @@ nnans = 0; for (i = 0; i <= 32; i += skip[0]) { - if (!xfinite (ivl->fx[i])) + if (! xfinite (ivl->fx[i])) { nans[nnans++] = i; ivl->fx[i] = 0.0; @@ -2044,16 +2051,16 @@ if (wrap) { for (i = 0; i < n[0] - 1; i++) - ex (i) = tan (M_PI / 2 * (mr + xi[(i + 1) * skip[0]] * hr)); + ex(i) = tan (M_PI / 2 * (mr + xi[(i + 1) * skip[0]] * hr)); } else { for (i = 0; i < n[0] - 1; i++) - ex (i) = mr + xi[(i + 1) * skip[0]] * hr; + ex(i) = mr + xi[(i + 1) * skip[0]] * hr; } fargs(0) = ex; fvals = feval (fcn, fargs, 1); - if (fvals.length () != 1 || !fvals(0).is_real_matrix ()) + if (fvals.length () != 1 || ! fvals(0).is_real_matrix ()) { error ("quadcc: integrand F must return a single, real-valued vector"); return retval; @@ -2068,7 +2075,7 @@ for (i = 0; i < n[0] - 1; i++) { j = (i + 1) * skip[0]; - ivr->fx[j] = effex (i); + ivr->fx[j] = effex(i); if (wrap) { xw = ex(i); @@ -2079,7 +2086,7 @@ nnans = 0; for (i = 0; i <= 32; i += skip[0]) { - if (!xfinite (ivr->fx[i])) + if (! xfinite (ivr->fx[i])) { nans[nnans++] = i; ivr->fx[i] = 0.0; @@ -2195,16 +2202,16 @@ } - /* If the heap is about to overflow, remove the last two - intervals. */ + /* If the heap is about to overflow, remove the last two intervals. */ while (nivals > cquad_heapsize - 2) { iv = &(ivals[heap[nivals - 1]]); -/* printf +#if (DEBUG_QUADCC) + printf ("quadcc: dropping ival %i (of %i) with [%e,%e] int=%e, err=%e, depth=%i\n", heap[0], nivals, iv->a, iv->b, iv->igral, iv->err, iv->depth); -*/ +#endif err_final += iv->err; igral_final += iv->igral; nivals--; @@ -2222,7 +2229,8 @@ } /* Dump the contents of the heap. */ -/* for (i = 0; i < nivals; i++) +#if (DEBUG_QUADCC) + for (i = 0; i < nivals; i++) { iv = &(ivals[heap[i]]); printf @@ -2230,7 +2238,8 @@ i, heap[i], iv->a, iv->b, iv->igral, iv->err, iv->depth, iv->rdepth, iv->ndiv); } -*/ +#endif + /* Clean up and present the results. */ if (nargout > 2) retval(2) = neval; @@ -2265,7 +2274,7 @@ %!test %! [q, err, npoints] = quadcc ("__nansin", -pi, pi); -%! assert (q, 0, eps); +%! assert (q, 0, 1e-6); %! assert (err, 0, 15*eps); %% Test input validation
--- a/libinterp/dldfcn/fftw.cc +++ b/libinterp/dldfcn/fftw.cc @@ -38,6 +38,8 @@ @deftypefnx {Loadable Function} {} fftw (\"planner\", @var{method})\n\ @deftypefnx {Loadable Function} {@var{wisdom} =} fftw (\"dwisdom\")\n\ @deftypefnx {Loadable Function} {} fftw (\"dwisdom\", @var{wisdom})\n\ +@deftypefnx {Loadable Function} {} fftw (\"threads\", @var{nthreads})\n\ +@deftypefnx {Loadable Function} {@var{nthreads} =} fftw (\"threads\")\n\ \n\ Manage @sc{fftw} wisdom data. Wisdom data can be used to significantly\n\ accelerate the calculation of the FFTs, but implies an initial cost\n\ @@ -60,7 +62,7 @@ fftw (\"dwisdom\", @var{wisdom})\n\ @end example\n\ \n\ -If @var{wisdom} is an empty matrix, then the wisdom used is cleared.\n\ +If @var{wisdom} is an empty string, then the wisdom used is cleared.\n\ \n\ During the calculation of Fourier transforms further wisdom is generated.\n\ The fashion in which this wisdom is generated is also controlled by\n\ @@ -110,6 +112,17 @@ the wisdom data can be reloaded if it is saved to a file as described\n\ above. Saved wisdom files should not be used on different platforms since\n\ they will not be efficient and the point of calculating the wisdom is lost.\n\ +\n\ +The number of threads used for computing the plans and executing the\n\ +transforms can be set with\n\ +\n\ +@example\n\ +fftw (\"threads\", @var{NTHREADS})\n\ +@end example\n\ +\n\ +Note that octave must be compiled with multi-threaded FFTW support for this feature.\n\ +The number of processors available to the current process is used per default.\n\ +\n\ @seealso{fft, ifft, fft2, ifft2, fftn, ifftn}\n\ @end deftypefn") { @@ -127,106 +140,76 @@ if (args(0).is_string ()) { std::string arg0 = args(0).string_value (); - if (!error_state) { - // Use STL function to convert to lower case - std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower); - - if (nargin == 2) + if (arg0 == "planner") { - std::string arg1 = args(1).string_value (); - if (!error_state) + if (nargin == 2) //planner setter { - if (arg0 == "planner") + if (args(1).is_string ()) { - std::transform (arg1.begin (), arg1.end (), - arg1.begin (), tolower); - octave_fftw_planner::FftwMethod meth - = octave_fftw_planner::UNKNOWN; - octave_float_fftw_planner::FftwMethod methf - = octave_float_fftw_planner::UNKNOWN; - - if (arg1 == "estimate") - { - meth = octave_fftw_planner::ESTIMATE; - methf = octave_float_fftw_planner::ESTIMATE; - } - else if (arg1 == "measure") - { - meth = octave_fftw_planner::MEASURE; - methf = octave_float_fftw_planner::MEASURE; - } - else if (arg1 == "patient") - { - meth = octave_fftw_planner::PATIENT; - methf = octave_float_fftw_planner::PATIENT; - } - else if (arg1 == "exhaustive") - { - meth = octave_fftw_planner::EXHAUSTIVE; - methf = octave_float_fftw_planner::EXHAUSTIVE; - } - else if (arg1 == "hybrid") - { - meth = octave_fftw_planner::HYBRID; - methf = octave_float_fftw_planner::HYBRID; - } - else - error ("unrecognized planner METHOD"); - + // Use STL function to convert to lower case + std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower); + std::string arg1 = args(1).string_value (); if (!error_state) { - meth = octave_fftw_planner::method (meth); - octave_float_fftw_planner::method (methf); + std::transform (arg1.begin (), arg1.end (), + arg1.begin (), tolower); + octave_fftw_planner::FftwMethod meth + = octave_fftw_planner::UNKNOWN; + octave_float_fftw_planner::FftwMethod methf + = octave_float_fftw_planner::UNKNOWN; - if (meth == octave_fftw_planner::MEASURE) - retval = octave_value ("measure"); - else if (meth == octave_fftw_planner::PATIENT) - retval = octave_value ("patient"); - else if (meth == octave_fftw_planner::EXHAUSTIVE) - retval = octave_value ("exhaustive"); - else if (meth == octave_fftw_planner::HYBRID) - retval = octave_value ("hybrid"); + if (arg1 == "estimate") + { + meth = octave_fftw_planner::ESTIMATE; + methf = octave_float_fftw_planner::ESTIMATE; + } + else if (arg1 == "measure") + { + meth = octave_fftw_planner::MEASURE; + methf = octave_float_fftw_planner::MEASURE; + } + else if (arg1 == "patient") + { + meth = octave_fftw_planner::PATIENT; + methf = octave_float_fftw_planner::PATIENT; + } + else if (arg1 == "exhaustive") + { + meth = octave_fftw_planner::EXHAUSTIVE; + methf = octave_float_fftw_planner::EXHAUSTIVE; + } + else if (arg1 == "hybrid") + { + meth = octave_fftw_planner::HYBRID; + methf = octave_float_fftw_planner::HYBRID; + } else - retval = octave_value ("estimate"); + error ("unrecognized planner METHOD"); + + if (!error_state) + { + meth = octave_fftw_planner::method (meth); + octave_float_fftw_planner::method (methf); + + if (meth == octave_fftw_planner::MEASURE) + retval = octave_value ("measure"); + else if (meth == octave_fftw_planner::PATIENT) + retval = octave_value ("patient"); + else if (meth == octave_fftw_planner::EXHAUSTIVE) + retval = octave_value ("exhaustive"); + else if (meth == octave_fftw_planner::HYBRID) + retval = octave_value ("hybrid"); + else + retval = octave_value ("estimate"); + } } } - else if (arg0 == "dwisdom") - { - char *str = fftw_export_wisdom_to_string (); - - if (arg1.length () < 1) - fftw_forget_wisdom (); - else if (! fftw_import_wisdom_from_string (arg1.c_str ())) - error ("could not import supplied WISDOM"); - - if (!error_state) - retval = octave_value (std::string (str)); - - free (str); - } - else if (arg0 == "swisdom") - { - char *str = fftwf_export_wisdom_to_string (); - - if (arg1.length () < 1) - fftwf_forget_wisdom (); - else if (! fftwf_import_wisdom_from_string (arg1.c_str ())) - error ("could not import supplied WISDOM"); - - if (!error_state) - retval = octave_value (std::string (str)); - - free (str); - } else - error ("unrecognized argument"); + error ("fftw planner expects a string value as METHOD"); } - } - else - { - if (arg0 == "planner") + else //planner getter { octave_fftw_planner::FftwMethod meth = octave_fftw_planner::method (); @@ -242,23 +225,111 @@ else retval = octave_value ("estimate"); } - else if (arg0 == "dwisdom") + } + else if (arg0 == "dwisdom") + { + if (nargin == 2) //dwisdom setter + { + if (args(1).is_string ()) + { + // Use STL function to convert to lower case + std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower); + std::string arg1 = args(1).string_value (); + if (!error_state) + { + char *str = fftw_export_wisdom_to_string (); + + if (arg1.length () < 1) + fftw_forget_wisdom (); + else if (! fftw_import_wisdom_from_string (arg1.c_str ())) + error ("could not import supplied WISDOM"); + + if (!error_state) + retval = octave_value (std::string (str)); + + free (str); + } + } + } + else //dwisdom getter { char *str = fftw_export_wisdom_to_string (); retval = octave_value (std::string (str)); free (str); } - else if (arg0 == "swisdom") + } + else if (arg0 == "swisdom") + { + //swisdom uses fftwf_ functions (float), dwisdom fftw_ (real) + if (nargin == 2) //swisdom setter + { + if (args(1).is_string ()) + { + // Use STL function to convert to lower case + std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower); + std::string arg1 = args(1).string_value (); + if (!error_state) + { + char *str = fftwf_export_wisdom_to_string (); + + if (arg1.length () < 1) + fftwf_forget_wisdom (); + else if (! fftwf_import_wisdom_from_string (arg1.c_str ())) + error ("could not import supplied WISDOM"); + + if (!error_state) + retval = octave_value (std::string (str)); + + free (str); + } + } + } + else //swisdom getter { char *str = fftwf_export_wisdom_to_string (); retval = octave_value (std::string (str)); free (str); } - else - error ("unrecognized argument"); } + else if (arg0 == "threads") + { + if (nargin == 2) //threads setter + { + if (args(1).is_real_scalar ()) + { + int nthreads = args(1).int_value(); + if ( nthreads >= 1) + { +#if defined (HAVE_FFTW3_THREADS) + octave_fftw_planner::threads (nthreads); +#else + warning ("this copy of Octave was not configured to use the multithreaded fftw libraries."); +#endif +#if defined (HAVE_FFTW3F_THREADS) + octave_float_fftw_planner::threads (nthreads); +#else + warning ("this copy of Octave was not configured to use the multithreaded fftwf libraries."); +#endif + } + else + error ("number of threads must be >=1"); + } + else + error ("setting threads needs one integer argument."); + } + else //threads getter +#if defined (HAVE_FFTW3_THREADS) + retval = octave_value (octave_fftw_planner::threads()); +#else + retval = 1; +#endif + } + else + error ("unrecognized argument"); } } + else + error ("unrecognized argument"); #else warning ("fftw: this copy of Octave was not configured to use the FFTW3 planner"); @@ -269,7 +340,6 @@ } /* - %!testif HAVE_FFTW %! def_method = fftw ("planner"); %! unwind_protect @@ -295,4 +365,12 @@ %!error <Invalid call to fftw> fftw (); %!error <Invalid call to fftw> fftw ("planner", "estimate", "measure"); +%!testif HAVE_FFTW3_THREADS +%! n = fftw ("threads"); +%! unwind_protect +%! fftw ("threads", 3); +%! assert (fftw ("threads"), 3); +%! unwind_protect_cleanup +%! fftw ("threads", n); +%! end_unwind_protect */
--- a/libinterp/interp-core/c-file-ptr-stream.cc +++ b/libinterp/interp-core/c-file-ptr-stream.cc @@ -193,15 +193,15 @@ } int -c_file_ptr_buf::seek (long offset, int origin) +c_file_ptr_buf::seek (off_t offset, int origin) { - return f ? gnulib::fseek (f, offset, origin) : -1; + return f ? gnulib::fseeko (f, offset, origin) : -1; } -long +off_t c_file_ptr_buf::tell (void) { - return f ? gnulib::ftell (f) : -1; + return f ? gnulib::ftello (f) : -1; } int
--- a/libinterp/interp-core/c-file-ptr-stream.h +++ b/libinterp/interp-core/c-file-ptr-stream.h @@ -74,9 +74,9 @@ int file_number () const { return f ? fileno (f) : -1; } - int seek (long offset, int origin); + int seek (off_t offset, int origin); - long tell (void); + off_t tell (void); void clear (void) { if (f) clearerr (f); } @@ -117,10 +117,10 @@ void stream_close (void) { if (buf) buf->buf_close (); } - int seek (long offset, int origin) + int seek (off_t offset, int origin) { return buf ? buf->seek (offset, origin) : -1; } - long tell (void) { return buf ? buf->tell () : -1; } + off_t tell (void) { return buf ? buf->tell () : -1; } void clear (void) { if (buf) buf->clear (); STREAM_T::clear (); } @@ -192,10 +192,10 @@ int file_number () const { return -1; } - int seek (long offset, int origin) - { return f ? gzseek (f, offset, origin) : -1; } + int seek (off_t offset, int origin) + { return f ? gzseek (f, offset, origin) >= 0 : -1; } - long tell (void) { return f ? gztell (f) : -1; } + off_t tell (void) { return f ? gztell (f) : -1; } void clear (void) { if (f) gzclearerr (f); }
--- a/libinterp/interp-core/oct-fstrm.cc +++ b/libinterp/interp-core/oct-fstrm.cc @@ -62,7 +62,7 @@ // Position a stream at OFFSET relative to ORIGIN. int -octave_fstream::seek (long, int) +octave_fstream::seek (off_t, int) { error ("fseek: invalid_operation"); return -1; @@ -70,7 +70,7 @@ // Return current stream position. -long +off_t octave_fstream::tell (void) { error ("ftell: invalid_operation");
--- a/libinterp/interp-core/oct-fstrm.h +++ b/libinterp/interp-core/oct-fstrm.h @@ -46,11 +46,11 @@ // Position a stream at OFFSET relative to ORIGIN. - int seek (long offset, int origin); + int seek (off_t offset, int origin); // Return current stream position. - long tell (void); + off_t tell (void); // Return non-zero if EOF has been reached on this stream.
--- a/libinterp/interp-core/oct-iostrm.cc +++ b/libinterp/interp-core/oct-iostrm.cc @@ -30,7 +30,7 @@ // Position a stream at OFFSET relative to ORIGIN. int -octave_base_iostream::seek (long, int) +octave_base_iostream::seek (off_t, int) { invalid_operation (); return -1; @@ -38,7 +38,7 @@ // Return current stream position. -long +off_t octave_base_iostream::tell (void) { invalid_operation ();
--- a/libinterp/interp-core/oct-iostrm.h +++ b/libinterp/interp-core/oct-iostrm.h @@ -40,11 +40,11 @@ // Position a stream at OFFSET relative to ORIGIN. - int seek (long offset, int origin); + int seek (off_t offset, int origin); // Return current stream position. - long tell (void); + off_t tell (void); // Return non-zero if EOF has been reached on this stream.
--- a/libinterp/interp-core/oct-stdstrm.h +++ b/libinterp/interp-core/oct-stdstrm.h @@ -43,12 +43,12 @@ // Position a stream at OFFSET relative to ORIGIN. - int seek (long offset, int origin) + int seek (off_t offset, int origin) { return s ? s->seek (offset, origin) : -1; } // Return current stream position. - long tell (void) { return s ? s->tell () : -1; } + off_t tell (void) { return s ? s->tell () : -1; } // Return non-zero if EOF has been reached on this stream.
--- a/libinterp/interp-core/oct-stream.cc +++ b/libinterp/interp-core/oct-stream.cc @@ -1028,10 +1028,10 @@ return do_gets (max_len, err, false, who); } -long -octave_base_stream::skipl (long num, bool& err, const std::string& who) +off_t +octave_base_stream::skipl (off_t num, bool& err, const std::string& who) { - long cnt = -1; + off_t cnt = -1; if ((interactive || forced_interactive) && file_number () == 0) { @@ -2816,10 +2816,10 @@ return retval; } -long -octave_stream::skipl (long count, bool& err, const std::string& who) +off_t +octave_stream::skipl (off_t count, bool& err, const std::string& who) { - long retval = -1; + off_t retval = -1; if (stream_ok ()) retval = rep->skipl (count, err, who); @@ -2827,10 +2827,10 @@ return retval; } -long +off_t octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who) { - long retval = -1; + off_t retval = -1; err = false; @@ -2861,7 +2861,7 @@ } int -octave_stream::seek (long offset, int origin) +octave_stream::seek (off_t offset, int origin) { int status = -1; @@ -2871,7 +2871,7 @@ // Find current position so we can return to it if needed. - long orig_pos = rep->tell (); + off_t orig_pos = rep->tell (); // Move to end of file. If successful, find the offset of the end. @@ -2879,7 +2879,7 @@ if (status == 0) { - long eof_pos = rep->tell (); + off_t eof_pos = rep->tell (); if (origin == SEEK_CUR) { @@ -2899,7 +2899,7 @@ { // Where are we after moving to desired position? - long desired_pos = rep->tell (); + off_t desired_pos = rep->tell (); // I don't think save_pos can be less than zero, but we'll // check anyway... @@ -2935,7 +2935,10 @@ { int retval = -1; - long xoffset = tc_offset.long_value (true); + // FIXME -- should we have octave_value methods that handle off_t + // explicitly? + octave_int64 val = tc_offset.int64_scalar_value (); + off_t xoffset = val.value (); if (! error_state) { @@ -2989,10 +2992,10 @@ return retval; } -long +off_t octave_stream::tell (void) { - long retval = -1; + off_t retval = -1; if (stream_ok ()) retval = rep->tell (); @@ -3561,17 +3564,17 @@ // Seek to skip when inside bounds of existing file. // Otherwise, write NUL to skip. - long orig_pos = tell (); + off_t orig_pos = tell (); seek (0, SEEK_END); - long eof_pos = tell (); + off_t eof_pos = tell (); // Is it possible for this to fail to return us to the // original position? seek (orig_pos, SEEK_SET); - long remaining = eof_pos - orig_pos; + off_t remaining = eof_pos - orig_pos; if (remaining < skip) {
--- a/libinterp/interp-core/oct-stream.h +++ b/libinterp/interp-core/oct-stream.h @@ -345,11 +345,11 @@ // Position a stream at OFFSET relative to ORIGIN. - virtual int seek (long offset, int origin) = 0; + virtual int seek (off_t offset, int origin) = 0; // Return current stream position. - virtual long tell (void) = 0; + virtual off_t tell (void) = 0; // Return TRUE if EOF has been reached on this stream. @@ -460,7 +460,7 @@ std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */); std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */); - long skipl (long count, bool& err, const std::string& who /* = "skipl" */); + off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec, octave_idx_type& count, @@ -524,13 +524,13 @@ std::string gets (const octave_value& max_len, bool& err, const std::string& who /* = "gets" */); - long skipl (long count, bool& err, const std::string& who /* = "skipl" */); - long skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */); + off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); + off_t skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */); - int seek (long offset, int origin); + int seek (off_t offset, int origin); int seek (const octave_value& offset, const octave_value& origin); - long tell (void); + off_t tell (void); int rewind (void);
--- a/libinterp/interp-core/oct-strstrm.cc +++ b/libinterp/interp-core/oct-strstrm.cc @@ -29,7 +29,7 @@ // Position a stream at OFFSET relative to ORIGIN. int -octave_base_strstream::seek (long, int) +octave_base_strstream::seek (off_t, int) { error ("fseek: invalid operation"); return -1; @@ -37,7 +37,7 @@ // Return current stream position. -long +off_t octave_base_strstream::tell (void) { error ("ftell: invalid operation");
--- a/libinterp/interp-core/oct-strstrm.h +++ b/libinterp/interp-core/oct-strstrm.h @@ -40,11 +40,11 @@ // Position a stream at OFFSET relative to ORIGIN. - int seek (long, int); + int seek (off_t, int); // Return current stream position. - virtual long tell (void); + virtual off_t tell (void); // The name of the file. @@ -104,7 +104,7 @@ std::ostream *output_stream (void) { return 0; } - long tell (void) { return is.tellg (); } + off_t tell (void) { return is.tellg (); } std::streambuf *rdbuf (void) { return is ? is.rdbuf () : 0; }
--- a/libinterp/interp-core/xgl2ps.c +++ b/libinterp/interp-core/xgl2ps.c @@ -20,8 +20,10 @@ */ -// Wrapper for "imported" file gl2ps.c so that config.h will be included -// before any other system or gnulib headers. +/* + * Wrapper for "imported" file gl2ps.c so that config.h will be included + * before any other system or gnulib headers. + */ #ifdef HAVE_CONFIG_H #include <config.h>
--- a/libinterp/interpfcn/defaults.cc +++ b/libinterp/interpfcn/defaults.cc @@ -75,6 +75,7 @@ std::string Vlocal_fcn_file_dir; std::string Voct_etc_dir; +std::string Voct_locale_dir; std::string Voct_file_dir; std::string Vfcn_file_dir; @@ -224,6 +225,12 @@ } static void +set_default_oct_locale_dir (void) +{ + Voct_locale_dir = subst_octave_home (OCTAVE_OCTLOCALEDIR); +} + +static void set_default_oct_file_dir (void) { Voct_file_dir = subst_octave_home (OCTAVE_OCTFILEDIR); @@ -428,6 +435,7 @@ set_default_local_fcn_file_dir (); set_default_oct_etc_dir (); + set_default_oct_locale_dir (); set_default_fcn_file_dir (); set_default_oct_file_dir ();
--- a/libinterp/interpfcn/defaults.in.h +++ b/libinterp/interpfcn/defaults.in.h @@ -156,6 +156,10 @@ #define OCTAVE_OCTETCDIR %OCTAVE_OCTETCDIR% #endif +#ifndef OCTAVE_OCTLOCALEDIR +#define OCTAVE_OCTLOCALEDIR %OCTAVE_OCTLOCALEDIR% +#endif + #ifndef OCTAVE_OCTINCLUDEDIR #define OCTAVE_OCTINCLUDEDIR %OCTAVE_OCTINCLUDEDIR% #endif @@ -164,6 +168,10 @@ #define OCTAVE_OCTLIBDIR %OCTAVE_OCTLIBDIR% #endif +#ifndef OCTAVE_OCTTESTSDIR +#define OCTAVE_OCTTESTSDIR %OCTAVE_OCTTESTSDIR% +#endif + #ifndef OCTAVE_PREFIX #define OCTAVE_PREFIX %OCTAVE_PREFIX% #endif @@ -195,6 +203,7 @@ extern OCTINTERP_API std::string Vlocal_fcn_file_dir; extern OCTINTERP_API std::string Voct_etc_dir; +extern OCTINTERP_API std::string Voct_locale_dir; extern OCTINTERP_API std::string Voct_file_dir; extern OCTINTERP_API std::string Vfcn_file_dir;
--- a/libinterp/interpfcn/file-io.cc +++ b/libinterp/interpfcn/file-io.cc @@ -436,7 +436,7 @@ bool err = false; - long tmp = os.skipl (count_arg, err, who); + off_t tmp = os.skipl (count_arg, err, who); if (! (error_state || err)) retval = tmp;
--- a/libinterp/interpfcn/oct-hist.cc +++ b/libinterp/interpfcn/oct-hist.cc @@ -91,7 +91,7 @@ static int default_history_size (void) { - int size = 1024; + int size = 1000; std::string env_size = octave_env::getenv ("OCTAVE_HISTSIZE"); @@ -374,23 +374,21 @@ string_vector hlist = command_history::list (); - int hist_count = hlist.length (); + int hist_count = hlist.length () - 1; // switch to zero-based indexing // The current command line is already part of the history list by // the time we get to this point. Delete it from the list. - hist_count -= 2; - if (! insert_curr) command_history::remove (hist_count); - hist_count--; + hist_count--; // skip last entry in history list // If no numbers have been specified, the default is to edit the // last command in the history list. + int hist_beg = hist_count; int hist_end = hist_count; - int hist_beg = hist_count; bool reverse = false; @@ -436,9 +434,7 @@ if (hist_end < hist_beg) { - int t = hist_end; - hist_end = hist_beg; - hist_beg = t; + std::swap (hist_end, hist_beg); reverse = true; } @@ -496,10 +492,18 @@ volatile octave_interrupt_handler old_interrupt_handler = octave_ignore_interrupts (); - system (cmd.c_str ()); + int status = system (cmd.c_str ()); octave_set_interrupt_handler (old_interrupt_handler); + // Check if text edition was successfull. Abort the operation + // in case of failure. + if (status != EXIT_SUCCESS) + { + error ("edit_history: text editor command failed"); + return; + } + // Write the commands to the history file since source_file // disables command line history while it executes. @@ -524,6 +528,8 @@ } else edit_history_add_hist (line); + + delete [] line; } file.close (); @@ -729,7 +735,7 @@ @deftypefn {Built-in Function} {@var{val} =} history_size ()\n\ @deftypefnx {Built-in Function} {@var{old_val} =} history_size (@var{new_val})\n\ Query or set the internal variable that specifies how many entries\n\ -to store in the history file. The default value is @code{1024},\n\ +to store in the history file. The default value is @code{1000},\n\ but may be overridden by the environment variable @w{@env{OCTAVE_HISTSIZE}}.\n\ @seealso{history_file, history_timestamp_format_string, saving_history}\n\ @end deftypefn")
--- a/libinterp/interpfcn/sysdep.cc +++ b/libinterp/interpfcn/sysdep.cc @@ -653,9 +653,8 @@ if (c == -1) c = 0; - char *s = new char [2]; - s[0] = c; - s[1] = '\0'; + char s[2] = {c, '\0'}; + retval = s; }
--- a/libinterp/interpfcn/toplev.cc +++ b/libinterp/interpfcn/toplev.cc @@ -1414,6 +1414,7 @@ { true, "octetcdir", OCTAVE_OCTETCDIR }, { true, "octincludedir", OCTAVE_OCTINCLUDEDIR }, { true, "octlibdir", OCTAVE_OCTLIBDIR }, + { true, "octtestsdir", OCTAVE_OCTTESTSDIR }, { true, "prefix", OCTAVE_PREFIX }, { true, "startupfiledir", OCTAVE_STARTUPFILEDIR }, { false, "version", OCTAVE_VERSION },
--- a/libinterp/octave-value/ov-fcn-inline.cc +++ b/libinterp/octave-value/ov-fcn-inline.cc @@ -645,7 +645,8 @@ be noted that i, and j are ignored as arguments due to the\n\ ambiguity between their use as a variable or their use as an inbuilt\n\ constant. All arguments followed by a parenthesis are considered\n\ -to be functions.\n\ +to be functions. If no arguments are found, a function taking a single\n\ +argument named @code{x} will be created.\n\ \n\ If the second and subsequent arguments are character strings,\n\ they are the names of the arguments of the function.\n\ @@ -752,15 +753,19 @@ // Sort the arguments into ascii order. fargs.sort (); + + if (fargs.length () == 0) + fargs.append (std::string ("x")); + } else if (nargin == 2 && args(1).is_numeric_type ()) { - if (! args(1).is_scalar_type ()) + if (! args(1).is_scalar_type ()) { error ("inline: N must be an integer"); return retval; } - + int n = args(1).int_value (); if (! error_state) @@ -825,9 +830,11 @@ %! fn = inline ("x.^2 + 1"); %!assert (feval (fn, 6), 37) %!assert (fn (6), 37) -## FIXME: Need tests for other 2 calling forms of inline() +%!assert (feval (inline ("sum (x(:))"), [1 2; 3 4]), 10) +%!assert (feval (inline ("sqrt (x^2 + y^2)", "x", "y"), 3, 4), 5) +%!assert (feval (inline ("exp (P1*x) + P2", 3), 3, 4, 5), exp(3*4) + 5) -## Test input validation +## Test input validation %!error inline () %!error <STR argument must be a string> inline (1) %!error <N must be an integer> inline ("2", ones (2,2))
--- a/liboctave/Makefile.am +++ b/liboctave/Makefile.am @@ -75,6 +75,8 @@ ## C++ files with templates that are #included, not compiled TEMPLATE_SRC = +## A list of all files that could include tests + include array/module.mk include numeric/module.mk include operators/module.mk @@ -117,5 +119,21 @@ -bindir $(bindir) \ $(LIBOCTAVE_LINK_OPTS) +## Rules to build test files + +LIBOCTAVE_TST_SRC = \ + $(array_libarray_la_SOURCES) \ + $(numeric_libnumeric_la_SOURCES) \ + $(system_libsystem_la_SOURCES) \ + $(util_libutil_la_SOURCES) + +TST_FILES_SRC := $(shell $(top_srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(LIBOCTAVE_TST_SRC)) + +TST_FILES := $(addsuffix -tst,$(TST_FILES_SRC)) + +liboctavetestsdir := $(octtestsdir)/liboctave + +nobase_liboctavetests_DATA = $(TST_FILES) + DISTCLEANFILES += $(BUILT_INCS)
--- a/liboctave/numeric/oct-fftw.cc +++ b/liboctave/numeric/oct-fftw.cc @@ -35,6 +35,10 @@ #include "oct-locbuf.h" #include "singleton-cleanup.h" +#if defined (HAVE_FFTW3_THREADS) +#include "nproc.h" +#endif + octave_fftw_planner *octave_fftw_planner::instance = 0; // Helper class to create and cache FFTW plans for both 1D and @@ -65,6 +69,16 @@ inplace[0] = inplace[1] = false; n[0] = n[1] = dim_vector (); +#if defined (HAVE_FFTW3_THREADS) + int init_ret = fftw_init_threads (); + if (!init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW threads"); + //Use number of processors available to the current process + //This can be later changed with fftw ("threads", nthreads) + nthreads = num_processors (NPROC_CURRENT); + fftw_plan_with_nthreads (nthreads); +#endif + // If we have a system wide wisdom file, import it. fftw_import_system_wisdom (); } @@ -395,6 +409,16 @@ inplace[0] = inplace[1] = false; n[0] = n[1] = dim_vector (); +#if defined (HAVE_FFTW3F_THREADS) + int init_ret = fftwf_init_threads (); + if (!init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW3F threads"); + //Use number of processors available to the current process + //This can be later changed with fftw ("threads", nthreads) + nthreads = num_processors (NPROC_CURRENT); + fftwf_plan_with_nthreads (nthreads); +#endif + // If we have a system wide wisdom file, import it. fftwf_import_system_wisdom (); }
--- a/liboctave/numeric/oct-fftw.h +++ b/liboctave/numeric/oct-fftw.h @@ -98,6 +98,24 @@ return instance_ok () ? instance->do_method (_meth) : dummy; } +#if defined (HAVE_FFTW3F_THREADS) + static void threads (int _nthreads) + { + if (instance_ok () && _nthreads != threads ()) + { + instance->nthreads = _nthreads; + fftw_plan_with_nthreads (_nthreads); + //Clear the current plans + instance->rplan = instance->plan[0] = instance->plan[1] = 0; + } + } + + static int threads () + { + return instance_ok () ? instance->nthreads : 0; + } +#endif + private: // No copying! @@ -169,6 +187,11 @@ dim_vector rn; bool rsimd_align; + +#if defined (HAVE_FFTW3_THREADS) + //number of threads when compiled with Multi-threading support + int nthreads; +#endif }; class @@ -235,6 +258,24 @@ return instance_ok () ? instance->do_method (_meth) : dummy; } +#if defined (HAVE_FFTW3F_THREADS) + static void threads (int _nthreads) + { + if (instance_ok () && _nthreads != threads ()) + { + instance->nthreads = _nthreads; + fftwf_plan_with_nthreads (_nthreads); + //Clear the current plans + instance->rplan = instance->plan[0] = instance->plan[1] = 0; + } + } + + static int threads () + { + return instance_ok () ? instance->nthreads : 0; + } +#endif + private: // No copying! @@ -306,6 +347,11 @@ dim_vector rn; bool rsimd_align; + +#if defined (HAVE_FFTW3F_THREADS) + //number of threads when compiled with Multi-threading support + int nthreads; +#endif }; class
--- a/liboctave/numeric/randmtzig.c +++ b/liboctave/numeric/randmtzig.c @@ -637,7 +637,7 @@ const int idx = (int)(ri & 0xFF); const double x = ri * we[idx]; if (ri < ke[idx]) - return x; // 98.9% of the time we return here 1st try + return x; /* 98.9% of the time we return here 1st try */ else if (idx == 0) { /* As stated in Marsaglia and Tsang @@ -804,7 +804,7 @@ const int idx = (int)(ri & 0xFF); const float x = ri * fwe[idx]; if (ri < fke[idx]) - return x; // 98.9% of the time we return here 1st try + return x; /* 98.9% of the time we return here 1st try */ else if (idx == 0) { /* As stated in Marsaglia and Tsang
--- a/liboctave/util/cmd-hist.cc +++ b/liboctave/util/cmd-hist.cc @@ -192,8 +192,14 @@ if (s.empty () || (s.length () == 1 && (s[0] == '\r' || s[0] == '\n'))) return; + + // Strip newline before adding to list + std::string stmp = s; + int stmp_len = stmp.length (); + if (stmp[stmp_len - 1] == '\n') + stmp.resize (stmp_len - 1); - lines_this_session += ::octave_add_history (s.c_str (), history_control); + lines_this_session += ::octave_add_history (stmp.c_str (), history_control); } }
--- a/m4/acinclude.m4 +++ b/m4/acinclude.m4 @@ -93,6 +93,57 @@ fi ]) dnl +dnl Check whether the FFTW library supports multi-threading. This macro +dnl should be called once per FFTW precision passing in the library +dnl variant (e.g. "fftw3") and a function in the thread support API +dnl (e.g. "fftw_plan_with_nthreads"). Depending on how FFTW was built, +dnl the thread functions could be compiled into the main FFTW library or +dnl could be a separate add-on library that is passed to the linker +dnl ahead of the main FFTW library. +dnl +AC_DEFUN([OCTAVE_CHECK_FFTW_THREADS], [ + ac_octave_save_CPPFLAGS="$CPPFLAGS" + ac_octave_save_LDFLAGS="$LDFLAGS" + ac_octave_save_LIBS="$LIBS" + CPPFLAGS="$m4_toupper([$1])_CPPFLAGS $CPPFLAGS" + LDFLAGS="$m4_toupper([$1])_LDFLAGS $LDFLAGS" + LIBS="$m4_toupper([$1])_LIBS $LIBS" + AC_CACHE_CHECK([for $1 multi-threading support], + [octave_cv_[$1]_threads_lib], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include <fftw3.h> + ]], [[ + $2 (2); + ]])], + [octave_cv_[$1]_threads_lib=yes], + [LIBS="-l[$1]_threads $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include <fftw3.h> + ]], [[ + $2 (2); + ]])], + [octave_cv_[$1]_threads_lib="-l[$1]_threads"], + [octave_cv_[$1]_threads_lib=no]) + ]) + ]) + case $octave_cv_[$1]_threads_lib in + -l*) + m4_toupper([$1])_LIBS="$octave_cv_[$1]_threads_lib $m4_toupper([$1])_LIBS" + ;; + no) + AC_MSG_WARN([No $1 multi-threading support found.]) + AC_MSG_WARN([The single-threaded library will be used instead.]) + ;; + esac + if test $octave_cv_[$1]_threads_lib != no; then + AC_DEFINE([HAVE_]m4_toupper([$1])[_THREADS], 1, + [Define to 1 if ]m4_toupper([$1])[ has multi-threading support.]) + fi + CPPFLAGS="$ac_octave_save_CPPFLAGS" + LDFLAGS="$ac_octave_save_LDFLAGS" + LIBS="$ac_octave_save_LIBS" +]) +dnl dnl Check whether a math mapper function is available in <cmath>. dnl Will define HAVE_CMATH_FUNC if there is a double variant and dnl HAVE_CMATH_FUNCF if there is a float variant. @@ -1486,7 +1537,12 @@ dnl exist which will then fool the 'test -z' line. AC_CHECK_PROG(MKINFO, makeinfo, makeinfo, []) if test -z "$MKINFO"; then - AC_MSG_ERROR([makeinfo program required for reading documentation]) + warn_makeinfo=" + +I didn't find makeinfo, which is required for reading documentation. +You may install a copy later for Octave to use. +" + OCTAVE_CONFIGURE_WARNING([warn_makeinfo]) fi ]) dnl
--- a/run-octave.in +++ b/run-octave.in @@ -63,7 +63,7 @@ shift elif [ "x$1" = "x-gud2" ]; then ## The latest version of gud needs -i=mi. There isn't a good way to check - ## this at configure time, so we just add a gdb2 flag + ## this at configure time, so we just add a gud2 flag driver="gdb -i=mi --args" shift elif [ "x$1" = "x-valgrind" ]; then @@ -80,6 +80,7 @@ OCTAVE_SITE_INITFILE="$top_srcdir/scripts/startup/main-rcfile" \ OCTAVE_DEFAULT_QT_SETTINGS="$top_srcdir/libgui/default-qt-settings" \ +OCTAVE_LOCALE_DIR="$top_srcdir/libgui/languages" \ OCTAVE_JAVA_DIR="$builddir/scripts/java" \ exec $builddir/libtool --mode=execute $driver \ "$octave_executable" --no-init-path --path="$LOADPATH" \
--- a/scripts/miscellaneous/edit.m +++ b/scripts/miscellaneous/edit.m @@ -243,10 +243,11 @@ if (nargin < 1) if (exist (FUNCTION.HOME, "dir") == 7 && (isunix () || ! ispc ())) system (cstrcat ("cd \"", FUNCTION.HOME, "\" ; ", - sprintf (FUNCTION.EDITOR, "")), + sprintf (undo_string_escapes (FUNCTION.EDITOR), "")), [], FUNCTION.MODE); else - system (sprintf (FUNCTION.EDITOR,""), [], FUNCTION.MODE); + system (sprintf (undo_string_escapes (FUNCTION.EDITOR), ""), + [], FUNCTION.MODE); endif return; endif @@ -328,7 +329,8 @@ ## If the file exists, then edit it. if (FUNCTION.EDITINPLACE) ## Edit in place even if it is protected. - system (sprintf (FUNCTION.EDITOR, cstrcat ("\"", fileandpath, "\"")), + system (sprintf (undo_string_escapes (FUNCTION.EDITOR), + cstrcat ("\"", fileandpath, "\"")), [], FUNCTION.MODE); return; else @@ -345,7 +347,8 @@ else fclose (fid); endif - system (sprintf (FUNCTION.EDITOR, cstrcat ("\"", fileandpath, "\"")), + system (sprintf (undo_string_escapes (FUNCTION.EDITOR), + cstrcat ("\"", fileandpath, "\"")), [], FUNCTION.MODE); return; endif @@ -361,7 +364,8 @@ case {"cc", "m"} 0; otherwise - system (sprintf (FUNCTION.EDITOR, cstrcat ("\"", fileandpath, "\"")), + system (sprintf (undo_string_escapes (FUNCTION.EDITOR), + cstrcat ("\"", fileandpath, "\"")), [], FUNCTION.MODE); return; endswitch @@ -512,7 +516,8 @@ fclose (fid); ## Finally we are ready to edit it! - system (sprintf (FUNCTION.EDITOR, cstrcat ("\"", fileandpath, "\"")), + system (sprintf (undo_string_escapes (FUNCTION.EDITOR), + cstrcat ("\"", fileandpath, "\"")), [], FUNCTION.MODE); endif
--- a/scripts/optimization/fsolve.m +++ b/scripts/optimization/fsolve.m @@ -96,7 +96,7 @@ ## employ OutputFcn: After a vector is evaluated for residuals, if OutputFcn is ## called with that vector, then the intermediate results should be saved for ## future Jacobian evaluation, and should be kept until a Jacobian evaluation -## is requested or until outputfcn is called with a different vector, in which +## is requested or until OutputFcn is called with a different vector, in which ## case they should be dropped in favor of this most recent vector. A short ## example how this can be achieved follows: ##
--- a/scripts/pkg/private/configure_make.m +++ b/scripts/pkg/private/configure_make.m @@ -28,11 +28,11 @@ src = fullfile (packdir, "src"); octave_bindir = octave_config_info ("bindir"); ver = version (); - mkoctfile = fullfile (octave_bindir, sprintf ("mkoctfile-%s", ver)); - octave_config = fullfile (octave_bindir, sprintf ("octave-config-%s", ver)); + mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s", ver)); + octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s", ver)); octave_binary = fullfile (octave_bindir, sprintf ("octave-%s", ver)); - cenv = {"MKOCTFILE"; mkoctfile; - "OCTAVE_CONFIG"; octave_config; + cenv = {"MKOCTFILE"; mkoctfile_program; + "OCTAVE_CONFIG"; octave_config_program; "OCTAVE"; octave_binary; "INSTALLDIR"; desc.dir}; scenv = sprintf ("%s=\"%s\" ", cenv{:}); @@ -40,16 +40,16 @@ if (exist (fullfile (src, "configure"), "file")) flags = ""; if (isempty (getenv ("CC"))) - flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\""); + flags = cstrcat (flags, " CC=\"", mkoctfile ("-p", "CC"), "\""); endif if (isempty (getenv ("CXX"))) - flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\""); + flags = cstrcat (flags, " CXX=\"", mkoctfile ("-p", "CXX"), "\""); endif if (isempty (getenv ("AR"))) - flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\""); + flags = cstrcat (flags, " AR=\"", mkoctfile ("-p", "AR"), "\""); endif if (isempty (getenv ("RANLIB"))) - flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\""); + flags = cstrcat (flags, " RANLIB=\"", mkoctfile ("-p", "RANLIB"), "\""); endif [status, output] = shell (cstrcat ("cd '", src, "'; ", scenv, "./configure --prefix=\"",
--- a/scripts/pkg/private/get_forge_pkg.m +++ b/scripts/pkg/private/get_forge_pkg.m @@ -39,7 +39,7 @@ name = tolower (name); ## Try to download package's index page. - [html, succ] = urlread (sprintf ("http://octave.sourceforge.net/%s/index.html", name)); + [html, succ] = urlread (sprintf ("http://packages.octave.org/%s/index.html", name)); if (succ) ## Remove blanks for simpler matching. html(isspace(html)) = []; @@ -52,17 +52,17 @@ ver = t{1}{1}; if (nargout > 1) # Build download string. - urlbase = "http://downloads.sourceforge.net/octave/%s-%s.tar.gz?download"; - url = sprintf (urlbase, name, ver); - ## Verify that the string exists on the page. - if (isempty (strfind (html, url))) + pkg_file = sprintf ("%s-%s.tar.gz", name, ver); + url = cstrcat ("http://packages.octave.org/download/", pkg_file); + ## Verify that the package string exists on the page. + if (isempty (strfind (html, pkg_file))) warning ("get_forge_pkg: download URL not verified"); endif endif endif else ## Try get the list of all packages. - [html, succ] = urlread ("http://octave.sourceforge.net/packages.php"); + [html, succ] = urlread ("http://packages.octave.org/packages.php"); if (succ) t = regexp (html, "<div class=""package"" id=""(\\w+)"">", "tokens"); t = horzcat (t{:});
--- a/scripts/pkg/private/list_forge_packages.m +++ b/scripts/pkg/private/list_forge_packages.m @@ -23,7 +23,7 @@ ## @end deftypefn function list = list_forge_packages () - [list, succ] = urlread ("http://octave.sourceforge.net/list_packages.php"); + [list, succ] = urlread ("http://packages.octave.org/list_packages.php"); if (succ) list = strsplit (list, " \n\t", true); else
--- a/scripts/plot/legend.m +++ b/scripts/plot/legend.m @@ -874,6 +874,7 @@ if (addprops) addlistener (hlegend, "edgecolor", @updatelegendtext); addlistener (hlegend, "textcolor", @updatelegendtext); + addlistener (hlegend, "fontsize", @updatelegendtext); addlistener (hlegend, "interpreter", @updatelegendtext); addlistener (hlegend, "location", @updatelegend); addlistener (hlegend, "orientation", @updatelegend); @@ -915,7 +916,10 @@ text_kids = findobj (kids, "-property", "interpreter", "type", "text"); interpreter = get (h, "interpreter"); textcolor = get (h, "textcolor"); - set (text_kids, "interpreter", interpreter, "color", textcolor); + fontsize = get (h, "fontsize"); + set (text_kids, "interpreter", interpreter, + "fontsize", fontsize, + "color", textcolor); endfunction function hideshowlegend (h, d, ca, pos1, pos2)
--- a/scripts/plot/module.mk +++ b/scripts/plot/module.mk @@ -150,6 +150,7 @@ plot/plotyy.m \ plot/polar.m \ plot/print.m \ + plot/printd.m \ plot/quiver.m \ plot/quiver3.m \ plot/rectangle.m \ @@ -174,6 +175,7 @@ plot/stairs.m \ plot/stem.m \ plot/stem3.m \ + plot/stemleaf.m \ plot/struct2hdl.m \ plot/subplot.m \ plot/surf.m \
new file mode 100644 --- /dev/null +++ b/scripts/plot/printd.m @@ -0,0 +1,101 @@ +## Copyright (C) 2013 Michael D. Godfrey +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public +## License as published by the Free Software Foundation; +## either version 3 of the License, or (at your option) any +## later version. +## +## Octave is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied +## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public +## License along with Octave; see the file COPYING. If not, +## see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} printd (@var{obj}, @var{filename}) +## +## Convert any object acceptable to @code{disp} into the format +## selected by the suffix of @var{filename}. +## +## This function is intended to facilitate manipulation of the output +## of functions such as @code{stemleaf}. +## @seealso{stemleaf} +## @end deftypefn + +## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com> +## Description: Convert objects into other file formats. + +function printd (obj, filename) + ## Convert any object acceptable to disp() into various display formats. + ## obj is the input object. + ## filename is the output file (with required suffix). + + ## Extract .suffix from filename + if ((sufix = rindex (filename, ".")) <= 0) + error ("The output filename: %s requires a suffix.\nOptions are: pdf ps eps txt jpg jpeg", filename); + endif + opt = substr (filename, sufix+1); + [pf, tempf, mag] = mkstemp ("oct-XXXXXX", 1); # Safe version of tmpnam() + fprintf (pf, "%s", disp (obj)); + frewind (pf); + + ## It seems best to only use convert for image output. Its ps and pdf + ## are badly rendered. + opt = lower (opt); + switch opt + case {"pdf"} + enscr = sprintf ( + "enscript --no-header -o %s.ps %s ; ps2pdf %s.ps %s.pdf; mv %s.pdf %s;exit",... + tempf, tempf, tempf, tempf, tempf, filename); + system (enscr); + delete ([tempf ".ps"]); + case {"ps"} + enscr = sprintf ("enscript --no-header -o %s %s ; exit", filename, tempf); + system (enscr); + case {"eps"} + enscr = sprintf ( + "enscript --no-header -o %s.ps %s ; ps2eps --ignoreBB %s.ps; mv %s.eps %s; exit",... + tempf, tempf, tempf, tempf, filename); + system (enscr); + delete ([tempf ".ps"]); + case {"txt"} + enscr = sprintf ("cp %s %s", tempf, filename); + system (enscr); + case {"jpg" "jpeg"} + enscr = sprintf ("convert -trim txt:%s jpg:%s", tempf, filename); + system (enscr); + otherwise + fclose (pf); + delete (tempf); + error ("Unknown conversion type: %s.\nOptions are: pdf ps eps txt jpg jpeg", opt); + + endswitch + fclose (pf); + delete (tempf); + printf ("%s file %s written\n", opt, filename); +endfunction + +%!demo +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 12, hi: 42\n";... +%! " 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; +%! printd (r2, "test_p.txt"); +%! system ("cat test_p.txt"); +%! delete ("test_p.txt"); + +%!test +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 12, hi: 42\n";... +%! " 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; +%! printd (r2, "test_p.txt"); +%! r4 = fileread ("test_p.txt"); +%! delete ("test_p.txt"); +%! r2 = disp (r2); +%! assert (r4, r2) + +
--- a/scripts/plot/private/__go_draw_axes__.m +++ b/scripts/plot/private/__go_draw_axes__.m @@ -1591,7 +1591,19 @@ else fontspec = ""; endif - colorspec = get_text_colorspec (hlgnd.textcolor, mono); + textcolors = get (findobj (hlgnd.children, "type", "text"), "color"); + if (iscell (textcolors)) + textcolors = cell2mat (textcolors); + textcolors = unique (textcolors, "rows"); + endif + if (rows (textcolors) > 1) + ## Gnuplot is unable to assign arbitrary colors to each text entry + ## for the key/legend. But, the text color can be set to match the + ## color of the plot object. + colorspec = "textcolor variable"; + else + colorspec = get_text_colorspec (textcolors, mono); + endif fprintf (plot_stream, "set key %s %s;\nset key %s %s %s %s %s;\n", inout, pos, box, reverse, horzvert, fontspec, colorspec); else @@ -2350,7 +2362,7 @@ persistent sym = __setup_sym_table__ (); persistent flds = fieldnames (sym); - [s, e, m] = regexp (str,'\\\\([a-zA-Z]+|0)','start','end','matches'); + [s, e, m] = regexp (str, "\\\\([a-zA-Z]+|0)", "start", "end", "matches"); for i = length (s) : -1 : 1 ## special case for "\0" and replace with "{/Symbol \306}'
new file mode 100644 --- /dev/null +++ b/scripts/plot/stemleaf.m @@ -0,0 +1,318 @@ +## Copyright (C) 2013 Michael D. Godfrey +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public +## License as published by the Free Software Foundation; +## either version 3 of the License, or (at your option) any +## later version. +## +## Octave is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied +## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public +## License along with Octave; see the file COPYING. If not, +## see <http://www.gnu.org/licenses/>. + + +## -*- texinfo -*- +## @deftypefn {Function File} {} stemleaf (@var{x}) +## @deftypefnx {Function File} {@var{plot} =} stemleaf (@var{x}, @var{opt}) +## +## Compute and display a stem and leaf plot of the vector @var{x}. +## +## The @var{x} vector is converted to integer by @var{x} = @code{fix} (@var{x}). +## If an output argument is provided, the plot is returned as +## an array of strings. The first element is the heading +## followed by an element for each stem. +## The default stem step is 10. +## The @var{x} vector should be integers. It will be treated so that +## the last digit is the leaf value and the other digits are +## the stems. +## The leaf digits are not sorted. If sorted leaf values +## are wanted, use @code{sort} (@var{x}) before calling @code{stemleaf} (@var{x}). +## The stem and leaf plot is described in: Ch. 3, +## Exploratory Data Analysis by J. W. Tukey, Addison-Wesley, 1977. +## @seealso{hist, printd} +## @end deftypefn + +## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com> +## Description: Compute stem and leaf plot + +function varargout = stemleaf (x, stem_unit) + ## Compute and display a stem and leaf plot of the vector x. The x + ## vector is converted to integer by x = fix(x). If an output argument + ## is provided, the plot is returned as an array of strings. The + ## first element is the heading followed by an element for each stem. + ## + ## The default stem step is 10. If stem_unit is provided the stem + ## step is set to: 10^(stem_unit+1) The x vector should be integers. + ## It will be treated so that the last digit is the leaf value and the + ## other digits are the stems. + ## + ## When we first implemented stem and leaf plots in the early 1960's + ## there was some discussion about sorting vs. leaving the leaf + ## entries in the original order in the data. We decided in favor or + ## sorting the leaves for most purposes. This is the choice + ## implemented in the SNAP/IEDA system that was written at that time. + ## + ## SNAP/IEDA and particularly its stem and leaf plotting were further + ## developed by Hale Trotter, David Hoagland (at Princeton and MIT) + ## and others. + ## + ## Tukey, in EDA, generally uses unsorted leaves. In addition, he + ## described a wide range of additional display formats. This + ## implementation does not sort the leaves, but if the x vector is + ## sorted then the leaves come out sorted. A simple display format is + ## used. + ## + ## I doubt if providing other options is worthwhile. The code can + ## quite easily be modified to provide specific display results. Or, + ## the returned output string can be edited. The returned output is an + ## array of strings with each row containing a line of the plot + ## preceded by the lines of header text as the first row. This + ## facilitates annotation. + ## + ## Note that the code has some added complexity due to the need to + ## distinguish both + and - 0 stems. The +- stem values are essential + ## for all plots which span 0. After dealing with +-0 stems, the added + ## complexity of putting +- data values in the correct stem is minor, + ## but the sign of 0 leaves must be checked. And, the cases where the + ## stems start or end at +- 0 must also be considered. + ## + ## The fact that IEEE floating point defines +- 0 helps make this + ## easier. + ## + ## + ## Michael D. Godfrey January 2013 + + ## More could be implemented for better data scaling. And, of course, + ## other options for the kinds of plots described by Tukey could be + ## provided. This may best be left to users. + + if (nargin >= 2) + stem_step = 10^(stem_unit+1); + else + stem_step = 10; + endif + if (any (x == int32 (x)) == 0) + printf ('Input vector truncated to integer values.\n') + x = fix (x); + endif + + ## Avoid use of int32 due to: + + ## floor (int32 (-44)/10) == -4 and floor (int32 (-46)/10) = -5 !!! + ## x = sort (fix (x)); % User can decide about sorting x. + ## x = fix (x); + ## %Adjust scale if too small. + ## while any(abs((fix(x) - x)) >= abs(x/100)) + ## x =10*x; + ## endwhile + + ## Note that IEEE 754 states that -+ 0 should compare equal. This has + ## led to C sort (and therefore Octave) treating them as equal. Thus, + ## sort([ -1 0 -0 1]) yields: -1 0 -0 1. and, sort([-1 -0 0 1]) + ## yields: -1 -0 0 1. This means that stem-and-leaf plotting cannot + ## rely on sort to order the data as needed for display. + + if (all((sort(x) == x)) == 1) + hsort = 'sorted.'; + else + hsort = 'unsorted.'; + endif + nx = max (size (x)); + ## Determine stem values + if (min(x) < 0) + if (signbit(max(x)) == 0) # max is positive + stems = [fix(min(x)/stem_step)-1 : -1 -0]; + stems = [stems 0 : fix(max(x)/stem_step)+1 ]; + else + if (max(x) < 0) + stems = [(fix(min(x)/stem_step)-1) : fix(max(x)/stem_step)]; + else + stems = [(fix(min(x)/stem_step)-1) : -1 -0]; + stems = [stems 0 : fix(max(x)/stem_step)]; + endif + endif + else # All stems are > 0 + stems = [fix(min(x)/stem_step) : fix(max(x)/stem_step) + 1]; + endif + ##stems + ##x + nstems = max(size(stems)); + ## compute hinges at +- 1.5 * quartiles + ## this requires sorted data! + xs = sort (x); # Note that sort preserves -0 + threeh = 1.5; + two = 2.0; + j = idivide(nx, 4, "fix") + 1; # Use F95 truncation. + k = nx - j + 1; + hl = xs (j); + hu = xs (k); + if ( (nx + 1) == (4 * j) ) + hl = (xs (j + 1) + hl) / two; + hu = (xs (k - 1) + hu) / two; + endif + + ## :::::::: determine h-spread (dh) and fences :::::::: + dh = hu - hl; + fu = hu + threeh * dh; + fl = hl - threeh * dh; + + ## :::::::: find value adjacent to lower fence :::::::: + for i = 1:j + if ( xs (i) >= fl ) + continue; + endif + endfor + ilow = i; + xlo = xs (ilow); + + ## :::::::: find value adjacent to upper fence :::::::: + for i = 1:j + if ( xs (nx -i + 1) <= fu ) + continue; + endif + endfor + + ihi = nx - i + 1; + xhi = xs (ihi); + + ## Heading for output: + plot_out = ""; + plot_out = [plot_out sprintf("stem step: %i, data: %s\nHinges: lo: %g, hi: %g\n", + stem_step, hsort, xlo, xhi)]; + + ## This may appear to be a good place to use vectorization using the + ## stem and data arrays but the necessary special case treatment of 0 + ## and -0 seems to result in little reduction of complexity, and since + ## this algorithm is for small data vectors only there would be + ## practically no performance improvement. + + ## Determine leaves for each stem: + for kx = 2:nstems + line_out = ""; + steml = ""; + ## Build a string of leaf digits for stem(kx) if stem(kx) <= 0, or + ## stem(kx-1) if stem(kx) > 0 + + ## stems -+ 0 have to be handled as special cases. + for xi = 1:nx + if(signbit(stems(kx)) == 1) + t1 = ((x(xi) <= stems(kx)*10) && (x(xi) > (stems(kx-1)*10))); + else + t1 = ((x(xi) < stems(kx)*10) && (x(xi) >= (stems(kx-1)*10))); + endif + ## Special tests for stem -+ 0 + if ((stems(kx) == 0) && signbit(stems(kx)) && (x(xi) == 0)) && !signbit(x(xi)) + t1 = 0; + endif + if ((stems(kx-1) == 0) && !signbit(stems(kx-1)) && (x(xi) == 0)) && signbit(x(xi)) + t1 = 0; + endif + ## Create line as a string + if t1 + if (stems(kx) <= 0) + xz = abs (x(xi) - stems(kx)*10); + else + xz = abs (x(xi) - stems(kx-1)*10); + endif + if ((stems(kx) == 0) && signbit(stems(kx))) + steml = [steml sprintf("%d", abs(x(xi) - stems(kx)*10))]; + else + steml = [steml sprintf("%d", xz)]; + endif + endif % t1 + endfor % xi = 1:nx + + ## Set correct -0 + if ((stems(kx) == 0) && signbit(stems(kx))) + line_out = [line_out sprintf(" -0 | %s", steml)]; % -0 stem. + else + if( stems(kx) < 0) + line_out = [line_out sprintf("%4d | %s", stems(kx), steml)]; + else + if stems(kx) > 0 + line_out = [line_out sprintf("%4d | %s", stems(kx-1), steml)]; + endif + endif + endif + plot_out = [plot_out; line_out]; + endfor % kx = 2:nstems + if (nargout == 0) + rows = size (plot_out)(1); + cols = size (plot_out)(2); + for k = 1:rows + printf("%s\n", plot_out(k,1:cols)); + endfor + else + varargout{1} = plot_out; + endif +endfunction + +%!demo +%! ## Unsorted plot: +%! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44]; +%! stemleaf (x, 0); + +%!demo +%! ## Sorted leaves: +%! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44]; +%! y = sort(x); +%! stemleaf (y, 0); + +%!demo +%! ## More data (sorted) +%! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ]; +%! y = sort(x); +%! stemleaf (y, 0); + +%!test +%! ## test minus to plus +%! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ]; +%! x = sort(x); +%! r2 = ["stem step: 10, data: sorted.\nHinges: lo: 30, hi: 116\n";... +%! " -2 | 82";" -1 | 3";" -0 | 2";" 0 | 00177";... +%! " 1 | 00112288";" 2 | 001133577777899";... +%! " 3 | 000111123456777889";" 4 | 00122233344456788";... +%! " 5 | 223788";" 6 | 138";" 7 | 11";" 8 | ";... +%! " 9 | 69";" 10 | 04555567999";" 11 | 0133344455566667777899";... +%! " 12 | 0011223444555677788";" 13 | 1239";" 14 | 16"]; +%! rx = stemleaf (x, 0); +%! assert(r2, rx); +%!test +%! ## positive values above 0 +%! x = [22 12 28 52 39 12 11 11 42 38 44 18 44 ]; +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 12, hi: 42\n";... +%! " 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; +%! rx = stemleaf (x, 0); +%! assert(r2, rx); +%!test +%! ## negative values below 0 +%! x = [22 12 28 52 39 12 11 11 42 38 44 18 44]; +%! x = -x; +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: -42, hi: -12\n";... +%! " -5 | 2";" -4 | 244";" -3 | 98";" -2 | 28";" -1 | 22118"]; +%! rx = stemleaf (x, 0); +%! assert(r2, rx); +%!test +%! ## positive values from 0 +%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44]; +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 11, hi: 42\n";... +%! " 0 | 20";" 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; +%! rx = stemleaf (x, 0); +%! assert(r2, rx); +%!test +%! ## negative values from 0 +%! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44]; +%! x = -x; +%! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: -42, hi: -11\n";... +%! " -5 | 2";" -4 | 244";" -3 | 98";" -2 | 28";" -1 | 22118";" -0 | 20"]; +%! rx = stemleaf (x, 0); +%! assert(r2, rx); +
--- a/scripts/plot/struct2hdl.m +++ b/scripts/plot/struct2hdl.m @@ -148,6 +148,8 @@ h = createsurface (s, par); elseif (strcmp (s.type, "hggroup")) [h, s, p] = createhg (s, p, par, hilev); + else + error ("struct2hdl: %s objects are not implemented yet", s.type) endif ## children
new file mode 100644 --- /dev/null +++ b/scripts/testfun/__printf_assert__.m @@ -0,0 +1,27 @@ +## Copyright (C) 2005-2012 David Bateman +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} __printf_assert__ (@dots{}) +## Undocumented internal function. +## @end deftypefn + +function __printf_assert__ (varargin) + global _assert_printf; + _assert_printf = cat (2, _assert_printf, sprintf (varargin{:})); +endfunction
new file mode 100644 --- /dev/null +++ b/scripts/testfun/__prog_output_assert__.m @@ -0,0 +1,34 @@ +## Copyright (C) 2005-2012 David Bateman +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} __prog_output_assert__ (@var{str}) +## Undocumented internal function. +## @end deftypefn + +function ret = __prog_output_assert__ (str) + global _assert_printf; + if (isempty (_assert_printf)) + ret = isempty (str); + elseif (_assert_printf(end) == "\n") + ret = strcmp (_assert_printf(1:(end-1)), str); + else + ret = strcmp (_assert_printf, str); + endif + _assert_printf = ""; +endfunction
new file mode 100644 --- /dev/null +++ b/scripts/testfun/__run_test_suite__.m @@ -0,0 +1,285 @@ +## Copyright (C) 2005-2012 David Bateman +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {Function File} {} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs}) +## Undocumented internal function. +## @end deftypefn + +function __run_test_suite__ (fcndirs, fixedtestdirs) + testsdir = octave_config_info ("octtestsdir"); + libinterptestdir = fullfile (testsdir, "libinterp"); + liboctavetestdir = fullfile (testsdir, "liboctave"); + fixedtestdir = fullfile (testsdir, "fixed"); + fcnfiledir = octave_config_info ("fcnfiledir"); + if (nargin == 0) + fcndirs = { libinterptestdir, liboctavetestdir, fcnfiledir }; + fixedtestdirs = { fixedtestdir }; + endif + global files_with_no_tests = {}; + global files_with_tests = {}; + ## FIXME -- these names don't really make sense if we are running + ## tests for an installed copy of Octave. + global topsrcdir = fcnfiledir; + global topbuilddir = testsdir; + pso = page_screen_output (); + warn_state = warning ("query", "quiet"); + warning ("on", "quiet"); + try + page_screen_output (0); + warning ("off", "Octave:deprecated-function"); + fid = fopen ("fntests.log", "wt"); + if (fid < 0) + error ("could not open fntests.log for writing"); + endif + test ("", "explain", fid); + dp = dn = dxf = dsk = 0; + puts ("\nIntegrated test scripts:\n\n"); + for i = 1:length (fcndirs) + [p, n, xf, sk] = run_test_script (fid, fcndirs{i}); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endfor + puts ("\nFixed test scripts:\n\n"); + for i = 1:length (fixedtestdirs) + [p, n, xf, sk] = run_test_dir (fid, fixedtestdirs{i}); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endfor + puts ("\nSummary:\n\n"); + nfail = dn - dp; + printf (" PASS %6d\n", dp); + printf (" FAIL %6d\n", nfail); + if (dxf > 0) + printf (" XFAIL %6d\n", dxf); + endif + if (dsk > 0) + printf (" SKIPPED %6d\n", dsk); + endif + puts ("\n"); + puts ("See the file test/fntests.log for additional details.\n"); + if (dxf > 0) + puts ("\n"); + puts ("Expected failures (listed as XFAIL above) are known bugs.\n"); + puts ("Please help improve Octave by contributing fixes for them.\n"); + endif + if (dsk > 0) + puts ("\n"); + puts ("Tests are most often skipped because the features they require\n"); + puts ("have been disabled. Features are most often disabled because\n"); + puts ("they require dependencies that were not present when Octave\n"); + puts ("was built. The configure script should have printed a summary\n"); + puts ("at the end of its run indicating which dependencies were not found.\n"); + endif + + ## Weed out deprecated and private functions + weed_idx = cellfun (@isempty, regexp (files_with_tests, '\bdeprecated\b|\bprivate\b', 'once')); + files_with_tests = files_with_tests(weed_idx); + weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\bdeprecated\b|\bprivate\b', 'once')); + files_with_no_tests = files_with_no_tests(weed_idx); + + report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m"); + + puts ("\nPlease help improve Octave by contributing tests for\n"); + puts ("these files (see the list in the file fntests.log).\n\n"); + + fprintf (fid, "\nFiles with no tests:\n\n%s", + list_in_columns (files_with_no_tests, 80)); + fclose (fid); + + page_screen_output (pso); + warning (warn_state.state, "quiet"); + catch + page_screen_output (pso); + warning (warn_state.state, "quiet"); + disp (lasterr ()); + end_try_catch +endfunction + +function print_test_file_name (nm) + filler = repmat (".", 1, 55-length (nm)); + printf (" %s %s", nm, filler); +endfunction + +function print_pass_fail (n, p) + if (n > 0) + printf (" PASS %4d/%-4d", p, n); + nfail = n - p; + if (nfail > 0) + printf (" FAIL %d", nfail); + endif + endif + puts ("\n"); +endfunction + +function retval = has_functions (f) + n = length (f); + if (n > 3 && strcmp (f((end-2):end), ".cc")) + fid = fopen (f); + if (fid >= 0) + str = fread (fid, "*char")'; + fclose (fid); + retval = ! isempty (regexp (str,'^(DEFUN|DEFUN_DLD)\b', 'lineanchors')); + else + error ("fopen failed: %s", f); + endif + elseif (n > 2 && strcmp (f((end-1):end), ".m")) + retval = true; + else + retval = false; + endif +endfunction + +function retval = has_tests (f) + fid = fopen (f); + if (fid >= 0) + str = fread (fid, "*char")'; + fclose (fid); + retval = ! isempty (regexp (str, '^%!(assert|error|fail|test|warning)', "lineanchors")); + else + error ("fopen failed: %s", f); + endif +endfunction + +function retval = has_demos (f) + fid = fopen (f); + if (fid >= 0) + str = fread (fid, "*char")'; + fclose (fid); + retval = ! isempty (regexp (str, '^%!demo', "lineanchors")); + else + error ("fopen failed: %s", f); + endif +endfunction + +function [dp, dn, dxf, dsk] = run_test_dir (fid, d); + global files_with_tests; + global files_with_no_tests; + lst = dir (d); + dp = dn = dxf = dsk = 0; + for i = 1:length (lst) + nm = lst(i).name; + if (lst(i).isdir + && ! strcmp (nm, ".") && ! strcmp (nm, "..") + && ! strcmp (nm, "private") && nm(1) != "@" + && ! strcmp (nm, "CVS")) + [p, n, xf, sk] = run_test_dir (fid, [d, filesep, nm]); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endif + endfor + saved_dir = pwd (); + unwind_protect + chdir (d); + for i = 1:length (lst) + nm = lst(i).name; + if (length (nm) > 4 && strcmp (nm((end-3):end), ".tst")) + p = n = xf = sk = 0; + ffnm = fullfile (d, nm); + if (has_tests (ffnm)) + print_test_file_name (nm); + [p, n, xf, sk] = test (nm, "quiet", fid); + print_pass_fail (n, p); + files_with_tests(end+1) = ffnm; + ##elseif (has_demos (ffnm)) + ## files_with_tests(end+1) = ffnm; + else + files_with_no_tests(end+1) = ffnm; + endif + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endif + endfor + unwind_protect_cleanup + chdir (saved_dir); + end_unwind_protect +endfunction + +function [dp, dn, dxf, dsk] = run_test_script (fid, d); + global files_with_tests; + global files_with_no_tests; + global topsrcdir; + global topbuilddir; + lst = dir (d); + dp = dn = dxf = dsk = 0; + for i = 1:length (lst) + nm = lst(i).name; + if (lst(i).isdir && ! strcmp (nm, ".") && ! strcmp (nm, "..") + && ! strcmp (nm, "CVS")) + [p, n, xf, sk] = run_test_script (fid, [d, filesep, nm]); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endif + endfor + for i = 1:length (lst) + nm = lst(i).name; + ## Ignore hidden files + if (nm(1) == '.') + continue + endif + f = fullfile (d, nm); + if ((length (nm) > 2 && strcmp (nm((end-1):end), ".m")) + || (length (nm) > 4 + && (strcmp (nm((end-3):end), "-tst") + || strcmp (nm((end-3):end), ".tst")))) + p = n = xf = 0; + ## Only run if it contains %!test, %!assert %!error or %!warning + if (has_tests (f)) + tmp = strrep (f, [topsrcdir, filesep], ""); + tmp = strrep (tmp, [topbuilddir, filesep], ""); + print_test_file_name (tmp); + [p, n, xf, sk] = test (f, "quiet", fid); + print_pass_fail (n, p); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + files_with_tests(end+1) = f; + ##elseif (has_demos (f)) + ## files_with_tests(end+1) = f; + else + ## To reduce the list length, only mark .cc files that contain + ## DEFUN definitions. + files_with_no_tests(end+1) = f; + endif + endif + endfor + ## printf("%s%s -> passes %d of %d tests\n", ident, d, dp, dn); +endfunction + +function n = num_elts_matching_pattern (lst, pat) + n = sum (cellfun (@(x) !isempty (x), regexp (lst, pat, 'once'))); +endfunction + +function report_files_with_no_tests (with, without, typ) + pat = cstrcat ('\', typ, "$"); + n_with = num_elts_matching_pattern (with, pat); + n_without = num_elts_matching_pattern (without, pat); + n_tot = n_with + n_without; + printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ); +endfunction
--- a/scripts/testfun/module.mk +++ b/scripts/testfun/module.mk @@ -1,6 +1,9 @@ FCN_FILE_DIRS += testfun testfun_FCN_FILES = \ + testfun/__printf_assert__.m \ + testfun/__prog_output_assert__.m \ + testfun/__run_test_suite__.m \ testfun/assert.m \ testfun/demo.m \ testfun/example.m \
--- a/scripts/testfun/test.m +++ b/scripts/testfun/test.m @@ -771,7 +771,7 @@ %!test a=3; # assign to a shared variable %!test assert (a,3) # variable should equal 3 %!shared b,c # replace shared variables -%!test assert (!exist ("a")); # a no longer exists +%!test assert (!exist ("a", "var")); # a no longer exists %!test assert (isempty (b)); # variables start off empty %!shared a,b,c # recreate a shared variable %!test assert (isempty (a)); # value is empty even if it had a previous value @@ -780,7 +780,7 @@ %!test c=6; # update a value %!test assert ([a, b, c],[1, 2, 6]); # show that the update sticks %!shared # clear all shared variables -%!test assert (!exist ("a")) # show that they are cleared +%!test assert (!exist ("a", "var")) # show that they are cleared %!shared a,b,c # support for initializer shorthand %! a=1; b=2; c=4; @@ -835,7 +835,7 @@ % !demo with syntax error # syntax errors in demo fail properly % !shared a,b,c % !demo # shared variables not available in demo -% ! assert(exist("a")) +% ! assert(exist("a", "var")) % !error % ! test('/etc/passwd'); % ! test("nonexistent file");
--- a/src/mkoctfile.in.cc +++ b/src/mkoctfile.in.cc @@ -214,6 +214,9 @@ vars["XTRA_CFLAGS"] = get_variable ("XTRA_CFLAGS", %OCTAVE_CONF_XTRA_CFLAGS%); vars["XTRA_CXXFLAGS"] = get_variable ("XTRA_CXXFLAGS", %OCTAVE_CONF_XTRA_CXXFLAGS%); + vars["AR"] = get_variable ("AR", %OCTAVE_CONF_MKOCTFILE_AR%); + vars["RANLIB"] = get_variable ("RANLIB", %OCTAVE_CONF_MKOCTFILE_RANLIB%); + vars["DEPEND_FLAGS"] = get_variable ("DEPEND_FLAGS", %OCTAVE_CONF_DEPEND_FLAGS%); vars["DEPEND_EXTRA_SED_PATTERN"] = get_variable ("DEPEND_EXTRA_SED_PATTERN", %OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%); @@ -299,30 +302,29 @@ " -p VAR, --print VAR Print configuration variable VAR. Recognized\n" " variables are:\n" "\n" -" ALL_CFLAGS FLIBS\n" -" ALL_CXXFLAGS FPICFLAG\n" -" ALL_FFLAGS INCFLAGS\n" -" ALL_LDFLAGS LAPACK_LIBS\n" -" BLAS_LIBS LDFLAGS\n" -" CC LD_CXX\n" -" CFLAGS LD_STATIC_FLAG\n" -" CPICFLAG LFLAGS\n" -" CPPFLAGS LIBOCTAVE\n" -" CXX LIBOCTINTERP\n" -" CXXFLAGS LIBS\n" -" CXXPICFLAG OCTAVE_LIBS\n" -" DEPEND_EXTRA_SED_PATTERN OCTAVE_LINK_DEPS\n" -" DEPEND_FLAGS OCTAVE_LINK_OPTS\n" -" DL_LD OCT_LINK_DEPS\n" -" DL_LDFLAGS OCT_LINK_OPTS\n" -" EXEEXT RDYNAMIC_FLAG\n" -" F77 READLINE_LIBS\n" -" F77_INTEGER_8_FLAG SED\n" -" FFLAGS XTRA_CFLAGS\n" -" FFTW3_LDFLAGS XTRA_CXXFLAGS\n" -" FFTW3_LIBS\n" -" FFTW3F_LDFLAGS\n" -" FFTW3F_LIBS\n" +" ALL_CFLAGS FFTW3F_LDFLAGS\n" +" ALL_CXXFLAGS FFTW3F_LIBS\n" +" ALL_FFLAGS FLIBS\n" +" ALL_LDFLAGS FPICFLAG\n" +" AR INCFLAGS\n" +" BLAS_LIBS LAPACK_LIBS\n" +" CC LDFLAGS\n" +" CFLAGS LD_CXX\n" +" CPICFLAG LD_STATIC_FLAG\n" +" CPPFLAGS LFLAGS\n" +" CXX LIBOCTAVE\n" +" CXXFLAGS LIBOCTINTERP\n" +" CXXPICFLAG LIBS\n" +" DEPEND_EXTRA_SED_PATTERN OCTAVE_LIBS\n" +" DEPEND_FLAGS OCTAVE_LINK_DEPS\n" +" DL_LD OCT_LINK_DEPS\n" +" DL_LDFLAGS RANLIB\n" +" EXEEXT RDYNAMIC_FLAG\n" +" F77 READLINE_LIBS\n" +" F77_INTEGER_8_FLAG SED\n" +" FFLAGS XTRA_CFLAGS\n" +" FFTW3_LDFLAGS XTRA_CXXFLAGS\n" +" FFTW3_LIBS\n" "\n" " --link-stand-alone Link a stand-alone executable file.\n" "\n"
--- a/src/mkoctfile.in.sh +++ b/src/mkoctfile.in.sh @@ -79,6 +79,9 @@ : ${XTRA_CFLAGS=%OCTAVE_CONF_XTRA_CFLAGS%} : ${XTRA_CXXFLAGS=%OCTAVE_CONF_XTRA_CXXFLAGS%} +: ${AR=%OCTAVE_CONF_MKOCTFILE_AR%} +: ${RANLIB=%OCTAVE_CONF_MKOCTFILE_RANLIB%} + : ${DEPEND_FLAGS=%OCTAVE_CONF_DEPEND_FLAGS%} : ${DEPEND_EXTRA_SED_PATTERN=%OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%} @@ -233,29 +236,30 @@ -p VAR, --print VAR Print configuration variable VAR. Recognized variables are: - ALL_CFLAGS FFTW3F_LIBS - ALL_CXXFLAGS FLIBS - ALL_FFLAGS FPICFLAG - ALL_LDFLAGS INCFLAGS + ALL_CFLAGS FFTW3F_LDFLAGS + ALL_CXXFLAGS FFTW3F_LIBS + ALL_FFLAGS FLIBS + ALL_LDFLAGS FPICFLAG + AR INCFLAGS BLAS_LIBS LAPACK_LIBS CC LDFLAGS CFLAGS LD_CXX CPICFLAG LD_STATIC_FLAG CPPFLAGS LFLAGS - CXX LIBOCTAVE - CXXFLAGS LIBOCTINTERP - CXXPICFLAG LIBS - DEPEND_EXTRA_SED_PATTERN OCTAVE_LIBS + CXX LIBOCTAVE + CXXFLAGS LIBOCTINTERP + CXXPICFLAG LIBS + DEPEND_EXTRA_SED_PATTERN OCTAVE_LIBS DEPEND_FLAGS OCTAVE_LINK_DEPS - DL_LD OCT_LINK_DEPS - DL_LDFLAGS RDYNAMIC_FLAG - EXEEXT READLINE_LIBS - F77 SED - F77_INTEGER_8_FLAG XTRA_CFLAGS - FFLAGS XTRA_CXXFLAGS - FFTW3_LDFLAGS + DL_LD OCT_LINK_DEPS + DL_LDFLAGS RANLIB + EXEEXT RDYNAMIC_FLAG + F77 READLINE_LIBS + F77_INTEGER_8_FLAG SED + FFLAGS XTRA_CFLAGS + FFTW3_LDFLAGS XTRA_CXXFLAGS FFTW3_LIBS - FFTW3F_LDFLAGS + -v, --verbose Echo commands as they are executed.
--- a/test/Makefile.am +++ b/test/Makefile.am @@ -22,36 +22,37 @@ FCN_FILES = \ fntests.m \ - test_args.m \ - test_bug_31371.m \ - test_diag_perm.m \ - test_error.m \ - test_eval-catch.m \ - test_for.m \ - test_func.m \ - test_global.m \ - test_if.m \ - test_index.m \ - test_io.m \ - test_line_continue.m \ - test_logical_index.m \ - test_null_assign.m \ - test_parser.m \ - test_prefer.m \ - test_range.m \ - test_recursion.m \ - test_return.m \ - test_slice.m \ - test_struct.m \ - test_switch.m \ - test_system.m \ - test_transpose.m \ - test_try.m \ - test_unwind.m \ - test_while.m + args.tst \ + bug-31371.tst \ + diag-perm.tst \ + error.tst \ + eval-catch.tst \ + for.tst \ + func.tst \ + global.tst \ + if.tst \ + index.tst \ + io.tst \ + line-continue.tst \ + logical-index.tst \ + null-assign.tst \ + parser.tst \ + prefer.tst \ + range.tst \ + recursion.tst \ + return.tst \ + slice.tst \ + struct.tst \ + switch.tst \ + system.tst \ + transpose.tst \ + try.tst \ + unwind.tst \ + while.tst include bug-35448/module.mk include bug-36025/module.mk +include bug-38236/module.mk include classdef/module.mk include classes/module.mk include class-concat/module.mk @@ -59,30 +60,45 @@ include fcn-handle-derived-resolution/module.mk include nest/module.mk -check: test_sparse.m test_bc_overloads.m +check: sparse.tst bc-overload-tests.stamp $(top_builddir)/run-octave --norc --silent --no-history $(srcdir)/fntests.m $(srcdir) -test_sparse.m: build_sparse_tests.sh - $(srcdir)/build_sparse_tests.sh +sparse.tst: build-sparse-tests.sh + $(srcdir)/build-sparse-tests.sh + +GENERATED_BC_OVERLOADS_DIRS := \ + $(shell $(srcdir)/build-bc-overload-tests.sh --list-dirs) -test_bc_overloads.m: build_bc_overload_tests.sh bc_overloads_expected - $(srcdir)/build_bc_overload_tests.sh $(srcdir)/bc_overloads_expected +GENERATED_BC_OVERLOADS_FILES := \ + $(shell $(srcdir)/build-bc-overload-tests.sh --list-files) + +bc-overload-tests.stamp: build-bc-overload-tests.sh bc-overloads-expected + $(srcdir)/build-bc-overload-tests.sh $(srcdir)/bc-overloads-expected + touch $@ + +BUILT_SOURCES = bc-overload-tests.stamp EXTRA_DIST = \ - build_sparse_tests.sh \ - build_bc_overload_tests.sh \ - bc_overloads_expected \ + build-sparse-tests.sh \ + build-bc-overload-tests.sh \ + bc-overloads-expected \ build_bc_overloads_expected.m \ $(FCN_FILES) CLEANFILES = \ - test_sparse.m \ - test_bc_overloads.m \ - tbcover.m + sparse.tst \ + bc-overload-tests.stamp \ + $(GENERATED_BC_OVERLOADS_FILES) DISTCLEANFILES = \ fntests.log - + +fixedtestsdir := $(octtestsdir)/fixed + +nobase_fixedtests_DATA = \ + sparse.tst \ + $(GENERATED_BC_OVERLOADS_FILES) \ + $(filter-out fntests.m, $(FCN_FILES)) + clean-local: - -rm -rf @double @logical @int8 @uint64 @int64 @cell @single @int32 \ - @uint8 @uint16 @uint32 @struct @int16 @function_handle @char + -rm -rf $(GENERATED_BC_OVERLOADS_DIRS)
--- a/test/bug-35448/module.mk +++ b/test/bug-35448/module.mk @@ -2,6 +2,6 @@ bug-35448/fA.m \ bug-35448/fB.m \ bug-35448/fC.m \ - bug-35448/test_bug_35448.m + bug-35448/bug-35448.tst FCN_FILES += $(bug_35448_FCN_FILES)
--- a/test/bug-36025/module.mk +++ b/test/bug-36025/module.mk @@ -2,6 +2,6 @@ bug-36025/@testclass/one.m \ bug-36025/@testclass/testclass.m \ bug-36025/@testclass/two.m \ - bug-36025/test_bug_36025.m + bug-36025/bug-36025.tst FCN_FILES += $(bug_36025_FCN_FILES)
new file mode 100644 --- /dev/null +++ b/test/bug-38236/bug-38236.tst @@ -0,0 +1,3 @@ +%!test +%! u_vr +
new file mode 100644 --- /dev/null +++ b/test/bug-38236/module.mk @@ -0,0 +1,6 @@ +bug_38236_FCN_FILES = \ + bug-38236/df_vr.m \ + bug-38236/u_vr.m \ + bug-38236/bug-38236.tst + +FCN_FILES += $(bug_38236_FCN_FILES)
new file mode 100644 --- /dev/null +++ b/test/bug-38236/u_vr.m @@ -0,0 +1,17 @@ +# u_vr.m + +cmd = "\ +function __demo__ () \ + df_vr; \ + v = vr * 2; \ +endfunction \ +"; + +for ii = 1:2 + unwind_protect + eval (cmd); + __demo__; + unwind_protect_cleanup + clear __demo__ + end_unwind_protect +endfor \ No newline at end of file
rename from test/build_bc_overload_tests.sh rename to test/build-bc-overload-tests.sh --- a/test/build_bc_overload_tests.sh +++ b/test/build-bc-overload-tests.sh @@ -37,7 +37,29 @@ " if [ $# -eq 1 ]; then - expected_results_file="$1" + case "$1" in + --list-files) + echo tbcover.m + echo bc-overloads.tst + for class in $CLASSES; do + echo @$class/tbcover.m + done + exit + ;; + --list-dirs) + for class in $CLASSES; do + echo @$class + done + exit + ;; + --list-classes) + echo $CLASSES + exit + ;; + *) + expected_results_file="$1" + ;; + esac else echo "usage: build_bc_overload_tests.sh expected-results-file" 1>&2 exit 1 @@ -65,7 +87,7 @@ exit fi -cat > test_bc_overloads.m << EOF +cat > bc-overloads.tst << EOF ## !!! DO NOT EDIT !!! ## THIS IS AN AUTOMATICALLY GENERATED FILE ## modify build_bc_overload_tests.sh to generate the tests you need. @@ -91,7 +113,7 @@ cat $expected_results_file | \ while read cl1 cl2 clr ; do - cat >> test_bc_overloads.m << EOF + cat >> bc-overloads.tst << EOF %% Name call %!assert (tbcover (ex.$cl1, ex.$cl2), "$clr") %% Handle call @@ -100,7 +122,7 @@ EOF done -cat >> test_bc_overloads.m << EOF +cat >> bc-overloads.tst << EOF %%test handles through cellfun %!test %! f = fieldnames (ex);
rename from test/build_sparse_tests.sh rename to test/build-sparse-tests.sh --- a/test/build_sparse_tests.sh +++ b/test/build-sparse-tests.sh @@ -22,12 +22,12 @@ # Search for "# fails" # ./build_sparse_tests.sh preset -# creates test_sparse.m with preset tests. -# Use "test test_sparse" from octave to run the tests. +# creates sparse.tst with preset tests. +# Use "test sparse.tst" from octave to run the tests. # # ./build_sparse_tests.sh random -# Creates test_sprandom.m with randomly generated matrices. -# Use "test test_sprandom" from octave to run the tests. +# Creates sprandom.tst with randomly generated matrices. +# Use "test sprandom.tst" from octave to run the tests. # build_sparse_tests.sh generates tests for real and complex sparse matrices. # Also, we want to run both fixed tests with known outputs (quick tests) @@ -114,9 +114,9 @@ esac if $preset; then - TESTS=test_sparse.m + TESTS=sparse.tst else - TESTS=test_sprandom.m + TESTS=sprandom.tst fi # create initial file @@ -238,7 +238,7 @@ ## run preset sparse tests. All should pass. function [passes, tests] = test_sparse disp ("writing test output to sptest.log"); - test ("test_sparse", "normal", "sptest.log"); + test ("sparse.tst", "normal", "sptest.log"); endfunction EOF @@ -258,7 +258,7 @@ warning ("untested --- fix the source in build_sparse_tests.sh"); disp ("appending test output to sprandomtest.log"); fid = fopen ("sprandomtest.log", "at"); - test ("test_sprandom", "normal", fid); + test ("sprandom.tst", "normal", fid); ##[passes, total] = test("sprandomtest","normal",fid); fclose (fid); endfunction
--- a/test/class-concat/module.mk +++ b/test/class-concat/module.mk @@ -1,5 +1,5 @@ class_concat_FCN_FILES = \ class-concat/@foo/foo.m \ - class-concat/test_class_concat.m + class-concat/class-concat.tst FCN_FILES += $(class_concat_FCN_FILES)
--- a/test/classdef/module.mk +++ b/test/classdef/module.mk @@ -2,6 +2,6 @@ classdef/foo_method_changes_property_size.m \ classdef/foo_static_method_constant_property.m \ classdef/foo_value_class.m \ - classdef/test_classdef.m + classdef/classdef.tst FCN_FILES += $(classdef_FCN_FILES)
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/double.m @@ -0,0 +1,6 @@ +function x = double(snk) + + x = snk.gick; + +end +
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/eq.m @@ -0,0 +1,8 @@ +function b = eq(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + b = isequal(x1, x2); + +end \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/ge.m @@ -0,0 +1,8 @@ +function b = ge(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + b = (x1(1) >= x2(1)); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/gt.m @@ -0,0 +1,8 @@ +function b = gt(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + b = (x1(1) > x2(1)); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/horzcat.m @@ -0,0 +1,8 @@ +function s = horzcat(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork([x1 x2]); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/ldivide.m @@ -0,0 +1,8 @@ +function s = ldivide(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 .\ x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/le.m @@ -0,0 +1,8 @@ +function b = le(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + b = (x1(1) <= x2(1)); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/lt.m @@ -0,0 +1,8 @@ +function b = lt(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + b = (x1(1) < x2(1)); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/minus.m @@ -0,0 +1,8 @@ +function s = minus(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 - x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/mldivide.m @@ -0,0 +1,8 @@ +function s = mldivide(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 \ x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/mpower.m @@ -0,0 +1,10 @@ +function s = mpower(s1, x) + + if ~isa(s1, 'Snork') || isa(x, 'Snork') + error('mpower Snork!!!'); + end + + s = s1; + s.gick = s.gick ^ x; + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/mrdivide.m @@ -0,0 +1,8 @@ +function s = mrdivide(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 / x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/mtimes.m @@ -0,0 +1,8 @@ +function s = mtimes(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 * x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/ne.m @@ -0,0 +1,5 @@ +function b = ne(s1, s2) + + b = ~(s1 == s2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/plus.m @@ -0,0 +1,8 @@ +function s = plus(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 + x2); + +end \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/power.m @@ -0,0 +1,10 @@ +function s = power(s1, x) + + if ~isa(s1, 'Snork') || isa(x, 'Snork') + error('power Snork!!!'); + end + + s = s1; + s.gick = s.gick .^ x; + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/rdivide.m @@ -0,0 +1,8 @@ +function s = rdivide(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 ./ x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/times.m @@ -0,0 +1,8 @@ +function s = times(s1, s2, s3) + + x1 = double(s1); + x2 = double(s2); + + s = Snork(x1 .* x2); + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/uminus.m @@ -0,0 +1,6 @@ +function s = uminus(s1) + + s = s1; + s.gick = - s.gick; + +end \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/uplus.m @@ -0,0 +1,5 @@ +function s = uplus(s1) + + s = s1; + +end
new file mode 100644 --- /dev/null +++ b/test/classes/@Snork/vertcat.m @@ -0,0 +1,8 @@ +function s = vertcat(s1, s2) + + x1 = double(s1); + x2 = double(s2); + + s = Snork([x1; x2]); + +end
rename from test/classes/test_classes.m rename to test/classes/classes.tst --- a/test/classes/test_classes.m +++ b/test/classes/classes.tst @@ -1,3 +1,4 @@ +## Copyright (C) 2013 Julien Bect ## Copyright (C) 2009-2012 Robert T. Short ## ## This file is part of Octave. @@ -16,61 +17,66 @@ ## along with Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. -%% Test script for legacy OOP. -%% Requires the path to contain the test classes. +%% Test script for legacy OOP. +%% Requires the path to contain the test classes. %% -%% Note: This script and all classes are also intended to run -%% in MATLAB to test compatibility. Don't break that! +%% Note: This script and all classes are also intended to run +%% in MATLAB to test compatibility. Don't break that! %% -%% To Do: This script tests to ensure that things done correctly work -%% corrrectly. It should also check that things done incorrectly -%% error properly. +%% Note(JBect, 2013/01/27) : in order to ease to process of testing +%% Matlab compatibility, the syntax assert(observed, expected) should +%% be avoided. I use assert(isequal(observed, expected) instead. %% -%% The classes used for the tests reside in the test directory. +%% To Do: This script tests to ensure that things done correctly work +%% corrrectly. It should also check that things done incorrectly +%% error properly. +%% +%% The classes used for the tests reside in the test directory. %% -%% The classes provide the ability to test most of the major features -%% of the legacy OOP facilities. There are a number of classes, mostly -%% kind of the same, that create a hierarchy. +%% The classes provide the ability to test most of the major features +%% of the legacy OOP facilities. There are a number of classes, mostly +%% kind of the same, that create a hierarchy. -%% Test the Snork class. The Snork class has a number of the standard -%% methods that the others don't so we can test indexing and other -%% features. +%% Test the Snork class. The Snork class has a number of the standard +%% methods that the others don't so we can test indexing and other +%% features. %!shared snk, snk1, snk2 %!test snk = Snork(); -%! assert(gick(snk),1) -%! assert(snk.gick,1) -%! assert(snk(2),1); -%! assert(snk{end},3); -%!test snk = gick(snk,2); -%! assert(gick(snk),2) -%!test snk = set(snk,'gick',7); -%! assert(get(snk, 'gick'), 7) +%! assert (isequal (gick (snk), 1)); +%! assert (isequal (snk.gick, 1)); +%! assert (isequal (snk(2), 1)); +%! assert (isequal (snk{end}, 3)); +%!test snk = gick (snk, 2); +%! assert (isequal (gick (snk), 2)); +%!test snk = set (snk, 'gick', 7); +%! assert (isequal (get (snk, 'gick'), 7)); %!test snk.gick = 4; -%! assert(gick(snk),4) -%! snk(1) = 3; +%! assert (isequal (gick (snk),4)); +%! snk(1) = 3; %!test snk{end} = 9; -%! assert(cack(snk),[3 1 2 9]) -%! assert(getStash(snk),1) % Check private functions. -%! assert(isobject(snk)) -%! assert(class(snk),'Snork') -%! assert(isa(snk,'Snork')) -%! assert(~isa(snk,'Sneetch')) -%! assert(ismethod(snk,'gick')) -%! assert(~ismethod(snk,'bletch')) -%! assert(exist('snk')) -%! assert(~exist('blink')) +%! assert (isequal (cack (snk), [3 1 2 9])); +%! assert (isequal (getStash (snk), 1)); % Check private functions. +%! assert (isobject (snk)); +%! assert (isequal (class (snk), 'Snork')); +%! assert (isa (snk, 'Snork')); +%! assert (~isa (snk, 'Sneetch')); +%! assert (ismethod (snk, 'gick')); +%! assert (~ismethod (snk, 'bletch')); +%! assert (exist ('snk') == 1); +%! assert (exist ('blink') == 0); %!test snk1 = Snork(snk); -%! assert(class(snk1),'Snork') -%! assert(gick(snk1),4) +%! assert (isequal (class (snk1), 'Snork')); +%! assert (isequal (gick (snk1), 4)); %!test snk2 = Snork(-3); -%! assert(class(snk2),'Snork') -%! assert(gick(snk2),-3) -%!test x=[1 2 3 4]; -%! assert(x(snk),1); -%% x=methods('Snork'); % Need to test the methods function. +%! assert (isequal (class (snk2), 'Snork')); +%! assert (isequal (gick (snk2), -3)); +%!test x = [1 2 3 4]; +%! assert (isequal (x(snk), 1)); + +%% x = methods ('Snork'); % Need to test the methods function. %% save temp snk; -%% load temp % This load causes a segment fault. -%% assert(cack(snk),[-1 -2 -3 -4]); % This is a major bug! +%% load temp % This load causes a segfault. +%% assert (isequal (cack(snk), [-1 -2 -3 -4])); % This is a major bug! %% The Spork class is a near clone of Snork but without as many standard %% methods. We are testing no new octave features, but this is makes @@ -78,13 +84,13 @@ %% changes. We use Spork in the class hierarchy. %!shared sprk %!test sprk = Spork(); -%! assert(geek(sprk),1) -%!test sprk = geek(sprk,3); -%! assert(geek(sprk),3) -%!test sprk = set(sprk,'geek',7); -%! assert(get(sprk, 'geek'), 7) -%! assert(class(sprk),'Spork'); -%! assert(isa(sprk,'Spork')) +%! assert (isequal (geek (sprk), 1)); +%!test sprk = geek (sprk, 3); +%! assert (isequal (geek (sprk), 3)); +%!test sprk = set (sprk,'geek',7); +%! assert (isequal (get (sprk, 'geek'), 7)); +%! assert (isequal (class (sprk), 'Spork')); +%! assert (isa (sprk, 'Spork')); %% The Blork class is a near clone of Snork but without as many standard %% methods. We are testing no new octave features, but this is makes @@ -92,13 +98,13 @@ %% changes. We use Blork in the class hierarchy. %!shared blrk %!test blrk = Blork(); -%! assert(bleek(blrk),1) -%!test blrk = bleek(blrk,3); -%! assert(bleek(blrk),3) -%!test blrk = set(blrk,'bleek',13); -%! assert(get(blrk, 'bleek'), 13) -%! assert(class(blrk),'Blork'); -%! assert(isa(blrk,'Blork')) +%! assert (isequal (bleek(blrk), 1)); +%!test blrk = bleek (blrk, 3); +%! assert (isequal (bleek (blrk), 3)); +%!test blrk = set (blrk, 'bleek', 13); +%! assert (isequal (get (blrk, 'bleek'), 13)); +%! assert (isequal (class (blrk), 'Blork')); +%! assert (isa (blrk, 'Blork')); %% The Cork class is a near clone of Snork but without as many standard %% methods. We are testing no new octave features, but this is makes @@ -106,96 +112,207 @@ %% changes. We use Cork in the class hierarchy. %!shared crk %!test crk = Cork(23); -%! assert(click(crk),23) +%! assert (isequal (click(crk), 23)); %!test crk = click(crk,3); -%! assert(click(crk),3) -%!test crk = set(crk,'click',13); -%! assert(get(crk, 'click'), 13) -%! assert(class(crk),'Cork'); -%! assert(isa(crk,'Cork')) +%! assert (isequal (click(crk), 3)); +%!test crk = set (crk, 'click', 13); +%! assert (isequal (get (crk, 'click'), 13)); +%! assert (isequal (class (crk), 'Cork')); +%! assert (isa (crk, 'Cork')); %% The Dork class tests single inheritance. %!shared drk %!test drk = Dork(); -%! assert(gack(drk),0) -%!test drk = gack(drk,-2); -%! assert(gack(drk),-2) -%!test drk = gick(drk,2); -%! assert(gick(drk),2); -%!test drk = set(drk, 'gick',3, 'gack',-3); -%! assert(get(drk, 'gick'), 3) -%! assert(get(drk, 'gack'), -3) -%! assert(class(drk),'Dork') -%! assert(isa(drk,'Dork')) -%! assert(isa(drk,'Snork')) -%! assert(getStash(drk),2) +%! assert (isequal (gack (drk),0)); +%!test drk = gack (drk,-2); +%! assert (isequal (gack (drk),-2)); +%!test drk = gick (drk,2); +%! assert (isequal (gick (drk),2)); +%!test drk = set (drk, 'gick',3, 'gack',-3); +%! assert (isequal (get (drk, 'gick'), 3)); +%! assert (isequal (get (drk, 'gack'), -3)); +%! assert (isequal (class (drk), 'Dork')); +%! assert (isa (drk, 'Dork')); +%! assert (isa (drk, 'Snork')); +%! assert (isequal (getStash (drk), 2)); %!test drk1 = Dork(drk); -%! assert(class(drk1),'Dork') -%! assert(isa(drk1,'Snork')) -%! assert(gick(drk1),3) -%! assert(gack(drk1),-3) -%!test drk2 = Dork(-4,4); -%! assert(class(drk2),'Dork') -%! assert(isa(drk2,'Snork')) -%! assert(gick(drk2),-4) -%! assert(gack(drk2),4) +%! assert (isequal (class (drk1), 'Dork')); +%! assert (isa (drk1, 'Snork')); +%! assert (isequal (gick (drk1), 3)); +%! assert (isequal (gack (drk1), -3)); +%!test drk2 = Dork(-4, 4); +%! assert (isequal (class (drk2), 'Dork')); +%! assert (isa (drk2, 'Snork')); +%! assert (isequal (gick (drk2), -4)); +%! assert (isequal (gack (drk2), 4)); %% The Pork class is essentially a clone of Dork. It is used as part %% of the multiple inheritance test. %!shared prk, drk %!test prk = Pork(); -%! assert(geek(prk),1) -%! assert(gurk(prk),0) -%!test prk = gurk(prk,-3); -%! assert(gurk(prk),-3) -%!test prk = geek(prk,9); -%! assert(geek(prk),9) -%! assert(class(prk),'Pork') -%! assert(isa(prk,'Pork')) -%! assert(isa(prk,'Spork')) +%! assert (isequal (geek (prk), 1)); +%! assert (isequal (gurk (prk), 0)); +%!test prk = gurk (prk,-3); +%! assert (isequal (gurk (prk), -3)); +%!test prk = geek (prk,9); +%! assert (isequal (geek (prk), 9)); +%! assert (isequal (class (prk), 'Pork')); +%! assert (isa (prk, 'Pork')); +%! assert (isa (prk, 'Spork')); %!test drk = Dork(); % Precedence. -%! assert(bling(drk,prk),2) -%! assert(bling(prk,drk),2) - +%! assert (isequal (bling (drk, prk), 2)); +%! assert (isequal (bling (prk, drk), 2)); + %% The Gork class tests aggregation and multiple inheritance. %!shared grk %!test grk = Gork(); -%! assert(gick(grk),1) -%! assert(geek(grk),1) -%! assert(gack(grk),0) -%! assert(gurk(grk),0) -%! assert(bleek(grk),1) -%! assert(gark(grk),-2) -%! assert(click(cork(grk)),17) -%! assert(class(cork(grk)),'Cork') -%!test grk = gick(grk,3); -%!test grk = geek(grk,4); -%!test grk = gack(grk,-9); -%!test grk = gurk(grk,-8); -%!test grk = bleek(grk,-7); -%!test grk = gark(grk,-6); -%!test grk = cork(grk,click(cork(grk),23)); -%! assert(gick(grk),3) -%! assert(geek(grk),4) -%! assert(gack(grk),-9) -%! assert(gurk(grk),-8) -%! assert(bleek(grk),-7) -%! assert(gark(grk),-6) -%! assert(click(cork(grk)),23) +%! assert (isequal (gick (grk), 1)); +%! assert (isequal (geek (grk), 1)); +%! assert (isequal (gack (grk), 0)); +%! assert (isequal (gurk (grk), 0)); +%! assert (isequal (bleek (grk), 1)); +%! assert (isequal (gark(grk), -2)); +%! assert (isequal (click (cork (grk)), 17)); +%! assert (isequal (class (cork (grk)), 'Cork')); +%!test grk = gick (grk, 3); +%!test grk = geek (grk, 4); +%!test grk = gack (grk, -9); +%!test grk = gurk (grk, -8); +%!test grk = bleek (grk, -7); +%!test grk = gark (grk, -6); +%!test grk = cork (grk, click (cork (grk), 23)); +%! assert (isequal (gick (grk), 3)); +%! assert (isequal (geek (grk), 4)); +%! assert (isequal (gack (grk), -9)); +%! assert (isequal (gurk (grk), -8)); +%! assert (isequal (bleek (grk), -7)); +%! assert (isequal (gark (grk), -6)); +%! assert (isequal (click (cork (grk)), 23)); %!test -%! cork1 = Cork(13); -%! grk = set(grk, 'gick',-5, 'gack',-6, 'gark',-7, 'cork',cork1); -%! assert(get(grk,'gick'),-5) -%! assert(get(grk,'gack'),-6) -%! assert(get(grk,'gark'),-7) -%! assert(click(get(grk, 'cork')),13); -%!test grk = set(grk, 'cork',12); -%! assert(click(get(grk, 'cork')),12); -%! assert(class(cork(grk)),'Cork') -%! assert(class(grk),'Gork') -%! assert(isa(grk,'Gork')) -%! assert(isa(grk,'Dork')) -%! assert(isa(grk,'Pork')) -%! assert(isa(grk,'Blork')) -%! assert(isa(grk,'Snork')) -%! assert(isa(grk,'Spork')) +%! cork1 = Cork(13); +%! grk = set (grk, 'gick', -5, 'gack', -6, 'gark', -7, 'cork', cork1); +%! assert (isequal (get (grk, 'gick'), -5)); +%! assert (isequal (get (grk, 'gack'), -6)); +%! assert (isequal (get (grk, 'gark'), -7)); +%! assert (isequal (click(get (grk, 'cork')), 13)); +%!test grk = set (grk, 'cork', 12); +%! assert (isequal (click(get (grk, 'cork')),12)); +%! assert (isequal (class (cork(grk)), 'Cork')); +%! assert (isequal (class (grk), 'Gork')); +%! assert (isa (grk, 'Gork')); +%! assert (isa (grk, 'Dork')); +%! assert (isa (grk, 'Pork')); +%! assert (isa (grk, 'Blork')); +%! assert (isa (grk, 'Snork')); +%! assert (isa (grk, 'Spork')); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Testing (some) overloaded operators %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Common variables for testing overloaded operators +%!shared x1, x2, x3, s1, s2, s3 +%! x1 = 1 + rand(3); s1 = Snork(x1); +%! x2 = 1 + rand(3); s2 = Snork(x2); +%! x3 = diag([1 2 3]); s3 = Snork(x3); + +%% Test overloaded plus (+) and uplus (unitary +) for the Snork class +%!test s = s1 + s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2)); +%!test s = s1 + x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2)); +%!test s = x1 + s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 + x2)); +%!test s = +s1; assert (isequal (s, s1)); + +%% Test overloaded minus (-) for the Snork class +%!test s = s1 - s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2)); +%!test s = s1 - x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2)); +%!test s = x1 - s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 - x2)); +%!test s = -s1; assert (isequal (s, Snork(-x1))); + +%% Test overloaded mtimes (*) for the Snork class +%!test s = s1 * s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2)); +%!test s = s1 * x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2)); +%!test s = x1 * s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 * x2)); + +%% Test overloaded times (.*) for the Snork class +%!test s = s1 .* s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2)); +%!test s = s1 .* x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2)); +%!test s = x1 .* s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .* x2)); + +%% Test overloaded mpower (^) for the Snork class +%!test s = s1 ^ 3; assert (isa (s, 'Snork') && isequal (s.gick, x1 ^ 3)); +%!error <mpower Snork!!!> s = s1 ^ s1; +%!error <mpower Snork!!!> s = 20 ^ s1; + +%% Test overloaded power (.^) for the Snork class +%!test s = s1 .^ 2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .^ 2)); +%!error <power Snork!!!> s = s1 .^ s1; +%!error <power Snork!!!> s = 20 .^ s1; + +%% Test overloaded rdivide (./) for the Snork class +%!test s = s1 ./ s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2)); +%!test s = s1 ./ x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2)); +%!test s = x1 ./ s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 ./ x2)); + +%% Test overloaded ldivide (.\) for the Snork class +%!test s = s1 .\ s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .\ x2)); +%!test s = s1 .\ x2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .\ x2)); +%!test s = x1 .\ s2; assert (isa (s, 'Snork') && isequal (s.gick, x1 .\ x2)); + +%% Test overloaded mrdivide (/) for the Snork class +%!test s = s1 / s3; assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3)); +%!test s = s1 / x3; assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3)); +%!test s = x1 / s3; assert (isa (s, 'Snork') && isequal (s.gick, x1 / x3)); + +%% Test overloaded mldivide (\) for the Snork class +%!test s = s3 \ s2; assert (isa (s, 'Snork') && isequal (s.gick, x3 \ x2)); +%!test s = s3 \ x2; assert (isa (s, 'Snork') && isequal (s.gick, x3 \ x2)); +%!test s = x3 \ s2; assert (isa (s, 'Snork') && isequal (s.gick, x3 \ x2)); + +%% Test overloaded eq (==) for the Snork class +%!assert (s1 == s1) +%!assert (s1 == x1) +%!assert (x1 == s1) +%!assert (~(s1 == (s1 + 1))) +%!assert (~(s1 == (x1 + 1))) +%!assert (~(x1 == (s1 + 1))) + +%% Test overloaded ne (~=) for the Snork class +%!assert (~(s1 ~= s1)) +%!assert (~(s1 ~= x1)) +%!assert (~(x1 ~= s1)) +%!assert (s1 ~= (s1 + 1)) +%!assert (x1 ~= (s1 + 1)) +%!assert (s1 ~= (x1 + 1)) + +%% Test overloaded lt (<) for the Snork class +%!assert (s1 < (s1 + 1)) +%!assert (s1 < (x1 + 1)) +%!assert (x1 < (s1 + 1)) + +%% Test overloaded gt (>) for the Snork class +%!assert (s1 > (s1 - 1)) +%!assert (s1 > (x1 - 1)) +%!assert (x1 > (s1 - 1)) + +%% Test overloaded lt (<=) for the Snork class +%!assert (s1 <= (s1 + 1)) +%!assert (s1 <= (x1 + 1)) +%!assert (x1 <= (s1 + 1)) + +%% Test overloaded gt (>=) for the Snork class +%!assert (s1 >= (s1 - 1)) +%!assert (s1 >= (x1 - 1)) +%!assert (x1 >= (s1 - 1)) + +%% Test overloaded vertcat() for the Snork class +%% See bug #38170 (http://savannah.gnu.org/bugs/?38170) +%!test s = [s1; s2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2])); +%!xtest s = [s1; x2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2])); +%!xtest s = [x1; s2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1; x2])); + +%% Test overloaded horzcat() for the Snork class +%% See bug #38170 (http://savannah.gnu.org/bugs/?38170) +%!test s = [s1 s2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2])); +%!xtest s = [s1 x2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2])); +%!xtest s = [x1 s2]; assert (isa (s, 'Snork') && isequal (s.gick, [x1 x2])); +
--- a/test/classes/module.mk +++ b/test/classes/module.mk @@ -37,17 +37,38 @@ classes/@Snork/Snork.m \ classes/@Snork/cack.m \ classes/@Snork/display.m \ + classes/@Snork/double.m \ classes/@Snork/end.m \ + classes/@Snork/eq.m \ + classes/@Snork/ge.m \ classes/@Snork/get.m \ classes/@Snork/getStash.m \ classes/@Snork/gick.m \ + classes/@Snork/gt.m \ + classes/@Snork/horzcat.m \ + classes/@Snork/ldivide.m \ + classes/@Snork/le.m \ classes/@Snork/loadobj.m \ + classes/@Snork/lt.m \ + classes/@Snork/minus.m \ + classes/@Snork/mldivide.m \ + classes/@Snork/mpower.m \ + classes/@Snork/mrdivide.m \ + classes/@Snork/mtimes.m \ + classes/@Snork/ne.m \ + classes/@Snork/plus.m \ + classes/@Snork/power.m \ classes/@Snork/private/myStash.m \ + classes/@Snork/rdivide.m \ classes/@Snork/saveobj.m \ classes/@Snork/set.m \ classes/@Snork/subsasgn.m \ classes/@Snork/subsindex.m \ classes/@Snork/subsref.m \ + classes/@Snork/times.m \ + classes/@Snork/uminus.m \ + classes/@Snork/uplus.m \ + classes/@Snork/vertcat.m \ classes/@Spork/Spork.m \ classes/@Spork/cack.m \ classes/@Spork/display.m \ @@ -58,6 +79,6 @@ classes/@Spork/private/myStash.m \ classes/@Spork/saveobj.m \ classes/@Spork/set.m \ - classes/test_classes.m + classes/classes.tst FCN_FILES += $(classes_FCN_FILES)
rename from test/ctor-vs-method/test_ctor_vs_method.m rename to test/ctor-vs-method/ctor-vs-method.tst
--- a/test/ctor-vs-method/module.mk +++ b/test/ctor-vs-method/module.mk @@ -6,6 +6,6 @@ ctor-vs-method/@parent/method.m \ ctor-vs-method/@parent/parent.m \ ctor-vs-method/__trace__.m \ - ctor-vs-method/test_ctor_vs_method.m + ctor-vs-method/ctor-vs-method.tst FCN_FILES += $(ctor_vs_method_FCN_FILES)
rename from test/fcn-handle-derived-resolution/test_fcn_handle_derived_resolution.m rename to test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst
--- a/test/fcn-handle-derived-resolution/module.mk +++ b/test/fcn-handle-derived-resolution/module.mk @@ -6,6 +6,6 @@ fcn-handle-derived-resolution/@other/other.m \ fcn-handle-derived-resolution/@parent/numel.m \ fcn-handle-derived-resolution/@parent/parent.m \ - fcn-handle-derived-resolution/test_fcn_handle_derived_resolution.m + fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst FCN_FILES += $(fcn_handle_derived_resolution_FCN_FILES)
--- a/test/fntests.m +++ b/test/fntests.m @@ -41,8 +41,8 @@ testdirs = {currdir, srcdir}; endif -src_tree = canonicalize_file_name (fullfile (topsrcdir, "libinterp")); -liboctave_tree = canonicalize_file_name (fullfile (topsrcdir, "liboctave")); +src_tree = canonicalize_file_name (fullfile (topbuilddir, "libinterp")); +liboctave_tree = canonicalize_file_name (fullfile (topbuilddir, "liboctave")); script_tree = canonicalize_file_name (fullfile (topsrcdir, "scripts")); local_script_tree = canonicalize_file_name (fullfile (currdir, "../scripts")); @@ -52,265 +52,4 @@ fundirs{end+1} = local_script_tree; endif -function print_test_file_name (nm) - filler = repmat (".", 1, 55-length (nm)); - printf (" %s %s", nm, filler); -endfunction - -function print_pass_fail (n, p) - if (n > 0) - printf (" PASS %4d/%-4d", p, n); - nfail = n - p; - if (nfail > 0) - printf (" FAIL %d", nfail); - endif - endif - puts ("\n"); -endfunction - -function retval = has_functions (f) - n = length (f); - if (n > 3 && strcmp (f((end-2):end), ".cc")) - fid = fopen (f); - if (fid >= 0) - str = fread (fid, "*char")'; - fclose (fid); - retval = ! isempty (regexp (str,'^(DEFUN|DEFUN_DLD)\b', 'lineanchors')); - else - error ("fopen failed: %s", f); - endif - elseif (n > 2 && strcmp (f((end-1):end), ".m")) - retval = true; - else - retval = false; - endif -endfunction - -function retval = has_tests (f) - fid = fopen (f); - if (fid >= 0) - str = fread (fid, "*char")'; - fclose (fid); - retval = ! isempty (regexp (str, '^%!(assert|error|fail|test|warning)', "lineanchors")); - else - error ("fopen failed: %s", f); - endif -endfunction - -function retval = has_demos (f) - fid = fopen (f); - if (fid >= 0) - str = fread (fid, "*char")'; - fclose (fid); - retval = ! isempty (regexp (str, '^%!demo', "lineanchors")); - else - error ("fopen failed: %s", f); - endif -endfunction - -function [dp, dn, dxf, dsk] = run_test_dir (fid, d); - global files_with_tests; - global files_with_no_tests; - lst = dir (d); - dp = dn = dxf = dsk = 0; - for i = 1:length (lst) - nm = lst(i).name; - if (lst(i).isdir - && ! strcmp (nm, ".") && ! strcmp (nm, "..") - && ! strcmp (nm, "private") && nm(1) != "@" - && ! strcmp (nm, "CVS")) - [p, n, xf, sk] = run_test_dir (fid, [d, filesep, nm]); - dp += p; - dn += n; - dxf += xf; - dsk += sk; - endif - endfor - saved_dir = pwd (); - unwind_protect - chdir (d); - for i = 1:length (lst) - nm = lst(i).name; - if (length (nm) > 5 && strcmp (nm(1:5), "test_") - && strcmp (nm((end-1):end), ".m")) - p = n = xf = sk = 0; - ffnm = fullfile (d, nm); - if (has_tests (ffnm)) - print_test_file_name (nm); - [p, n, xf, sk] = test (nm(1:(end-2)), "quiet", fid); - print_pass_fail (n, p); - files_with_tests(end+1) = ffnm; - ##elseif (has_demos (ffnm)) - ## files_with_tests(end+1) = ffnm; - else - files_with_no_tests(end+1) = ffnm; - endif - dp += p; - dn += n; - dxf += xf; - dsk += sk; - endif - endfor - unwind_protect_cleanup - chdir (saved_dir); - end_unwind_protect -endfunction - -function [dp, dn, dxf, dsk] = run_test_script (fid, d); - global files_with_tests; - global files_with_no_tests; - global topsrcdir; - global topbuilddir; - lst = dir (d); - dp = dn = dxf = dsk = 0; - for i = 1:length (lst) - nm = lst(i).name; - if (lst(i).isdir && ! strcmp (nm, ".") && ! strcmp (nm, "..") - && ! strcmp (nm, "CVS")) - [p, n, xf, sk] = run_test_script (fid, [d, filesep, nm]); - dp += p; - dn += n; - dxf += xf; - dsk += sk; - endif - endfor - for i = 1:length (lst) - nm = lst(i).name; - ## Ignore hidden files - if (nm(1) == '.') - continue - endif - f = fullfile (d, nm); - if ((length (nm) > 2 && strcmp (nm((end-1):end), ".m")) || - (length (nm) > 3 && strcmp (nm((end-2):end), ".cc"))) - p = n = xf = 0; - ## Only run if it contains %!test, %!assert %!error or %!warning - if (has_tests (f)) - tmp = strrep (f, [topsrcdir, filesep], ""); - tmp = strrep (tmp, [topbuilddir, filesep], ["..", filesep]); - print_test_file_name (tmp); - [p, n, xf, sk] = test (f, "quiet", fid); - print_pass_fail (n, p); - dp += p; - dn += n; - dxf += xf; - dsk += sk; - files_with_tests(end+1) = f; - ##elseif (has_demos (f)) - ## files_with_tests(end+1) = f; - elseif (has_functions (f)) - ## To reduce the list length, only mark .cc files that contain - ## DEFUN definitions. - files_with_no_tests(end+1) = f; - endif - endif - endfor - ## printf("%s%s -> passes %d of %d tests\n", ident, d, dp, dn); -endfunction - -function printf_assert (varargin) - global _assert_printf; - _assert_printf = cat (2, _assert_printf, sprintf (varargin{:})); -endfunction - -function ret = prog_output_assert (str) - global _assert_printf; - if (isempty (_assert_printf)) - ret = isempty (str); - elseif (_assert_printf(end) == "\n") - ret = strcmp (_assert_printf(1:(end-1)), str); - else - ret = strcmp (_assert_printf, str); - endif - _assert_printf = ""; -endfunction - -function n = num_elts_matching_pattern (lst, pat) - n = sum (cellfun (@(x) !isempty (x), regexp (lst, pat, 'once'))); -endfunction - -function report_files_with_no_tests (with, without, typ) - pat = cstrcat ('\', typ, "$"); - n_with = num_elts_matching_pattern (with, pat); - n_without = num_elts_matching_pattern (without, pat); - n_tot = n_with + n_without; - printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ); -endfunction - -pso = page_screen_output (); -warn_state = warning ("query", "quiet"); -warning ("on", "quiet"); -try - page_screen_output (0); - warning ("off", "Octave:deprecated-function"); - fid = fopen ("fntests.log", "wt"); - if (fid < 0) - error ("could not open fntests.log for writing"); - endif - test ("", "explain", fid); - dp = dn = dxf = dsk = 0; - puts ("\nIntegrated test scripts:\n\n"); - for i = 1:length (fundirs) - [p, n, xf, sk] = run_test_script (fid, fundirs{i}); - dp += p; - dn += n; - dxf += xf; - dsk += sk; - endfor - puts ("\nFixed test scripts:\n\n"); - for i = 1:length (testdirs) - [p, n, xf, sk] = run_test_dir (fid, testdirs{i}); - dp += p; - dn += n; - dxf += xf; - dsk += sk; - endfor - puts ("\nSummary:\n\n"); - nfail = dn - dp; - printf (" PASS %6d\n", dp); - printf (" FAIL %6d\n", nfail); - if (dxf > 0) - printf (" XFAIL %6d\n", dxf); - endif - if (dsk > 0) - printf (" SKIPPED %6d\n", dsk); - endif - puts ("\n"); - puts ("See the file test/fntests.log for additional details.\n"); - if (dxf > 0) - puts ("\n"); - puts ("Expected failures (listed as XFAIL above) are known bugs.\n"); - puts ("Please help improve Octave by contributing fixes for them.\n"); - endif - if (dsk > 0) - puts ("\n"); - puts ("Tests are most often skipped because the features they require\n"); - puts ("have been disabled. Features are most often disabled because\n"); - puts ("they require dependencies that were not present when Octave\n"); - puts ("was built. The configure script should have printed a summary\n"); - puts ("at the end of its run indicating which dependencies were not found.\n"); - endif - - ## Weed out deprecated and private functions - weed_idx = cellfun (@isempty, regexp (files_with_tests, '\bdeprecated\b|\bprivate\b', 'once')); - files_with_tests = files_with_tests(weed_idx); - weed_idx = cellfun (@isempty, regexp (files_with_no_tests, '\bdeprecated\b|\bprivate\b', 'once')); - files_with_no_tests = files_with_no_tests(weed_idx); - - report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m"); - report_files_with_no_tests (files_with_tests, files_with_no_tests, ".cc"); - - puts ("\nPlease help improve Octave by contributing tests for\n"); - puts ("these files (see the list in the file fntests.log).\n\n"); - - fprintf (fid, "\nFiles with no tests:\n\n%s", - list_in_columns (files_with_no_tests, 80)); - fclose (fid); - - page_screen_output (pso); - warning (warn_state.state, "quiet"); -catch - page_screen_output (pso); - warning (warn_state.state, "quiet"); - disp (lasterr ()); -end_try_catch +__run_test_suite__ (fundirs, testdirs);
rename from test/test_for.m rename to test/for.tst --- a/test/test_for.m +++ b/test/for.tst @@ -19,60 +19,60 @@ %% test/octave.test/for/for-1.m %!test %! for i = 1 -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! end -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1")); %% test/octave.test/for/for-2.m %!test %! for i = 1:4 -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1234")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1234")); %% test/octave.test/for/for-3.m %!test %! for i = [1,2,3,4] -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1234")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1234")); %% test/octave.test/for/for-4.m %!test %! for i = [1,2;3,4] -%! printf_assert ("%d", i(1,1)); -%! printf_assert ("%d", i(2,1)); +%! __printf_assert__ ("%d", i(1,1)); +%! __printf_assert__ ("%d", i(2,1)); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1324")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1324")); %% test/octave.test/for/for-5.m %!test %! for i = I -%! printf_assert ("%d", imag (i)); +%! __printf_assert__ ("%d", imag (i)); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1")); %% test/octave.test/for/for-6.m %!test %! for i = [1,2,3,4]*I -%! printf_assert ("%d", imag (i)); +%! __printf_assert__ ("%d", imag (i)); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1234")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1234")); %% test/octave.test/for/for-7.m %!test %! for i = [1,2;3,4]*I -%! printf_assert ("%d", imag (i(1,1))); -%! printf_assert ("%d", imag (i(2,1))); +%! __printf_assert__ ("%d", imag (i(1,1))); +%! __printf_assert__ ("%d", imag (i(2,1))); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("1324")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("1324")); %% test/octave.test/for/for-8.m %!test @@ -80,10 +80,10 @@ %! if (i > 2) %! break; %! endif -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("12")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("12")); %% test/octave.test/for/for-9.m %!test @@ -91,10 +91,10 @@ %! if (i < 3) %! continue; %! endif -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endfor -%! printf_assert ("\n"); -%! assert (prog_output_assert ("34")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("34")); %!test %! a = [1,3;2,4];
rename from test/test_if.m rename to test/if.tst --- a/test/test_if.m +++ b/test/if.tst @@ -21,67 +21,67 @@ %! i = 0; %! if (i == 0) %! i++; -%! printf_assert ("%d\n", i); +%! __printf_assert__ ("%d\n", i); %! endif -%! assert (prog_output_assert ("1")); +%! assert (__prog_output_assert__ ("1")); %% test/octave.test/if/if-2.m %!test %! if (eye (2)) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! else -%! printf_assert ("pass\n"); +%! __printf_assert__ ("pass\n"); %! end -%! assert (prog_output_assert ("pass")); +%! assert (__prog_output_assert__ ("pass")); %% test/octave.test/if/if-3.m %!test %! x = 2; %! if (eye (2)) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (x) -%! printf_assert ("pass\n"); +%! __printf_assert__ ("pass\n"); %! endif -%! assert (prog_output_assert ("pass")); +%! assert (__prog_output_assert__ ("pass")); %% test/octave.test/if/if-4.m %!test %! x = 0; %! y = -2; %! if (eye (2)) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (x) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (y) -%! printf_assert ("pass\n"); +%! __printf_assert__ ("pass\n"); %! end -%! assert (prog_output_assert ("pass")); +%! assert (__prog_output_assert__ ("pass")); %% test/octave.test/if/if-5.m %!test %! x = 0; %! y = -2; %! if (eye (2)) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (x) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (x) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! else -%! printf_assert ("pass\n"); +%! __printf_assert__ ("pass\n"); %! endif -%! assert (prog_output_assert ("pass")); +%! assert (__prog_output_assert__ ("pass")); %% test/octave.test/if/if-6.m %!test %! x = 0; %! y = -2; %! if (y) -%! printf_assert ("pass\n"); +%! __printf_assert__ ("pass\n"); %! elseif (x) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! elseif (x) -%! printf_assert ("fail\n"); +%! __printf_assert__ ("fail\n"); %! end -%! assert (prog_output_assert ("pass")); +%! assert (__prog_output_assert__ ("pass"));
rename from test/test_io.m rename to test/io.tst --- a/test/test_io.m +++ b/test/io.tst @@ -352,7 +352,7 @@ %! mode = deblank (mode_list (k,:)); %! [id, err] = fopen (nm, mode, arch); %! if (id < 0) -%! printf_assert ("open failed: %s (%s, %s): %s\n", nm, mode, arch, err); +%! __printf_assert__ ("open failed: %s (%s, %s): %s\n", nm, mode, arch, err); %! status = 0; %! break; %! else @@ -361,7 +361,7 @@ %! tmp_mode = cstrcat (mode, "b"); %! [id, err] = fopen (nm, tmp_mode, arch); %! if (id < 0) -%! printf_assert ("open failed: %s (%s, %s): %s\n", nm, tmp_mode, arch, err); +%! __printf_assert__ ("open failed: %s (%s, %s): %s\n", nm, tmp_mode, arch, err); %! status = 0; %! break; %! else @@ -370,7 +370,7 @@ %! tmp_mode = cstrcat (mode, "t"); %! [id, err] = fopen (nm, tmp_mode, arch); %! if (id < 0) -%! printf_assert ("open failed: %s (%s, %s): %s\n", nm, tmp_mode, arch, err); +%! __printf_assert__ ("open failed: %s (%s, %s): %s\n", nm, tmp_mode, arch, err); %! status = 0; %! break; %! else @@ -399,7 +399,7 @@ %% test/octave.test/io/fopen-4.m %! fopen ("foo", "wb", "noodle"); -%! assert (prog_output_assert ("error:")); +%! assert (__prog_output_assert__ ("error:")); %% test/octave.test/io/fopen-5.m %!error <Invalid call to fopen> fopen () @@ -452,13 +452,13 @@ %! endfor %! %! if (x == 1:n) -%! printf_assert ("ok\n"); +%! __printf_assert__ ("ok\n"); %! endif %! endif %! endif %! %! unlink (nm); -%! assert (prog_output_assert ("ok")); +%! assert (__prog_output_assert__ ("ok")); %% test/octave.test/io/file-pos-1.m %!test
--- a/test/nest/module.mk +++ b/test/nest/module.mk @@ -1,4 +1,4 @@ -nest_FCN_FILES = \ +nest_fcn_files = \ nest/arg_nest.m \ nest/arg_ret.m \ nest/nest_eval.m \ @@ -13,7 +13,7 @@ nest/scope3.m \ nest/script_nest.m \ nest/script_nest_script.m \ - nest/test_nest.m \ + nest/nest.tst \ nest/varg_nest.m \ nest/varg_nest2.m
rename from test/test_system.m rename to test/system.tst --- a/test/test_system.m +++ b/test/system.tst @@ -39,8 +39,8 @@ %% test/octave.test/system/pause-1.m %!test %! pause (0); -%! printf_assert ("ok\n"); -%! assert (prog_output_assert ("ok")); +%! __printf_assert__ ("ok\n"); +%! assert (__prog_output_assert__ ("ok")); %% test/octave.test/system/pause-2.m %!error <Invalid call to pause> pause (1, 2) @@ -48,8 +48,8 @@ %% test/octave.test/system/sleep-1.m %!test %! sleep (0); -%! printf_assert ("ok\n"); -%! assert (prog_output_assert ("ok")); +%! __printf_assert__ ("ok\n"); +%! assert (__prog_output_assert__ ("ok")); %% test/octave.test/system/sleep-2.m %!error <Invalid call to sleep> sleep () @@ -60,8 +60,8 @@ %% test/octave.test/system/usleep-1.m %!test %! usleep (0); -%! printf_assert ("ok\n"); -%! assert (prog_output_assert ("ok")); +%! __printf_assert__ ("ok\n"); +%! assert (__prog_output_assert__ ("ok")); %% test/octave.test/system/usleep-2.m %!error <Invalid call to usleep> usleep ()
rename from test/test_while.m rename to test/while.tst --- a/test/test_while.m +++ b/test/while.tst @@ -21,28 +21,28 @@ %! i = 0; %! while (eye (2)) %! i++; -%! printf_assert ("%d\n", i); +%! __printf_assert__ ("%d\n", i); %! endwhile -%! assert (prog_output_assert ("")); +%! assert (__prog_output_assert__ ("")); %% test/octave.test/while/while-2.m %!test %! i = 5; %! while (--i) -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endwhile -%! printf_assert ("\n"); -%! assert (prog_output_assert ("4321")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("4321")); %% test/octave.test/while/while-3.m %!test %! i = 5; %! while (i) %! i--; -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endwhile -%! printf_assert ("\n"); -%! assert (prog_output_assert ("43210")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("43210")); %% test/octave.test/while/while-4.m %!test @@ -51,10 +51,10 @@ %! if (i > 2) %! break; %! endif -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endwhile -%! printf_assert ("\n"); -%! assert (prog_output_assert ("12")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("12")); %% test/octave.test/while/while-5.m %!test @@ -63,8 +63,8 @@ %! if (i < 3) %! continue; %! endif -%! printf_assert ("%d", i); +%! __printf_assert__ ("%d", i); %! endwhile -%! printf_assert ("\n"); -%! assert (prog_output_assert ("34")); +%! __printf_assert__ ("\n"); +%! assert (__prog_output_assert__ ("34"));