changeset 25043:cc20786d2165

maint: Merge stable to default.
author Rik <rik@octave.org>
date Wed, 28 Mar 2018 14:07:12 -0700
parents ae487ce89992 (current diff) ba5af45bbfc4 (diff)
children 135cc24efe4c
files NEWS
diffstat 36 files changed, 538 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Mar 28 05:44:28 2018 -0400
+++ b/NEWS	Wed Mar 28 14:07:12 2018 -0700
@@ -320,6 +320,8 @@
       desktop              | isguirunning
       tmpnam               | tempname
       toascii              | double
+      java2mat             | __java2mat__
+
 
  ** The following functions were deprecated in Octave 4.0 and have been
     removed from Octave 4.4.
--- a/libgui/src/documentation-dock-widget.cc	Wed Mar 28 05:44:28 2018 -0400
+++ b/libgui/src/documentation-dock-widget.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -39,42 +39,38 @@
     set_title (tr ("Documentation"));
     setStatusTip (tr ("See the documentation for help."));
 
-    m_webinfo = new octave::webinfo (this);
-    setWidget (m_webinfo);
-    setFocusProxy (m_webinfo);
+    m_docs = new octave::documentation (this);
+    setWidget (m_docs);
+    setFocusProxy (m_docs);
 
     connect (p, SIGNAL (show_doc_signal (const QString&)),
              this, SLOT (showDoc (const QString&)));
   }
 
-  void documentation_dock_widget::notice_settings (const QSettings *settings)
+  documentation_dock_widget::~documentation_dock_widget (void)
   {
-    m_webinfo->notice_settings (settings);
+    if (m_docs)
+      delete m_docs;
   }
 
-  void documentation_dock_widget::load_info_file (void)
+  void documentation_dock_widget::notice_settings (const QSettings *settings)
   {
-    octave::help_system& help_sys
-      = octave::__get_help_system__ ("doc widget: load_info_file");
-
-    QString info_file = QString::fromStdString (help_sys.info_file ());
-
-    m_webinfo->load_info_file (info_file);
+    m_docs->notice_settings (settings);
   }
 
   void documentation_dock_widget::copyClipboard (void)
   {
-    m_webinfo->copyClipboard ();
+    m_docs->copyClipboard ();
   }
 
   void documentation_dock_widget::pasteClipboard (void)
   {
-    m_webinfo->pasteClipboard ();
+    m_docs->pasteClipboard ();
   }
 
   void documentation_dock_widget::selectAll (void)
   {
-    m_webinfo->selectAll ();
+    m_docs->selectAll ();
   }
 
   void documentation_dock_widget::showDoc (const QString& name)
@@ -85,6 +81,6 @@
 
     raise ();
 
-    m_webinfo->load_ref (name);
+    m_docs->load_ref (name);
   }
 }
--- a/libgui/src/documentation-dock-widget.h	Wed Mar 28 05:44:28 2018 -0400
+++ b/libgui/src/documentation-dock-widget.h	Wed Mar 28 14:07:12 2018 -0700
@@ -24,8 +24,7 @@
 #define octave_documentation_dock_widget_h 1
 
 #include "octave-dock-widget.h"
