~ubuntu-branches/ubuntu/precise/gst0.10-python/precise

« back to all changes in this revision

Viewing changes to codegen/docextract.py

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier
  • Date: 2006-06-25 19:37:45 UTC
  • Revision ID: james.westby@ubuntu.com-20060625193745-9yeg0wq56r24n57x
Tags: upstream-0.10.4
ImportĀ upstreamĀ versionĀ 0.10.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.'''
 
4
 
 
5
import sys, os, string, re
 
6
 
 
7
__all__ = ['extract']
 
8
 
 
9
class FunctionDoc:
 
10
    def __init__(self):
 
11
        self.name = None
 
12
        self.params = []
 
13
        self.description = ''
 
14
        self.ret = ''
 
15
    def set_name(self, name):
 
16
        self.name = name
 
17
    def add_param(self, name, description):
 
18
        if name == '...':
 
19
            name = 'Varargs'
 
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)
 
27
                return
 
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
 
34
 
 
35
    def get_param_description(self, name):
 
36
        for param, description in self.params:
 
37
            if param == name:
 
38
                return description
 
39
        else:
 
40
            return ''
 
41
 
 
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?)$',
 
47
                        re.IGNORECASE)
 
48
param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$')
 
49
 
 
50
def parse_file(fp, doc_dict):
 
51
    line = fp.readline()
 
52
    in_comment_block = 0
 
53
    while line:
 
54
        if not in_comment_block:
 
55
            if comment_start_pat.match(line):
 
56
                in_comment_block = 1
 
57
                cur_doc = FunctionDoc()
 
58
                in_description = 0
 
59
                in_return = 0
 
60
            line = fp.readline()
 
61
            continue
 
62
        
 
63
        # we are inside a comment block ...
 
64
        if comment_end_pat.match(line):
 
65
            if not cur_doc.name:
 
66
                sys.stderr.write("no function name found in doc comment\n")
 
67
            else:
 
68
                doc_dict[cur_doc.name] = cur_doc
 
69
            in_comment_block = 0
 
70
            line = fp.readline()
 
71
            continue
 
72
 
 
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'
 
76
 
 
77
        if not cur_doc.name:
 
78
            match = funcname_pat.match(line)
 
79
            if match:
 
80
                cur_doc.set_name(match.group(1))
 
81
        elif in_return:
 
82
            match = return_pat.match(line)
 
83
            if match:
 
84
                # assume the last return statement was really part of the
 
85
                # description
 
86
                cur_doc.description = cur_doc.description + return_start + \
 
87
                                      cur_doc.ret
 
88
                return_start = match.group(1)
 
89
                cur_doc.ret = match.group(2)
 
90
            else:
 
91
                cur_doc.append_return(line)
 
92
        elif in_description:
 
93
            if line[:12] == 'Description:':
 
94
                line = line[12:]
 
95
            match = return_pat.match(line)
 
96
            if match:
 
97
                in_return = 1
 
98
                return_start = match.group(1)
 
99
                cur_doc.append_return(match.group(2))
 
100
            else:
 
101
                cur_doc.append_description(line)
 
102
        elif line == '\n':
 
103
            # end of parameters
 
104
            in_description = 1
 
105
        else:
 
106
            match = param_pat.match(line)
 
107
            if match:
 
108
                param = match.group(1)
 
109
                desc = match.group(2)
 
110
                if param == 'returns':
 
111
                    cur_doc.ret = desc
 
112
                else:
 
113
                    cur_doc.add_param(param, desc)
 
114
            else:
 
115
                # must be continuation
 
116
                try:
 
117
                    if param == 'returns':
 
118
                        cur_doc.append_return(line)
 
119
                    else:
 
120
                        cur_doc.append_to_last_param(line)
 
121
                except:
 
122
                    sys.stderr.write('something weird while reading param\n')
 
123
        line = fp.readline()
 
124
 
 
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)
 
133
 
 
134
def extract(dirs, doc_dict=None):
 
135
    if not doc_dict: doc_dict = {}
 
136
    for dir in dirs:
 
137
        parse_dir(dir, doc_dict)
 
138
    return doc_dict
 
139
 
 
140
tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$')
 
141
def parse_tmpl(fp, doc_dict):
 
142
    cur_doc = None
 
143
 
 
144
    line = fp.readline()
 
145
    while line:
 
146
        match = tmpl_section_pat.match(line)
 
147
        if match:
 
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)
 
151
 
 
152
            if sect_type == 'FUNCTION':
 
153
                cur_doc = doc_dict.get(sect_name)
 
154
                if not cur_doc:
 
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.
 
160
        elif cur_doc:
 
161
            if line[:10] == '@Returns: ':
 
162
                if string.strip(line[10:]):
 
163
                    cur_doc.append_return(line[10:])
 
164
            elif line[0] == '@':
 
165
                pos = string.find(line, ':')
 
166
                if pos >= 0:
 
167
                    cur_doc.append_to_named_param(line[1:pos], line[pos+1:])
 
168
                else:
 
169
                    cur_doc.append_description(line)
 
170
            else:
 
171
                cur_doc.append_description(line)
 
172
 
 
173
        line = fp.readline()
 
174
 
 
175
def extract_tmpl(dirs, doc_dict=None):
 
176
    if not doc_dict: doc_dict = {}
 
177
    for dir in dirs:
 
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):
 
182
                continue
 
183
            if len(file) > 2 and file[-2:] == '.sgml':
 
184
                parse_tmpl(open(path, 'r'), doc_dict)
 
185
    return doc_dict