diff options
-rwxr-xr-x | bitbake/bin/bitdoc | 519 |
1 files changed, 0 insertions, 519 deletions
diff --git a/bitbake/bin/bitdoc b/bitbake/bin/bitdoc deleted file mode 100755 index 9bd02be69c..0000000000 --- a/bitbake/bin/bitdoc +++ /dev/null | |||
@@ -1,519 +0,0 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # | ||
3 | # Copyright (C) 2005 Holger Hans Peter Freyther | ||
4 | # | ||
5 | # SPDX-License-Identifier: GPL-2.0-only | ||
6 | # | ||
7 | |||
8 | import optparse, os, sys | ||
9 | |||
10 | # bitbake | ||
11 | sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__), 'lib')) | ||
12 | import bb | ||
13 | import bb.parse | ||
14 | from string import split, join | ||
15 | |||
16 | __version__ = "0.0.2" | ||
17 | |||
18 | class HTMLFormatter: | ||
19 | """ | ||
20 | Simple class to help to generate some sort of HTML files. It is | ||
21 | quite inferior solution compared to docbook, gtkdoc, doxygen but it | ||
22 | should work for now. | ||
23 | We've a global introduction site (index.html) and then one site for | ||
24 | the list of keys (alphabetical sorted) and one for the list of groups, | ||
25 | one site for each key with links to the relations and groups. | ||
26 | |||
27 | index.html | ||
28 | all_keys.html | ||
29 | all_groups.html | ||
30 | groupNAME.html | ||
31 | keyNAME.html | ||
32 | """ | ||
33 | |||
34 | def replace(self, text, *pairs): | ||
35 | """ | ||
36 | From pydoc... almost identical at least | ||
37 | """ | ||
38 | while pairs: | ||
39 | (a, b) = pairs[0] | ||
40 | text = join(split(text, a), b) | ||
41 | pairs = pairs[1:] | ||
42 | return text | ||
43 | def escape(self, text): | ||
44 | """ | ||
45 | Escape string to be conform HTML | ||
46 | """ | ||
47 | return self.replace(text, | ||
48 | ('&', '&'), | ||
49 | ('<', '<' ), | ||
50 | ('>', '>' ) ) | ||
51 | def createNavigator(self): | ||
52 | """ | ||
53 | Create the navgiator | ||
54 | """ | ||
55 | return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> | ||
56 | <tr valign="middle"> | ||
57 | <td><a accesskey="g" href="index.html">Home</a></td> | ||
58 | <td><a accesskey="n" href="all_groups.html">Groups</a></td> | ||
59 | <td><a accesskey="u" href="all_keys.html">Keys</a></td> | ||
60 | </tr></table> | ||
61 | """ | ||
62 | |||
63 | def relatedKeys(self, item): | ||
64 | """ | ||
65 | Create HTML to link to foreign keys | ||
66 | """ | ||
67 | |||
68 | if len(item.related()) == 0: | ||
69 | return "" | ||
70 | |||
71 | txt = "<p><b>See also:</b><br>" | ||
72 | txts = [] | ||
73 | for it in item.related(): | ||
74 | txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() ) | ||
75 | |||
76 | return txt + ",".join(txts) | ||
77 | |||
78 | def groups(self, item): | ||
79 | """ | ||
80 | Create HTML to link to related groups | ||
81 | """ | ||
82 | |||
83 | if len(item.groups()) == 0: | ||
84 | return "" | ||
85 | |||
86 | |||
87 | txt = "<p><b>See also:</b><br>" | ||
88 | txts = [] | ||
89 | for group in item.groups(): | ||
90 | txts.append( """<a href="group%s.html">%s</a> """ % (group, group) ) | ||
91 | |||
92 | return txt + ",".join(txts) | ||
93 | |||
94 | |||
95 | def createKeySite(self, item): | ||
96 | """ | ||
97 | Create a site for a key. It contains the header/navigator, a heading, | ||
98 | the description, links to related keys and to the groups. | ||
99 | """ | ||
100 | |||
101 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
102 | <html><head><title>Key %s</title></head> | ||
103 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
104 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
105 | %s | ||
106 | <h2><span class="refentrytitle">%s</span></h2> | ||
107 | |||
108 | <div class="refsynopsisdiv"> | ||
109 | <h2>Synopsis</h2> | ||
110 | <p> | ||
111 | %s | ||
112 | </p> | ||
113 | </div> | ||
114 | |||
115 | <div class="refsynopsisdiv"> | ||
116 | <h2>Related Keys</h2> | ||
117 | <p> | ||
118 | %s | ||
119 | </p> | ||
120 | </div> | ||
121 | |||
122 | <div class="refsynopsisdiv"> | ||
123 | <h2>Groups</h2> | ||
124 | <p> | ||
125 | %s | ||
126 | </p> | ||
127 | </div> | ||
128 | |||
129 | |||
130 | </body> | ||
131 | """ % (item.name(), self.createNavigator(), item.name(), | ||
132 | self.escape(item.description()), self.relatedKeys(item), self.groups(item)) | ||
133 | |||
134 | def createGroupsSite(self, doc): | ||
135 | """ | ||
136 | Create the Group Overview site | ||
137 | """ | ||
138 | |||
139 | groups = "" | ||
140 | sorted_groups = sorted(doc.groups()) | ||
141 | for group in sorted_groups: | ||
142 | groups += """<a href="group%s.html">%s</a><br>""" % (group, group) | ||
143 | |||
144 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
145 | <html><head><title>Group overview</title></head> | ||
146 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
147 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
148 | %s | ||
149 | <h2>Available Groups</h2> | ||
150 | %s | ||
151 | </body> | ||
152 | """ % (self.createNavigator(), groups) | ||
153 | |||
154 | def createIndex(self): | ||
155 | """ | ||
156 | Create the index file | ||
157 | """ | ||
158 | |||
159 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
160 | <html><head><title>Bitbake Documentation</title></head> | ||
161 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
162 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
163 | %s | ||
164 | <h2>Documentation Entrance</h2> | ||
165 | <a href="all_groups.html">All available groups</a><br> | ||
166 | <a href="all_keys.html">All available keys</a><br> | ||
167 | </body> | ||
168 | """ % self.createNavigator() | ||
169 | |||
170 | def createKeysSite(self, doc): | ||
171 | """ | ||
172 | Create Overview of all avilable keys | ||
173 | """ | ||
174 | keys = "" | ||
175 | sorted_keys = sorted(doc.doc_keys()) | ||
176 | for key in sorted_keys: | ||
177 | keys += """<a href="key%s.html">%s</a><br>""" % (key, key) | ||
178 | |||
179 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
180 | <html><head><title>Key overview</title></head> | ||
181 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
182 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
183 | %s | ||
184 | <h2>Available Keys</h2> | ||
185 | %s | ||
186 | </body> | ||
187 | """ % (self.createNavigator(), keys) | ||
188 | |||
189 | def createGroupSite(self, gr, items, _description = None): | ||
190 | """ | ||
191 | Create a site for a group: | ||
192 | Group the name of the group, items contain the name of the keys | ||
193 | inside this group | ||
194 | """ | ||
195 | groups = "" | ||
196 | description = "" | ||
197 | |||
198 | # create a section with the group descriptions | ||
199 | if _description: | ||
200 | description += "<h2 Description of Grozp %s</h2>" % gr | ||
201 | description += _description | ||
202 | |||
203 | items.sort(lambda x, y:cmp(x.name(), y.name())) | ||
204 | for group in items: | ||
205 | groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name()) | ||
206 | |||
207 | return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
208 | <html><head><title>Group %s</title></head> | ||
209 | <link rel="stylesheet" href="style.css" type="text/css"> | ||
210 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||
211 | %s | ||
212 | %s | ||
213 | <div class="refsynopsisdiv"> | ||
214 | <h2>Keys in Group %s</h2> | ||
215 | <pre class="synopsis"> | ||
216 | %s | ||
217 | </pre> | ||
218 | </div> | ||
219 | </body> | ||
220 | """ % (gr, self.createNavigator(), description, gr, groups) | ||
221 | |||
222 | |||
223 | |||
224 | def createCSS(self): | ||
225 | """ | ||
226 | Create the CSS file | ||
227 | """ | ||
228 | return """.synopsis, .classsynopsis | ||
229 | { | ||
230 | background: #eeeeee; | ||
231 | border: solid 1px #aaaaaa; | ||
232 | padding: 0.5em; | ||
233 | } | ||
234 | .programlisting | ||
235 | { | ||
236 | background: #eeeeff; | ||
237 | border: solid 1px #aaaaff; | ||
238 | padding: 0.5em; | ||
239 | } | ||
240 | .variablelist | ||
241 | { | ||
242 | padding: 4px; | ||
243 | margin-left: 3em; | ||
244 | } | ||
245 | .variablelist td:first-child | ||
246 | { | ||
247 | vertical-align: top; | ||
248 | } | ||
249 | table.navigation | ||
250 | { | ||
251 | background: #ffeeee; | ||
252 | border: solid 1px #ffaaaa; | ||
253 | margin-top: 0.5em; | ||
254 | margin-bottom: 0.5em; | ||
255 | } | ||
256 | .navigation a | ||
257 | { | ||
258 | color: #770000; | ||
259 | } | ||
260 | .navigation a:visited | ||
261 | { | ||
262 | color: #550000; | ||
263 | } | ||
264 | .navigation .title | ||
265 | { | ||
266 | font-size: 200%; | ||
267 | } | ||
268 | div.refnamediv | ||
269 | { | ||
270 | margin-top: 2em; | ||
271 | } | ||
272 | div.gallery-float | ||
273 | { | ||
274 | float: left; | ||
275 | padding: 10px; | ||
276 | } | ||
277 | div.gallery-float img | ||
278 | { | ||
279 | border-style: none; | ||
280 | } | ||
281 | div.gallery-spacer | ||
282 | { | ||
283 | clear: both; | ||
284 | } | ||
285 | a | ||
286 | { | ||
287 | text-decoration: none; | ||
288 | } | ||
289 | a:hover | ||
290 | { | ||
291 | text-decoration: underline; | ||
292 | color: #FF0000; | ||
293 | } | ||
294 | """ | ||
295 | |||
296 | |||
297 | |||
298 | class DocumentationItem: | ||
299 | """ | ||
300 | A class to hold information about a configuration | ||
301 | item. It contains the key name, description, a list of related names, | ||
302 | and the group this item is contained in. | ||
303 | """ | ||
304 | |||
305 | def __init__(self): | ||
306 | self._groups = [] | ||
307 | self._related = [] | ||
308 | self._name = "" | ||
309 | self._desc = "" | ||
310 | |||
311 | def groups(self): | ||
312 | return self._groups | ||
313 | |||
314 | def name(self): | ||
315 | return self._name | ||
316 | |||
317 | def description(self): | ||
318 | return self._desc | ||
319 | |||
320 | def related(self): | ||
321 | return self._related | ||
322 | |||
323 | def setName(self, name): | ||
324 | self._name = name | ||
325 | |||
326 | def setDescription(self, desc): | ||
327 | self._desc = desc | ||
328 | |||
329 | def addGroup(self, group): | ||
330 | self._groups.append(group) | ||
331 | |||
332 | def addRelation(self, relation): | ||
333 | self._related.append(relation) | ||
334 | |||
335 | def sort(self): | ||
336 | self._related.sort() | ||
337 | self._groups.sort() | ||
338 | |||
339 | |||
340 | class Documentation: | ||
341 | """ | ||
342 | Holds the documentation... with mappings from key to items... | ||
343 | """ | ||
344 | |||
345 | def __init__(self): | ||
346 | self.__keys = {} | ||
347 | self.__groups = {} | ||
348 | |||
349 | def insert_doc_item(self, item): | ||
350 | """ | ||
351 | Insert the Doc Item into the internal list | ||
352 | of representation | ||
353 | """ | ||
354 | item.sort() | ||
355 | self.__keys[item.name()] = item | ||
356 | |||
357 | for group in item.groups(): | ||
358 | if not group in self.__groups: | ||
359 | self.__groups[group] = [] | ||
360 | self.__groups[group].append(item) | ||
361 | self.__groups[group].sort() | ||
362 | |||
363 | |||
364 | def doc_item(self, key): | ||
365 | """ | ||
366 | Return the DocumentationInstance describing the key | ||
367 | """ | ||
368 | try: | ||
369 | return self.__keys[key] | ||
370 | except KeyError: | ||
371 | return None | ||
372 | |||
373 | def doc_keys(self): | ||
374 | """ | ||
375 | Return the documented KEYS (names) | ||
376 | """ | ||
377 | return self.__keys.keys() | ||
378 | |||
379 | def groups(self): | ||
380 | """ | ||
381 | Return the names of available groups | ||
382 | """ | ||
383 | return self.__groups.keys() | ||
384 | |||
385 | def group_content(self, group_name): | ||
386 | """ | ||
387 | Return a list of keys/names that are in a specefic | ||
388 | group or the empty list | ||
389 | """ | ||
390 | try: | ||
391 | return self.__groups[group_name] | ||
392 | except KeyError: | ||
393 | return [] | ||
394 | |||
395 | |||
396 | def parse_cmdline(args): | ||
397 | """ | ||
398 | Parse the CMD line and return the result as a n-tuple | ||
399 | """ | ||
400 | |||
401 | parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__, __version__)) | ||
402 | usage = """%prog [options] | ||
403 | |||
404 | Create a set of html pages (documentation) for a bitbake.conf.... | ||
405 | """ | ||
406 | |||
407 | # Add the needed options | ||
408 | parser.add_option( "-c", "--config", help = "Use the specified configuration file as source", | ||
409 | action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") ) | ||
410 | |||
411 | parser.add_option( "-o", "--output", help = "Output directory for html files", | ||
412 | action = "store", dest = "output", default = "html/" ) | ||
413 | |||
414 | parser.add_option( "-D", "--debug", help = "Increase the debug level", | ||
415 | action = "count", dest = "debug", default = 0 ) | ||
416 | |||
417 | parser.add_option( "-v", "--verbose", help = "output more chit-char to the terminal", | ||
418 | action = "store_true", dest = "verbose", default = False ) | ||
419 | |||
420 | options, args = parser.parse_args( sys.argv ) | ||
421 | |||
422 | bb.msg.init_msgconfig(options.verbose, options.debug) | ||
423 | |||
424 | return options.config, options.output | ||
425 | |||
426 | def main(): | ||
427 | """ | ||
428 | The main Method | ||
429 | """ | ||
430 | |||
431 | (config_file, output_dir) = parse_cmdline( sys.argv ) | ||
432 | |||
433 | # right to let us load the file now | ||
434 | try: | ||
435 | documentation = bb.parse.handle( config_file, bb.data.init() ) | ||
436 | except IOError: | ||
437 | bb.fatal( "Unable to open %s" % config_file ) | ||
438 | except bb.parse.ParseError: | ||
439 | bb.fatal( "Unable to parse %s" % config_file ) | ||
440 | |||
441 | if isinstance(documentation, dict): | ||
442 | documentation = documentation[""] | ||
443 | |||
444 | # Assuming we've the file loaded now, we will initialize the 'tree' | ||
445 | doc = Documentation() | ||
446 | |||
447 | # defined states | ||
448 | state_begin = 0 | ||
449 | state_see = 1 | ||
450 | state_group = 2 | ||
451 | |||
452 | for key in bb.data.keys(documentation): | ||
453 | data = documentation.getVarFlag(key, "doc", False) | ||
454 | if not data: | ||
455 | continue | ||
456 | |||
457 | # The Documentation now starts | ||
458 | doc_ins = DocumentationItem() | ||
459 | doc_ins.setName(key) | ||
460 | |||
461 | |||
462 | tokens = data.split(' ') | ||
463 | state = state_begin | ||
464 | string= "" | ||
465 | for token in tokens: | ||
466 | token = token.strip(',') | ||
467 | |||
468 | if not state == state_see and token == "@see": | ||
469 | state = state_see | ||
470 | continue | ||
471 | elif not state == state_group and token == "@group": | ||
472 | state = state_group | ||
473 | continue | ||
474 | |||
475 | if state == state_begin: | ||
476 | string += " %s" % token | ||
477 | elif state == state_see: | ||
478 | doc_ins.addRelation(token) | ||
479 | elif state == state_group: | ||
480 | doc_ins.addGroup(token) | ||
481 | |||
482 | # set the description | ||
483 | doc_ins.setDescription(string) | ||
484 | doc.insert_doc_item(doc_ins) | ||
485 | |||
486 | # let us create the HTML now | ||
487 | bb.utils.mkdirhier(output_dir) | ||
488 | os.chdir(output_dir) | ||
489 | |||
490 | # Let us create the sites now. We do it in the following order | ||
491 | # Start with the index.html. It will point to sites explaining all | ||
492 | # keys and groups | ||
493 | html_slave = HTMLFormatter() | ||
494 | |||
495 | f = file('style.css', 'w') | ||
496 | print >> f, html_slave.createCSS() | ||
497 | |||
498 | f = file('index.html', 'w') | ||
499 | print >> f, html_slave.createIndex() | ||
500 | |||
501 | f = file('all_groups.html', 'w') | ||
502 | print >> f, html_slave.createGroupsSite(doc) | ||
503 | |||
504 | f = file('all_keys.html', 'w') | ||
505 | print >> f, html_slave.createKeysSite(doc) | ||
506 | |||
507 | # now for each group create the site | ||
508 | for group in doc.groups(): | ||
509 | f = file('group%s.html' % group, 'w') | ||
510 | print >> f, html_slave.createGroupSite(group, doc.group_content(group)) | ||
511 | |||
512 | # now for the keys | ||
513 | for key in doc.doc_keys(): | ||
514 | f = file('key%s.html' % doc.doc_item(key).name(), 'w') | ||
515 | print >> f, html_slave.createKeySite(doc.doc_item(key)) | ||
516 | |||
517 | |||
518 | if __name__ == "__main__": | ||
519 | main() | ||