2 # -*- Mode: Python; py-indent-offset: 4 -*-
4 # This litte script outputs the C doc comments to an XML format.
5 # So far it's only used by gtkmm (The C++ bindings). Murray Cumming.
7 # # ./docextract_to_xml.py -s /gnome/head/cvs/gtk+/gtk/ -s /gnome/head/cvs/gtk+/docs/reference/gtk/tmpl/ > gtk_docs.xml
17 sys.stderr.write('usage: docextract_to_xml.py ' +
18 '[-s /src/dir | --source-dir=/src/dir] ' +
19 '[-a | --with-annotations] [-p | --with-properties] ' +
20 '[-i | --with-signals ]\n')
23 # Translates special texts to &... HTML acceptable format. Also replace
24 # occurrences of '/*' and '*/' with '/ *' and '* /' respectively to avoid
25 # comment errors (note the spaces). Some function descriptions include C++
26 # multi-line comments which cause errors when the description is included in a
27 # C++ Doxygen comment block.
28 def escape_text(unescaped_text):
29 # Escape every "&" not part of an entity reference
30 escaped_text = re.sub(r'&(?![A-Za-z]+;)', '&', unescaped_text)
32 # These weird entities turn up in the output...
33 escaped_text = string.replace(escaped_text, '—', '—')
34 escaped_text = string.replace(escaped_text, '*', '*')
35 escaped_text = string.replace(escaped_text, '%', '%')
36 escaped_text = string.replace(escaped_text, '@', '@')
37 escaped_text = string.replace(escaped_text, '#', '#')
38 escaped_text = string.replace(escaped_text, ' ', ' ')
39 # This represents a '/' before or after an '*' so replace with slash but
41 escaped_text = string.replace(escaped_text, '/', ' / ')
43 # Escape for both tag contents and attribute values
44 escaped_text = string.replace(escaped_text, '<', '<')
45 escaped_text = string.replace(escaped_text, '>', '>')
46 escaped_text = string.replace(escaped_text, '"', '"')
48 # Replace C++ comment begin and ends to ones that don't affect Doxygen.
49 escaped_text = string.replace(escaped_text, '/*', '/ *')
50 escaped_text = string.replace(escaped_text, '*/', '* /')
54 def print_annotations(annotations):
55 for annotation in annotations:
56 print "<annotation name=" + annotation[0] + ">" + \
57 escape_text(annotation[1]) + "</annotation>"
59 if __name__ == '__main__':
61 opts, args = getopt.getopt(sys.argv[1:], "d:s:o:api",
62 ["source-dir=", "with-annotations",
63 "with-properties", "with-signals"])
64 except getopt.error, e:
65 sys.stderr.write('docextract_to_xml.py: %s\n' % e)
68 with_annotations = False
70 with_properties = False
72 if opt in ('-s', '--source-dir'):
73 source_dirs.append(arg)
74 if opt in ('-a', '--with-annotations'):
75 with_annotations = True
76 if opt in ('-p', '--with-properties'):
77 with_properties = True
78 if opt in ('-i', '--with-signals'):
83 docs = docextract.extract(source_dirs);
84 docextract.extract_tmpl(source_dirs, docs); #Try the tmpl sgml files too.
92 for name, value in sorted(docs.items()):
93 # Get the type of comment block ('function', 'signal' or
94 # 'property') (the value is a GtkDoc).
95 block_type = value.get_type()
97 # Skip signals if the option was not specified.
98 if block_type == 'signal' and not with_signals:
100 # Likewise for properties.
101 elif block_type == 'property' and not with_properties:
104 print "<" + block_type + " name=\"" + escape_text(name) + "\">"
106 print "<description>"
107 print escape_text(value.get_description())
108 print "</description>"
110 # Loop through the parameters if not dealing with a property:
111 if block_type != 'property':
113 for name, description, annotations in value.params:
114 print "<parameter name=\"" + escape_text(name) + "\">"
115 print "<parameter_description>" + escape_text(description) + "</parameter_description>"
118 print_annotations(annotations)
122 print "</parameters>"
124 # Show the return-type (also if not dealing with a property):
127 print "<return_description>" + escape_text(value.ret[0]) + \
128 "</return_description>"
129 print_annotations(value.ret[1])
132 print "<return>" + escape_text(value.ret[0]) + "</return>"
135 print_annotations(value.get_annotations())
137 print "</" + block_type + ">\n"