2 # nghttp2 - HTTP/2 C Library
4 # Copyright (c) 2012 Tatsuhiro Tsujikawa
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 # Generates API reference from C source code.
26 from __future__ import print_function # At least python 2.6 is required
27 import re, sys, argparse
30 def __init__(self, name, content, domain):
32 self.content = content
36 print('''.. {}:: {}'''.format(self.domain, self.name))
38 for line in self.content:
39 print(' {}'.format(line))
42 def __init__(self, name, content, members, member_domain):
44 self.content = content
45 self.members = members
46 self.member_domain = member_domain
50 print('''.. type:: {}'''.format(self.name))
52 for line in self.content:
53 print(' {}'.format(line))
55 for name, content in self.members:
56 print(''' .. {}:: {}'''.format(self.member_domain, name))
59 print(''' {}'''.format(line))
63 def __init__(self, name, content):
65 self.content = content
68 print('''.. macro:: {}'''.format(self.name))
70 for line in self.content:
71 print(' {}'.format(line))
73 def make_api_ref(infiles):
78 for infile in infiles:
80 line = infile.readline()
84 line = infile.readline()
85 doctype = line.split()[1]
86 if doctype == '@function':
87 functions.append(process_function('function', infile))
88 elif doctype == '@functypedef':
89 types.append(process_function('type', infile))
90 elif doctype == '@struct' or doctype == '@union':
91 types.append(process_struct(infile))
92 elif doctype == '@enum':
93 enums.append(process_enum(infile))
94 elif doctype == '@macro':
95 macros.append(process_macro(infile))
96 alldocs = [('Macros', macros),
98 ('Types (structs, unions and typedefs)', types),
99 ('Functions', functions)]
100 for title, docs in alldocs:
104 print('-'*len(title))
106 doc.write(sys.stdout)
110 def process_macro(infile):
111 content = read_content(infile)
112 line = infile.readline()
113 macro_name = line.split()[1]
114 return MacroDoc(macro_name, content)
116 def process_enum(infile):
119 content = read_content(infile)
121 line = infile.readline()
124 elif re.match(r'\s*/\*\*\n', line):
125 member_content = read_content(infile)
126 line = infile.readline()
128 member_name = items[0]
130 member_content.insert(0, '(``{}``) '\
131 .format(' '.join(items[2:]).rstrip(',')))
132 members.append((member_name, member_content))
133 elif line.startswith('}'):
134 enum_name = line.rstrip().split()[1]
135 enum_name = re.sub(r';$', '', enum_name)
137 return StructDoc(enum_name, content, members, 'macro')
139 def process_struct(infile):
142 content = read_content(infile)
144 line = infile.readline()
147 elif re.match(r'\s*/\*\*\n', line):
148 member_content = read_content(infile)
149 line = infile.readline()
150 member_name = line.rstrip().rstrip(';')
151 members.append((member_name, member_content))
152 elif line.startswith('}') or\
153 (line.startswith('typedef ') and line.endswith(';\n')):
154 if line.startswith('}'):
158 struct_name = line.rstrip().split()[index]
159 struct_name = re.sub(r';$', '', struct_name)
161 return StructDoc(struct_name, content, members, 'member')
163 def process_function(domain, infile):
164 content = read_content(infile)
167 line = infile.readline()
173 func_proto.append(line)
174 func_proto = ''.join(func_proto)
175 func_proto = re.sub(r';\n$', '', func_proto)
176 func_proto = re.sub(r'\s+', ' ', func_proto)
177 return FunctionDoc(func_proto, content, domain)
179 def read_content(infile):
182 line = infile.readline()
185 if re.match(r'\s*\*/\n', line):
188 content.append(transform_content(line.rstrip()))
191 def arg_repl(matchobj):
192 return '*{}*'.format(matchobj.group(1).replace('*', '\\*'))
194 def transform_content(content):
195 content = re.sub(r'^\s+\* ?', '', content)
196 content = re.sub(r'\|([^\s|]+)\|', arg_repl, content)
197 content = re.sub(r':enum:', ':macro:', content)
200 if __name__ == '__main__':
201 parser = argparse.ArgumentParser(description="Generate API reference")
202 parser.add_argument('--header', type=argparse.FileType('r'),
203 help='header inserted at the top of the page')
204 parser.add_argument('files', nargs='+', type=argparse.FileType('r'),
206 args = parser.parse_args()
208 print(args.header.read())
209 for infile in args.files:
210 make_api_ref(args.files)