-
-#include "webinfo.h"
+#include "documentation.h"
 
 namespace octave
 {
@@ -36,13 +35,12 @@
   public:
 
     documentation_dock_widget (QWidget *parent = nullptr);
+    ~documentation_dock_widget (void);
 
   public slots:
 
     void notice_settings (const QSettings *settings);
 
-    void load_info_file (void);
-
   protected slots:
 
     void copyClipboard (void);
@@ -53,7 +51,7 @@
 
   private:
 
-    octave::webinfo *m_webinfo;
+    octave::documentation *m_docs;
   };
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/documentation.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -0,0 +1,256 @@
+/*
+
+Copyright (C) 2018 Torsten <mttl@maibox.org>
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <QApplication>
+#include <QCompleter>
+#include <QHelpContentWidget>
+#include <QHelpIndexWidget>
+#include <QHelpSearchEngine>
+#include <QHelpSearchQueryWidget>
+#include <QHelpSearchResultWidget>
+#include <QLabel>
+#include <QLineEdit>
+#include <QTabWidget>
+#include <QMessageBox>
+#include <QVBoxLayout>
+
+#include "documentation.h"
+
+namespace octave
+{
+  // The documentation splitter, which is the main widget
+  // of the doc dock widget
+  documentation::documentation (QWidget *p)
+    : QSplitter (Qt::Horizontal, p)
+  {
+    QString collection = getenv ("OCTAVE_QTHELP_COLLECTION");
+
+    // Setup the help engine and load the help data
+    m_help_engine = new QHelpEngine (collection, this);
+
+    connect(m_help_engine, SIGNAL(setupFinished()),
+            m_help_engine->searchEngine(), SLOT(indexDocumentation()));
+
+    if (! m_help_engine->setupData())
+      {
+        QMessageBox::warning (this, tr ("Octave Documentation"),
+                              tr ("Could not setup the data required for the\n"
+                                  "documentation viewer. Only help texts in\n"
+                                  "the Console Widget will be available."));
+        if (m_help_engine)
+          {
+            delete m_help_engine;
+            m_help_engine = 0;
+          }
+      }
+
+    // The browser
+    m_doc_browser = new documentation_browser (m_help_engine, this);
+
+    // Layout contents, index and search
+    QTabWidget *navi = new QTabWidget (this);
+    navi->setTabsClosable (false);
+    navi->setMovable (true);
+
+    // Contents
+    QHelpContentWidget *content = m_help_engine->contentWidget ();
+    navi->addTab (content, tr ("Contents"));
+
+    connect(m_help_engine->contentWidget (),
+            SIGNAL (linkActivated (const QUrl&)),
+            m_doc_browser, SLOT(handle_index_clicked (const QUrl&)));
+
+    // Index
+    QHelpIndexWidget *index = m_help_engine->indexWidget ();
+
+    m_filter = new QComboBox (this);
+    m_filter->setToolTip (tr ("Enter text to search the indices"));
+    m_filter->setEditable (true);
+    m_filter->setInsertPolicy (QComboBox::NoInsert);
+    m_filter->setMaxCount (10);
+    m_filter->setMaxVisibleItems (10);
+    m_filter->setSizeAdjustPolicy (
+      QComboBox::AdjustToMinimumContentsLengthWithIcon);
+    QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
+    m_filter->setSizePolicy (sizePol);
+    m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
+    QLabel *filter_label = new QLabel (tr ("Search"));
+
+    QWidget *filter_all = new QWidget (navi);
+    QHBoxLayout *h_box_index = new QHBoxLayout (filter_all);
+    h_box_index->addWidget (filter_label);
+    h_box_index->addWidget (m_filter);
+    h_box_index->setMargin (2);
+    filter_all->setLayout (h_box_index);
+
+    QWidget *index_all = new QWidget (navi);
+    QVBoxLayout *v_box_index = new QVBoxLayout (index_all);
+    v_box_index->addWidget (filter_all);
+    v_box_index->addWidget (index);
+    index_all->setLayout (v_box_index);
+
+    navi->addTab (index_all, tr ("Index"));
+
+    connect(m_help_engine->indexWidget (),
+            SIGNAL (linkActivated (const QUrl&, const QString&)),
+            m_doc_browser, SLOT(handle_index_clicked (const QUrl&,
+                                                       const QString&)));
+
+    connect (m_filter, SIGNAL (editTextChanged (const QString&)),
+             this, SLOT(filter_update (const QString&)));
+
+    connect (m_filter->lineEdit (), SIGNAL (editingFinished (void)),
+             this, SLOT(filter_update_history (void)));
+
+    // Search
+    QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
+    QHelpSearchQueryWidget *search = search_engine->queryWidget ();
+    QHelpSearchResultWidget *result = search_engine->resultWidget ();
+    QWidget *search_all = new QWidget (navi);
+    QVBoxLayout *v_box_search = new QVBoxLayout (search_all);
+    v_box_search->addWidget (search);
+    v_box_search->addWidget (result);
+    search_all->setLayout (v_box_search);
+    navi->addTab (search_all, tr ("Search"));
+
+    connect (search, SIGNAL (search (void)),
+             this, SLOT(global_search (void)));
+
+    connect (search_engine, SIGNAL (searchingStarted (void)),
+             this, SLOT(global_search_started (void)));
+    connect (search_engine, SIGNAL (searchingFinished (int)),
+             this, SLOT(global_search_finished (int)));
+
+    connect (search_engine->resultWidget (),
+             SIGNAL (requestShowLink (const QUrl&)),
+             m_doc_browser,
+             SLOT(handle_index_clicked (const QUrl&)));
+
+    // Fill the splitter
+    insertWidget (0, navi);
+    insertWidget (1, m_doc_browser);
+    setStretchFactor (1, 1);
+
+    // Initial view: Contents
+    m_doc_browser->setSource (QUrl (
+        "qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html"));
+  }
+
+  documentation::~documentation (void)
+  {
+    if (m_help_engine)
+      delete m_help_engine;
+  }
+
+  void documentation::global_search (void)
+  {
+    QList<QHelpSearchQuery> queries
+      = m_help_engine->searchEngine ()->queryWidget ()->query ();
+    m_help_engine->searchEngine ()->search (queries);
+  }
+
+  void documentation::global_search_started (void)
+  {
+    qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+  }
+
+  void documentation::global_search_finished (int)
+  {
+    qApp->restoreOverrideCursor();
+  }
+
+  void documentation::notice_settings (const QSettings *) { }
+
+  void documentation::copyClipboard (void) { }
+
+  void documentation::pasteClipboard (void) { }
+
+  void documentation::selectAll (void) { }
+
+  void documentation::load_ref (const QString& ref_name)
+  {
+    if (m_help_engine)
+      {
+        QMap<QString, QUrl> found_links
+          = m_help_engine->linksForIdentifier (ref_name);
+        if (found_links.count() > 0)
+          m_doc_browser->setSource (found_links.constBegin().value());
+      }
+  }
+
+  void documentation::filter_update (const QString& expression)
+  {
+    if (! m_help_engine)
+      return;
+
+    QString wildcard;
+    if (expression.contains(QLatin1Char('*')))
+      wildcard = expression;
+
+    m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
+  }
+
+  void documentation::filter_update_history (void)
+  {
+    QString text = m_filter->currentText ();   // get current text
+    int index = m_filter->findText (text);     // and its actual index
+
+    if (index > -1)
+      m_filter->removeItem (index);            // remove if already existing
+
+    m_filter->insertItem (0, text);            // (re)insert at beginning
+    m_filter->setCurrentIndex (0);
+  }
+
+
+
+  // The documentation browser
+  documentation_browser::documentation_browser (QHelpEngine *he, QWidget *p)
+    : QTextBrowser (p), m_help_engine (he)
+  { }
+
+  documentation_browser::~documentation_browser (void)
+  { }
+
+  void documentation_browser::handle_index_clicked (const QUrl& url,
+                                                    const QString&)
+  {
+    setSource (url);
+  }
+
+  void documentation_browser::notice_settings (const QSettings *)
+  { }
+
+  QVariant documentation_browser::loadResource (int type,
+                                                const QUrl &url)
+    {
+        if (url.scheme () == "qthelp")
+          return QVariant (m_help_engine->fileData(url));
+        else
+          return QTextBrowser::loadResource(type, url);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/documentation.h	Wed Mar 28 14:07:12 2018 -0700
@@ -0,0 +1,98 @@
+/*
+
+Copyright (C) 2018 Torsten <mttl@maibox.org>
+
+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
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_documentation_h)
+#define octave_documentation_h 1
+
+#include <QComboBox>
+#include <QWidget>
+#include <QSettings>
+#include <QSplitter>
+#include <QTextBrowser>
+#include <QtHelp/QHelpEngine>
+
+namespace octave
+{
+  // The documentation browser
+  class documentation_browser : public QTextBrowser
+  {
+    Q_OBJECT
+
+  public:
+
+    documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr);
+    ~documentation_browser (void);
+
+    virtual QVariant loadResource (int type, const QUrl &url);
+
+  public slots:
+
+    void handle_index_clicked (const QUrl& url,
+                               const QString& keyword = QString ());
+    void notice_settings (const QSettings *settings);
+
+  private:
+
+    QHelpEngine *m_help_engine;
+
+  };
+
+
+  // The documentaiton main class (splitter)
+  class documentation : public QSplitter
+  {
+    Q_OBJECT
+
+  public:
+
+    documentation (QWidget *parent = nullptr);
+    ~documentation (void);
+
+  public slots:
+
+    void notice_settings (const QSettings *settings);
+
+    void copyClipboard (void);
+    void pasteClipboard (void);
+    void selectAll (void);
+
+    void load_ref (const QString & name);
+
+  private slots:
+
+    void global_search (void);
+    void global_search_started (void);
+    void global_search_finished (int hits);
+    void filter_update (const QString& expression);
+    void filter_update_history (void);
+
+  private:
+
+    QHelpEngine *m_help_engine;
+    documentation_browser *m_doc_browser;
+    QComboBox *m_filter;
+
+  };
+
+}
+
+#endif
--- a/libgui/src/m-editor/file-editor.cc	Wed Mar 28 05:44:28 2018 -0400
+++ b/libgui/src/m-editor/file-editor.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -37,6 +37,7 @@
 #include <QMessageBox>
 #include <QMimeData>
 #include <QProcess>
+#include <QPushButton>
 #include <QStyle>
 #include <QTabBar>
 #include <QTextStream>
@@ -987,15 +988,15 @@
     m_tool_bar->setIconSize (QSize (icon_size,icon_size));
 
     int tab_width_min = settings->value ("editor/notebook_tab_width_min", 160)
-      .toInt ();
+                        .toInt ();
     int tab_width_max = settings->value ("editor/notebook_tab_width_max", 300)
-      .toInt ();
+                        .toInt ();
 
     if (settings->value ("editor/longWindowTitle", false).toBool ())
       {
         QString style_sheet = QString ("QTabBar::tab "
                                        "{min-width: %1px; max-width: %2px;}")
-          .arg (tab_width_min).arg (tab_width_max);
+                              .arg (tab_width_min).arg (tab_width_max);
         m_tab_widget->setElideMode (Qt::ElideLeft);
         m_tab_widget->setStyleSheet (style_sheet);
       }
@@ -1516,7 +1517,7 @@
     QSettings *settings = resource_manager::get_settings ();
     m_mru_files = settings->value ("editor/mru_file_list").toStringList ();
     m_mru_files_encodings = settings->value ("editor/mru_file_encodings")
-      .toStringList ();
+                            .toStringList ();
 
     if (m_mru_files_encodings.count () != m_mru_files.count ())
       {
--- a/libgui/src/main-window.cc	Wed Mar 28 05:44:28 2018 -0400
+++ b/libgui/src/main-window.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -40,6 +40,7 @@
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QIcon>
+#include <QTextBrowser>
 #include <QTextStream>
 #include <QThread>
 #include <QDateTime>
@@ -211,9 +212,6 @@
     connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
              this, SLOT (handle_octave_ready (void)));
 
-    connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
-             m_doc_browser_window, SLOT (load_info_file (void)));
-
     connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
              this, SLOT (handle_octave_finished (int)));
 
@@ -662,14 +660,14 @@
     }
 
     widget_icon_data[] =
-      {
-        // array of possible icon sets (name, path (complete for NONE))
-        // the first entry here is the default!
-        {"NONE",    ":/actions/icons/logo.png"},
-        {"GRAPHIC", ":/actions/icons/graphic_logo_"},
-        {"LETTER",  ":/actions/icons/letter_logo_"},
-        {"", ""} // end marker has empty name
-      };
+    {
+      // array of possible icon sets (name, path (complete for NONE))
+      // the first entry here is the default!
+      {"NONE",    ":/actions/icons/logo.png"},
+      {"GRAPHIC", ":/actions/icons/graphic_logo_"},
+      {"LETTER",  ":/actions/icons/letter_logo_"},
+      {"", ""} // end marker has empty name
+    };
 
     int count = 0;
     int icon_set_found = 0; // default
@@ -691,7 +689,8 @@
       {
         QString name = widget->objectName ();
         if (! name.isEmpty ())
-          { // if children has a name
+          {
+            // if children has a name
             icon = widget_icon_data[icon_set_found].path; // prefix | octave-logo
             if (widget_icon_data[icon_set_found].name != "NONE")
               icon += name + ".png"; // add widget name and ext.
@@ -700,7 +699,7 @@
       }
     if (widget_icon_data[icon_set_found].name != "NONE")
       m_release_notes_icon = widget_icon_data[icon_set_found].path
-        + "ReleaseWidget.png";
+                             + "ReleaseWidget.png";
     else
       m_release_notes_icon = ":/actions/icons/logo.png";
 
@@ -2571,7 +2570,8 @@
     // file menu
     shortcut_manager::set_shortcut (m_open_action, "main_file:open_file");
     shortcut_manager::set_shortcut (m_new_script_action, "main_file:new_file");
-    shortcut_manager::set_shortcut (m_new_function_action, "main_file:new_function");
+    shortcut_manager::set_shortcut (m_new_function_action,
+                                    "main_file:new_function");
     shortcut_manager::set_shortcut (m_new_function_action, "main_file:new_figure");
     shortcut_manager::set_shortcut (m_load_workspace_action,
                                     "main_file:load_workspace");
@@ -2611,7 +2611,8 @@
                                     "main_window:show_workspace");
     shortcut_manager::set_shortcut (m_show_file_browser_action,
                                     "main_window:show_file_browser");
-    shortcut_manager::set_shortcut (m_show_editor_action, "main_window:show_editor");
+    shortcut_manager::set_shortcut (m_show_editor_action,
+                                    "main_window:show_editor");
     shortcut_manager::set_shortcut (m_show_documentation_action,
                                     "main_window:show_doc");
     shortcut_manager::set_shortcut (m_show_variable_editor_action,
@@ -2623,7 +2624,8 @@
                                     "main_window:file_browser");
     shortcut_manager::set_shortcut (m_editor_action, "main_window:editor");
     shortcut_manager::set_shortcut (m_documentation_action, "main_window:doc");
-    shortcut_manager::set_shortcut (m_variable_editor_action, "main_window:variable_editor");
+    shortcut_manager::set_shortcut (m_variable_editor_action,
+                                    "main_window:variable_editor");
     shortcut_manager::set_shortcut (m_reset_windows_action, "main_window:reset");
 
     // help menu
--- a/libgui/src/module.mk	Wed Mar 28 05:44:28 2018 -0400
+++ b/libgui/src/module.mk	Wed Mar 28 14:07:12 2018 -0700
@@ -106,6 +106,7 @@
   %reldir%/moc-external-editor-interface.cc \
   %reldir%/moc-dialog.cc \
   %reldir%/moc-documentation-dock-widget.cc \
+  %reldir%/moc-documentation.cc \
   %reldir%/moc-files-dock-widget.cc \
   %reldir%/moc-history-dock-widget.cc \
   %reldir%/moc-main-window.cc \
@@ -152,6 +153,7 @@
   %reldir%/dialog.h \
   %reldir%/octave-dock-widget.h \
   %reldir%/documentation-dock-widget.h \
+  %reldir%/documentation.h \
   %reldir%/external-editor-interface.h \
   %reldir%/files-dock-widget.h \
   %reldir%/history-dock-widget.h \
@@ -187,6 +189,7 @@
 %canon_reldir%_%canon_reldir%_la_SOURCES = \
   %reldir%/dialog.cc \
   %reldir%/documentation-dock-widget.cc \
+  %reldir%/documentation.cc \
   %reldir%/external-editor-interface.cc \
   %reldir%/files-dock-widget.cc \
   %reldir%/history-dock-widget.cc \
--- a/libinterp/corefcn/lu.cc	Wed Mar 28 05:44:28 2018 -0400
+++ b/libinterp/corefcn/lu.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -103,14 +103,14 @@
 The matrix is not required to be square.
 
 When called with two or three output arguments and a sparse input matrix,
-@code{lu} does not attempt to perform sparsity preserving column
-permutations.  Called with a fourth output argument, the sparsity
-preserving column transformation @var{Q} is returned, such that
-@code{@var{P} * @var{A} * @var{Q} = @var{L} * @var{U}}.
+@code{lu} does not attempt to perform sparsity preserving column permutations.
+Called with a fourth output argument, the sparsity preserving column
+transformation @var{Q} is returned, such that
+@code{@var{P} * @var{A} * @var{Q} = @var{L} * @var{U}}.  This is the
+@strong{preferred} way to call @code{lu} with sparse input matrices.
 
-Called with a fifth output argument and a sparse input matrix,
-@code{lu} attempts to use a scaling factor @var{R} on the input matrix
-such that
+Called with a fifth output argument and a sparse input matrix, @code{lu}
+attempts to use a scaling factor @var{R} on the input matrix such that
 @code{@var{P} * (@var{R} \ @var{A}) * @var{Q} = @var{L} * @var{U}}.
 This typically leads to a sparser and more stable factorization.
 
@@ -196,10 +196,14 @@
 
           if (nargout < 4)
             {
+              warning_with_id ("Octave:lu:sparse_input",
+                               "lu: function may fail when called with less than 4 output arguments and a sparse input");
+
               ColumnVector Qinit (nc);
               for (octave_idx_type i = 0; i < nc; i++)
                 Qinit(i) = i;
-              octave::math::sparse_lu<SparseMatrix> fact (m, Qinit, thres, false, true);
+              octave::math::sparse_lu<SparseMatrix> fact (m, Qinit, thres,
+                                                          false, true);
 
               if (nargout < 2)
                 retval(0) = fact.Y ();
@@ -261,6 +265,9 @@
 
           if (nargout < 4)
             {
+              warning_with_id ("Octave:lu:sparse_input",
+                               "lu: function may fail when called with less than 4 output arguments and a sparse input");
+
               ColumnVector Qinit (nc);
               for (octave_idx_type i = 0; i < nc; i++)
                 Qinit(i) = i;
@@ -299,7 +306,8 @@
           else
             {
               retval.resize (scale ? 5 : 4);
-              octave::math::sparse_lu<SparseComplexMatrix> fact (m, thres, scale);
+              octave::math::sparse_lu<SparseComplexMatrix> fact (m, thres,
+                                                                 scale);
 
               retval(0) = octave_value (fact.L (),
                                         MatrixType (MatrixType::Lower));
@@ -530,14 +538,12 @@
 %! assert (u, single ([5, 6; 0, 4/5]), sqrt (eps ("single")));
 %! assert (p(:,:), single ([0, 0, 1; 1, 0, 0; 0 1 0]), sqrt (eps ("single")));
 
-%!error lu ()
-%!error <can not define pivoting threshold> lu ([1, 2; 3, 4], 2)
-
 %!testif HAVE_UMFPACK
 %! Bi = [1 2 3 4 5 2 3 6 7 8 4 5 7 8 9];
 %! Bj = [1 3 4 5 6 7 8 9 11 12 13 14 15 16 17];
 %! Bv = [1 1 1 1 1 1 -1 1 1 1 1 -1 1 -1 1];
 %! B = sparse (Bi, Bj, Bv);
+%! warning ("off", "Octave:lu:sparse_input", "local");
 %! [L, U] = lu (B);
 %! assert (L*U, B);
 %! [L, U, P] = lu(B);
@@ -545,6 +551,11 @@
 %! [L, U, P, Q] = lu (B);
 %! assert (P'*L*U*Q', B);
 
+%!error lu ()
+%!warning <function may fail>
+%! [l,u] = lu (sparse (magic (3)));
+%!error <can not define pivoting threshold> lu ([1, 2; 3, 4], 2)
+
 */
 
 static
