Documentation Generator for Matlab M-files and Toolboxes in HTML

$0

Description

function m2html(varargin)
%M2HTML - Documentation Generator for Matlab M-files and Toolboxes in HTML
% M2HTML by itself generates an HTML documentation of the Matlab M-files found
% in the direct subdirectories of the current directory. HTML files are 
% written in a 'doc' directory (created if necessary). All the others options
% are set to default (in brackets in the following).
% M2HTML('PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2,...)
% sets multiple option values. The list of option names and default values is:
% o mFiles - Cell array of strings or character array containing the
% list of M-files and/or directories of M-files for which an HTML
% documentation will be built (use relative paths without backtracking).
% Launch M2HTML one directory above the directory your wanting to
% generate documentation for [ <all direct subdirectories> ]
% o htmlDir - Top level directory for generated HTML files [ 'doc' ]
% o recursive - Process subdirectories recursively [ on | {off} ]
% o source - Include Matlab source code in the generated documentation
% [ {on} | off ]
% o download - Add a link to download each M-file separately [ on | {off} ]
% o syntaxHighlighting - Source Code Syntax Highlighting [ {on} | off ]
% o tabs - Replace '\t' (horizontal tab) in source code by n white space
% characters [ 0 ... {4} ... n ]
% o globalHypertextLinks - Hypertext links among separate Matlab 
% directories [ on | {off} ]
% o todo - Create a TODO list in each directory summarizing all the
% '% TODO %' lines found in Matlab code [ on | {off}]
% o graph - Compute a dependency graph using GraphViz [ on | {off}]
% 'dot' required, see <http://www.graphviz.org/>
% o indexFile - Basename of the HTML index file [ 'index' ]
% o extension - Extension of generated HTML files [ '.html' ]
% o template - HTML template name to use [ {'blue'} | 'frame' | ... ]
% o search - Add a PHP search engine [ on | {off}] - beta version!
% o save - Save current state after M-files parsing in 'm2html.mat' 
% in directory htmlDir [ on | {off}]
% o load - Load a previously saved '.mat' M2HTML state to generate HTML 
% files once again with possibly other options [ <none> ]
% o verbose - Verbose mode [ {on} | off ]
%
% For more information, please read the M2HTML tutorial and FAQ at:
% <http://www.artefact.tk/software/matlab/m2html/>
%
% Examples:
% >> m2html('mfiles','matlab', 'htmldir','doc');
% >> m2html('mfiles',{'matlab/signal' 'matlab/image'}, 'htmldir','doc');
% >> m2html('mfiles','matlab', 'htmldir','doc', 'recursive','on');
% >> m2html('mfiles','mytoolbox', 'htmldir','doc', 'source','off');
% >> m2html('mfiles','matlab', 'htmldir','doc', 'global','on');
% >> m2html( ... , 'template','frame', 'index','menu');
%
% See also MWIZARD, MDOT, TEMPLATE.

% Copyright (C) 2005 Guillaume Flandin <Guillaume@artefact.tk>
% $Revision: 1.5 $Date: 2005/04/29 16:04:17 $

% 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 2
% of the License, or 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, write to the Free Software
% Foundation Inc, 59 Temple Pl. - Suite 330, Boston, MA 02111-1307, USA.

% Suggestions for improvement and fixes are always welcome, although no
% guarantee is made whether and when they will be implemented.
% Send requests to Guillaume@artefact.tk

% For tips on how to write Matlab code, see:
% * MATLAB Programming Style Guidelines, by R. Johnson:
% <http://www.datatool.com/prod02.htm>
% * For tips on creating help for your m-files 'type help.m'.
% * Matlab documentation on M-file Programming:
% <http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/ch_funh8.html>

% This function uses the Template class so that you can fully customize 
% the output. You can modify .tpl files in templates/blue/ or create new
% templates in a new directory.
% See the template class documentation for more details.
% <http://www.artefact.tk/software/matlab/template/>

% Latest information on M2HTML is available on the web through:
% <http://www.artefact.tk/software/matlab/m2html/>

% Other Matlab to HTML converters available on the web:
% 1/ mat2html.pl, J.C. Kantor, in Perl, 1995: 
% <http://fresh.t-systems-sfr.com/unix/src/www/mat2html>
% 2/ htmltools, B. Alsberg, in Matlab, 1997:
% <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=175>
% 3/ mtree2html2001, H. Pohlheim, in Perl, 1996, 2001:
% <http://www.pohlheim.com/perl_main.html#matlabdocu>
% 4/ MatlabToHTML, T. Kristjansson, binary, 2001:
% <http://www.psi.utoronto.ca/~trausti/MatlabToHTML/MatlabToHTML.html>
% 5/ Highlight, G. Flandin, in Matlab, 2003:
% <http://www.artefact.tk/software/matlab/highlight/>
% 6/ mdoc, P. Brinkmann, in Matlab, 2003:
% <http://www.math.uiuc.edu/~brinkman/software/mdoc/>
% 7/ Ocamaweb, Miriad Technologies, in Ocaml, 2002:
% <http://ocamaweb.sourceforge.net/>
% 8/ Matdoc, M. Kaminsky, in Perl, 2003:
% <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=3498>
% 9/ Matlab itself, The Mathworks Inc, with HELPWIN, DOC and PUBLISH (R14)

%-------------------------------------------------------------------------------
%- Set up options and default parameters
%-------------------------------------------------------------------------------
t0 = clock; % for statistics
msgInvalidPair = 'Bad value for argument: ''%s''';

options = struct('verbose', 1,...
 'mFiles', {{'.'}},...
 'htmlDir', 'doc',...
 'recursive', 0,...
 'source', 1,...
 'download',0,...
 'syntaxHighlighting', 1,...
 'tabs', 4,...
 'globalHypertextLinks', 0,...
 'graph', 0,...
 'todo', 0,...
 'load', 0,...
 'save', 0,...
 'search', 0,...
 'helptocxml', 0,...
 'indexFile', 'index',...
 'extension', '.html',...
 'template', 'blue',...
 'rootdir', pwd,...
 'language', 'english');

if nargin == 1 & isstruct(varargin{1})
 paramlist = [ fieldnames(varargin{1}) ...
 struct2cell(varargin{1}) ]';
 paramlist = { paramlist{:} };
else
 if mod(nargin,2)
 error('Invalid parameter/value pair arguments.');
 end
 paramlist = varargin;
end

optionsnames = lower(fieldnames(options));
for i=1:2:length(paramlist)
 pname = paramlist{i};
 pvalue = paramlist{i+1};
 ind = strmatch(lower(pname),optionsnames);
 if isempty(ind)
 error(['Invalid parameter: ''' pname '''.']);
 elseif length(ind) > 1
 error(['Ambiguous parameter: ''' pname '''.']);
 end
 switch(optionsnames{ind})
 case 'verbose'
 if strcmpi(pvalue,'on')
 options.verbose = 1;
 elseif strcmpi(pvalue,'off')
 options.verbose = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'mfiles'
 if iscellstr(pvalue)
 options.mFiles = pvalue;
 elseif ischar(pvalue)
 options.mFiles = cellstr(pvalue);
 else
 error(sprintf(msgInvalidPair,pname));
 end
 options.load = 0;
 case 'htmldir'
 if ischar(pvalue)
 if isempty(pvalue),
 options.htmlDir = '.';
 else
 options.htmlDir = pvalue;
 end
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'recursive'
 if strcmpi(pvalue,'on')
 options.recursive = 1;
 elseif strcmpi(pvalue,'off')
 options.recursive = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 options.load = 0;
 case 'source'
 if strcmpi(pvalue,'on')
 options.source = 1;
 elseif strcmpi(pvalue,'off')
 options.source = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'download'
 if strcmpi(pvalue,'on')
 options.download = 1;
 elseif strcmpi(pvalue,'off')
 options.download = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'syntaxhighlighting'
 if strcmpi(pvalue,'on')
 options.syntaxHighlighting = 1;
 elseif strcmpi(pvalue,'off')
 options.syntaxHighlighting = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'tabs'
 if pvalue >= 0
 options.tabs = pvalue;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'globalhypertextlinks'
 if strcmpi(pvalue,'on')
 options.globalHypertextLinks = 1;
 elseif strcmpi(pvalue,'off')
 options.globalHypertextLinks = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 options.load = 0;
 case 'graph'
 if strcmpi(pvalue,'on')
 options.graph = 1;
 elseif strcmpi(pvalue,'off')
 options.graph = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'todo'
 if strcmpi(pvalue,'on')
 options.todo = 1;
 elseif strcmpi(pvalue,'off')
 options.todo = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'load'
 if ischar(pvalue)
 if exist(pvalue) == 7 % directory provided
 pvalue = fullfile(pvalue,'m2html.mat');
 end 
 try
 load(pvalue);
 catch
 error(sprintf('Unable to load %s.', pvalue));
 end
 options.load = 1;
 [dummy options.template] = fileparts(options.template);
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'save'
 if strcmpi(pvalue,'on')
 options.save = 1;
 elseif strcmpi(pvalue,'off')
 options.save = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'search'
 if strcmpi(pvalue,'on')
 options.search = 1;
 elseif strcmpi(pvalue,'off')
 options.search = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'helptocxml'
 if strcmpi(pvalue,'on')
 options.helptocxml = 1;
 elseif strcmpi(pvalue,'off')
 options.helptocxml = 0;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'indexfile'
 if ischar(pvalue)
 options.indexFile = pvalue;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'extension'
 if ischar(pvalue) & pvalue(1) == '.'
 options.extension = pvalue;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'template'
 if ischar(pvalue)
 options.template = pvalue;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 case 'language'
 if ischar(pvalue)
 options.language = pvalue;
 else
 error(sprintf(msgInvalidPair,pname));
 end
 otherwise
 error(['Invalid parameter: ''' pname '''.']);
 end
end

%-------------------------------------------------------------------------------
%- Get template files location
%-------------------------------------------------------------------------------
s = fileparts(which(mfilename));
options.template = fullfile(s,'templates',options.template);
if exist(options.template) ~= 7
 error('[Template] Unknown template.');
end

%-------------------------------------------------------------------------------
%- Get list of M-files
%-------------------------------------------------------------------------------
if ~options.load
 if strcmp(options.mFiles,'.')
 d = dir(pwd); d = {d([d.isdir]).name};
 options.mFiles = {d{~ismember(d,{'.' '..'})}};
 end
 mfiles = getmfiles(options.mFiles,{},options.recursive);
 if ~length(mfiles), fprintf('Nothing to be done.\n'); return; end
 if options.verbose,
 fprintf('Found %d M-files.\n',length(mfiles));
 end
 mfiles = sort(mfiles); % sort list of M-files in dictionary order
end

%-------------------------------------------------------------------------------
%- Get list of (unique) directories and (unique) names
%-------------------------------------------------------------------------------
if ~options.load
 mdirs = {};
 names = {};
 for i=1:length(mfiles)
 [mdirs{i}, names{i}] = fileparts(mfiles{i});
 if isempty(mdirs{i}), mdirs{i} = '.'; end
 end

mdir = unique(mdirs);
 if options.verbose,
 fprintf('Found %d unique Matlab directories.\n',length(mdir));
 end

name = names;
 %name = unique(names); % output is sorted
 %if options.verbose,
 % fprintf('Found %d unique Matlab files.\n',length(name));
 %end
end

%-------------------------------------------------------------------------------
%- Create output directory, if necessary
%-------------------------------------------------------------------------------
if isempty(dir(options.htmlDir)) 
 %- Create the top level output directory 
 if options.verbose 
 fprintf('Creating directory %s...\n',options.htmlDir); 
 end 
 if options.htmlDir(end) == filesep, 
 options.htmlDir(end) = []; 
 end 
 [pathdir, namedir] = fileparts(options.htmlDir); 
 if isempty(pathdir) 
 [status, msg] = mkdir(escapeblank(namedir)); 
 else 
 [status, msg] = mkdir(escapeblank(pathdir), escapeblank(namedir)); 
 end 
 if ~status, error(msg); end 
end

%-------------------------------------------------------------------------------
%- Get synopsis, H1 line, script/function, subroutines, cross-references, todo
%-------------------------------------------------------------------------------
if ~options.load
 synopsis = cell(size(mfiles));
 h1line = cell(size(mfiles));
 subroutine = cell(size(mfiles));
 hrefs = sparse(length(mfiles), length(mfiles));
 todo = struct('mfile',[], 'line',[], 'comment',{{}});
 ismex = zeros(length(mfiles), length(mexexts));
 statlist = {};
 statinfo = sparse(1,length(mfiles));
 kw = cell(size(mfiles));
 freq = cell(size(mfiles));

for i=1:length(mfiles)
 if options.verbose
 fprintf('Processing file %s...',mfiles{i});
 end
 s = mfileparse(mfiles{i}, mdirs, names, options);
 synopsis{i} = s.synopsis;
 h1line{i} = s.h1line;
 subroutine{i} = s.subroutine;
 hrefs(i,:) = s.hrefs;
 todo.mfile = [todo.mfile repmat(i,1,length(s.todo.line))];
 todo.line = [todo.line s.todo.line];
 todo.comment = {todo.comment{:} s.todo.comment{:}};
 ismex(i,:) = s.ismex;
 if options.search
 if options.verbose, fprintf('search...'); end
 [kw{i}, freq{i}] = searchindex(mfiles{i});
 statlist = union(statlist, kw{i});
 end
 if options.verbose, fprintf('\n'); end
 end
 hrefs = hrefs > 0;
 if options.search
 if options.verbose
 fprintf('Creating the search index...');
 end
 statinfo = sparse(length(statlist),length(mfiles));
 for i=1:length(mfiles)
 i1 = find(ismember(statlist, kw{i}));
 i2 = repmat(i,1,length(i1));
 if ~isempty(i1)
 statinfo(sub2ind(size(statinfo),i1,i2)) = freq{i};
 end
 if options.verbose, fprintf('.'); end
 end
 clear kw freq;
 if options.verbose, fprintf('\n'); end
 end
end

%-------------------------------------------------------------------------------
%- Save M-filenames and cross-references for further analysis
%-------------------------------------------------------------------------------
matfilesave = 'm2html.mat';

if options.save
 if options.verbose
 fprintf('Saving MAT file %s...\n',matfilesave);
 end
 save(fullfile(options.htmlDir,matfilesave), ...
 'mfiles', 'names', 'mdirs', 'name', 'mdir', 'options', ...
 'hrefs', 'synopsis', 'h1line', 'subroutine', 'todo', 'ismex', ...
 'statlist', 'statinfo');
end

%-------------------------------------------------------------------------------
%- Setup the output directories
%-------------------------------------------------------------------------------
for i=1:length(mdir)
 if exist(fullfile(options.htmlDir,mdir{i})) ~= 7
 ldir = splitpath(mdir{i});
 for j=1:length(ldir)
 if exist(fullfile(options.htmlDir,ldir{1:j})) ~= 7
 %- Create the output directory
 if options.verbose
 fprintf('Creating directory %s...\n',...
 fullfile(options.htmlDir,ldir{1:j}));
 end
 if j == 1
 [status, msg] = mkdir(escapeblank(options.htmlDir), ...
 escapeblank(ldir{1}));
 else
 [status, msg] = mkdir(escapeblank(options.htmlDir), ...
 escapeblank(fullfile(ldir{1:j})));
 end
 error(msg);
 end
 end
 end
end

%-------------------------------------------------------------------------------
%- Write the master index file
%-------------------------------------------------------------------------------
tpl_master = 'master.tpl';
tpl_master_identifier_nbyline = 4;
php_search = 'search.php';
dotbase = 'graph';

%- Create the HTML template
tpl = template(options.template,'remove');
tpl = set(tpl,'file','TPL_MASTER',tpl_master);
tpl = set(tpl,'block','TPL_MASTER','rowdir','rowdirs');
tpl = set(tpl,'block','TPL_MASTER','idrow','idrows');
tpl = set(tpl,'block','idrow','idcolumn','idcolumns');
tpl = set(tpl,'block','TPL_MASTER','search','searchs');
tpl = set(tpl,'block','TPL_MASTER','graph','graphs');

%- Open for writing the HTML master index file
curfile = fullfile(options.htmlDir,[options.indexFile options.extension]);
if options.verbose
 fprintf('Creating HTML file %s...\n',curfile);
end
fid = openfile(curfile,'w');

%- Set some template variables
tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);
tpl = set(tpl,'var','MASTERPATH', './');
tpl = set(tpl,'var','DIRS', sprintf('%s ',mdir{:}));

%- Print list of unique directories
for i=1:length(mdir)
 tpl = set(tpl,'var','L_DIR',...
 fullurl(mdir{i},[options.indexFile options.extension]));
 tpl = set(tpl,'var','DIR',mdir{i});
 tpl = parse(tpl,'rowdirs','rowdir',1);
end

%- Print full list of M-files (sorted by column)
[sortnames, ind] = sort(names);
m_mod = mod(length(sortnames), tpl_master_identifier_nbyline);
ind = [ind zeros(1,tpl_master_identifier_nbyline-m_mod)];
m_floor = floor(length(ind) / tpl_master_identifier_nbyline);
ind = reshape(ind,m_floor,tpl_master_identifier_nbyline)';

for i=1:prod(size(ind))
 if ind(i)
 tpl = set(tpl,'var','L_IDNAME',...
 fullurl(mdirs{ind(i)},[names{ind(i)} options.extension]));
 tpl = set(tpl,'var','T_IDNAME',mdirs{ind(i)});
 tpl = set(tpl,'var','IDNAME',names{ind(i)});
 tpl = parse(tpl,'idcolumns','idcolumn',1);
 else
 tpl = set(tpl,'var','L_IDNAME','');
 tpl = set(tpl,'var','T_IDNAME','');
 tpl = set(tpl,'var','IDNAME','');
 tpl = parse(tpl,'idcolumns','idcolumn',1);
 end
 if mod(i,tpl_master_identifier_nbyline) == 0
 tpl = parse(tpl,'idrows','idrow',1);
 tpl = set(tpl,'var','idcolumns','');
 end
end

%- Add a search form if necessary
tpl = set(tpl,'var','searchs','');
if options.search
 tpl = set(tpl,'var','PHPFILE',php_search);
 tpl = parse(tpl,'searchs','search',1);
end

%- Link to a full dependency graph, if necessary
tpl = set(tpl,'var','graphs','');
if options.graph & options.globalHypertextLinks & length(mdir) > 1
 tpl = set(tpl,'var','LGRAPH',[dotbase options.extension]);
 tpl = parse(tpl,'graphs','graph',1);
end

%- Print the template in the HTML file
tpl = parse(tpl,'OUT','TPL_MASTER');
fprintf(fid,'%s',get(tpl,'OUT'));
fclose(fid);

%-------------------------------------------------------------------------------
%- Copy template files (CSS, images, ...)
%-------------------------------------------------------------------------------
% Get list of files
d = dir(options.template);
d = {d(~[d.isdir]).name};
% Copy files
for i=1:length(d)
 [p, n, ext] = fileparts(d{i});
 if ~strcmp(ext,'.tpl') ... % do not copy .tpl files
 & ~strcmp([n ext],'Thumbs.db') % do not copy this Windows generated file
 if isempty(dir(fullfile(options.htmlDir,d{i})))
 if options.verbose
 fprintf('Copying template file %s...\n',d{i});
 end
 %- there is a bug with <copyfile> in Matlab 6.5 :
 % http://www.mathworks.com/support/solutions/data/1-1B5JY.html
 %- and <copyfile> does not overwrite files even if newer...
 [status, errmsg] = copyfile(fullfile(options.template,d{i}),...
 options.htmlDir);
 %- If you encounter this bug, please uncomment one of the following lines
 % eval(['!cp -rf ' fullfile(options.template,d{i}) ' ' options.htmlDir]);
 % eval(['!copy ' fullfile(options.template,d{i}) ' ' options.htmlDir]);
 % status = 1;
 if ~status
 if ~isempty(errmsg)
 error(errmsg)
 else
 warning(sprintf(['<copyfile> failed to do its job...\n' ...
 'This is a known bug in Matlab 6.5 (R13).\n' ...
 'See http://www.mathworks.com/support/solutions/data/1-1B5JY.html']));
 end
 end
 end
 end
end

%-------------------------------------------------------------------------------
%- Search engine (index file and PHP script)
%-------------------------------------------------------------------------------
tpl_search = 'search.tpl';
idx_search = 'search.idx';

% TODO % improving the fill in of 'statlist' and 'statinfo'
% TODO % improving the search template file and update the CSS file

if options.search
 %- Write the search index file in output directory
 if options.verbose
 fprintf('Creating Search Index file %s...\n', idx_search);
 end
 docinfo = cell(length(mfiles),2);
 for i=1:length(mfiles)
 docinfo{i,1} = h1line{i};
 docinfo{i,2} = fullurl(mdirs{i}, [names{i} options.extension]);
 end
 doxywrite(fullfile(options.htmlDir,idx_search),statlist,statinfo,docinfo);
 
 %- Create the PHP template
 tpl = template(options.template,'remove');
 tpl = set(tpl,'file','TPL_SEARCH',tpl_search);
 
 %- Open for writing the PHP search script
 curfile = fullfile(options.htmlDir, php_search); 
 if options.verbose
 fprintf('Creating PHP script %s...\n',curfile);
 end
 fid = openfile(curfile,'w');
 
 %- Set template fields
 tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH','./');
 tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);
 tpl = set(tpl,'var','IDXFILE',idx_search);
 tpl = set(tpl,'var','PHPFILE',php_search);
 
 %- Print the template in the HTML file
 tpl = parse(tpl,'OUT','TPL_SEARCH');
 fprintf(fid,'%s',get(tpl,'OUT'));
 fclose(fid);
end

%-------------------------------------------------------------------------------
%- Create <helptoc.xml> needed to display hierarchical entries in Contents panel
%-------------------------------------------------------------------------------
% See http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/guiref16.html
% and http://www.mathworks.com/support/solutions/data/1-18U6Q.html?solution=1-18U6Q

% TODO % display directories in TOC hierarchically instead of linearly
if options.helptocxml
 curfile = fullfile(options.htmlDir, 'helptoc.xml');
 if options.verbose
 fprintf('Creating XML Table-Of-Content %s...\n',curfile);
 end
 fid = openfile(curfile,'w');
 fprintf(fid,'<?xml version=''1.0'' encoding=''ISO-8859-1'' ?>\n');
 fprintf(fid,'<!-- $Date: %s $ -->\n\n', datestr(now,31));
 fprintf(fid,'<toc version="1.0">\n\n');
 fprintf(fid,['<tocitem target="%s" ',...
 'image="$toolbox/matlab/icons/book_mat.gif">%s\n'], ...
 [options.indexFile options.extension],'Toolbox');
 for i=1:length(mdir)
 fprintf(fid,['<tocitem target="%s" ',...
 'image="$toolbox/matlab/icons/reficon.gif">%s\n'], ...
 fullfile(mdir{i}, ...
 [options.indexFile options.extension]),mdir{i});
 if options.graph
 fprintf(fid,['\t<tocitem target="%s" ',...
 'image="$toolbox/matlab/icons/simulinkicon.gif">%s</tocitem>\n'], ...
 fullfile(mdir{i},...
 [dotbase options.extension]),'Dependency Graph');
 end
 if options.todo
 if ~isempty(intersect(find(strcmp(mdir{i},mdirs)),todo.mfile))
 fprintf(fid,['\t<tocitem target="%s" ',...
 'image="$toolbox/matlab/icons/demoicon.gif">%s</tocitem>\n'], ...
 fullfile(mdir{i},...
 ['todo' options.extension]),'Todo list');
 end
 end
 for j=1:length(mdirs)
 if strcmp(mdirs{j},mdir{i})
 curfile = fullfile(mdir{i},...
 [names{j} options.extension]);
 fprintf(fid,'\t<tocitem target="%s">%s</tocitem>\n', ...
 curfile,names{j});
 end
 end
 fprintf(fid,'</tocitem>\n');
 end
 fprintf(fid,'</tocitem>\n');
 fprintf(fid,'\n</toc>\n');
 fclose(fid);
end

%-------------------------------------------------------------------------------
%- Write an index for each output directory
%-------------------------------------------------------------------------------
tpl_mdir = 'mdir.tpl';
tpl_mdir_link = '<a href="%s">%s</a>';
%dotbase defined earlier

%- Create the HTML template
tpl = template(options.template,'remove');
tpl = set(tpl,'file','TPL_MDIR',tpl_mdir);
tpl = set(tpl,'block','TPL_MDIR','row-m','rows-m');
tpl = set(tpl,'block','row-m','mexfile','mex');
tpl = set(tpl,'block','TPL_MDIR','othermatlab','other');
tpl = set(tpl,'block','othermatlab','row-other','rows-other');
tpl = set(tpl,'block','TPL_MDIR','subfolder','subfold');
tpl = set(tpl,'block','subfolder','subdir','subdirs');
tpl = set(tpl,'block','TPL_MDIR','todolist','todolists');
tpl = set(tpl,'block','TPL_MDIR','graph','graphs');
tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);

for i=1:length(mdir)
 %- Open for writing each output directory index file
 curfile = fullfile(options.htmlDir,mdir{i},...
 [options.indexFile options.extension]);
 if options.verbose
 fprintf('Creating HTML file %s...\n',curfile);
 end
 fid = openfile(curfile,'w');

%- Set template fields
 tpl = set(tpl,'var','INDEX', [options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH',backtomaster(mdir{i}));
 tpl = set(tpl,'var','MDIR', mdir{i});
 
 %- Display Matlab m-files, their H1 line and their Mex status
 tpl = set(tpl,'var','rows-m','');
 for j=1:length(mdirs)
 if strcmp(mdirs{j},mdir{i})
 tpl = set(tpl,'var','L_NAME', [names{j} options.extension]);
 tpl = set(tpl,'var','NAME', names{j});
 tpl = set(tpl,'var','H1LINE', h1line{j});
 if any(ismex(j,:))
 tpl = parse(tpl,'mex','mexfile');
 else
 tpl = set(tpl,'var','mex','');
 end
 tpl = parse(tpl,'rows-m','row-m',1);
 end
 end
 
 %- Display other Matlab-specific files (.mat,.mdl,.p)
 tpl = set(tpl,'var','other','');
 tpl = set(tpl,'var','rows-other','');
 w = what(mdir{i}); w = w(1);
 w = {w.mat{:} w.mdl{:} w.p{:}};
 for j=1:length(w)
 tpl = set(tpl,'var','OTHERFILE',w{j});
 tpl = parse(tpl,'rows-other','row-other',1);
 end
 if ~isempty(w)
 tpl = parse(tpl,'other','othermatlab');
 end
 
 %- Display subsequent directories and classes
 tpl = set(tpl,'var','subdirs','');
 tpl = set(tpl,'var','subfold','');
 d = dir(mdir{i});
 d = {d([d.isdir]).name};
 d = {d{~ismember(d,{'.' '..'})}};
 for j=1:length(d)
 if ismember(fullfile(mdir{i},d{j}),mdir)
 tpl = set(tpl,'var','SUBDIRECTORY',...
 sprintf(tpl_mdir_link,...
 fullurl(d{j},[options.indexFile options.extension]),d{j}));
 else
 tpl = set(tpl,'var','SUBDIRECTORY',d{j});
 end
 tpl = parse(tpl,'subdirs','subdir',1);
 end
 if ~isempty(d)
 tpl = parse(tpl,'subfold','subfolder');
 end
 
 %- Link to the TODO list if necessary
 tpl = set(tpl,'var','todolists','');
 if options.todo
 if ~isempty(intersect(find(strcmp(mdir{i},mdirs)),todo.mfile))
 tpl = set(tpl,'var','LTODOLIST',['todo' options.extension]);
 tpl = parse(tpl,'todolists','todolist',1);
 end
 end
 
 %- Link to the dependency graph if necessary
 tpl = set(tpl,'var','graphs','');
 if options.graph
 tpl = set(tpl,'var','LGRAPH',[dotbase options.extension]);
 tpl = parse(tpl,'graphs','graph',1);
 end
 
 %- Print the template in the HTML file
 tpl = parse(tpl,'OUT','TPL_MDIR');
 fprintf(fid,'%s',get(tpl,'OUT'));
 fclose(fid);
end

%-------------------------------------------------------------------------------
%- Write a TODO list file for each output directory, if necessary
%-------------------------------------------------------------------------------
tpl_todo = 'todo.tpl';

if options.todo
 %- Create the HTML template
 tpl = template(options.template,'remove');
 tpl = set(tpl,'file','TPL_TODO',tpl_todo);
 tpl = set(tpl,'block','TPL_TODO','filelist','filelists');
 tpl = set(tpl,'block','filelist','row','rows');
 tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);

for i=1:length(mdir)
 mfilestodo = intersect(find(strcmp(mdir{i},mdirs)),todo.mfile);
 if ~isempty(mfilestodo)
 %- Open for writing each TODO list file
 curfile = fullfile(options.htmlDir,mdir{i},...
 ['todo' options.extension]);
 if options.verbose
 fprintf('Creating HTML file %s...\n',curfile);
 end
 fid = openfile(curfile,'w');
 
 %- Set template fields
 tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i}));
 tpl = set(tpl,'var','MDIR', mdir{i});
 tpl = set(tpl,'var','filelists', '');
 
 for k=1:length(mfilestodo)
 tpl = set(tpl,'var','MFILE',names{mfilestodo(k)});
 tpl = set(tpl,'var','rows','');
 nbtodo = find(todo.mfile == mfilestodo(k));
 for l=1:length(nbtodo)
 tpl = set(tpl,'var','L_NBLINE',...
 [names{mfilestodo(k)} ...
 options.extension ...
 '#l' num2str(todo.line(nbtodo(l)))]);
 tpl = set(tpl,'var','NBLINE',num2str(todo.line(nbtodo(l))));
 tpl = set(tpl,'var','COMMENT',todo.comment{nbtodo(l)});
 tpl = parse(tpl,'rows','row',1);
 end
 tpl = parse(tpl,'filelists','filelist',1);
 end
 
 %- Print the template in the HTML file
 tpl = parse(tpl,'OUT','TPL_TODO');
 fprintf(fid,'%s',get(tpl,'OUT'));
 fclose(fid);
 end
 end
end

%-------------------------------------------------------------------------------
%- Create dependency graphs using GraphViz, if requested
%-------------------------------------------------------------------------------
tpl_graph = 'graph.tpl';
% You may have to modify the following line with Matlab7 (R14) to specify
% the full path to where GraphViz is installed
dot_exec = 'dot';
%dotbase defined earlier

if options.graph
 %- Create the HTML template
 tpl = template(options.template,'remove');
 tpl = set(tpl,'file','TPL_GRAPH',tpl_graph);
 tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);
 
 %- Create a full dependency graph for all directories if possible
 if options.globalHypertextLinks & length(mdir) > 1
 mdotfile = fullfile(options.htmlDir,[dotbase '.dot']);
 if options.verbose
 fprintf('Creating full dependency graph %s...',mdotfile);
 end
 mdot({hrefs, names, options, mdirs}, mdotfile); %mfiles
 calldot(dot_exec, mdotfile, ...
 fullfile(options.htmlDir,[dotbase '.map']), ...
 fullfile(options.htmlDir,[dotbase '.png']));
 if options.verbose, fprintf('\n'); end
 fid = openfile(fullfile(options.htmlDir, [dotbase options.extension]),'w');
 tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH', './');
 tpl = set(tpl,'var','MDIR', 'the whole toolbox');
 tpl = set(tpl,'var','GRAPH_IMG', [dotbase '.png']);
 try % if <dot> failed...
 fmap = openfile(fullfile(options.htmlDir,[dotbase '.map']),'r');
 tpl = set(tpl,'var','GRAPH_MAP', fscanf(fmap,'%c'));
 fclose(fmap);
 end
 tpl = parse(tpl,'OUT','TPL_GRAPH');
 fprintf(fid,'%s', get(tpl,'OUT'));
 fclose(fid);
 end
 
 %- Create a dependency graph for each output directory
 for i=1:length(mdir)
 mdotfile = fullfile(options.htmlDir,mdir{i},[dotbase '.dot']);
 if options.verbose
 fprintf('Creating dependency graph %s...',mdotfile);
 end
 ind = find(strcmp(mdirs,mdir{i}));
 href1 = zeros(length(ind),length(hrefs));
 for j=1:length(hrefs), href1(:,j) = hrefs(ind,j); end
 href2 = zeros(length(ind));
 for j=1:length(ind), href2(j,:) = href1(j,ind); end
 mdot({href2, {names{ind}}, options}, mdotfile); %{mfiles{ind}}
 calldot(dot_exec, mdotfile, ...
 fullfile(options.htmlDir,mdir{i},[dotbase '.map']), ...
 fullfile(options.htmlDir,mdir{i},[dotbase '.png']));
 if options.verbose, fprintf('\n'); end
 fid = openfile(fullfile(options.htmlDir,mdir{i},...
 [dotbase options.extension]),'w');
 tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i}));
 tpl = set(tpl,'var','MDIR', mdir{i});
 tpl = set(tpl,'var','GRAPH_IMG', [dotbase '.png']);
 try % if <dot> failed, no '.map' file has been created
 fmap = openfile(fullfile(options.htmlDir,mdir{i},[dotbase '.map']),'r');
 tpl = set(tpl,'var','GRAPH_MAP', fscanf(fmap,'%c'));
 fclose(fmap);
 end
 tpl = parse(tpl,'OUT','TPL_GRAPH');
 fprintf(fid,'%s', get(tpl,'OUT'));
 fclose(fid);
 end
end

%-------------------------------------------------------------------------------
%- Write an HTML file for each M-file
%-------------------------------------------------------------------------------
%- List of Matlab keywords (output from iskeyword)
matlabKeywords = {'break', 'case', 'catch', 'continue', 'elseif', 'else', ...
 'end', 'for', 'function', 'global', 'if', 'otherwise', ...
 'persistent', 'return', 'switch', 'try', 'while'};
 %'keyboard', 'pause', 'eps', 'NaN', 'Inf'

tpl_mfile = 'mfile.tpl';

tpl_mfile_code = '<a href="%s" class="code" title="%s">%s</a>';
tpl_mfile_keyword = '<span class="keyword">%s</span>';
tpl_mfile_comment = '<span class="comment">%s</span>';
tpl_mfile_string = '<span class="string">%s</span>';
tpl_mfile_aname = '<a name="%s" href="#_subfunctions" class="code">%s</a>';
tpl_mfile_line = '%04d %s\n';

%- Delimiters used in strtok: some of them may be useless (% " .), removed '.'
strtok_delim = sprintf(' \t\n\r(){}[]<>+-*~!|\\@&/,:;="''%%');

%- Create the HTML template
tpl = template(options.template,'remove');
tpl = set(tpl,'file','TPL_MFILE',tpl_mfile);
tpl = set(tpl,'block','TPL_MFILE','pathline','pl');
tpl = set(tpl,'block','TPL_MFILE','mexfile','mex');
tpl = set(tpl,'block','TPL_MFILE','script','scriptfile');
tpl = set(tpl,'block','TPL_MFILE','crossrefcall','crossrefcalls');
tpl = set(tpl,'block','TPL_MFILE','crossrefcalled','crossrefcalleds');
tpl = set(tpl,'block','TPL_MFILE','subfunction','subf');
tpl = set(tpl,'block','subfunction','onesubfunction','onesubf');
tpl = set(tpl,'block','TPL_MFILE','source','thesource');
tpl = set(tpl,'block','TPL_MFILE','download','downloads');
tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
 datestr(now,13)]);

nblinetot = 0;
for i=1:length(mdir)
 for j=1:length(mdirs)
 if strcmp(mdirs{j},mdir{i})
 
 curfile = fullfile(options.htmlDir,mdir{i},...
 [names{j} options.extension]);
 
 %- Copy M-file for download, if necessary
 if options.download
 if options.verbose
 fprintf('Copying M-file %s.m to %s...\n',names{j},...
 fullfile(options.htmlDir,mdir{i}));
 end
 [status, errmsg] = copyfile(mfiles{j},...
 fullfile(options.htmlDir,mdir{i}));
 error(errmsg);
 end
 
 %- Open for writing the HTML file
 if options.verbose
 fprintf('Creating HTML file %s...\n',curfile);
 end
 fid = openfile(curfile,'w');
 if strcmp(names{j},options.indexFile)
 fprintf(['Warning: HTML index file %s will be ' ...
 'overwritten by Matlab function %s.\n'], ...
 [options.indexFile options.extension], mfiles{j});
 end
 
 %- Open for reading the M-file
 fid2 = openfile(mfiles{j},'r');
 
 %- Set some template fields
 tpl = set(tpl,'var','INDEX', [options.indexFile options.extension]);
 tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i}));
 tpl = set(tpl,'var','MDIR', mdirs{j});
 tpl = set(tpl,'var','NAME', names{j});
 tpl = set(tpl,'var','H1LINE', entity(h1line{j}));
 tpl = set(tpl,'var','scriptfile', '');
 if isempty(synopsis{j})
 tpl = set(tpl,'var','SYNOPSIS',get(tpl,'var','script'));
 else
 tpl = set(tpl,'var','SYNOPSIS', synopsis{j});
 end
 s = splitpath(mdir{i});
 tpl = set(tpl,'var','pl','');
 for k=1:length(s)
 c = cell(1,k); for l=1:k, c{l} = filesep; end
 cpath = {s{1:k};c{:}}; cpath = [cpath{:}];
 if ~isempty(cpath), cpath = cpath(1:end-1); end
 if ismember(cpath,mdir)
 tpl = set(tpl,'var','LPATHDIR',[repmat('../',...
 1,length(s)-k) options.indexFile options.extension]);
 else
 tpl = set(tpl,'var','LPATHDIR','#');
 end
 tpl = set(tpl,'var','PATHDIR',s{k});
 tpl = parse(tpl,'pl','pathline',1);
 end
 
 %- Handle mex files
 tpl = set(tpl,'var','mex', '');
 samename = dir(fullfile(mdir{i},[names{j} '.*']));
 samename = {samename.name};
 tpl = set(tpl,'var','MEXTYPE', 'mex');
 for k=1:length(samename)
 [dummy, dummy, ext] = fileparts(samename{k});
 switch ext
 case '.c'
 tpl = set(tpl,'var','MEXTYPE', 'c');
 case {'.cpp' '.c++' '.cxx' '.C'}
 tpl = set(tpl,'var','MEXTYPE', 'c++');
 case {'.for' '.f' '.FOR' '.F'}
 tpl = set(tpl,'var','MEXTYPE', 'fortran');
 otherwise
 %- Unknown mex file source
 end
 end
 [exts, platform] = mexexts;
 mexplatforms = sprintf('%s, ',platform{find(ismex(j,:))});
 if ~isempty(mexplatforms)
 tpl = set(tpl,'var','PLATFORMS', mexplatforms(1:end-2));
 tpl = parse(tpl,'mex','mexfile');
 end
 
 %- Set description template field
 descr = '';
 flagsynopcont = 0;
 flag_seealso = 0;
 while 1
 tline = fgets(fid2);
 if ~ischar(tline), break, end
 tline = entity(fliplr(deblank(fliplr(tline))));
 %- Synopsis line
 if ~isempty(strmatch('function',tline))
 if ~isempty(strmatch('...',fliplr(deblank(tline))))
 flagsynopcont = 1;
 end
 %- H1 line and description
 elseif ~isempty(strmatch('%',tline))
 %- Hypertext links on the "See also" line
 ind = findstr(lower(tline),'see also');
 if ~isempty(ind) | flag_seealso
 %- "See also" only in files in the same directory
 indsamedir = find(strcmp(mdirs{j},mdirs));
 hrefnames = {names{indsamedir}};
 r = deblank(tline);
 flag_seealso = 1; %(r(end) == ',');
 tline = '';
 while 1
 [t,r,q] = strtok(r,sprintf(' \t\n\r.,;%%'));
 tline = [tline q];
 if isempty(t), break, end;
 ii = strcmpi(hrefnames,t);
 if any(ii)
 jj = find(ii);
 tline = [tline sprintf(tpl_mfile_code,...
 [hrefnames{jj(1)} options.extension],...
 synopsis{indsamedir(jj(1))},t)];
 else
 tline = [tline t];
 end
 end
 tline = sprintf('%s\n',tline);
 end
 descr = [descr tline(2:end)];
 elseif isempty(tline)
 if ~isempty(descr), break, end;
 else
 if flagsynopcont
 if isempty(strmatch('...',fliplr(deblank(tline))))
 flagsynopcont = 0;
 end
 else
 break;
 end
 end
 end
 tpl = set(tpl,'var','DESCRIPTION',...
 horztab(descr,options.tabs));
 
 %- Set cross-references template fields:
 % Function called
 ind = find(hrefs(j,:) == 1);
 tpl = set(tpl,'var','crossrefcalls','');
 for k=1:length(ind)
 if strcmp(mdirs{j},mdirs{ind(k)})
 tpl = set(tpl,'var','L_NAME_CALL', ...
 [names{ind(k)} options.extension]);
 else
 tpl = set(tpl,'var','L_NAME_CALL', ...
 fullurl(backtomaster(mdirs{j}), ...
 mdirs{ind(k)}, ...
 [names{ind(k)} options.extension]));
 end
 tpl = set(tpl,'var','SYNOP_CALL', synopsis{ind(k)});
 tpl = set(tpl,'var','NAME_CALL', names{ind(k)});
 tpl = set(tpl,'var','H1LINE_CALL', h1line{ind(k)});
 tpl = parse(tpl,'crossrefcalls','crossrefcall',1);
 end
 % Callers
 ind = find(hrefs(:,j) == 1);
 tpl = set(tpl,'var','crossrefcalleds','');
 for k=1:length(ind)
 if strcmp(mdirs{j},mdirs{ind(k)})
 tpl = set(tpl,'var','L_NAME_CALLED', ...
 [names{ind(k)} options.extension]);
 else
 tpl = set(tpl,'var','L_NAME_CALLED', ...
 fullurl(backtomaster(mdirs{j}),...
 mdirs{ind(k)}, ...
 [names{ind(k)} options.extension]));
 end
 tpl = set(tpl,'var','SYNOP_CALLED', synopsis{ind(k)});
 tpl = set(tpl,'var','NAME_CALLED', names{ind(k)});
 tpl = set(tpl,'var','H1LINE_CALLED', h1line{ind(k)});
 tpl = parse(tpl,'crossrefcalleds','crossrefcalled',1);
 end
 
 %- Set subfunction template field
 tpl = set(tpl,'var',{'subf' 'onesubf'},{'' ''});
 if ~isempty(subroutine{j}) & options.source
 for k=1:length(subroutine{j})
 tpl = set(tpl, 'var', 'L_SUB', ['#_sub' num2str(k)]);
 tpl = set(tpl, 'var', 'SUB', subroutine{j}{k});
 tpl = parse(tpl, 'onesubf', 'onesubfunction',1);
 end
 tpl = parse(tpl,'subf','subfunction');
 end
 subname = extractname(subroutine{j});
 
 %- Link to M-file (for download)
 tpl = set(tpl,'var','downloads','');
 if options.download
 tpl = parse(tpl,'downloads','download',1);
 end
 
 %- Display source code with cross-references
 if options.source & ~strcmpi(names{j},'contents')
 fseek(fid2,0,-1);
 it = 1;
 matlabsource = '';
 nbsubroutine = 1;
 %- Get href function names of this file
 indhrefnames = find(hrefs(j,:) == 1);
 hrefnames = {names{indhrefnames}};
 %- Loop over lines
 while 1
 tline = fgetl(fid2);
 if ~ischar(tline), break, end
 myline = '';
 splitc = splitcode(entity(tline));
 for k=1:length(splitc)
 if isempty(splitc{k})
 elseif ~isempty(strmatch('function',splitc{k}))
 %- Subfunctions definition
 myline = [myline ...
 sprintf(tpl_mfile_aname,...
 ['_sub' num2str(nbsubroutine-1)],splitc{k})];
 nbsubroutine = nbsubroutine + 1;
 elseif splitc{k}(1) == ''''
 myline = [myline ...
 sprintf(tpl_mfile_string,splitc{k})];
 elseif splitc{k}(1) == '%'
 myline = [myline ...
 sprintf(tpl_mfile_comment,deblank(splitc{k}))];
 elseif ~isempty(strmatch('...',splitc{k}))
 myline = [myline sprintf(tpl_mfile_keyword,'...')];
 if ~isempty(splitc{k}(4:end))
 myline = [myline ...
 sprintf(tpl_mfile_comment,splitc{k}(4:end))];
 end
 else
 %- Look for keywords
 r = splitc{k};
 while 1
 [t,r,q] = strtok(r,strtok_delim);
 myline = [myline q];
 if isempty(t), break, end;
 %- Highlight Matlab keywords &
 % cross-references on known functions
 if options.syntaxHighlighting & ...
 any(strcmp(matlabKeywords,t))
 if strcmp('end',t)
 rr = fliplr(deblank(fliplr(r)));
 icomma = strmatch(',',rr);
 isemicolon = strmatch(';',rr);
 if ~(isempty(rr) | ~isempty([icomma isemicolon]))
 myline = [myline t];
 else
 myline = [myline sprintf(tpl_mfile_keyword,t)];
 end
 else
 myline = [myline sprintf(tpl_mfile_keyword,t)];
 end
 elseif any(strcmp(hrefnames,t))
 indt = indhrefnames(logical(strcmp(hrefnames,t)));
 flink = [t options.extension];
 ii = ismember({mdirs{indt}},mdirs{j});
 if ~any(ii)
 % take the first one...
 flink = fullurl(backtomaster(mdirs{j}),...
 mdirs{indt(1)}, flink);
 else
 indt = indt(logical(ii));
 end
 myline = [myline sprintf(tpl_mfile_code,...
 flink, synopsis{indt(1)}, t)];
 elseif any(strcmp(subname,t))
 ii = find(strcmp(subname,t));
 myline = [myline sprintf(tpl_mfile_code,...
 ['#_sub' num2str(ii)],...
 ['sub' subroutine{j}{ii}],t)];
 else
 myline = [myline t];
 end
 end
 end
 end
 matlabsource = [matlabsource sprintf(tpl_mfile_line,it,myline)];
 it = it + 1;
 end
 nblinetot = nblinetot + it - 1;
 tpl = set(tpl,'var','SOURCECODE',...
 horztab(matlabsource,options.tabs));
 tpl = parse(tpl,'thesource','source');
 else
 tpl = set(tpl,'var','thesource','');
 end
 tpl = parse(tpl,'OUT','TPL_MFILE');
 fprintf(fid,'%s',get(tpl,'OUT'));
 fclose(fid2);
 fclose(fid);
 end
 end
end

%-------------------------------------------------------------------------------
%- Display Statistics
%-------------------------------------------------------------------------------
if options.verbose
 prnbline = '';
 if options.source
 prnbline = sprintf('(%d lines) ', nblinetot);
 end
 fprintf('Stats: %d M-files %sin %d directories documented in %d s.\n', ...
 length(mfiles), prnbline, length(mdir), round(etime(clock,t0)));
end

%===============================================================================
function mfiles = getmfiles(mdirs, mfiles, recursive)
 %- Extract M-files from a list of directories and/or M-files

for i=1:length(mdirs)
 currentdir = fullfile(pwd, mdirs{i});
 if exist(currentdir) == 2 % M-file
 mfiles{end+1} = mdirs{i};
 elseif exist(currentdir) == 7 % Directory
 d = dir(fullfile(currentdir, '*.m'));
 d = {d(~[d.isdir]).name};
 for j=1:length(d)
 %- don't take care of files containing ','
 % probably a sccs file...
 if isempty(findstr(',',d{j}))
 mfiles{end+1} = fullfile(mdirs{i}, d{j});
 end
 end
 if recursive
 d = dir(currentdir);
 d = {d([d.isdir]).name};
 d = {d{~ismember(d,{'.' '..'})}};
 for j=1:length(d)
 mfiles = getmfiles(cellstr(fullfile(mdirs{i},d{j})), ...
 mfiles, recursive);
 end
 end
 else
 fprintf('Warning: Unprocessed file %s.\n',mdirs{i});
 if ~isempty(strmatch('/',mdirs{i})) | findstr(':',mdirs{i})
 fprintf(' Use relative paths in ''mfiles'' option\n');
 end 
 end
 end

%===============================================================================
function calldot(dotexec, mdotfile, mapfile, pngfile, opt)
 %- Draw a dependency graph in a PNG image using <dot> from GraphViz

if nargin == 4, opt = ''; end
 try
 %- See <http://www.graphviz.org/>
 % <dot> must be in your system path, see M2HTML FAQ:
 % <http://www.artefact.tk/software/matlab/m2html/faq.php>

eval(['!"' dotexec '" ' opt ' -Tcmap -Tpng "' mdotfile ...
 '" -o "' mapfile ... 
 '" -o "' pngfile '"']);
 % use '!' rather than 'system' for backward compability with Matlab 5.3
 catch % use of '!' prevents errors to be catched...
 fprintf('<dot> failed.');
 end
 
%===============================================================================
function s = backtomaster(mdir)
 %- Provide filesystem path to go back to the root folder

ldir = splitpath(mdir);
 s = repmat('../',1,length(ldir));
 
%===============================================================================
function ldir = splitpath(p)
 %- Split a filesystem path into parts using filesep as separator

ldir = {};
 p = deblank(p);
 while 1
 [t,p] = strtok(p,filesep);
 if isempty(t), break; end
 if ~strcmp(t,'.')
 ldir{end+1} = t;
 end
 end
 if isempty(ldir)
 ldir{1} = '.'; % should be removed
 end

%===============================================================================
function name = extractname(synopsis)
 %- Extract function name in a synopsis

if ischar(synopsis), synopsis = {synopsis}; end
 name = cell(size(synopsis));
 for i=1:length(synopsis)
 ind = findstr(synopsis{i},'=');
 if isempty(ind)
 ind = findstr(synopsis{i},'function');
 s = synopsis{i}(ind(1)+8:end);
 else
 s = synopsis{i}(ind(1)+1:end);
 end
 name{i} = strtok(s,[9:13 32 40]); % white space characters and '('
 end
 if length(name) == 1, name = name{1}; end

%===============================================================================
function f = fullurl(varargin)
 %- Build full url from parts (using '/' and not filesep)
 
 f = strrep(fullfile(varargin{:}),'\','/');

%===============================================================================
function str = escapeblank(str)
 %- Escape white spaces using '\'
 
 str = deblank(fliplr(deblank(fliplr(str))));
 str = strrep(str,' ','\ ');

%===============================================================================
function str = entity(str)
 %- Escape HTML special characters
 %- See http://www.w3.org/TR/html4/charset.html#h-5.3.2
 
 str = strrep(str,'&','&amp;');
 str = strrep(str,'<','&lt;');
 str = strrep(str,'>','&gt;');
 str = strrep(str,'"','&quot;');
 
%===============================================================================
function str = horztab(str,n)
 %- For browsers, the horizontal tab character is the smallest non-zero 
 %- number of spaces necessary to line characters up along tab stops that are
 %- every 8 characters: behaviour obtained when n = 0.
 
 if n > 0
 str = strrep(str,sprintf('\t'),blanks(n));
 end

Reviews

There are no reviews yet.

Be the first to review “Documentation Generator for Matlab M-files and Toolboxes in HTML”
Category: