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 ignoredDir - List of directories to be ignored [ {'.svn' 'cvs'} ]
% 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/05/01 16:15:30 $
% 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/ MatlabCodeColorizer, S. Faridani, in C#, 2005:
% <http://www.pitchup.com/matlabcolorizer/>
% 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,...
'ignoredDir', {{'.svn' 'cvs'}}, ...
'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 'ignoreddir'
if iscellstr(pvalue)
options.ignoredDir = pvalue;
elseif ischar(pvalue)
options.ignoredDir = cellstr(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,{'.' '..' options.ignoredDir{:}})}};
end
mfiles = getmfiles(options.mFiles,{},options.recursive,options.ignoredDir);
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,{'.' '..' options.ignoredDir{:}})}};
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', ...
fliplr(deblank(fliplr(splitc{k})))))
if isspace(splitc{k}(1))
nbs = find(diff(isspace(splitc{k}))==-1);
myline = [myline splitc{k}(1:nbs(1))];
splitc{k} = splitc{k}(nbs(1)+1:end);
end
%- 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, ignoredDir)
%- Extract M-files from a list of directories and/or M-files
if nargin < 4, ignoredDir = {}; end
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,{'.' '..' ignoredDir{:}})}};
for j=1:length(d)
mfiles = getmfiles(cellstr(fullfile(mdirs{i},d{j})), ...
mfiles, recursive, ignoredDir);
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 '"']);
system([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,'&','&');
str = strrep(str,'<','<');
str = strrep(str,'>','>');
str = strrep(str,'"','"');
%===============================================================================
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