--- a/libinterp/octave-value/ov-java.cc	Wed Mar 28 05:44:28 2018 -0400
+++ b/libinterp/octave-value/ov-java.cc	Wed Mar 28 14:07:12 2018 -0700
@@ -1848,7 +1848,7 @@
 //! Initializes the fields #jvm, #jvm_attached, #jvm_lib, and
 //! #octave_thread_ID.  To ensure that java is initialized, this method is
 //! used as part of octave functions @c javaObject, @c javaMethod,
-//! @c __java_get__, @c __java_set__, and @c java2mat.
+//! @c __java_get__, @c __java_set__, and @c __java2mat__.
 
 static void
 initialize_java (void)
@@ -3180,9 +3180,9 @@
 #endif
 }
 
-DEFUN (java2mat, args, ,
+DEFUN (__java2mat__, args, ,
        doc: /* -*- texinfo -*-
-@deftypefn {} {} java2mat (@var{javaobj})
+@deftypefn {} {} __java2mat__ (@var{javaobj})
 Undocumented internal function.
 @end deftypefn */)
 {
@@ -3211,7 +3211,7 @@
 
   octave_unused_parameter (args);
 
-  err_disabled_feature ("java2mat", "Java");
+  err_disabled_feature ("__java2mat__", "Java");
 
 #endif
 }
--- a/liboctave/numeric/bsxfun.h	Wed Mar 28 05:44:28 2018 -0400
+++ b/liboctave/numeric/bsxfun.h	Wed Mar 28 14:07:12 2018 -0700
@@ -31,6 +31,7 @@
 #include <string>
 
 #include "dim-vector.h"
+#include "lo-error.h"
 
 inline
 bool
--- a/m4/acinclude.m4	Wed Mar 28 05:44:28 2018 -0400
+++ b/m4/acinclude.m4	Wed Mar 28 14:07:12 2018 -0700
@@ -1835,10 +1835,10 @@
   ## Check for Qt libraries
   case "$qt_version" in
     4)
