source: MML/trunk/applications/m2html/m2html.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 10 years ago

Initial import--MML version from SOLEIL@2013

File size: 48.5 KB
Line 
1function m2html(varargin)
2%M2HTML - Documentation Generator for Matlab M-files and Toolboxes in HTML
3%  M2HTML by itself generates an HTML documentation of the Matlab M-files found
4%  in the direct subdirectories of the current directory. HTML files are
5%  written in a 'doc' directory (created if necessary). All the others options
6%  are set to default (in brackets in the following).
7%  M2HTML('PropertyName1',PropertyValue1,'PropertyName2',PropertyValue2,...)
8%  sets multiple option values. The list of option names and default values is:
9%    o mFiles - Cell array of strings or character array containing the
10%       list of M-files and/or directories of M-files for which an HTML
11%       documentation will be built (use relative paths without backtracking).
12%       Launch M2HTML one directory above the directory your wanting to
13%       generate documentation for  [ <all direct subdirectories> ]
14%    o htmlDir - Top level directory for generated HTML files [ 'doc' ]
15%    o recursive - Process subdirectories recursively [ on | {off} ]
16%    o source - Include Matlab source code in the generated documentation
17%                               [ {on} | off ]
18%    o download - Add a link to download each M-file separately [ on | {off} ]
19%    o syntaxHighlighting - Source Code Syntax Highlighting [ {on} | off ]
20%    o tabs - Replace '\t' (horizontal tab) in source code by n white space
21%        characters [ 0 ... {4} ... n ]
22%    o globalHypertextLinks - Hypertext links among separate Matlab
23%        directories [ on | {off} ]
24%    o todo - Create a TODO list in each directory summarizing all the
25%        '% TODO %' lines found in Matlab code [ on | {off}]
26%    o graph - Compute a dependency graph using GraphViz [ on | {off}]
27%        'dot' required, see <http://www.graphviz.org/>
28%    o indexFile - Basename of the HTML index file [ 'index' ]
29%    o extension - Extension of generated HTML files [ '.html' ]
30%    o template - HTML template name to use [ {'blue'} | 'frame' | ... ]
31%    o search - Add a PHP search engine [ on | {off}] - beta version!
32%    o ignoredDir - List of directories to be ignored [ {'.svn' 'cvs'} ]
33%    o save - Save current state after M-files parsing in 'm2html.mat'
34%        in directory htmlDir [ on | {off}]
35%    o load - Load a previously saved '.mat' M2HTML state to generate HTML
36%        files once again with possibly other options [ <none> ]
37%    o verbose - Verbose mode [ {on} | off ]
38%
39%  For more information, please read the M2HTML tutorial and FAQ at:
40%    <http://www.artefact.tk/software/matlab/m2html/>
41%
42%  Examples:
43%    >> m2html('mfiles','matlab', 'htmldir','doc');
44%    >> m2html('mfiles',{'matlab/signal' 'matlab/image'}, 'htmldir','doc');
45%    >> m2html('mfiles','matlab', 'htmldir','doc', 'recursive','on');
46%    >> m2html('mfiles','mytoolbox', 'htmldir','doc', 'source','off');
47%    >> m2html('mfiles','matlab', 'htmldir','doc', 'global','on');
48%    >> m2html( ... , 'template','frame', 'index','menu');
49%
50%  See also MWIZARD, MDOT, TEMPLATE.
51
52%  Copyright (C) 2005 Guillaume Flandin <Guillaume@artefact.tk>
53%  $Revision: 1.5 $Date: 2005/05/01 16:15:30 $
54
55%  This program is free software; you can redistribute it and/or
56%  modify it under the terms of the GNU General Public License
57%  as published by the Free Software Foundation; either version 2
58%  of the License, or any later version.
59%
60%  This program is distributed in the hope that it will be useful,
61%  but WITHOUT ANY WARRANTY; without even the implied warranty of
62%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
63%  GNU General Public License for more details.
64%
65%  You should have received a copy of the GNU General Public License
66%  along with this program; if not, write to the Free Software
67%  Foundation Inc, 59 Temple Pl. - Suite 330, Boston, MA 02111-1307, USA.
68
69%  Suggestions for improvement and fixes are always welcome, although no
70%  guarantee is made whether and when they will be implemented.
71%  Send requests to <Guillaume@artefact.tk>
72
73%  For tips on how to write Matlab code, see:
74%     * MATLAB Programming Style Guidelines, by R. Johnson:
75%       <http://www.datatool.com/prod02.htm>
76%     * For tips on creating help for your m-files 'type help.m'.
77%     * Matlab documentation on M-file Programming:
78%  <http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_prog/ch_funh8.html>
79
80%  This function uses the Template class so that you can fully customize
81%  the output. You can modify .tpl files in templates/blue/ or create new
82%  templates in a new directory.
83%  See the template class documentation for more details.
84%  <http://www.artefact.tk/software/matlab/template/>
85
86%  Latest information on M2HTML is available on the web through:
87%  <http://www.artefact.tk/software/matlab/m2html/>
88
89%  Other Matlab to HTML converters available on the web:
90%  1/ mat2html.pl, J.C. Kantor, in Perl, 1995:
91%     <http://fresh.t-systems-sfr.com/unix/src/www/mat2html>
92%  2/ htmltools, B. Alsberg, in Matlab, 1997:
93%     <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=175>
94%  3/ mtree2html2001, H. Pohlheim, in Perl, 1996, 2001:
95%     <http://www.pohlheim.com/perl_main.html#matlabdocu>
96%  4/ MatlabCodeColorizer, S. Faridani, in C#, 2005:
97%     <http://www.pitchup.com/matlabcolorizer/>
98%  5/ Highlight, G. Flandin, in Matlab, 2003:
99%     <http://www.artefact.tk/software/matlab/highlight/>
100%  6/ mdoc, P. Brinkmann, in Matlab, 2003:
101%     <http://www.math.uiuc.edu/~brinkman/software/mdoc/>
102%  7/ Ocamaweb, Miriad Technologies, in Ocaml, 2002:
103%     <http://ocamaweb.sourceforge.net/>
104%  8/ Matdoc, M. Kaminsky, in Perl, 2003:
105%     <http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=3498>
106%  9/ Matlab itself, The Mathworks Inc, with HELPWIN, DOC and PUBLISH (R14)
107
108%-------------------------------------------------------------------------------
109%- Set up options and default parameters
110%-------------------------------------------------------------------------------
111t0 = clock; % for statistics
112msgInvalidPair = 'Bad value for argument: ''%s''';
113
114options = struct('verbose', 1,...
115                                 'mFiles', {{'.'}},...
116                                 'htmlDir', 'doc',...
117                                 'recursive', 0,...
118                                 'source', 1,...
119                                 'download',0,...
120                                 'syntaxHighlighting', 1,...
121                                 'tabs', 4,...
122                                 'globalHypertextLinks', 0,...
123                                 'graph', 0,...
124                                 'todo', 0,...
125                                 'load', 0,...
126                                 'save', 0,...
127                                 'search', 0,...
128                                 'helptocxml', 0,...
129                                 'indexFile', 'index',...
130                                 'extension', '.html',...
131                                 'template', 'blue',...
132                 'rootdir', pwd,...
133                                 'ignoredDir', {{'.svn' 'cvs'}}, ...
134                 'language', 'english');
135
136if nargin == 1 & isstruct(varargin{1})
137        paramlist = [ fieldnames(varargin{1}) ...
138                                  struct2cell(varargin{1}) ]';
139        paramlist = { paramlist{:} };
140else
141        if mod(nargin,2)
142                error('Invalid parameter/value pair arguments.');
143        end
144        paramlist = varargin;
145end
146
147optionsnames = lower(fieldnames(options));
148for i=1:2:length(paramlist)
149        pname = paramlist{i};
150        pvalue = paramlist{i+1};
151        ind = strmatch(lower(pname),optionsnames);
152        if isempty(ind)
153                error(['Invalid parameter: ''' pname '''.']);
154        elseif length(ind) > 1
155                error(['Ambiguous parameter: ''' pname '''.']);
156        end
157        switch(optionsnames{ind})
158                case 'verbose'
159                        if strcmpi(pvalue,'on')
160                                options.verbose = 1;
161                        elseif strcmpi(pvalue,'off')
162                                options.verbose = 0;
163                        else
164                                error(sprintf(msgInvalidPair,pname));
165                        end
166                case 'mfiles'
167                        if iscellstr(pvalue)
168                                options.mFiles = pvalue;
169                        elseif ischar(pvalue)
170                                options.mFiles = cellstr(pvalue);
171                        else
172                                error(sprintf(msgInvalidPair,pname));
173                        end
174                        options.load = 0;
175                case 'htmldir'
176                        if ischar(pvalue)
177                                if isempty(pvalue),
178                                        options.htmlDir = '.';
179                                else
180                                        options.htmlDir = pvalue;
181                                end
182                        else
183                                error(sprintf(msgInvalidPair,pname));
184                        end
185                case 'recursive'
186                        if strcmpi(pvalue,'on')
187                                options.recursive = 1;
188                        elseif strcmpi(pvalue,'off')
189                                options.recursive = 0;
190                        else
191                                error(sprintf(msgInvalidPair,pname));
192                        end
193                        options.load = 0;
194                case 'source'
195                        if strcmpi(pvalue,'on')
196                                options.source = 1;
197                        elseif strcmpi(pvalue,'off')
198                                options.source = 0;
199                        else
200                                error(sprintf(msgInvalidPair,pname));
201                        end
202                case 'download'
203                        if strcmpi(pvalue,'on')
204                                options.download = 1;
205                        elseif strcmpi(pvalue,'off')
206                                options.download = 0;
207                        else
208                                error(sprintf(msgInvalidPair,pname));
209                        end
210                case 'syntaxhighlighting'
211                        if strcmpi(pvalue,'on')
212                                options.syntaxHighlighting = 1;
213                        elseif strcmpi(pvalue,'off')
214                                options.syntaxHighlighting = 0;
215                        else
216                                error(sprintf(msgInvalidPair,pname));
217                        end
218                case 'tabs'
219                        if pvalue >= 0
220                                options.tabs = pvalue;
221                        else
222                                error(sprintf(msgInvalidPair,pname));
223                        end
224                case 'globalhypertextlinks'
225                        if strcmpi(pvalue,'on')
226                                options.globalHypertextLinks = 1;
227                        elseif strcmpi(pvalue,'off')
228                                options.globalHypertextLinks = 0;
229                        else
230                                error(sprintf(msgInvalidPair,pname));
231                        end
232                        options.load = 0;
233                case 'graph'
234                        if strcmpi(pvalue,'on')
235                                options.graph = 1;
236                        elseif strcmpi(pvalue,'off')
237                                options.graph = 0;
238                        else
239                                error(sprintf(msgInvalidPair,pname));
240                        end
241                case 'todo'
242                        if strcmpi(pvalue,'on')
243                                options.todo = 1;
244                        elseif strcmpi(pvalue,'off')
245                                options.todo = 0;
246                        else
247                                error(sprintf(msgInvalidPair,pname));
248                        end
249                case 'load'
250                        if ischar(pvalue)
251                if exist(pvalue) == 7 % directory provided
252                    pvalue = fullfile(pvalue,'m2html.mat');
253                end         
254                                try
255                                        load(pvalue);
256                                catch
257                                        error(sprintf('Unable to load %s.', pvalue));
258                                end
259                                options.load = 1;
260                                [dummy options.template] = fileparts(options.template);
261                        else
262                                error(sprintf(msgInvalidPair,pname));
263                        end
264                case 'save'
265                        if strcmpi(pvalue,'on')
266                                options.save = 1;
267                        elseif strcmpi(pvalue,'off')
268                                options.save = 0;
269                        else
270                                error(sprintf(msgInvalidPair,pname));
271                        end
272                case 'search'
273                        if strcmpi(pvalue,'on')
274                                options.search = 1;
275                        elseif strcmpi(pvalue,'off')
276                                options.search = 0;
277                        else
278                                error(sprintf(msgInvalidPair,pname));
279                        end
280                case 'helptocxml'
281                        if strcmpi(pvalue,'on')
282                                options.helptocxml = 1;
283                        elseif strcmpi(pvalue,'off')
284                                options.helptocxml = 0;
285                        else
286                                error(sprintf(msgInvalidPair,pname));
287                        end
288                case 'indexfile'
289                        if ischar(pvalue)
290                                options.indexFile = pvalue;
291                        else
292                                error(sprintf(msgInvalidPair,pname));
293                        end
294                case 'extension'
295                        if ischar(pvalue) & pvalue(1) == '.'
296                                options.extension = pvalue;
297                        else
298                                error(sprintf(msgInvalidPair,pname));
299                        end
300                case 'template'
301                        if ischar(pvalue)
302                                options.template = pvalue;
303                        else
304                                error(sprintf(msgInvalidPair,pname));
305                        end
306                case 'ignoreddir'
307            if iscellstr(pvalue)
308                                options.language = pvalue;
309                        elseif ischar(pvalue)
310                                options.language = cellstr(pvalue);
311                        else
312                                error(sprintf(msgInvalidPair,pname));
313                        end
314        case 'language'
315            if ischar(pvalue)
316                                options.language = pvalue;
317                        else
318                                error(sprintf(msgInvalidPair,pname));
319                        end
320                otherwise
321                        error(['Invalid parameter: ''' pname '''.']);
322        end
323end
324
325%-------------------------------------------------------------------------------
326%- Get template files location
327%-------------------------------------------------------------------------------
328s = fileparts(which(mfilename));
329options.template = fullfile(s,'templates',options.template);
330if exist(options.template) ~= 7
331        error('[Template] Unknown template.');
332end
333
334%-------------------------------------------------------------------------------
335%- Get list of M-files
336%-------------------------------------------------------------------------------
337if ~options.load
338        if strcmp(options.mFiles,'.')
339                d = dir(pwd); d = {d([d.isdir]).name};
340                options.mFiles = {d{~ismember(d,{'.' '..' options.ignoredDir{:}})}};
341        end
342        mfiles = getmfiles(options.mFiles,{},options.recursive,options.ignoredDir);
343        if ~length(mfiles), fprintf('Nothing to be done.\n'); return; end
344        if options.verbose,
345                fprintf('Found %d M-files.\n',length(mfiles));
346        end
347        mfiles = sort(mfiles); % sort list of M-files in dictionary order
348end
349
350%-------------------------------------------------------------------------------
351%- Get list of (unique) directories and (unique) names
352%-------------------------------------------------------------------------------
353if ~options.load
354        mdirs = {};
355        names = {};
356        for i=1:length(mfiles)
357                [mdirs{i}, names{i}] = fileparts(mfiles{i});
358                if isempty(mdirs{i}), mdirs{i} = '.'; end
359        end
360
361        mdir = unique(mdirs);
362        if options.verbose,
363                fprintf('Found %d unique Matlab directories.\n',length(mdir));
364        end
365
366        name = names;
367        %name = unique(names); % output is sorted
368        %if options.verbose,
369        %       fprintf('Found %d unique Matlab files.\n',length(name));
370        %end
371end
372
373%-------------------------------------------------------------------------------
374%- Create output directory, if necessary
375%-------------------------------------------------------------------------------
376if isempty(dir(options.htmlDir))                                                                                       
377        %- Create the top level output directory                                                               
378        if options.verbose                                                                                                     
379                fprintf('Creating directory %s...\n',options.htmlDir);                         
380        end                                                                                                                                   
381        if options.htmlDir(end) == filesep,                                                                   
382                options.htmlDir(end) = [];                                                                             
383        end                                                                                                                                   
384        [pathdir, namedir] = fileparts(options.htmlDir);                                               
385        if isempty(pathdir)                                                                                                   
386                [status, msg] = mkdir(escapeblank(namedir));                                                                   
387        else                                                                                                                                   
388                [status, msg] = mkdir(escapeblank(pathdir), escapeblank(namedir));                                                     
389        end                                                                                                                                   
390        if ~status, error(msg); end                                                                                                                   
391end                                                                                                                                           
392
393%-------------------------------------------------------------------------------
394%- Get synopsis, H1 line, script/function, subroutines, cross-references, todo
395%-------------------------------------------------------------------------------
396if ~options.load
397        synopsis   = cell(size(mfiles));
398        h1line     = cell(size(mfiles));
399        subroutine = cell(size(mfiles));
400        hrefs      = sparse(length(mfiles), length(mfiles));
401        todo       = struct('mfile',[], 'line',[], 'comment',{{}});
402        ismex      = zeros(length(mfiles), length(mexexts));
403        statlist   = {};
404        statinfo   = sparse(1,length(mfiles));
405        kw         = cell(size(mfiles));
406        freq       = cell(size(mfiles));
407
408        for i=1:length(mfiles)
409                if options.verbose
410                        fprintf('Processing file %s...',mfiles{i});
411                end
412                s = mfileparse(mfiles{i}, mdirs, names, options);
413                synopsis{i}   = s.synopsis;
414                h1line{i}     = s.h1line;
415                subroutine{i} = s.subroutine;
416                hrefs(i,:)    = s.hrefs;
417                todo.mfile    = [todo.mfile repmat(i,1,length(s.todo.line))];
418                todo.line     = [todo.line s.todo.line];
419                todo.comment  = {todo.comment{:} s.todo.comment{:}};
420                ismex(i,:)    = s.ismex;
421                if options.search
422                        if options.verbose, fprintf('search...'); end
423                        [kw{i}, freq{i}] = searchindex(mfiles{i});
424                        statlist = union(statlist, kw{i});
425                end
426                if options.verbose, fprintf('\n'); end
427        end
428        hrefs = hrefs > 0;
429        if options.search
430                if options.verbose
431                        fprintf('Creating the search index...');
432                end
433                statinfo = sparse(length(statlist),length(mfiles));
434                for i=1:length(mfiles)
435                        i1 = find(ismember(statlist, kw{i}));
436                        i2 = repmat(i,1,length(i1));
437                        if ~isempty(i1)
438                                statinfo(sub2ind(size(statinfo),i1,i2)) = freq{i};
439                        end
440                        if options.verbose, fprintf('.'); end
441                end
442                clear kw freq;
443                if options.verbose, fprintf('\n'); end
444        end
445end
446
447%-------------------------------------------------------------------------------
448%- Save M-filenames and cross-references for further analysis
449%-------------------------------------------------------------------------------
450matfilesave = 'm2html.mat';
451
452if options.save
453        if options.verbose
454                fprintf('Saving MAT file %s...\n',matfilesave);
455        end
456        save(fullfile(options.htmlDir,matfilesave), ...
457                'mfiles', 'names', 'mdirs', 'name', 'mdir', 'options', ...
458                'hrefs', 'synopsis', 'h1line', 'subroutine', 'todo', 'ismex', ...
459                'statlist', 'statinfo');
460end
461
462%-------------------------------------------------------------------------------
463%- Setup the output directories
464%-------------------------------------------------------------------------------
465for i=1:length(mdir)
466        if exist(fullfile(options.htmlDir,mdir{i})) ~= 7
467                ldir = splitpath(mdir{i});
468                for j=1:length(ldir)
469                        if exist(fullfile(options.htmlDir,ldir{1:j})) ~= 7
470                                %- Create the output directory
471                                if options.verbose
472                                        fprintf('Creating directory %s...\n',...
473                                                        fullfile(options.htmlDir,ldir{1:j}));
474                                end
475                                if j == 1
476                                        [status, msg] = mkdir(escapeblank(options.htmlDir), ...
477                                                escapeblank(ldir{1}));
478                                else
479                                        [status, msg] = mkdir(escapeblank(options.htmlDir), ...
480                                                escapeblank(fullfile(ldir{1:j})));
481                                end
482                                error(msg);
483                        end
484                end
485        end
486end
487
488%-------------------------------------------------------------------------------
489%- Write the master index file
490%-------------------------------------------------------------------------------
491tpl_master = 'master.tpl';
492tpl_master_identifier_nbyline = 4;
493php_search = 'search.php';
494dotbase = 'graph';
495
496%- Create the HTML template
497tpl = template(options.template,'remove');
498tpl = set(tpl,'file','TPL_MASTER',tpl_master);
499tpl = set(tpl,'block','TPL_MASTER','rowdir','rowdirs');
500tpl = set(tpl,'block','TPL_MASTER','idrow','idrows');
501tpl = set(tpl,'block','idrow','idcolumn','idcolumns');
502tpl = set(tpl,'block','TPL_MASTER','search','searchs');
503tpl = set(tpl,'block','TPL_MASTER','graph','graphs');
504
505%- Open for writing the HTML master index file
506curfile = fullfile(options.htmlDir,[options.indexFile options.extension]);
507if options.verbose
508        fprintf('Creating HTML file %s...\n',curfile);
509end
510fid = openfile(curfile,'w');
511
512%- Set some template variables
513tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
514                                                        datestr(now,13)]);
515tpl = set(tpl,'var','MASTERPATH', './');
516tpl = set(tpl,'var','DIRS', sprintf('%s ',mdir{:}));
517
518%- Print list of unique directories
519for i=1:length(mdir)
520        tpl = set(tpl,'var','L_DIR',...
521                          fullurl(mdir{i},[options.indexFile options.extension]));
522        tpl = set(tpl,'var','DIR',mdir{i});
523        tpl = parse(tpl,'rowdirs','rowdir',1);
524end
525
526%- Print full list of M-files (sorted by column)
527[sortnames, ind] = sort(names);
528m_mod = mod(length(sortnames), tpl_master_identifier_nbyline);
529ind = [ind zeros(1,tpl_master_identifier_nbyline-m_mod)];
530m_floor = floor(length(ind) / tpl_master_identifier_nbyline);
531ind = reshape(ind,m_floor,tpl_master_identifier_nbyline)';
532
533for i=1:prod(size(ind))
534        if ind(i)
535                tpl = set(tpl,'var','L_IDNAME',...
536                        fullurl(mdirs{ind(i)},[names{ind(i)} options.extension]));
537                tpl = set(tpl,'var','T_IDNAME',mdirs{ind(i)});
538                tpl = set(tpl,'var','IDNAME',names{ind(i)});
539                tpl = parse(tpl,'idcolumns','idcolumn',1);
540        else
541                tpl = set(tpl,'var','L_IDNAME','');
542                tpl = set(tpl,'var','T_IDNAME','');
543                tpl = set(tpl,'var','IDNAME','');
544                tpl = parse(tpl,'idcolumns','idcolumn',1);
545        end
546        if mod(i,tpl_master_identifier_nbyline) == 0
547                tpl = parse(tpl,'idrows','idrow',1);
548                tpl = set(tpl,'var','idcolumns','');
549        end
550end
551
552%- Add a search form if necessary
553tpl = set(tpl,'var','searchs','');
554if options.search
555        tpl = set(tpl,'var','PHPFILE',php_search);
556        tpl = parse(tpl,'searchs','search',1);
557end
558
559%- Link to a full dependency graph, if necessary
560tpl = set(tpl,'var','graphs','');
561if options.graph & options.globalHypertextLinks & length(mdir) > 1
562    tpl = set(tpl,'var','LGRAPH',[dotbase options.extension]);
563    tpl = parse(tpl,'graphs','graph',1);
564end
565
566%- Print the template in the HTML file
567tpl = parse(tpl,'OUT','TPL_MASTER');
568fprintf(fid,'%s',get(tpl,'OUT'));
569fclose(fid);
570
571%-------------------------------------------------------------------------------
572%- Copy template files (CSS, images, ...)
573%-------------------------------------------------------------------------------
574% Get list of files
575d = dir(options.template);
576d = {d(~[d.isdir]).name};
577% Copy files
578for i=1:length(d)
579        [p, n, ext] = fileparts(d{i});
580        if ~strcmp(ext,'.tpl') ... % do not copy .tpl files
581       & ~strcmp([n ext],'Thumbs.db') % do not copy this Windows generated file
582                if isempty(dir(fullfile(options.htmlDir,d{i})))
583                        if options.verbose
584                                fprintf('Copying template file %s...\n',d{i});
585                        end
586                        %- there is a bug with <copyfile> in Matlab 6.5 :
587                        %   http://www.mathworks.com/support/solutions/data/1-1B5JY.html
588                        %- and <copyfile> does not overwrite files even if newer...
589                        [status, errmsg] = copyfile(fullfile(options.template,d{i}),...
590                                                                                options.htmlDir);
591                        %- If you encounter this bug, please uncomment one of the following lines
592                        % eval(['!cp -rf ' fullfile(options.template,d{i}) ' ' options.htmlDir]);
593                        % eval(['!copy ' fullfile(options.template,d{i}) ' ' options.htmlDir]);
594                        % status = 1;
595                        if ~status
596                                if ~isempty(errmsg)
597                                        error(errmsg)
598                                else
599                                        warning(sprintf(['<copyfile> failed to do its job...\n' ...
600                                'This is a known bug in Matlab 6.5 (R13).\n' ...
601                                'See http://www.mathworks.com/support/solutions/data/1-1B5JY.html']));
602                                end
603                        end
604                end
605        end
606end
607
608%-------------------------------------------------------------------------------
609%- Search engine (index file and PHP script)
610%-------------------------------------------------------------------------------
611tpl_search = 'search.tpl';
612idx_search = 'search.idx';
613
614% TODO % improving the fill in of 'statlist' and 'statinfo'
615% TODO % improving the search template file and update the CSS file
616
617if options.search
618        %- Write the search index file in output directory
619        if options.verbose
620                fprintf('Creating Search Index file %s...\n', idx_search);
621        end
622        docinfo = cell(length(mfiles),2);
623        for i=1:length(mfiles)
624                docinfo{i,1} = h1line{i};
625                docinfo{i,2} = fullurl(mdirs{i}, [names{i} options.extension]);
626        end
627        doxywrite(fullfile(options.htmlDir,idx_search),statlist,statinfo,docinfo);
628       
629        %- Create the PHP template
630        tpl = template(options.template,'remove');
631        tpl = set(tpl,'file','TPL_SEARCH',tpl_search);
632       
633        %- Open for writing the PHP search script
634        curfile = fullfile(options.htmlDir, php_search);
635        if options.verbose
636                fprintf('Creating PHP script %s...\n',curfile);
637        end
638        fid = openfile(curfile,'w');
639       
640        %- Set template fields
641        tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
642        tpl = set(tpl,'var','MASTERPATH','./');
643        tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
644                                                                datestr(now,13)]);
645        tpl = set(tpl,'var','IDXFILE',idx_search);
646        tpl = set(tpl,'var','PHPFILE',php_search);
647       
648        %- Print the template in the HTML file
649        tpl = parse(tpl,'OUT','TPL_SEARCH');
650        fprintf(fid,'%s',get(tpl,'OUT'));
651        fclose(fid);
652end
653
654%-------------------------------------------------------------------------------
655%- Create <helptoc.xml> needed to display hierarchical entries in Contents panel
656%-------------------------------------------------------------------------------
657% See http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/guiref16.html
658% and http://www.mathworks.com/support/solutions/data/1-18U6Q.html?solution=1-18U6Q
659
660% TODO % display directories in TOC hierarchically instead of linearly
661if options.helptocxml
662        curfile = fullfile(options.htmlDir, 'helptoc.xml');
663        if options.verbose
664                fprintf('Creating XML Table-Of-Content %s...\n',curfile);
665        end
666        fid = openfile(curfile,'w');
667        fprintf(fid,'<?xml version=''1.0'' encoding=''ISO-8859-1'' ?>\n');
668        fprintf(fid,'<!-- $Date: %s $ -->\n\n', datestr(now,31));
669        fprintf(fid,'<toc version="1.0">\n\n');
670        fprintf(fid,['<tocitem target="%s" ',...
671                'image="$toolbox/matlab/icons/book_mat.gif">%s\n'], ...
672                [options.indexFile options.extension],'Toolbox');
673        for i=1:length(mdir)
674                fprintf(fid,['<tocitem target="%s" ',...
675                        'image="$toolbox/matlab/icons/reficon.gif">%s\n'], ...
676                        fullfile(mdir{i}, ...
677                                [options.indexFile options.extension]),mdir{i});
678                if options.graph
679                        fprintf(fid,['\t<tocitem target="%s" ',...
680                        'image="$toolbox/matlab/icons/simulinkicon.gif">%s</tocitem>\n'], ...
681                                fullfile(mdir{i},...
682                                [dotbase options.extension]),'Dependency Graph');
683                end
684                if options.todo
685                        if ~isempty(intersect(find(strcmp(mdir{i},mdirs)),todo.mfile))
686                                fprintf(fid,['\t<tocitem target="%s" ',...
687                                'image="$toolbox/matlab/icons/demoicon.gif">%s</tocitem>\n'], ...
688                                        fullfile(mdir{i},...
689                                        ['todo' options.extension]),'Todo list');
690                        end
691                end
692                for j=1:length(mdirs)
693                        if strcmp(mdirs{j},mdir{i})
694                                curfile = fullfile(mdir{i},...
695                                        [names{j} options.extension]);
696                                fprintf(fid,'\t<tocitem target="%s">%s</tocitem>\n', ...
697                                        curfile,names{j});
698                        end
699                end
700                fprintf(fid,'</tocitem>\n');
701        end
702        fprintf(fid,'</tocitem>\n');
703        fprintf(fid,'\n</toc>\n');
704        fclose(fid);
705end
706
707%-------------------------------------------------------------------------------
708%- Write an index for each output directory
709%-------------------------------------------------------------------------------
710tpl_mdir = 'mdir.tpl';
711tpl_mdir_link = '<a href="%s">%s</a>';
712%dotbase defined earlier
713
714%- Create the HTML template
715tpl = template(options.template,'remove');
716tpl = set(tpl,'file','TPL_MDIR',tpl_mdir);
717tpl = set(tpl,'block','TPL_MDIR','row-m','rows-m');
718tpl = set(tpl,'block','row-m','mexfile','mex');
719tpl = set(tpl,'block','TPL_MDIR','othermatlab','other');
720tpl = set(tpl,'block','othermatlab','row-other','rows-other');
721tpl = set(tpl,'block','TPL_MDIR','subfolder','subfold');
722tpl = set(tpl,'block','subfolder','subdir','subdirs');
723tpl = set(tpl,'block','TPL_MDIR','todolist','todolists');
724tpl = set(tpl,'block','TPL_MDIR','graph','graphs');
725tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
726                                                        datestr(now,13)]);
727
728for i=1:length(mdir)
729        %- Open for writing each output directory index file
730        curfile = fullfile(options.htmlDir,mdir{i},...
731                                           [options.indexFile options.extension]);
732        if options.verbose
733                fprintf('Creating HTML file %s...\n',curfile);
734        end
735        fid = openfile(curfile,'w');
736
737        %- Set template fields
738        tpl = set(tpl,'var','INDEX',     [options.indexFile options.extension]);
739        tpl = set(tpl,'var','MASTERPATH',backtomaster(mdir{i}));
740        tpl = set(tpl,'var','MDIR',      mdir{i});
741       
742        %- Display Matlab m-files, their H1 line and their Mex status
743        tpl = set(tpl,'var','rows-m','');
744        for j=1:length(mdirs)
745                if strcmp(mdirs{j},mdir{i})
746                        tpl = set(tpl,'var','L_NAME', [names{j} options.extension]);
747                        tpl = set(tpl,'var','NAME',   names{j});
748                        tpl = set(tpl,'var','H1LINE', h1line{j});
749                        if any(ismex(j,:))
750                                tpl = parse(tpl,'mex','mexfile');
751                        else
752                                tpl = set(tpl,'var','mex','');
753                        end
754                        tpl = parse(tpl,'rows-m','row-m',1);
755                end
756        end
757       
758        %- Display other Matlab-specific files (.mat,.mdl,.p)
759        tpl = set(tpl,'var','other','');
760        tpl = set(tpl,'var','rows-other','');
761        w = what(mdir{i}); w = w(1);
762        w = {w.mat{:} w.mdl{:} w.p{:}};
763        for j=1:length(w)
764                tpl = set(tpl,'var','OTHERFILE',w{j});
765                tpl = parse(tpl,'rows-other','row-other',1);
766        end
767        if ~isempty(w)
768                tpl = parse(tpl,'other','othermatlab');
769        end
770       
771        %- Display subsequent directories and classes
772        tpl = set(tpl,'var','subdirs','');
773        tpl = set(tpl,'var','subfold','');
774        d = dir(mdir{i});
775        d = {d([d.isdir]).name};
776        d = {d{~ismember(d,{'.' '..' options.ignoredDir{:}})}};
777        for j=1:length(d)
778                if ismember(fullfile(mdir{i},d{j}),mdir)
779                        tpl = set(tpl,'var','SUBDIRECTORY',...
780                                sprintf(tpl_mdir_link,...
781                                fullurl(d{j},[options.indexFile options.extension]),d{j}));
782                else
783                        tpl = set(tpl,'var','SUBDIRECTORY',d{j});
784                end
785                tpl = parse(tpl,'subdirs','subdir',1);
786        end
787        if ~isempty(d)
788                tpl = parse(tpl,'subfold','subfolder');
789        end
790       
791        %- Link to the TODO list if necessary
792        tpl = set(tpl,'var','todolists','');
793        if options.todo
794                if ~isempty(intersect(find(strcmp(mdir{i},mdirs)),todo.mfile))
795                        tpl = set(tpl,'var','LTODOLIST',['todo' options.extension]);
796                        tpl = parse(tpl,'todolists','todolist',1);
797                end
798        end
799       
800        %- Link to the dependency graph if necessary
801        tpl = set(tpl,'var','graphs','');
802        if options.graph
803                tpl = set(tpl,'var','LGRAPH',[dotbase options.extension]);
804                tpl = parse(tpl,'graphs','graph',1);
805        end
806       
807        %- Print the template in the HTML file
808        tpl = parse(tpl,'OUT','TPL_MDIR');
809        fprintf(fid,'%s',get(tpl,'OUT'));
810        fclose(fid);
811end
812
813%-------------------------------------------------------------------------------
814%- Write a TODO list file for each output directory, if necessary
815%-------------------------------------------------------------------------------
816tpl_todo = 'todo.tpl';
817
818if options.todo
819        %- Create the HTML template
820        tpl = template(options.template,'remove');
821        tpl = set(tpl,'file','TPL_TODO',tpl_todo);
822        tpl = set(tpl,'block','TPL_TODO','filelist','filelists');
823        tpl = set(tpl,'block','filelist','row','rows');
824        tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
825                                                                datestr(now,13)]);
826
827        for i=1:length(mdir)
828                mfilestodo = intersect(find(strcmp(mdir{i},mdirs)),todo.mfile);
829                if ~isempty(mfilestodo)
830                        %- Open for writing each TODO list file
831                        curfile = fullfile(options.htmlDir,mdir{i},...
832                                                           ['todo' options.extension]);
833                        if options.verbose
834                                fprintf('Creating HTML file %s...\n',curfile);
835                        end
836                        fid = openfile(curfile,'w');
837                       
838                        %- Set template fields
839                        tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
840                        tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i}));
841                        tpl = set(tpl,'var','MDIR',       mdir{i});
842                        tpl = set(tpl,'var','filelists',  '');
843       
844                        for k=1:length(mfilestodo)
845                                tpl = set(tpl,'var','MFILE',names{mfilestodo(k)});
846                                tpl = set(tpl,'var','rows','');
847                                nbtodo = find(todo.mfile == mfilestodo(k));
848                                for l=1:length(nbtodo)
849                                        tpl = set(tpl,'var','L_NBLINE',...
850                                                [names{mfilestodo(k)} ...
851                                                        options.extension ...
852                                                        '#l' num2str(todo.line(nbtodo(l)))]);
853                                        tpl = set(tpl,'var','NBLINE',num2str(todo.line(nbtodo(l))));
854                                        tpl = set(tpl,'var','COMMENT',todo.comment{nbtodo(l)});
855                                        tpl = parse(tpl,'rows','row',1);
856                                end
857                                tpl = parse(tpl,'filelists','filelist',1);
858                        end
859       
860                        %- Print the template in the HTML file
861                        tpl = parse(tpl,'OUT','TPL_TODO');
862                        fprintf(fid,'%s',get(tpl,'OUT'));
863                        fclose(fid);
864                end
865        end
866end
867
868%-------------------------------------------------------------------------------
869%- Create dependency graphs using GraphViz, if requested
870%-------------------------------------------------------------------------------
871tpl_graph = 'graph.tpl';
872% You may have to modify the following line with Matlab7 (R14) to specify
873% the full path to where GraphViz is installed
874dot_exec  = 'dot';
875%dotbase defined earlier
876
877if options.graph
878        %- Create the HTML template
879        tpl = template(options.template,'remove');
880        tpl = set(tpl,'file','TPL_GRAPH',tpl_graph);
881        tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
882                                                                datestr(now,13)]);
883       
884    %- Create a full dependency graph for all directories if possible
885    if options.globalHypertextLinks & length(mdir) > 1
886        mdotfile = fullfile(options.htmlDir,[dotbase '.dot']);
887        if options.verbose
888                        fprintf('Creating full dependency graph %s...',mdotfile);
889                end
890        mdot({hrefs, names, options, mdirs}, mdotfile); %mfiles
891        calldot(dot_exec, mdotfile, ...
892                fullfile(options.htmlDir,[dotbase '.map']), ...
893                fullfile(options.htmlDir,[dotbase '.png']));
894        if options.verbose, fprintf('\n'); end
895        fid = openfile(fullfile(options.htmlDir, [dotbase options.extension]),'w');
896        tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
897            tpl = set(tpl,'var','MASTERPATH', './');
898            tpl = set(tpl,'var','MDIR',       'the whole toolbox');
899        tpl = set(tpl,'var','GRAPH_IMG',  [dotbase '.png']);
900        try % if <dot> failed...
901                fmap = openfile(fullfile(options.htmlDir,[dotbase '.map']),'r');
902                tpl = set(tpl,'var','GRAPH_MAP',  fscanf(fmap,'%c'));
903                    fclose(fmap);
904        end
905                tpl = parse(tpl,'OUT','TPL_GRAPH');
906                fprintf(fid,'%s', get(tpl,'OUT'));
907        fclose(fid);
908    end
909   
910    %- Create a dependency graph for each output directory
911        for i=1:length(mdir)
912                mdotfile = fullfile(options.htmlDir,mdir{i},[dotbase '.dot']);
913                if options.verbose
914                        fprintf('Creating dependency graph %s...',mdotfile);
915                end
916                ind = find(strcmp(mdirs,mdir{i}));
917                href1 = zeros(length(ind),length(hrefs));
918                for j=1:length(hrefs), href1(:,j) = hrefs(ind,j); end
919                href2 = zeros(length(ind));
920                for j=1:length(ind), href2(j,:) = href1(j,ind); end
921                mdot({href2, {names{ind}}, options}, mdotfile); %{mfiles{ind}}
922        calldot(dot_exec, mdotfile, ...
923                fullfile(options.htmlDir,mdir{i},[dotbase '.map']), ...
924                fullfile(options.htmlDir,mdir{i},[dotbase '.png']));
925                if options.verbose, fprintf('\n'); end
926                fid = openfile(fullfile(options.htmlDir,mdir{i},...
927                        [dotbase options.extension]),'w');
928                tpl = set(tpl,'var','INDEX',[options.indexFile options.extension]);
929                tpl = set(tpl,'var','MASTERPATH', backtomaster(mdir{i}));
930                tpl = set(tpl,'var','MDIR',       mdir{i});
931                tpl = set(tpl,'var','GRAPH_IMG',  [dotbase '.png']);
932        try % if <dot> failed, no '.map' file has been created
933                fmap = openfile(fullfile(options.htmlDir,mdir{i},[dotbase '.map']),'r');
934                tpl = set(tpl,'var','GRAPH_MAP',  fscanf(fmap,'%c'));
935                    fclose(fmap);
936        end
937                tpl = parse(tpl,'OUT','TPL_GRAPH');
938                fprintf(fid,'%s', get(tpl,'OUT'));
939                fclose(fid);
940        end
941end
942
943%-------------------------------------------------------------------------------
944%- Write an HTML file for each M-file
945%-------------------------------------------------------------------------------
946%- List of Matlab keywords (output from iskeyword)
947matlabKeywords = {'break', 'case', 'catch', 'continue', 'elseif', 'else', ...
948                                  'end', 'for', 'function', 'global', 'if', 'otherwise', ...
949                                  'persistent', 'return', 'switch', 'try', 'while'};
950                  %'keyboard', 'pause', 'eps', 'NaN', 'Inf'
951
952tpl_mfile = 'mfile.tpl';
953
954tpl_mfile_code     = '<a href="%s" class="code" title="%s">%s</a>';
955tpl_mfile_keyword  = '<span class="keyword">%s</span>';
956tpl_mfile_comment  = '<span class="comment">%s</span>';
957tpl_mfile_string   = '<span class="string">%s</span>';
958tpl_mfile_aname    = '<a name="%s" href="#_subfunctions" class="code">%s</a>';
959tpl_mfile_line     = '%04d %s\n';
960
961%- Delimiters used in strtok: some of them may be useless (% " .), removed '.'
962strtok_delim = sprintf(' \t\n\r(){}[]<>+-*~!|\\@&/,:;="''%%');
963
964%- Create the HTML template
965tpl = template(options.template,'remove');
966tpl = set(tpl,'file','TPL_MFILE',tpl_mfile);
967tpl = set(tpl,'block','TPL_MFILE','pathline','pl');
968tpl = set(tpl,'block','TPL_MFILE','mexfile','mex');
969tpl = set(tpl,'block','TPL_MFILE','script','scriptfile');
970tpl = set(tpl,'block','TPL_MFILE','crossrefcall','crossrefcalls');
971tpl = set(tpl,'block','TPL_MFILE','crossrefcalled','crossrefcalleds');
972tpl = set(tpl,'block','TPL_MFILE','subfunction','subf');
973tpl = set(tpl,'block','subfunction','onesubfunction','onesubf');
974tpl = set(tpl,'block','TPL_MFILE','source','thesource');
975tpl = set(tpl,'block','TPL_MFILE','download','downloads');
976tpl = set(tpl,'var','DATE',[datestr(now,8) ' ' datestr(now,1) ' ' ...
977                                                        datestr(now,13)]);
978
979nblinetot = 0;
980for i=1:length(mdir)
981        for j=1:length(mdirs)
982                if strcmp(mdirs{j},mdir{i})
983               
984                        curfile = fullfile(options.htmlDir,mdir{i},...
985                                                           [names{j} options.extension]);
986                                                           
987                        %- Copy M-file for download, if necessary
988                        if options.download
989                                if options.verbose
990                                        fprintf('Copying M-file %s.m to %s...\n',names{j},...
991                                                fullfile(options.htmlDir,mdir{i}));
992                                end
993                                [status, errmsg] = copyfile(mfiles{j},...
994                                        fullfile(options.htmlDir,mdir{i}));
995                                error(errmsg);
996                        end
997                       
998                        %- Open for writing the HTML file
999                        if options.verbose
1000                                fprintf('Creating HTML file %s...\n',curfile);
1001                        end
1002                        fid = openfile(curfile,'w');
1003                        if strcmp(names{j},options.indexFile)
1004                fprintf(['Warning: HTML index file %s will be ' ...
1005                        'overwritten by Matlab function %s.\n'], ...
1006                        [options.indexFile options.extension], mfiles{j});
1007            end
1008           
1009                        %- Open for reading the M-file
1010                        fid2 = openfile(mfiles{j},'r');
1011                       
1012                        %- Set some template fields
1013                        tpl = set(tpl,'var','INDEX', [options.indexFile options.extension]);
1014                        tpl = set(tpl,'var','MASTERPATH',       backtomaster(mdir{i}));
1015                        tpl = set(tpl,'var','MDIR',             mdirs{j});
1016                        tpl = set(tpl,'var','NAME',             names{j});
1017                        tpl = set(tpl,'var','H1LINE',           entity(h1line{j}));
1018                        tpl = set(tpl,'var','scriptfile',       '');
1019                        if isempty(synopsis{j})
1020                                tpl = set(tpl,'var','SYNOPSIS',get(tpl,'var','script'));
1021                        else
1022                                tpl = set(tpl,'var','SYNOPSIS', synopsis{j});
1023                        end
1024                        s = splitpath(mdir{i});
1025                        tpl = set(tpl,'var','pl','');
1026                        for k=1:length(s)
1027                                c = cell(1,k); for l=1:k, c{l} = filesep; end
1028                                cpath = {s{1:k};c{:}}; cpath = [cpath{:}];
1029                                if ~isempty(cpath), cpath = cpath(1:end-1); end
1030                                if ismember(cpath,mdir)
1031                                        tpl = set(tpl,'var','LPATHDIR',[repmat('../',...
1032                                                1,length(s)-k) options.indexFile options.extension]);
1033                                else
1034                                        tpl = set(tpl,'var','LPATHDIR','#');
1035                                end
1036                                tpl = set(tpl,'var','PATHDIR',s{k});
1037                                tpl = parse(tpl,'pl','pathline',1);
1038                        end
1039                       
1040                        %- Handle mex files
1041                        tpl = set(tpl,'var','mex', '');
1042                        samename = dir(fullfile(mdir{i},[names{j}       '.*']));
1043                        samename = {samename.name};
1044                        tpl = set(tpl,'var','MEXTYPE', 'mex');
1045                        for k=1:length(samename)
1046                                [dummy, dummy, ext] = fileparts(samename{k});
1047                                switch ext
1048                                        case '.c'
1049                                                tpl = set(tpl,'var','MEXTYPE', 'c');
1050                                        case {'.cpp' '.c++' '.cxx' '.C'}
1051                                                tpl = set(tpl,'var','MEXTYPE', 'c++');
1052                                        case {'.for' '.f' '.FOR' '.F'}
1053                                                tpl = set(tpl,'var','MEXTYPE', 'fortran');
1054                                        otherwise
1055                                                %- Unknown mex file source
1056                                end
1057                        end
1058                        [exts, platform] = mexexts;
1059                        mexplatforms = sprintf('%s, ',platform{find(ismex(j,:))});
1060                        if ~isempty(mexplatforms)
1061                                tpl = set(tpl,'var','PLATFORMS', mexplatforms(1:end-2));
1062                                tpl = parse(tpl,'mex','mexfile');
1063                        end
1064                       
1065                        %- Set description template field
1066                        descr = '';
1067                        flagsynopcont = 0;
1068                        flag_seealso  = 0;
1069                        while 1
1070                                tline = fgets(fid2);
1071                                if ~ischar(tline), break, end
1072                                tline = entity(fliplr(deblank(fliplr(tline))));
1073                                %- Synopsis line
1074                                if ~isempty(strmatch('function',tline))
1075                                        if ~isempty(strmatch('...',fliplr(deblank(tline))))
1076                                                flagsynopcont = 1;
1077                                        end
1078                                %- H1 line and description
1079                                elseif ~isempty(strmatch('%',tline))
1080                                        %- Hypertext links on the "See also" line
1081                                        ind = findstr(lower(tline),'see also');
1082                                        if ~isempty(ind) | flag_seealso
1083                                                %- "See also" only in files in the same directory
1084                                                indsamedir = find(strcmp(mdirs{j},mdirs));
1085                                                hrefnames = {names{indsamedir}};
1086                                                r = deblank(tline);
1087                                                flag_seealso = 1; %(r(end) == ',');
1088                                                tline = '';
1089                                                while 1
1090                                                        [t,r,q] = strtok(r,sprintf(' \t\n\r.,;%%'));
1091                                                        tline = [tline q];
1092                                                        if isempty(t), break, end;
1093                                                        ii = strcmpi(hrefnames,t);
1094                                                        if any(ii)
1095                                                                jj = find(ii);
1096                                                                tline = [tline sprintf(tpl_mfile_code,...
1097                                                                        [hrefnames{jj(1)} options.extension],...
1098                                                                        synopsis{indsamedir(jj(1))},t)];
1099                                                        else
1100                                                                tline = [tline t];
1101                                                        end
1102                                                end
1103                                                tline = sprintf('%s\n',tline);
1104                                        end
1105                                        descr = [descr tline(2:end)];
1106                                elseif isempty(tline)
1107                                        if ~isempty(descr), break, end;
1108                                else
1109                                        if flagsynopcont
1110                                                if isempty(strmatch('...',fliplr(deblank(tline))))
1111                                                        flagsynopcont = 0;
1112                                                end
1113                                        else
1114                                                break;
1115                                        end
1116                                end
1117                        end
1118                        tpl = set(tpl,'var','DESCRIPTION',...
1119                                horztab(descr,options.tabs));
1120                       
1121                        %- Set cross-references template fields:
1122                        %  Function called
1123                        ind = find(hrefs(j,:) == 1);
1124                        tpl = set(tpl,'var','crossrefcalls','');
1125                        for k=1:length(ind)
1126                                if strcmp(mdirs{j},mdirs{ind(k)})
1127                                        tpl = set(tpl,'var','L_NAME_CALL', ...
1128                                                [names{ind(k)} options.extension]);
1129                                else
1130                                        tpl = set(tpl,'var','L_NAME_CALL', ...
1131                                                          fullurl(backtomaster(mdirs{j}), ...
1132                                                                           mdirs{ind(k)}, ...
1133                                                                           [names{ind(k)} options.extension]));
1134                                end
1135                                tpl = set(tpl,'var','SYNOP_CALL',   synopsis{ind(k)});
1136                                tpl = set(tpl,'var','NAME_CALL',   names{ind(k)});
1137                                tpl = set(tpl,'var','H1LINE_CALL', h1line{ind(k)});
1138                                tpl = parse(tpl,'crossrefcalls','crossrefcall',1);
1139                        end
1140                        %  Callers
1141                        ind = find(hrefs(:,j) == 1);
1142                        tpl = set(tpl,'var','crossrefcalleds','');
1143                        for k=1:length(ind)
1144                                if strcmp(mdirs{j},mdirs{ind(k)})
1145                                        tpl = set(tpl,'var','L_NAME_CALLED', ...
1146                                                [names{ind(k)} options.extension]);
1147                                else
1148                                        tpl = set(tpl,'var','L_NAME_CALLED', ...
1149                                                fullurl(backtomaster(mdirs{j}),...
1150                                                        mdirs{ind(k)}, ...
1151                                                        [names{ind(k)} options.extension]));
1152                                end
1153                                tpl = set(tpl,'var','SYNOP_CALLED',   synopsis{ind(k)});
1154                                tpl = set(tpl,'var','NAME_CALLED',   names{ind(k)});
1155                                tpl = set(tpl,'var','H1LINE_CALLED', h1line{ind(k)});
1156                                tpl = parse(tpl,'crossrefcalleds','crossrefcalled',1);
1157                        end
1158                       
1159                        %- Set subfunction template field
1160                        tpl = set(tpl,'var',{'subf' 'onesubf'},{'' ''});
1161                        if ~isempty(subroutine{j}) & options.source
1162                                for k=1:length(subroutine{j})
1163                                        tpl = set(tpl, 'var', 'L_SUB', ['#_sub' num2str(k)]);
1164                                        tpl = set(tpl, 'var', 'SUB',   subroutine{j}{k});
1165                                        tpl = parse(tpl, 'onesubf', 'onesubfunction',1);
1166                                end
1167                                tpl = parse(tpl,'subf','subfunction');
1168                        end
1169                        subname = extractname(subroutine{j});
1170                       
1171                        %- Link to M-file (for download)
1172                        tpl = set(tpl,'var','downloads','');
1173                        if options.download
1174                                tpl = parse(tpl,'downloads','download',1);
1175                        end
1176                       
1177                        %- Display source code with cross-references
1178                        if options.source & ~strcmpi(names{j},'contents')
1179                                fseek(fid2,0,-1);
1180                                it = 1;
1181                                matlabsource = '';
1182                                nbsubroutine = 1;
1183                                %- Get href function names of this file
1184                                indhrefnames = find(hrefs(j,:) == 1);
1185                                hrefnames = {names{indhrefnames}};
1186                                %- Loop over lines
1187                                while 1
1188                                        tline = fgetl(fid2);
1189                                        if ~ischar(tline), break, end
1190                                        myline = '';
1191                                        splitc = splitcode(entity(tline));
1192                                        for k=1:length(splitc)
1193                                                if isempty(splitc{k})
1194                                                elseif ~isempty(strmatch('function', ...
1195                                                                                fliplr(deblank(fliplr(splitc{k})))))
1196                                                        if isspace(splitc{k}(1))
1197                                                                nbs = find(diff(isspace(splitc{k}))==-1);
1198                                                                myline = [myline splitc{k}(1:nbs(1))];
1199                                                                splitc{k} = splitc{k}(nbs(1)+1:end);
1200                                                        end
1201                                                        %- Subfunctions definition
1202                                                        myline = [myline ...
1203                                                                sprintf(tpl_mfile_aname,...
1204                                                                        ['_sub' num2str(nbsubroutine-1)],splitc{k})];
1205                                                        nbsubroutine = nbsubroutine + 1;
1206                                                elseif splitc{k}(1) == ''''
1207                                                        myline = [myline ...
1208                                                                sprintf(tpl_mfile_string,splitc{k})];
1209                                                elseif splitc{k}(1) == '%'
1210                                                        myline = [myline ...
1211                                                                sprintf(tpl_mfile_comment,deblank(splitc{k}))];
1212                                                elseif ~isempty(strmatch('...',splitc{k}))
1213                                                        myline = [myline sprintf(tpl_mfile_keyword,'...')];
1214                                                        if ~isempty(splitc{k}(4:end))
1215                                                                myline = [myline ...
1216                                                                        sprintf(tpl_mfile_comment,splitc{k}(4:end))];
1217                                                        end
1218                                                else
1219                                                        %- Look for keywords
1220                                                        r = splitc{k};
1221                                                        while 1
1222                                                                [t,r,q] = strtok(r,strtok_delim);
1223                                                                myline = [myline q];
1224                                                                if isempty(t), break, end;
1225                                                                %- Highlight Matlab keywords &
1226                                                                %  cross-references on known functions
1227                                                                if options.syntaxHighlighting & ...
1228                                                                                any(strcmp(matlabKeywords,t))
1229                                                                        if strcmp('end',t)
1230                                                                                rr = fliplr(deblank(fliplr(r)));
1231                                                                                icomma = strmatch(',',rr);
1232                                                                                isemicolon = strmatch(';',rr);
1233                                                                                if ~(isempty(rr) | ~isempty([icomma isemicolon]))
1234                                                                                        myline = [myline t];
1235                                                                                else
1236                                                                                        myline = [myline sprintf(tpl_mfile_keyword,t)];
1237                                                                                end
1238                                                                        else
1239                                                                                myline = [myline sprintf(tpl_mfile_keyword,t)];
1240                                                                        end
1241                                                                elseif any(strcmp(hrefnames,t))
1242                                                                        indt = indhrefnames(logical(strcmp(hrefnames,t)));
1243                                                                        flink = [t options.extension];
1244                                                                        ii = ismember({mdirs{indt}},mdirs{j});
1245                                                                        if ~any(ii)
1246                                                                                % take the first one...
1247                                                                                flink = fullurl(backtomaster(mdirs{j}),...
1248                                                                                                                 mdirs{indt(1)}, flink);
1249                                                                        else
1250                                                                                indt = indt(logical(ii));
1251                                                                        end
1252                                                                        myline = [myline sprintf(tpl_mfile_code,...
1253                                                                                          flink, synopsis{indt(1)}, t)];
1254                                                                elseif any(strcmp(subname,t))
1255                                                                        ii = find(strcmp(subname,t));
1256                                                                        myline = [myline sprintf(tpl_mfile_code,...
1257                                                                                ['#_sub' num2str(ii)],...
1258                                                                                ['sub' subroutine{j}{ii}],t)];
1259                                                                else
1260                                                                        myline = [myline t];
1261                                                                end
1262                                                        end
1263                                                end
1264                                        end
1265                                        matlabsource = [matlabsource sprintf(tpl_mfile_line,it,myline)];
1266                                        it = it + 1;
1267                                end
1268                nblinetot = nblinetot + it - 1;
1269                                tpl = set(tpl,'var','SOURCECODE',...
1270                                                  horztab(matlabsource,options.tabs));
1271                                tpl = parse(tpl,'thesource','source');
1272                        else
1273                                tpl = set(tpl,'var','thesource','');
1274                        end
1275                        tpl = parse(tpl,'OUT','TPL_MFILE');
1276                        fprintf(fid,'%s',get(tpl,'OUT'));
1277                        fclose(fid2);
1278                        fclose(fid);
1279                end
1280        end
1281end
1282
1283%-------------------------------------------------------------------------------
1284%- Display Statistics
1285%-------------------------------------------------------------------------------
1286if options.verbose
1287    prnbline = '';
1288    if options.source
1289        prnbline = sprintf('(%d lines) ', nblinetot);
1290    end
1291    fprintf('Stats: %d M-files %sin %d directories documented in %d s.\n', ...
1292            length(mfiles), prnbline, length(mdir), round(etime(clock,t0)));
1293end
1294
1295%===============================================================================
1296function mfiles = getmfiles(mdirs, mfiles, recursive,ignoredDir)
1297        %- Extract M-files from a list of directories and/or M-files
1298
1299        if nargin < 4, ignoredDir = {}; end
1300        for i=1:length(mdirs)
1301                currentdir = fullfile(pwd, mdirs{i});
1302                if exist(currentdir) == 2 % M-file
1303                        mfiles{end+1} = mdirs{i};
1304                elseif exist(currentdir) == 7 % Directory
1305                        d = dir(fullfile(currentdir, '*.m'));
1306                        d = {d(~[d.isdir]).name};
1307                        for j=1:length(d)
1308                                %- don't take care of files containing ','
1309                                %  probably a sccs file...
1310                                if isempty(findstr(',',d{j}))
1311                                        mfiles{end+1} = fullfile(mdirs{i}, d{j});
1312                                end
1313                        end
1314                        if recursive
1315                                d = dir(currentdir);
1316                                d = {d([d.isdir]).name};
1317                                d = {d{~ismember(d,{'.' '..' ignoredDir{:}})}};
1318                                for j=1:length(d)
1319                                        mfiles = getmfiles(cellstr(fullfile(mdirs{i},d{j})), ...
1320                                                                           mfiles, recursive);
1321                                end
1322                        end
1323                else
1324                        fprintf('Warning: Unprocessed file %s.\n',mdirs{i});
1325                        if ~isempty(strmatch('/',mdirs{i})) | findstr(':',mdirs{i})
1326                                fprintf('         Use relative paths in ''mfiles'' option\n');
1327                        end
1328                end
1329        end
1330
1331%===============================================================================
1332function calldot(dotexec, mdotfile, mapfile, pngfile, opt)
1333        %- Draw a dependency graph in a PNG image using <dot> from GraphViz
1334
1335    if nargin == 4, opt = ''; end
1336    try
1337        %- See <http://www.graphviz.org/>
1338        %  <dot> must be in your system path, see M2HTML FAQ:
1339        %  <http://www.artefact.tk/software/matlab/m2html/faq.php>
1340
1341        eval(['!"' dotexec '" ' opt ' -Tcmap -Tpng "' mdotfile ...
1342              '" -o "' mapfile ...
1343              '" -o "' pngfile '"']);
1344        % use '!' rather than 'system' for backward compability with Matlab 5.3
1345    catch % use of '!' prevents errors to be catched...
1346        fprintf('<dot> failed.');
1347    end
1348   
1349%===============================================================================
1350function s = backtomaster(mdir)
1351        %- Provide filesystem path to go back to the root folder
1352
1353        ldir = splitpath(mdir);
1354        s = repmat('../',1,length(ldir));
1355       
1356%===============================================================================
1357function ldir = splitpath(p)
1358        %- Split a filesystem path into parts using filesep as separator
1359
1360        ldir = {};
1361        p = deblank(p);
1362        while 1
1363                [t,p] = strtok(p,filesep);
1364                if isempty(t), break; end
1365                if ~strcmp(t,'.')
1366                        ldir{end+1} = t;
1367                end
1368        end
1369        if isempty(ldir)
1370                ldir{1} = '.'; % should be removed
1371        end
1372
1373%===============================================================================
1374function name = extractname(synopsis)
1375        %- Extract function name in a synopsis
1376
1377        if ischar(synopsis), synopsis = {synopsis}; end
1378        name = cell(size(synopsis));
1379        for i=1:length(synopsis)
1380                ind = findstr(synopsis{i},'=');
1381                if isempty(ind)
1382                        ind = findstr(synopsis{i},'function');
1383                        s = synopsis{i}(ind(1)+8:end);
1384                else
1385                        s = synopsis{i}(ind(1)+1:end);
1386                end
1387                name{i} = strtok(s,[9:13 32 40]); % white space characters and '('
1388        end
1389        if length(name) == 1, name = name{1}; end
1390
1391%===============================================================================
1392function f = fullurl(varargin)
1393        %- Build full url from parts (using '/' and not filesep)
1394       
1395        f = strrep(fullfile(varargin{:}),'\','/');
1396
1397%===============================================================================
1398function str = escapeblank(str)
1399        %- Escape white spaces using '\'
1400       
1401        str = deblank(fliplr(deblank(fliplr(str))));
1402        str = strrep(str,' ','\ ');
1403
1404%===============================================================================
1405function str = entity(str)
1406        %- Escape HTML special characters
1407        %- See http://www.w3.org/TR/html4/charset.html#h-5.3.2
1408       
1409        str = strrep(str,'&','&amp;');
1410        str = strrep(str,'<','&lt;');
1411        str = strrep(str,'>','&gt;');
1412        str = strrep(str,'"','&quot;');
1413       
1414%===============================================================================
1415function str = horztab(str,n)
1416        %- For browsers, the horizontal tab character is the smallest non-zero
1417        %- number of spaces necessary to line characters up along tab stops that are
1418        %- every 8 characters: behaviour obtained when n = 0.
1419       
1420        if n > 0
1421                str = strrep(str,sprintf('\t'),blanks(n));
1422        end
Note: See TracBrowser for help on using the repository browser.