8 sys
.path
.insert(0, '@CMAKE_BINARY_DIR@/data/python')
9 from FreeFOAM
.compat
import *
11 echo('Fixing up Doxygen generated API documentation')
13 srcdir
= '@PROJECT_SOURCE_DIR@'
16 # actually, there are many more characters to escape, but those
17 # should be the only ones relevant for FreeFOAM
24 # regular expression to match includes
25 incRegex
= re
.compile(
26 r
'(?P<ptxt>.*<span\s+class="preprocessor">\s*\s*#\s*include\s+' +
27 r
'(?:(?P<qinc>")|(?P<sinc><)))(?P<hdr>\S+.[CH])' +
28 r
'(?P<atxt>(?(qinc)"|>).*)')
30 glob_pattern
= op
.join(
31 '@CMAKE_CURRENT_BINARY_DIR@', '..', 'html', 'API',
34 class FilePathParser(HTMLParser
.HTMLParser
):
35 '''Parse file name and includes from Doxygen-generated documentation'''
37 HTMLParser
.HTMLParser
.__init
__(self
)
38 self
.inNavPath
= False
39 self
.inHeaderTitle
= False
43 def parse(self
, fname
):
44 '''Parse the HTML file `fname`'''
45 lines
= open(fname
, 'rt').readlines()
46 self
.feed(''.join(lines
))
48 # can't use HTMLParse for includes because of the discared white space
50 m
= incRegex
.search(l
)
52 self
._includes
.append(m
)
53 return op
.normpath(self
._path
), self
._includes
55 def handle_starttag(self
, tag
, attrs
):
57 if ('class', 'navpath') in attrs
:
59 elif ('class', 'headertitle') in attrs
:
60 self
.inHeaderTitle
= True
62 def handle_endtag(self
, tag
):
65 self
.inNavPath
= False
66 elif self
.inHeaderTitle
:
67 self
.inHeaderTitle
= False
69 def handle_data(self
, data
):
72 if self
.inNavPath
or self
.inHeaderTitle
:
73 self
._path
= op
.join(self
._path
, data
)
75 def parse_wrapper(hdr
):
76 incdir
= op
.join('@CMAKE_BINARY_DIR@', 'include')
77 wrapper
= op
.normpath(op
.join(srcdir
, incdir
, hdr
))
79 if op
.isfile(wrapper
):
80 # parse the file for the first #include statement and extract
82 for ll
in open(wrapper
, 'rt'):
83 mm
= re
.match(r
'#include "(.*)"', ll
)
88 echo('ERROR: Failed to parse include wrapper "%s"'%wrapper
,
91 # construct the absolute path to the header
92 realHdr
= op
.normpath(
93 op
.join(incdir
, op
.dirname(hdr
), realHdr
))
94 if not op
.isfile(realHdr
):
95 echo('ERROR: Wrapped include file "%s" does not exist'%realHdr
,
98 return op
.relpath(realHdr
, srcdir
)
103 echo('- Parsing *_source.html')
104 for f
in glob
.glob(glob_pattern
):
105 parser
= FilePathParser()
106 p
, incs
= parser
.parse(f
)
109 sysinc
= i
.group('sinc')!=None
112 if hdr
not in sysHdrMap
:
113 realHdr
= parse_wrapper(hdr
)
114 sysHdrMap
[hdr
] = realHdr
116 if p
not in quoteHdrMap
:
118 if hdr
not in quoteHdrMap
[p
]:
119 realHdr
= op
.normpath(op
.join(op
.dirname(p
), hdr
))
120 if not op
.isfile(op
.join(srcdir
, realHdr
)):
121 echo('ERROR: Failed to find include file "%s" in %s'%(hdr
, p
),
124 quoteHdrMap
[p
][hdr
] = realHdr
126 # find shortest unique partial paths and mimick the name-mangling used by
128 echo('- Computing mangled file names')
129 sources
= set(htmlDocMap
.itervalues())
130 docMap
= dict(zip(sources
, sources
))
131 for b
in map(op
.basename
, docMap
.itervalues()):
133 filter(lambda hd
: op
.basename(hd
[0])==b
, docMap
.iteritems()))
134 if len(subDocMap
) == 1:
135 prefix
= op
.dirname(subDocMap
.values()[0])+op
.sep
137 prefix
= op
.commonprefix(subDocMap
.values())
139 for h
, d
in subDocMap
.iteritems():
141 for o
, n
in escapeTable
:
143 # mimick file name truncation of Doxygen
145 d
= d
[:128-32] + md5
.new(d
).hexdigest()
148 # now do the actual work of fixing up the docs
149 echo('- Fixing #include linkes in the *_source.html files')
150 for f
, p
in htmlDocMap
.iteritems():
151 lines
= open(f
, 'rt').readlines()
152 for i
, l
in enumerate(lines
):
153 m
= incRegex
.match(l
)
156 sysinc
= m
.group('sinc')!=None
158 realHdr
= sysHdrMap
[hdr
]
160 realHdr
= quoteHdrMap
[p
][hdr
]
163 '<a class="code" href="%s.html">%s</a>'%(docMap
[realHdr
], hdr
),
166 open(f
, 'wt').writelines(lines
)
168 # replace #CONFIG_YEAR# and #CONFIG_DATE_STAMP#, delete
169 # #include <FOAM_LOCAL/hdr.H> and make #include "src/../hdr.H" links
170 echo('- Fixing remaining #include links and expanding placeholders')
171 year
= time
.strftime('%Y')
172 stamp
= time
.strftime('%a, %d %b %Y %H:%M:%S %Z')
173 for f
in glob
.glob(op
.join(
174 '@CMAKE_CURRENT_BINARY_DIR@', '..', 'html', 'API', '*.html')):
175 lines
= open(f
, 'rt').readlines()
176 for i
, l
in enumerate(lines
):
177 lines
[i
] = lines
[i
].replace('#CONFIG_YEAR#', year
)
178 lines
[i
] = lines
[i
].replace('#CONFIG_DATE_STAMP#', stamp
)
179 if re
.match(r
'^\s*<p><code>#include <.*>FOAM_LOCAL/', lines
[i
]):
182 m
= re
.match(r
'(\s*<code>#include ")((?:src|applications)/\S+\.H)' +
183 r
'("</code>.*)', lines
[i
])
190 '<a href="%s.html">%s</a>'%(html
, hdr
),
193 echo('WARNING: Failed to find HTML file for "%s"'%hdr
,
195 open(f
, 'wt').writelines(lines
)