-      QT_MODULES="QtCore QtGui QtNetwork QtOpenGL"
+      QT_MODULES="QtCore QtGui QtNetwork QtOpenGL QtHelp"
     ;;
     5)
-      QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5OpenGL Qt5PrintSupport"
+      QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5OpenGL Qt5PrintSupport Qt5Help"
     ;;
     *)
       AC_MSG_ERROR([Unrecognized Qt version $qt_version])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/java2mat.m	Wed Mar 28 14:07:12 2018 -0700
@@ -0,0 +1,43 @@
+## Copyright (C) 2018 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} java2mat (@var{javaobj})
+## @code{java2mat} is deprecated and will be removed in Octave version 4.8.
+##
+## For the next two releases, use @code{__java2mat__} if necessary, and file
+## a bug report explaining your programming use of @code{java2mat} and how it
+## can't be done with other Octave functions.
+## @end deftypefn
+
+function retval = java2mat (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "java2mat is obsolete and will be removed from a future version of Octave");
+  endif
+
+  retval = __java2mat__ (varargin{:});
+
+endfunction
+
+
+## No tests needed for alias.
+%!assert (1)
--- a/scripts/deprecated/module.mk	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/deprecated/module.mk	Wed Mar 28 14:07:12 2018 -0700
@@ -6,6 +6,7 @@
   %reldir%/comma.m \
   %reldir%/desktop.m \
   %reldir%/isstr.m \
