Hello community,

here is the log from the commit of package octave-forge-doctest for 
openSUSE:Factory checked in at 2018-07-28 12:40:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/octave-forge-doctest (Old)
 and      /work/SRC/openSUSE:Factory/.octave-forge-doctest.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "octave-forge-doctest"

Sat Jul 28 12:40:23 2018 rev:4 rq:624038 version:0.6.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/octave-forge-doctest/octave-forge-doctest.changes    
    2017-02-03 17:51:42.897841757 +0100
+++ 
/work/SRC/openSUSE:Factory/.octave-forge-doctest.new/octave-forge-doctest.changes
   2018-07-28 12:40:26.240429796 +0200
@@ -1,0 +2,18 @@
+Wed Jul 18 07:33:28 UTC 2018 - [email protected]
+
+- Update to version 0.6.1:
+  * Workaround regex bug on ARM (again!).
+- Changes from version 0.6.0:
+  * Tests can now call "clear" and "clear all".
+  * Fixes for running on Octave development versions (upcoming
+    4.4.0).
+  * Minimum supported Octave version is now 4.2.0.  The package no
+    longer has any compiled code and does not include an "evalc"
+    implementation.
+- Update Requires: octave-cli > 4.2.0 is now required.
+- Update file list: pkg no longer installs to libdir.
+- BuildArch: noarch because pkg no longer installs arch dependent
+  binaries.
+- Untar tarball in build dir before running checks.
+
+-------------------------------------------------------------------

Old:
----
  doctest-0.5.0.tar.gz

New:
----
  doctest-0.6.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ octave-forge-doctest.spec ++++++
--- /var/tmp/diff_new_pack.HAoxH5/_old  2018-07-28 12:40:26.728430734 +0200
+++ /var/tmp/diff_new_pack.HAoxH5/_new  2018-07-28 12:40:26.728430734 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package octave-forge-doctest
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,16 +18,17 @@
 
 %define octpkg  doctest
 Name:           octave-forge-%{octpkg}
-Version:        0.5.0
+Version:        0.6.1
 Release:        0
 Summary:        Octave-Forge documentation tests
-License:        GPL-3.0+ and BSD-3-Clause
+License:        GPL-3.0-or-later AND BSD-3-Clause
 Group:          Productivity/Scientific/Math
 Url:            http://octave.sourceforge.net
 Source0:        
http://downloads.sourceforge.net/octave/%{octpkg}-%{version}.tar.gz
 BuildRequires:  gcc-c++
 BuildRequires:  octave-devel
-Requires:       octave-cli >= 4.0.0
+Requires:       octave-cli >= 4.2.0
+BuildArch:      noarch
 
 %description
 The Octave-Forge Doctest package finds specially-formatted blocks of example
@@ -47,6 +48,7 @@
 %octave_pkg_install
 
 %check
+tar -zxvf %{octpkg}-%{version}.tar.gz
 %octave_pkg_test
 
 %post
@@ -58,6 +60,5 @@
 %files
 %defattr(-,root,root)
 %{octpackages_dir}/%{octpkg}-%{version}
-%{octlib_dir}/%{octpkg}-%{version}
 
 %changelog

++++++ doctest-0.5.0.tar.gz -> doctest-0.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/DESCRIPTION 
new/doctest-0.6.1/DESCRIPTION
--- old/doctest-0.5.0/DESCRIPTION       2016-11-14 07:08:14.000000000 +0100
+++ new/doctest-0.6.1/DESCRIPTION       2018-01-04 20:48:27.000000000 +0100
@@ -1,6 +1,6 @@
 Name: doctest
-Version: 0.5.0
-Date: 2016-11-13
+Version: 0.6.1
+Date: 2018-01-04
 Author: various authors
 Maintainer: Colin B. Macdonald <[email protected]>, Michael Walter 
<[email protected]>
 Title: Documentation tests
@@ -9,6 +9,6 @@
  the code and confirms the output is correct.  This can be useful as part of
  a testing framework or simply to ensure that documentation stays up-to-date
  during software development.
-Depends: octave (>= 4.0.0)
+Depends: octave (>= 4.2.0)
 Url: https://github.com/catch22/octave-doctest
 License: BSD-3-Clause
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/NEWS new/doctest-0.6.1/NEWS
--- old/doctest-0.5.0/NEWS      2016-11-14 07:08:14.000000000 +0100
+++ new/doctest-0.6.1/NEWS      2018-01-04 20:48:27.000000000 +0100
@@ -1,3 +1,22 @@
+doctest 0.6.1 (2018-01-04)
+==========================
+
+  * Workaround regex bug on ARM (again!).
+
+
+
+doctest 0.6.0 (2017-12-25)
+==========================
+
+  * Tests can now call "clear" and "clear all".
+
+  * Fixes for running on Octave development versions (upcoming 4.4.0).
+
+  * Minimum supported Octave version is now 4.2.0.  The package no longer
+    has any compiled code and does not include an "evalc" implementation.
+
+
+
 doctest 0.5.0 (2016-11-13)
 ==========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/doctest.m 
new/doctest-0.6.1/inst/doctest.m
--- old/doctest-0.5.0/inst/doctest.m    2016-11-14 07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/doctest.m    2018-01-04 20:48:27.000000000 +0100
@@ -1,6 +1,6 @@
 %% Copyright (c) 2010 Thomas Grenfell Smith
 %% Copyright (c) 2011, 2013-2016 Michael Walter
-%% Copyright (c) 2015-2016 Colin B. Macdonald
+%% Copyright (c) 2015-2017 Colin B. Macdonald
 %%
 %% Redistribution and use in source and binary forms, with or without
 %% modification, are permitted provided that the following conditions are met:
@@ -273,7 +273,7 @@
 [color_ok, color_err, color_warn, reset] = doctest_colors(fid);
 
 % print banner
