1
# -*- Mode: Python; py-indent-offset: 4 -*-
2
'''Simple module for extracting GNOME style doc comments from C
3
sources, so I can use them for other purposes.'''
5
import sys, os, string, re
15
def set_name(self, name):
17
def add_param(self, name, description):
20
self.params.append((name, description))
21
def append_to_last_param(self, extra):
22
self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra)
23
def append_to_named_param(self, name, extra):
24
for i in range(len(self.params)):
25
if self.params[i][0] == name:
26
self.params[i] = (name, self.params[i][1] + extra)
28
# fall through to adding extra parameter ...
29
self.add_param(name, extra)
30
def append_description(self, extra):
31
self.description = self.description + extra
32
def append_return(self, extra):
33
self.ret = self.ret + extra
35
def get_param_description(self, name):
36
for param, description in self.params:
42
comment_start_pat = re.compile(r'^\s*/\*\*\s')
43
comment_end_pat = re.compile(r'^\s*\*+/')
44
comment_line_lead = re.compile(r'^\s*\*\s*')
45
funcname_pat = re.compile(r'^(\w+)\s*:?')
46
return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$',
48
param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
50
def parse_file(fp, doc_dict):
54
if not in_comment_block:
55
if comment_start_pat.match(line):
57
cur_doc = FunctionDoc()
63
# we are inside a comment block ...
64
if comment_end_pat.match(line):
66
sys.stderr.write("no function name found in doc comment\n")
68
doc_dict[cur_doc.name] = cur_doc
73
# inside a comment block, and not the end of the block ...
74
line = comment_line_lead.sub('', line)
75
if not line: line = '\n'
78
match = funcname_pat.match(line)
80
cur_doc.set_name(match.group(1))
82
match = return_pat.match(line)
84
# assume the last return statement was really part of the
86
cur_doc.description = cur_doc.description + return_start + \
88
return_start = match.group(1)
89
cur_doc.ret = match.group(2)
91
cur_doc.append_return(line)
93
if line[:12] == 'Description:':
95
match = return_pat.match(line)
98
return_start = match.group(1)
99
cur_doc.append_return(match.group(2))
101
cur_doc.append_description(line)
106
match = param_pat.match(line)
108
param = match.group(1)
109
desc = match.group(2)
110
if param == 'returns':
113
cur_doc.add_param(param, desc)
115
# must be continuation
117
if param == 'returns':
118
cur_doc.append_return(line)
120
cur_doc.append_to_last_param(line)
122
sys.stderr.write('something weird while reading param\n')
125
def parse_dir(dir, doc_dict):
126
for file in os.listdir(dir):
127
if file in ('.', '..'): continue
128
path = os.path.join(dir, file)
129
if os.path.isdir(path):
130
parse_dir(path, doc_dict)
131
if len(file) > 2 and file[-2:] == '.c':
132
parse_file(open(path, 'r'), doc_dict)
134
def extract(dirs, doc_dict=None):
135
if not doc_dict: doc_dict = {}
137
parse_dir(dir, doc_dict)
140
tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
141
def parse_tmpl(fp, doc_dict):
146
match = tmpl_section_pat.match(line)
148
cur_doc = None # new input shouldn't affect the old doc dict
149
sect_type = match.group(1)
150
sect_name = match.group(2)
152
if sect_type == 'FUNCTION':
153
cur_doc = doc_dict.get(sect_name)
155
cur_doc = FunctionDoc()
156
cur_doc.set_name(sect_name)
157
doc_dict[sect_name] = cur_doc
158
elif line == '<!-- # Unused Parameters # -->\n':
159
cur_doc = None # don't worry about unused params.
161
if line[:10] == '@Returns: ':
162
if string.strip(line[10:]):
163
cur_doc.append_return(line[10:])
165
pos = string.find(line, ':')
167
cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
169
cur_doc.append_description(line)
171
cur_doc.append_description(line)
175
def extract_tmpl(dirs, doc_dict=None):
176
if not doc_dict: doc_dict = {}
178
for file in os.listdir(dir):
179
if file in ('.', '..'): continue
180
path = os.path.join(dir, file)
181
if os.path.isdir(path):
183
if len(file) > 2 and file[-2:] == '.sgml':
184
parse_tmpl(open(path, 'r'), doc_dict)