+  %reldir%/java2mat.m \
   %reldir%/mahalanobis.m \
   %reldir%/md5sum.m \
   %reldir%/octave_config_info.m \
--- a/scripts/deprecated/toascii.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/deprecated/toascii.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,12 +17,12 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} toascii (@var{s})
+## @deftypefn {} {} toascii (@var{str})
 ##
 ## @code{toascii} is deprecated and will be removed in Octave version 4.8.
 ## Use @code{double} instead.
 ##
-## Return ASCII representation of @var{s} in a matrix.
+## Return ASCII representation of @var{str} in a matrix.
 ##
 ## For example:
 ##
--- a/scripts/general/logspace.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/general/logspace.m	Wed Mar 28 14:07:12 2018 -0700
@@ -67,23 +67,23 @@
 
 ## Author: jwe
 
-function retval = logspace (base, limit, n = 50)
+function retval = logspace (a, b, n = 50)
 
   if (nargin != 2 && nargin != 3)
     print_usage ();
   endif
 
-  if (! (isscalar (base) && isscalar (limit) && isscalar (n)))
-    error ("logspace: arguments BASE, LIMIT, and N must be scalars");
+  if (! (isscalar (a) && isscalar (b) && isscalar (n)))
+    error ("logspace: arguments A, B, and N must be scalars");
   endif
 
   npoints = fix (n);
 