-fprintf(fid, 'Doctest v0.5.0: this is Free Software without warranty, see 
source.\n\n');
+fprintf(fid, 'Doctest v0.6.1: this is Free Software without warranty, see 
source.\n\n');
 
 
 summary = struct();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_collect.m 
new/doctest-0.6.1/inst/private/doctest_collect.m
--- old/doctest-0.5.0/inst/private/doctest_collect.m    2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_collect.m    2018-01-04 
20:48:27.000000000 +0100
@@ -1,13 +1,19 @@
 function summary = doctest_collect(what, directives, summary, recursive, 
depth, fid)
-% Find and run doctests.
+%DOCTEST_COLLECT  Find and run doctests.
 %
-% The parameter WHAT is the name of a class, directory, function or filename:
+%   The parameter WHAT is the name of a class, directory, function or filename:
 %   * For a directory, calls itself on the contents, recursively if
 %     RECURSIVE is true;
 %   * For a class, all methods are tested;
 %   * When running Octave, it can also be the filename of a Texinfo file.
-%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%
+% Copyright (c) 2010 Thomas Grenfell Smith
+% Copyright (c) 2015 Michael Walter
+% Copyright (c) 2015-2017 Colin B. Macdonald
+% Copyright (c) 2015 Oliver Heimlich
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
 
 % TODO: methods('logical') octave/matlab differ: which behaviour do we want?
 % TODO: what about builtin "test" versus dir "test/"?  Do we prefer dir?
@@ -170,7 +176,7 @@
   end
 
   % run doctest
-  results = doctest_run(target.docstring, directives);
+  results = doctest_run_docstring(target.docstring, directives);
 
   % determine number of tests passed
   num_tests = numel(results);
@@ -233,6 +239,19 @@
     % Octave methods('@foo') gives java error, Matlab just says "No methods"
     what = what(2:end);
   end
+
+  % TODO: workaround github.com/catch22/octave-doctest/issues/135 by
+  % accessing all non-constructor method help text *before* "help obj"
+  if (is_octave ())
+    meths = methods (what);
+    for i=1:numel (meths)
+      if (~ strcmp (meths{i}, what))  % skip @obj/obj
+        name = sprintf ('@%s%s%s', what, filesep (), meths{i});
+        [docstring, format] = get_help_text (name);
+      end
+    end
+  end  % end workaround
+
   % First, "help class".  For classdef, this differs from "help class.class"
   % (general class help vs constructor help).  For old-style classes we will
   % probably end up testing the constructor twice but... meh.
@@ -319,17 +338,40 @@
   % Mark the occurrence of “@example” and “@end example” to be able to find
   % example blocks after conversion from texi to plain text.  Also consider
   % indentation, so we can later correctly unindent the example's content.
-  % Note: uses “@example” instead of “$2” to avoid ARM-specific bug #130.
-  str = regexprep (str, ...
-                   '^([ \t]*)(\@example)(.*)$', ...
-                   [ '$1\@example$3\n', ... % retain original line
-                     '$1###### EXAMPLE START ######'], ...
-                   'lineanchors', 'dotexceptnewline', 'emptymatch');
-  str = regexprep (str, ...
-                   '^([ \t]*)(\@end example)(.*)$', ...
-                   [ '$1###### EXAMPLE STOP ######\n', ...
-                     '$1\@end example$3'], ... % retain original line
-                   'lineanchors', 'dotexceptnewline', 'emptymatch');
+
+  % These should work, but I keep hitting ARM-specific when $1 is empty:
+  % https://savannah.gnu.org/bugs/index.php?52810
+  %str = regexprep (str, ...
+  %                 '^([ \t]*)(\@example)(.*)$', ...
+  %                 [ '$1$2$3\n', ... % retain original line
+  %                   '$1###### EXAMPLE START ######'], ...
+  %                 'lineanchors', 'dotexceptnewline', 'emptymatch');
+  %str = regexprep (str, ...
+  %                 '^([ \t]*)(\@end example)(.*)$', ...
+  %                 [ '$1###### EXAMPLE STOP ######\n', ...
+  %                   '$1$2$3'], ... % retain original line
+  %                 'lineanchors', 'dotexceptnewline', 'emptymatch');
+
+  % Instead we do it manually
+  [S, E, TE, M, T, NM, SP] = regexp (str, '^([ \t]*)(\@example)(.*)$', ...
+                             'lineanchors', 'dotexceptnewline', 'emptymatch');
+  str = SP{1};
+  for i=1:length (T)
+    str = [str ...
+           T{i}{:} sprintf('\n') ...  % retain original line
+           T{i}{1} '###### EXAMPLE START ######' ...
+           SP{i+1}];
+  end
+
+  [S, E, TE, M, T, NM, SP] = regexp (str, '^([ \t]*)(\@end example)(.*)$', ...
+                             'lineanchors', 'dotexceptnewline', 'emptymatch');
+  str = SP{1};
+  for i=1:length (T)
+    str = [str ...
+           T{i}{1} '###### EXAMPLE STOP ######' sprintf('\n') ...
+           T{i}{:} ...  % retain original line
+           SP{i+1}];
+  end
 
   % special comments "@c doctest: cmd" are translated
   % FIXME the expression would also match @@c doctest: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_colors.m 
new/doctest-0.6.1/inst/private/doctest_colors.m
--- old/doctest-0.5.0/inst/private/doctest_colors.m     2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_colors.m     2018-01-04 
20:48:27.000000000 +0100
@@ -1,8 +1,13 @@
 function [color_ok, color_err, color_warn, reset] = doctest_colors(fid)
-% Return terminal color codes to use for current invocation of doctest.
+%DOCTEST_COLORS  Return terminal color codes.
 %
-% FIXME: Shouldn't use colors if stdout is not a TTY.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%   FIXME: Shouldn't use colors if stdout is not a TTY.
+
+%%
+% Copyright (c) 2015 Michael Walter
+% Copyright (c) 2015, 2017 Colin B. Macdonald
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
 
 % by default, no colors
 color_ok = '';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_compare.m 
new/doctest-0.6.1/inst/private/doctest_compare.m
--- old/doctest-0.5.0/inst/private/doctest_compare.m    2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_compare.m    2018-01-04 
20:48:27.000000000 +0100
@@ -1,5 +1,5 @@
 function match = doctest_compare(want, got, normalize_whitespace, ellipsis)
-%DOCTEST_COMPARE check if two strings match
+%DOCTEST_COMPARE  Check if two strings match.
 %
 %   Returns true if string GOT matches the template string WANT.  Basically
 %   WANT and GOT should be identical, except:
@@ -9,7 +9,13 @@
 %   * WANT can have "..."; matches anything in GOT (if ELLIPSIS is true);
 %   * WANT can omit "ans = ";
 %   * various other nonsense of unknown current relevance.
-%
+
+%%
+% Copyright (c) 2010 Thomas Grenfell Smith
+% Copyright (c) 2015 Michael Walter
+% Copyright (c) 2015-2016 Colin B. Macdonald
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
 
 % This looks bad, like hardcoding for lower-case "a href"
 % and a double quote... but that's what MATLAB looks for too.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_datastore.m 
new/doctest-0.6.1/inst/private/doctest_datastore.m
--- old/doctest-0.5.0/inst/private/doctest_datastore.m  1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_datastore.m  2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,44 @@
+function out = doctest_datastore(action, arg)
+%DOCTEST_DATASTORE  Used internally by doctest.
+%
+% Usage:
+%   doctest_datastore(action, arg)
+%       Store variables in a way that survives "clear" and "clear all".
+%
+% See https://gcurrentub.com/catch22/octave-doctest/issues/149 for discussion.
+
+%%
+% Copyright (c) 2017 Colin B. Macdonald
+% Copyright (c) 2017 Michael Walter
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
+
+mlock();
+persistent i tests;
+
+switch lower(action)
+  case 'clear_and_munlock'
+    % don't leave persistent data lying around
+    tests = [];
+    i = [];
+
+    % unlock so that changes to .m file are picked up again
+    munlock();
+
+  case 'set_tests'
+    tests = num2cell(arg); % cell array so it can be heterogeneous
+  case 'get_tests'
+    out = tests;
+
+  case 'set_current_index'
+    i = arg;
+  case 'set_current_test'
+    tests{i} = arg;
+  case 'get_current_test'
+    out = tests{i};
+
+  otherwise
+    error('unexpected action "%s"', action);
+end
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/doctest-0.5.0/inst/private/doctest_default_directives.m 
new/doctest-0.6.1/inst/private/doctest_default_directives.m
--- old/doctest-0.5.0/inst/private/doctest_default_directives.m 2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_default_directives.m 2018-01-04 
20:48:27.000000000 +0100
@@ -1,11 +1,16 @@
 function d = doctest_default_directives(varargin)
-%DOCTEST_DEFAULT_DIRECTIVES  Return/set defaults directives
+%DOCTEST_DEFAULT_DIRECTIVES  Return/set defaults directives.
 %   Possible calling forms:
 %     dirs = doctest_default_directives()
 %     dirs = doctest_default_directives('ellipsis', true)
 %     dirs = doctest_default_directives(dirs, 'ellipsis', true)
 %   See source/documentation for valid directives.
 
+%%
+% Copyright (c) 2015 Colin B. Macdonald
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
+
   defaults.normalize_whitespace = true;
   defaults.ellipsis = true;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/doctest-0.5.0/inst/private/doctest_format_exception.m 
new/doctest-0.6.1/inst/private/doctest_format_exception.m
--- old/doctest-0.5.0/inst/private/doctest_format_exception.m   1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_format_exception.m   2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,31 @@
+function formatted = doctest_format_exception(ex)
+%DOCTEST_FORMAT_EXCEPTION  Used internally by doctest.
+%
+% Usage:
+%   doctest_format_exception(ex)
+%       Given an exception, return error message to be reported.
+
+%%
+% Copyright (c) 2010 Thomas Grenfell Smith
+% Copyright (c) 2015 Colin B. Macdonald
+% Copyright (c) 2015, 2017 Michael Walter
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
+
+% octave?
+if is_octave()
+  formatted = ['??? ' ex.message];
+  return
+end
+
+% matlab!
+if strcmp(ex.stack(1).name, 'doctest_run_tests')
+  % we don't want the report, we just want the message
+  % otherwise it'll talk about evalc, which is not what the user got on
+  % the command line.
+  formatted = ['??? ' ex.message];
+else
+  formatted = ['??? ' ex.getReport('basic')];
+end
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_join_conditions.m 
new/doctest-0.6.1/inst/private/doctest_join_conditions.m
--- old/doctest-0.5.0/inst/private/doctest_join_conditions.m    1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_join_conditions.m    2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,20 @@
+function result = doctest_join_conditions(conditions)
+%DOCTEST_JOIN_CONDITIONS  Used internally by doctest.
+%
+% Usage:
+%   doctest_join_conditions(conditions)
+%       Given a cell array of conditions (represented as strings to be 
eval'ed),
+%       return the string that corresponds to their logical "or".
+
+%%
+% Copyright (c) 2015, 2017 Michael Walter
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
+
+if isempty(conditions)
+  result = 'false';
+else
+  result = strcat('(', strjoin(conditions, ') || ('), ')');
+end
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_run.m 
new/doctest-0.6.1/inst/private/doctest_run.m
--- old/doctest-0.5.0/inst/private/doctest_run.m        2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_run.m        1970-01-01 
01:00:00.000000000 +0100
@@ -1,179 +0,0 @@
-function results = doctest_run(docstring, defaults)
-%DOCTEST_RUN - used internally by doctest
-%
-% Usage:
-%   doctest_run(docstring)
-%       Runs all the examples in the given docstring and returns a
-%       structure with the results from running.
-%
-% The return value is a structure with the following fields:
-%
-% results.source:   the source code that was run
-% results.want:     the desired output
-% results.got:      the output that was recieved
-% results.passed:   whether .want and .got match each other according to
-%       doctest_compare.
-%
-
-% extract tests from docstring
-TEST_RE = [                               % loosely based on Python 2.6 
doctest.py, line 510
-    '(?m)(?-s)'                          ... % options
-    '(?:^ *>> )'                         ... % ">> "
-    '(.*(?:\n *\.\. .*)*)\n'             ... % rest of line + ".. " lines
-    '((?:(?:^ *$\n)?(?!\s*>>).*\S.*\n)*)'];  % the output
-
-tests = [];
-test_matches = regexp(docstring, TEST_RE, 'tokens');
-for i=1:length(test_matches)
-  % each block should be split into source and desired output
-  source = test_matches{i}{1};
-  tests(i).want = test_matches{i}{2};
-
-  % replace initial '..' by '  ' in subsequent lines
-  lines = strsplit(source, '\n');
-  source = lines{1};
-  for j = 2:length(lines)
-    T = regexp(lines{j}, '^\s*(\.\.)(.*)$', 'tokens');
-    assert(length(T) == 1);
-    T = T{1};
-    assert(length(T) == 2);
-    source = sprintf('%s\n   %s', source, T{2});
-  end
-  tests(i).source = source;
-
-  % set default options
-  tests(i).normalize_whitespace = defaults.normalize_whitespace;
-  tests(i).ellipsis = defaults.ellipsis;
-  tests(i).skip = {};
-  tests(i).xfail = {};
-
-  % find and process directives
-  re = [ ...
-    '[#%]\s*doctest:\s+' ... % e.g., "# doctest: "
-    '([\+\-]\w+)'        ... % token for cmd, e.g., "+XSKIP_IF"
-    '(\s*\('             ... % token for code, starting with "("
-      '[^#%\n]+'         ... % no newlines, no comments in code
-    '\))?'];                 % ")" of code, at most one code arg
-  directive_matches = regexp(tests(i).source, re, 'tokens');
-  for j = 1:length(directive_matches)
-    directive = directive_matches{j}{1};
-    if (strcmp('+SKIP_IF', directive) || strcmp('+SKIP_UNLESS', directive) || 
strcmp('+XFAIL_IF', directive) || strcmp('+XFAIL_UNLESS', directive))
-      if length(directive_matches{j}) == 2
-        condition = directive_matches{j}{2};
-      else
-        error('doctest: syntax error, expected %s(varname)', directive);
-      end
-    end
-
-    if strcmp('NORMALIZE_WHITESPACE', directive(2:end))
-      tests(i).normalize_whitespace = strcmp(directive(1), '+');
-    elseif strcmp('ELLIPSIS', directive(2:end))
-      tests(i).ellipsis = strcmp(directive(1), '+');
-    elseif strcmp('+SKIP', directive)
-      tests(i).skip{end + 1} = 'true';
-    elseif strcmp('+SKIP_IF', directive)
-      tests(i).skip{end + 1} = condition;
-    elseif strcmp('+SKIP_UNLESS', directive)
-      tests(i).skip{end + 1} = sprintf('~(%s)', condition);
-    elseif strcmp('+XFAIL', directive)
-      tests(i).xfail{end + 1} = 'true';
-    elseif strcmp('+XFAIL_IF', directive)
-      tests(i).xfail{end + 1} = condition;
-    elseif strcmp('+XFAIL_UNLESS', directive)
-      tests(i).xfail{end + 1} = sprintf('~(%s)', condition);
-    else
-      warning('Doctest:unexpected-directive', 'doctest: ignoring unexpected 
directive %s', directive);
-    end
-  end
-end
-
-% run tests in a local namespace
-results = DOCTEST__run_impl(tests);
-
-end
-
-
-% given a cell array of conditions (represented as strings to be eval'ed),
-% return the string that corresponds to their logical "or".
-function result = DOCTEST__join_conditions(conditions)
-  if isempty(conditions)
-    result = 'false';
-  else
-    result = strcat('(', strjoin(conditions, ') || ('), ')');
-  end
-end
-
-% the following function is used to evaluate all lines of code in same
-% namespace (the one of this invocation of DOCTEST__run_impl)
-function DOCTEST__results = DOCTEST__run_impl(DOCTEST__tests)
-
-% do not split long rows (TODO: how to do this on MATLAB?)
-if is_octave()
-  split_long_rows(0, 'local')
-end
-
-% define test-global constants
-DOCTEST_OCTAVE = is_octave();
-DOCTEST_MATLAB = ~DOCTEST_OCTAVE;
-
-% Octave has [no evalc command](https://savannah.gnu.org/patch/?8033)
-DOCTEST__has_builtin_evalc = exist('evalc', 'builtin');
-
-DOCTEST__results = [];
-for DOCTEST__i = 1:numel(DOCTEST__tests)
-  DOCTEST__result = DOCTEST__tests(DOCTEST__i);
-
-  % determine whether test should be skipped
-  % (careful about Octave bug #46397 to not change the current value of “ans”)
-  eval (strcat ('DOCTEST__result.skip = ', ...
-                 DOCTEST__join_conditions (DOCTEST__result.skip), ...
-                ';'));
-  if (DOCTEST__result.skip)
-     continue
-  end
-
-  % determine whether test is expected to fail
-  % (careful about Octave bug #46397 to not change the current value of “ans”)
-  eval (strcat ('DOCTEST__result.xfail = ', ...
-                 DOCTEST__join_conditions (DOCTEST__result.xfail), ...
-                ';'));
-
-  % evaluate input (structure adapted from a StackOverflow answer by user 
Amro, see http://stackoverflow.com/questions/3283586 and 
http://stackoverflow.com/users/97160/amro)
-  try
-    if (DOCTEST__has_builtin_evalc)
-      DOCTEST__result.got = evalc(DOCTEST__result.source);
-    else
-      DOCTEST__result.got = doctest_evalc(DOCTEST__result.source);
-    end
-  catch DOCTEST__exception
-    DOCTEST__result.got = DOCTEST__format_exception(DOCTEST__exception);
-  end
-
-  % determine if test has passed
-  DOCTEST__result.passed = doctest_compare(DOCTEST__result.want, 
DOCTEST__result.got, DOCTEST__result.normalize_whitespace, 
DOCTEST__result.ellipsis);
-  if DOCTEST__result.xfail
-    DOCTEST__result.passed = ~DOCTEST__result.passed;
-  end
-
-  DOCTEST__results = [DOCTEST__results; DOCTEST__result];
-end
-
-end
-
-
-function formatted = DOCTEST__format_exception(ex)
-
-  if is_octave()
-    formatted = ['??? ' ex.message];
-    return
-  end
-
-  if strcmp(ex.stack(1).name, 'DOCTEST__run_impl')
-    % we don't want the report, we just want the message
-    % otherwise it'll talk about evalc, which is not what the user got on
-    % the command line.
-    formatted = ['??? ' ex.message];
-  else
-    formatted = ['??? ' ex.getReport('basic')];
-  end
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_run_docstring.m 
new/doctest-0.6.1/inst/private/doctest_run_docstring.m
--- old/doctest-0.5.0/inst/private/doctest_run_docstring.m      1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_run_docstring.m      2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,98 @@
+function results = doctest_run_docstring(docstring, defaults)
+%DOCTEST_RUN_DOCSTRING  Used internally by doctest.
+%
+%   Usage: doctest_run_docstring(docstring, defaults)
+%       Extract all the examples in the input docstring into a
+%       structure.  Process various flags and directives that
+%       about each test.  Run the tests in a common namespace.
+%
+%   The return value is a structure with the following fields:
+%
+%   results.source:   the source code that was run
+%   results.want:     the desired output
+%   results.got:      the output that was recieved
+%   results.passed:   whether .want and .got match each other according to
+%                     doctest_compare.
+
+%%
+% Copyright (c) 2010 Thomas Grenfell Smith
+% Copyright (c) 2011, 2015 Michael Walter
+% Copyright (c) 2015-2017 Colin B. Macdonald
+% License: BSD-3-Clause, see doctest.m for details
+
+
+% extract tests from docstring
+TEST_RE = [                               % loosely based on Python 2.6 
doctest.py, line 510
+    '(?m)(?-s)'                          ... % options
+    '(?:^ *>> )'                         ... % ">> "
+    '(.*(?:\n *\.\. .*)*)\n'             ... % rest of line + ".. " lines
+    '((?:(?:^ *$\n)?(?!\s*>>).*\S.*\n)*)'];  % the output
+
+tests = [];
+test_matches = regexp(docstring, TEST_RE, 'tokens');
+for i=1:length(test_matches)
+  % each block should be split into source and desired output
+  source = test_matches{i}{1};
+  tests(i).want = test_matches{i}{2};
+
+  % replace initial '..' by '  ' in subsequent lines
+  lines = strsplit(source, '\n');
+  source = lines{1};
+  for j = 2:length(lines)
+    T = regexp(lines{j}, '^\s*(\.\.)(.*)$', 'tokens');
+    assert(length(T) == 1);
+    T = T{1};
+    assert(length(T) == 2);
+    source = sprintf('%s\n   %s', source, T{2});
+  end
+  tests(i).source = source;
+
+  % set default options
+  tests(i).normalize_whitespace = defaults.normalize_whitespace;
+  tests(i).ellipsis = defaults.ellipsis;
+  tests(i).skip = {};
+  tests(i).xfail = {};
+
+  % find and process directives
+  re = [ ...
+    '[#%]\s*doctest:\s+' ... % e.g., "# doctest: "
+    '([\+\-]\w+)'        ... % token for cmd, e.g., "+XSKIP_IF"
+    '(\s*\('             ... % token for code, starting with "("
+      '[^#%\n]+'         ... % no newlines, no comments in code
+    '\))?'];                 % ")" of code, at most one code arg
+  directive_matches = regexp(tests(i).source, re, 'tokens');
+  for j = 1:length(directive_matches)
+    directive = directive_matches{j}{1};
+    if (strcmp('+SKIP_IF', directive) || strcmp('+SKIP_UNLESS', directive) || 
strcmp('+XFAIL_IF', directive) || strcmp('+XFAIL_UNLESS', directive))
+      if length(directive_matches{j}) == 2
+        condition = directive_matches{j}{2};
+      else
+        error('doctest: syntax error, expected %s(varname)', directive);
+      end
+    end
+
+    if strcmp('NORMALIZE_WHITESPACE', directive(2:end))
+      tests(i).normalize_whitespace = strcmp(directive(1), '+');
+    elseif strcmp('ELLIPSIS', directive(2:end))
+      tests(i).ellipsis = strcmp(directive(1), '+');
+    elseif strcmp('+SKIP', directive)
+      tests(i).skip{end + 1} = 'true';
+    elseif strcmp('+SKIP_IF', directive)
+      tests(i).skip{end + 1} = condition;
+    elseif strcmp('+SKIP_UNLESS', directive)
+      tests(i).skip{end + 1} = sprintf('~(%s)', condition);
+    elseif strcmp('+XFAIL', directive)
+      tests(i).xfail{end + 1} = 'true';
+    elseif strcmp('+XFAIL_IF', directive)
+      tests(i).xfail{end + 1} = condition;
+    elseif strcmp('+XFAIL_UNLESS', directive)
+      tests(i).xfail{end + 1} = sprintf('~(%s)', condition);
+    else
+      warning('Doctest:unexpected-directive', 'doctest: ignoring unexpected 
directive %s', directive);
+    end
+  end
+end
+
+results = doctest_run_tests(tests);
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/doctest_run_tests.m 
new/doctest-0.6.1/inst/private/doctest_run_tests.m
--- old/doctest-0.5.0/inst/private/doctest_run_tests.m  1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/inst/private/doctest_run_tests.m  2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,98 @@
+function DOCTEST__results = doctest_run_tests(DOCTEST__tests)
+%DOCTEST_RUN_TESTS  Used internally by doctest.
+%
+%   Usage:
+%   doctest_run_tests(tests)
+%       Carefully evaluate each test in the "tests" structure in
+%       a common newly-created clean namespace (specifically, this
+%       functions workspace).
+%
+%   The input is a structure with various fields including "tests.source",
+%   the code to be run and "tests.want" the expected output.  Various
+%   other flags such as "tests.xfail" and "tests.ellipsis" effect how
+%   the test is run and how the test output is compared.
+%
+%   The return value is documented in "doctest_run_docstring".
+
+%%
+% Copyright (c) 2010 Thomas Grenfell Smith
+% Copyright (c) 2011, 2015 Michael Walter
+% Copyright (c) 2015-2017 Colin B. Macdonald
+% License: BSD-3-Clause, see doctest.m for details
+
+
+% Implementation note: all internal variables should start with
+% "DOCTEST__" as (1) these will necessarily be exposed to the tests
+% and (2) should not overwrite variables used by ongoing tests.
+
+% do not split long rows (TODO: how to do this on MATLAB?)
+if is_octave()
+  split_long_rows(0, 'local');
+end
+
+% initialize data store (used to preserve state across iterations
+% in the presence of "clear" and "clear all"s in tests)
+doctest_datastore('set_tests', DOCTEST__tests);
+
+for DOCTEST__i = 1:numel(DOCTEST__tests)
+  % from the second iteration on, the only local variable that we can
+  % rely on being present is DOCTEST__i
+  doctest_datastore('set_current_index', DOCTEST__i);
+  DOCTEST__current_test = doctest_datastore('get_current_test');
+
+  % define test-global constants (these are accessible by the tests)
+  DOCTEST_OCTAVE = is_octave();
+  DOCTEST_MATLAB = ~DOCTEST_OCTAVE;
+
+  % determine whether test should be skipped
+  % (careful about Octave bug #46397 to not change the current value of “ans”)
+  eval (strcat ('DOCTEST__current_test.skip = ', ...
+                 doctest_join_conditions(DOCTEST__current_test.skip), ...
+                ';'));
+  if (DOCTEST__current_test.skip)
+     doctest_datastore('set_current_test', DOCTEST__current_test);
+     continue
+  end
+
+  % determine whether test is expected to fail
+  % (careful about Octave bug #46397 to not change the current value of “ans”)
+  eval (strcat ('DOCTEST__current_test.xfail = ', ...
+                 doctest_join_conditions(DOCTEST__current_test.xfail), ...
+                ';'));
+  doctest_datastore('set_current_test', DOCTEST__current_test);
+
+  % run the test code
+  try
+    DOCTEST__got = evalc(DOCTEST__current_test.source);
+  catch DOCTEST__exception
+    DOCTEST__got = doctest_format_exception(DOCTEST__exception);
+  end
+
+  % at this point, we can only rely on the DOCTEST__got variable
+  % being available
+  DOCTEST__current_test = doctest_datastore('get_current_test');
+  DOCTEST__current_test.got = DOCTEST__got;
+
+  % determine if test has passed
+  DOCTEST__current_test.passed = doctest_compare(DOCTEST__current_test.want, 
DOCTEST__current_test.got, DOCTEST__current_test.normalize_whitespace, 
DOCTEST__current_test.ellipsis);
+  if DOCTEST__current_test.xfail
+    DOCTEST__current_test.passed = ~DOCTEST__current_test.passed;
+  end
+
+  doctest_datastore('set_current_test', DOCTEST__current_test);
+end
+
+% retrieve all tests from data store
+tests = doctest_datastore('get_tests');
+doctest_datastore('clear_and_munlock');
+
+% unwrap from cell-array, discarding skips
+%DOCTEST__results = cell2mat(tests);  % fails b/c they have different fields
+DOCTEST__results = [];
+for j=1:numel(tests)
+  if ~any(tests{j}.skip)
+    DOCTEST__results = [DOCTEST__results tests{j}];
+  end
+end
+
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/inst/private/is_octave.m 
new/doctest-0.6.1/inst/private/is_octave.m
--- old/doctest-0.5.0/inst/private/is_octave.m  2016-11-14 07:08:14.000000000 
+0100
+++ new/doctest-0.6.1/inst/private/is_octave.m  2018-01-04 20:48:27.000000000 
+0100
@@ -1,5 +1,10 @@
 function r = is_octave()
-%IS_OCTAVE  Return true if we are running Octave, false for Matlab.
+%IS_OCTAVE  True if we are running Octave, false for Matlab.
+
+%%
+% Copyright (c) 2015 Colin B. Macdonald
+% This is Free Software, BSD-3-Clause, see doctest.m for details.
+
 
 % Timings for different implementations, 10000 calls
 %
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/src/Makefile 
new/doctest-0.6.1/src/Makefile
--- old/doctest-0.5.0/src/Makefile      2016-11-14 07:08:14.000000000 +0100
+++ new/doctest-0.6.1/src/Makefile      1970-01-01 01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-all: doctest_evalc.oct
-
-%.oct: %.cc
-       $(MKOCTFILE) $<
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/src/doctest_evalc.cc 
new/doctest-0.6.1/src/doctest_evalc.cc
--- old/doctest-0.5.0/src/doctest_evalc.cc      2016-11-14 07:08:14.000000000 
+0100
+++ new/doctest-0.6.1/src/doctest_evalc.cc      1970-01-01 01:00:00.000000000 
+0100
@@ -1,87 +0,0 @@
-/*
-  Copyright 2015 Oliver Heimlich
-  
-  This program 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.
-  
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <octave/oct.h>
-#include <octave/parse.h>
-
-DEFUN_DLD (doctest_evalc, args, nargout,
-  "-*- texinfo -*-\n"
-  "@documentencoding UTF-8\n"
-  "@deftypefn  {Loadable Function} {@var{S} =} doctest_evalc (@var{TRY})\n"
-  "@deftypefnx {Loadable Function} {@var{S} =} doctest_evalc (@var{TRY}, 
@var{CATCH})\n"
-  "\n"
-  "Parse the string @var{TRY} and evaluate it as if it were an Octave "
-  "program.  If that fails, evaluate the optional string @var{CATCH}.  The "
-  "string @var{TRY} is evaluated in the current context, so any results "
-  "remain available after @command{doctest_evalc} returns."
-  "\n\n"
-  "This function is like @command{eval}, except any output that would "
-  "normally be written in the console is captured and returned as string "
-  "@var{S}."
-  "\n\n"
-  "@example\n"
-  "@group\n"
-  "s = doctest_evalc (\"t = 42\"), t\n"
-  "  @result{}\n"
-  "    s = t =  42\n\n"
-  "    t =  42\n"
-  "@end group\n"
-  "@end example\n"
-  "@seealso{eval, evalin}\n"
-  "@end deftypefn"
-  )
-{
-  octave_value_list retval;
-
-  int nargin = args.length ();
-
-  if (nargin > 0)
-    {
-      // Redirect stdout to capturing buffer
-      std::ostream & out_stream = octave_stdout;
-      std::ostream & err_stream = std::cerr;
-      out_stream.flush ();
-      err_stream.flush ();
-      std::ostringstream buffer;
-      std::streambuf* old_out_buf = out_stream.rdbuf (buffer.rdbuf ());
-      std::streambuf* old_err_buf = err_stream.rdbuf (buffer.rdbuf ());
-
-      int parse_status = 0;
-
-      octave_value_list tmp = eval_string (args(0).string_value (), false,
-                                           parse_status, 0);
-
-      if (nargin > 1 && (parse_status != 0 || error_state))
-        {
-          error_state = 0;
-
-          tmp = eval_string (args(1).string_value (), false,
-                             parse_status, 0);
-        }
-
-      // Stop capturing buffer and restore stdout
-      out_stream.flush ();
-      err_stream.flush ();
-      retval (0) = buffer.str ();
-      out_stream.rdbuf (old_out_buf);
-      err_stream.rdbuf (old_err_buf);
-    }
-  else
-    print_usage ();
-
-  return retval;
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/test/test_clear.m 
new/doctest-0.6.1/test/test_clear.m
--- old/doctest-0.5.0/test/test_clear.m 1970-01-01 01:00:00.000000000 +0100
+++ new/doctest-0.6.1/test/test_clear.m 2018-01-04 20:48:27.000000000 +0100
@@ -0,0 +1,29 @@
+function test_clear()
+% Easy things first, clearing one variable
+% >> a = 6;
+% >> b = 7;
+% >> clear a
+% >> b
+% b =  7
+% >> a
+% ??? ...ndefined ...
+%
+%
+% Harder:
+% >> clear
+% >> a
+% ??? ...ndefined ...
+%
+%
+% >> a = 4
+% a = 4
+%
+%
+% "clear all" clears stuff inside persistent vars
+% >> clear all
+% >> a
+% ??? ...ndefined ...
+%
+%
+% >> a = 5
+% a = 5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/test/test_clear_all_first.m 
new/doctest-0.6.1/test/test_clear_all_first.m
--- old/doctest-0.5.0/test/test_clear_all_first.m       1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/test/test_clear_all_first.m       2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,10 @@
+function test_clear_all_first()
+% If we "clear all" very early, our implementation may break if
+% subfunctions haven't yet been called.  At least on Octave 4.2.1.
+% >> clear all
+% >> a
+% ??? ...ndefined ...
+%
+%
+% >> a = 6
+% a =  6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/test/test_clear_isoctave.m 
new/doctest-0.6.1/test/test_clear_isoctave.m
--- old/doctest-0.5.0/test/test_clear_isoctave.m        1970-01-01 
01:00:00.000000000 +0100
+++ new/doctest-0.6.1/test/test_clear_isoctave.m        2018-01-04 
20:48:27.000000000 +0100
@@ -0,0 +1,19 @@
+function test_clear_isoctave()
+% Easy things first, clearing one variable
+% >> a = 6
+% a =  6
+%
+%
+% >> clear
+% >> a
+% ??? ...ndefined ...
+%
+%
+% >> clear all
+% >> a
+% ??? ...ndefined ...
+%
+%
+% Make sure these macros are still available after a clear
+% >> a = 42   % doctest: +XFAIL_IF(DOCTEST_OCTAVE | DOCTEST_MATLAB)
+% a =  0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/test/test_multi_return.texinfo 
new/doctest-0.6.1/test/test_multi_return.texinfo
--- old/doctest-0.5.0/test/test_multi_return.texinfo    2016-11-14 
07:08:14.000000000 +0100
+++ new/doctest-0.6.1/test/test_multi_return.texinfo    2018-01-04 
20:48:27.000000000 +0100
@@ -23,9 +23,11 @@
 Here the warning is not part of the result:
 
 @example
-inv (0)
+inv ([1 2; 2 4])
 @print{} warning: ...matrix singular to machine precision...
-@result{} ans = Inf
+@result{} ans =
+   Inf   Inf
+   Inf   Inf
 @end example
 
 Here we have two results:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/doctest-0.5.0/util/convert_comments.m 
new/doctest-0.6.1/util/convert_comments.m
--- old/doctest-0.5.0/util/convert_comments.m   2016-11-14 07:08:14.000000000 
+0100
+++ new/doctest-0.6.1/util/convert_comments.m   1970-01-01 01:00:00.000000000 
+0100
@@ -1,314 +0,0 @@
-%% Copyright (c) 2015 Colin B. Macdonald
-%%
-%% Redistribution and use in source and binary forms, with or without
-%% modification, are permitted provided that the following conditions are met:
-%%
-%% 1. Redistributions of source code must retain the above copyright notice,
-%% this list of conditions and the following disclaimer.
-%%
-%% 2. Redistributions in binary form must reproduce the above copyright notice,
-%% this list of conditions and the following disclaimer in the documentation
-%% and/or other materials provided with the distribution.
-%%
-%% 3. Neither the name of the copyright holder nor the names of its
-%% contributors may be used to endorse or promote products derived from this
-%% software without specific prior written permission.
-%%
-%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-%% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-%% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-%% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-%% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-%% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-%% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-%% POSSIBILITY OF SUCH DAMAGE.
-
-function convert_comments (basedir, subdir, dirout)
-% this slightly strange way of doing things (basedir, subdir) is
-% b/c I must "chdir" into base, but get_first_help_sentence() must
-% not be in the class dir...
-
-  %basedir, subdir, dirout
-  files = dir([basedir subdir]);
-  chdir(basedir)
-
-  for i=1:length(files)
-    if (~files(i).isdir)
-      [dir, name, ext] = fileparts(files(i).name);
-      if (strcmp(ext, '.m'))
-        if isempty(subdir)
-          octname = [name ext];
-        else
-          octname = [subdir '/' name ext];
-        end
-        fprintf('Converting texinfo to Matlab-style documentation: %s\n', 
octname)
-        r = convert_oct_2_ml (octname, [dirout octname]);
-        if ~r
-          [status, msg, msgid] = copyfile (octname, [dirout octname], 'f');
-          if (status ~= 1)
-            error(msg)
-          end
-          fprintf('**** COPYING %s UNMODIFIED ****\n', octname)
-        end
-      end
-    end
-  end
-end
-
-
-
-
-function success = convert_oct_2_ml (fname, foutname)
-
-  [dir, fcn, ext] = fileparts(fname);
-
-  newl = sprintf('\n');
-
-  [fi,msg] = fopen(fname, 'r');
-  if (fi < 0)
-    error(msg)
-  end
-
-  ins = {}; i = 0;
-  while (1)
-    temp = fgets(fi);
-    if ~ischar(temp) && temp == -1
-      break
-    end
-    i = i + 1;
-    ins{i} = temp;
-    % todo, possible strip newl
-  end
-
-  fclose(fi);
-
-  % trim newlines
-  ins = deblank(ins);
-
-
-  %% find the actual function [] = ... line
-  Nfcn = [];
-  for i = 1:length(ins)
-    I = strfind (ins{i}, 'function');
-    if ~isempty(I) && I(1) == 1
-      %disp ('found function header')
-      Nfcn = i;
-      break
-    end
-  end
-  if isempty(Nfcn)
-    disp('AFAICT, this is a script, not a function')
-    success = false;
-    return
-  end
-
-
-  %% copyright block
-  [cr,N] = findblock(ins, 1);
-  if (Nfcn < N)
-    warning('function header in first block (where copyright block should be), 
not converting')
-    success = false;
-    return
-  end
-  cr = ltrim(cr, 3);
-
-  % cut 2nd line if empty
-  if isempty(cr{2})
-    cr2 = cell(1,length(cr)-1);
-    cr2(1) = cr(1);
-    cr2(2:end) = cr(3:end);
-    cr = cr2;
-  end
-
-  cr = prepend_each_line(cr, '%', ' ');
-  cr{1} = ['%' cr{1}];
-  copyright_summary = 'This is free software, see .m file for license.';
-
-
-  %% use block
-  % we don't parse this, just call get_help_text
-  temp = ins{N};
-  if ~strcmp(temp, '%% -*- texinfo -*-')
-    error('can''t find the texinfo line, aborting')
-    %success = false;
-    %return
-  end
-
-  %% the "lookfor" line
-  lookforstr = get_first_help_sentence (fname);
-  if (~isempty(strfind(lookforstr, newl)))
-    lookforstr
-    error('lookfor string contains newline: missing period? too long? some 
other issue?')
-    %success = false;
-    %return
-  end
-  if (length(lookforstr) > 76)
-    error(sprintf('lookfor string of length %d deemed too long', 
length(lookforstr)))
-  end
-
-
-  %% get the texinfo source, and format it
-  [text, form] = get_help_text(fname);
-  if ~strcmp(form, 'texinfo')
-    text
-    form
-    error('formatted incorrectly, help text not texinfo')
-  end
-
-  % Doctest diary-mode compatibility: force two blank lines after example.
-  % Final "\n\n" is incase text immediately follows "@end example".
-  text = regexprep(text, '(^\s*)(@end example\n)', '$1$2 @*\n\n',
-                   'lineanchors');
-
-  usestr = __makeinfo__(text, 'plain text');
-
-
-  %% remove the lookforstr from the text
-  I = strfind(usestr, lookforstr);
-  if length(I) ~= 1
-    I
-    lookforstr
-    usestr
-    error('too many lookfor lines?')
-  end
-  len = length(lookforstr);
-  J = I + len;
-
-  % if usestr has only a lookfor line then no need to see what's next
-  if (J < length(usestr))
-    % find next non-empty char
-    %while isspace(usestr(J))
-    %  J = J + 1;
-    %end
-
-    % let's be more conservative trim newline in usual case:
-    if ~isspace(usestr(J))
-      error('no space or newline after lookfor line?');
-    end
-    J = J + 1;
-  end
-
-  usestr = usestr([1:(I-1) J:end]);
-
-  use = strsplit(usestr, newl, 'CollapseDelimiters', false);
-
-  %% remove this string
-  % and make sure these lines have the correct function name
-  remstr = '-- Function File: ';
-  for i=1:length(use)
-    if strfind(use{i}, remstr);
-      if isempty(strfind(use{i}, [' ' fcn]))
-        error('function @deftypefn line doesn''t include function name')
-      end
-    end
-    use{i} = strrep(use{i}, remstr, '    ');
-  end
-  %usestr = strrep(usestr, lookforstr, '');
-
-  use = ltrim(use, 2);
-  while isempty(use{end})
-    use = use(1:end-1);
-  end
-
-
-  %% the rest
-  N = Nfcn;
-  fcn_line = ins{N};
-
-  % sanity checks
-  I = strfind(ins{N+1}, '%');
-  if ~isempty(I) && I(1) == 1
-    ins{N}
-    ins{N+1}
-    error('possible duplicate comment header following function')
-  end
-
-  therest = ins(N+1:end);
-
-
-
-  %% Output
-  f = fopen(foutname, 'w');
-
-  fdisp(f, fcn_line)
-
-  fprintf(f, '%%%s   %s\n', upper(fcn), lookforstr)
-
-  for i=1:length(use)
-    fprintf(f, '%%%s\n', use{i});
-  end
-
-  fdisp(f, '%');
-  fprintf(f, '%%   %s\n', copyright_summary);
-
-  %fdisp(f, '%');
-  %fdisp(f, '%   [Genereated from a GNU Octave .m file, edit that instead.]');
-
-  %fprintf(f,(s)
-
-  fdisp(f, '');
-  fdisp(f, '%% Note for developers');
-  fdisp(f, '% This file is autogenerated from a GNU Octave .m file.');
-  fdisp(f, '% If you want to edit, please make changes to the original 
instead');
-
-  fdisp(f, '');
-  for i=1:length(cr)
-    fprintf(f, '%s\n', cr{i});
-  end
-
-  fdisp(f, '');
-
-  for i=1:length(therest)
-    fprintf(f, '%s\n', therest{i});
-  end
-
-  fclose(f);
-
-  success = true;
-
-end
-
-
-function [block,endl] = findblock(f, j)
-  block = {}; c = 0;
-  %newl = sprintf('\n');
-  for i = j:length(f)
-    temp = f{i};
-    %if (strcmp(temp, newl))
-    if (isempty(temp))
-      endl = i + 1;
-      break
-    end
-    c = c + 1;
-    block{c} = temp;
-  end
-end
-
-
-function g = ltrim(f, n)
-  g = {};
-  for i = 1:length(f)
-    temp = f{i};
-    if length(temp) < n
-      g{i} = '';
-    else
-      g{i} = substr(temp, n+1);
-    end
-  end
-end
-
-
-function g = prepend_each_line(f, pre, pad)
-  g = {};
-  for i = 1:length(f)
-    temp = f{i};
-    if isempty(temp)
-      g{i} = pre;
-    else
-      g{i} = [pre pad temp];
-    end
-  end
-end


Reply via email to