-  if (limit == pi)
-    limit = log10 (pi);
+  if (b == pi)
+    b = log10 (pi);
   endif
 
-  retval = 10 .^ (linspace (base, limit, npoints));
+  retval = 10 .^ (linspace (a, b, npoints));
 
 endfunction
 
--- a/scripts/general/private/__splinen__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/general/private/__splinen__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -19,7 +19,7 @@
 ## Undocumented internal function.
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{yi} =} __splinen__ (@var{x}, @var{y}, @var{xi})
+## @deftypefn {} {@var{yi} =} __splinen__ (@var{x}, @var{y}, @var{xi}, @var{extrapval}, @var{f})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/gui/private/__fltk_file_filter__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/gui/private/__fltk_file_filter__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{filterspec} =} __fltk_file_filter__ (@var{filter})
+## @deftypefn {} {@var{filterspec} =} __fltk_file_filter__ (@var{file_filter})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/gui/private/__uigetfile_fltk__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/gui/private/__uigetfile_fltk__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uigetfile_fltk__ ()
+## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uigetfile_fltk__ (@var{filters}, @var{title}, @var{defval}, @var{position}, @var{multiselect}, @var{defdir})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/gui/private/__uiobject_split_args__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/gui/private/__uiobject_split_args__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{p}, @var{args}] =} __uiobject_split_args__ (@var{who}, @var{args}, @var{parent_type}, @var{use_gcf})
+## @deftypefn {} {[@var{p}, @var{args}] =} __uiobject_split_args__ (@var{who}, @var{in_args}, @var{parent_type}, @var{use_gcf})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/gui/private/__uiputfile_fltk__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/gui/private/__uiputfile_fltk__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uiputfile_fltk__ ()
+## @deftypefn {} {[@var{fname}, @var{fpath}, @var{fltidx}] =} __uiputfile_fltk__ (@var{filters}, @var{title}, @var{defval}, @var{position}, @var{tag}, @var{defdir})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/help/__makeinfo__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/help/__makeinfo__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type})
-## @deftypefnx {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}, @var{see_also})
+## @deftypefnx {} {[@var{retval}, @var{status}] =} __makeinfo__ (@var{text}, @var{output_type}, @var{fsee_also})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -34,11 +34,11 @@
 ## macro is expanded, but otherwise the text is unaltered.
 ##
 ## If the optional argument @var{see_also} is present, it is used to expand the
-## Octave specific @t{@@seealso} macro.  This argument must be a function handle,
-## that accepts a cell array of strings as input argument (each elements of the
-## array corresponds to the arguments to the @t{@@seealso} macro), and return
-## the expanded string.  If this argument is not given, the @t{@@seealso} macro
-## will be expanded to the text
+## Octave specific @t{@@seealso} macro.  This argument must be a function
+## handle, that accepts a cell array of strings as input argument (each
+## elements of the array corresponds to the arguments to the @t{@@seealso}
+## macro), and return the expanded string.  If this argument is not given, the
+## @t{@@seealso} macro will be expanded to the text
 ##
 ## @example
 ## See also: arg1, arg2, ...
--- a/scripts/help/warning_ids.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/help/warning_ids.m	Wed Mar 28 14:07:12 2018 -0700
@@ -214,6 +214,13 @@
 ## @item Octave:logical-conversion
 ## By default, the @code{Octave:logical-conversion} warning is enabled.
 ##
+## @item Octave:lu:sparse_input
+## If the @code{Octave:lu:sparse_input} warning is enabled, Octave
+## will warn when the lu function is called with a sparse input and less than
+## four output arguments.  In this case, sparsity-preserving column
+## permutations are not performed and the result may be inaccurate.
+## By default, the @code{Octave:lu:sparse_input} warning is enabled.
+##
 ## @item Octave:missing-glyph
 ## By default, the @code{Octave:missing-glyph} warning is enabled.
 ##
--- a/scripts/miscellaneous/copyfile.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/miscellaneous/copyfile.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,12 +17,16 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2})
-## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@var{f1}, @var{f2}, 'f')
-## Copy the source files or directories @var{f1} to the destination @var{f2}.
+## @deftypefn  {} {} copyfile @var{f1} @var{f2}
+## @deftypefnx {} {} copyfile @var{f1} @var{f2} f
+## @deftypefnx {} {} copyfile (@var{f1}, @var{f2})
+## @deftypefnx {} {} copyfile (@var{f1}, @var{f2}, 'f')
+## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} copyfile (@dots{})
+## Copy the source file(s) or directory @var{f1} to the destination @var{f2}.
 ##
-## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
-## multiple filenames, @var{f2} must be a directory.
+## The name @var{f1} may contain globbing patterns, or may be a cell array of
+## strings.  If @var{f1} expands to multiple filenames, @var{f2} must be a
+## directory.
 ##
 ## When the force flag @qcode{'f'} is given any existing files will be
 ## overwritten without prompting.
--- a/scripts/miscellaneous/mkdir.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/miscellaneous/mkdir.m	Wed Mar 28 14:07:12 2018 -0700
@@ -16,13 +16,15 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {} {} mkdir @var{dir}
-## @deftypefnx {} {} mkdir (@var{parent}, @var{dir})
+## @deftypefn  {} {} mkdir @var{dirname}
+## @deftypefnx {} {} mkdir @var{parent} @var{dirname}
+## @deftypefnx {} {} mkdir (@var{dirname})
+## @deftypefnx {} {} mkdir (@var{parent}, @var{dirname})
 ## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@dots{})
-## Create a directory named @var{dir} in the directory @var{parent},
+## Create a directory named @var{dirname} in the directory @var{parent},
 ## creating any intermediate directories if necessary.
 ##
-## If @var{dir} is a relative path and no @var{parent} directory is specified
+## If @var{dir} is a relative path, and no @var{parent} directory is specified,
 ## then the present working directory is used.
 ##
 ## If successful, @var{status} is 1, and @var{msg} and @var{msgid} are empty
--- a/scripts/miscellaneous/movefile.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/miscellaneous/movefile.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,16 +17,22 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {} {} movefile (@var{f1})
+## @deftypefn  {} {} movefile @var{f1}
+## @deftypefnx {} {} movefile @var{f1} @var{f2}
+## @deftypefnx {} {} movefile @var{f1} @var{f2} f
+## @deftypefnx {} {} movefile (@var{f1})
 ## @deftypefnx {} {} movefile (@var{f1}, @var{f2})
 ## @deftypefnx {} {} movefile (@var{f1}, @var{f2}, 'f')
 ## @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} movefile (@dots{})
-## Move the source files or directories @var{f1} to the destination @var{f2}.
+## Move the source file or directory @var{f1} to the destination @var{f2}.
 ##
-## The name @var{f1} may contain globbing patterns.  If @var{f1} expands to
-## multiple filenames, @var{f2} must be a directory.  If no destination
-## @var{f2} is specified then the destination is the present working directory.
-## If @var{f2} is a filename then @var{f1} is renamed to @var{f2}.
+## The name @var{f1} may contain globbing patterns, or may be a cell array of
+## strings.  If @var{f1} expands to multiple filenames, @var{f2} must be a
+## directory.
+##
+## If no destination @var{f2} is specified then the destination is the present
+## working directory.  If @var{f2} is a filename then @var{f1} is renamed to
+## @var{f2}.
 ##
 ## When the force flag @qcode{'f'} is given any existing files will be
 ## overwritten without prompting.
--- a/scripts/optimization/private/__fdjac__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/optimization/private/__fdjac__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} __fdjac__ (@var{fcn}, @var{x}, @var{fvec}, @var{err})
+## @deftypefn {} {} __fdjac__ (@var{fcn}, @var{x}, @var{fvec}, @var{typicalx}, @var{cdif}, @var{err})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/appearance/__getlegenddata__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/appearance/__getlegenddata__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{hplots}, @var{strings}] =} __getlegenddata__ (@var{h})
+## @deftypefn {} {[@var{hplots}, @var{strings}] =} __getlegenddata__ (@var{hlegend})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/appearance/private/__axis_label__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/appearance/private/__axis_label__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} __axis_label__ (@var{caller}, @var{h}, @var{txt}, @dots{})
+## @deftypefn {} {} __axis_label__ (@var{caller}, @var{hax}, @var{txt}, @dots{})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/draw/private/__errplot__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/draw/private/__errplot__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{h} =} __errplot__ (@var{fstr}, @var{hax}, @dots{})
+## @deftypefn {} {@var{h} =} __errplot__ (@var{caller}, @var{hax}, @dots{})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/draw/private/__interp_cube__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/draw/private/__interp_cube__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -19,7 +19,7 @@
 ## Author: Martin Helm <martin@mhelm.de>
 
 ## -*- texinfo -*-
-## @deftypefn {} {[@var{vxyz}, @var{idx}, @var{frac}] =} __interp_cube__ (@var{caller}, @var{x}, @var{y}, @var{z}, @var{val}, @var{v})
+## @deftypefn {} {[@var{vxyz}, @var{idx}, @var{frac}] =} __interp_cube__ (@var{caller}, @var{x}, @var{y}, @var{z}, @var{val}, @var{v}, @var{req})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/util/__pltopt__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/util/__pltopt__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,11 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} __pltopt__ (@var{caller}, @var{opt})
-## Undocumented internal function.
-## @end deftypefn
-
-## @deftypefn {} {} __pltopt__ (@var{caller}, @var{opt})
+## @deftypefn {} {} __pltopt__ (@var{caller}, @var{opt}, @var{err_on_invalid})
 ##
 ## Decode plot option strings.
 ##
@@ -86,6 +82,7 @@
 ##
 ## The legend may be fixed to include the name of the variable
 ## plotted in some future version of Octave.
+## @end deftypefn
 
 ## Author: jwe
 
--- a/scripts/plot/util/private/__gnuplot_get_var__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/util/private/__gnuplot_get_var__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,7 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{name}, @var{fmt})
+## @deftypefn {} {@var{value} =} __gnuplot_get_var__ (@var{h}, @var{gp_var_name}, @var{fmt})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/plot/util/private/__gnuplot_has_terminal__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/plot/util/private/__gnuplot_has_terminal__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,8 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{has_terminal} =} __gnuplot_has_terminal__ (@var{terminal})
+## @deftypefn  {} {@var{has_terminal} =} __gnuplot_has_terminal__ (@var{term})
+## @deftypefnx {} {@var{has_terminal} =} __gnuplot_has_terminal__ (@var{term}, @var{plot_stream})
 ## Undocumented internal function.
 ## @end deftypefn
 
--- a/scripts/strings/isstring.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/strings/isstring.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,8 +17,8 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} isstring (@var{x})
-## Return true if @var{x} is a string array.
+## @deftypefn {} {} isstring (@var{s})
+## Return true if @var{s} is a string array.
 ##
 ## A string array is a data type that stores strings (row vectors of
 ## characters) at each element in the array.  It is distinct from character
--- a/scripts/testfun/__run_test_suite__.m	Wed Mar 28 05:44:28 2018 -0400
+++ b/scripts/testfun/__run_test_suite__.m	Wed Mar 28 14:07:12 2018 -0700
@@ -17,7 +17,8 @@
 ## <https://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {} {} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs})
+## @deftypefn  {} {} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs})
+## @deftypefnx {} {} __run_test_suite__ (@var{fcndirs}, @var{fixedtestdirs}, @var{topsrcdir}, @var{topbuilddir})
 ## Undocumented internal function.
 ## @end deftypefn