xref: /btstack/doc/manual/markdown_create_apis.py (revision d7ef06763dbbdaadb5793c01f64e681cf932d402)
1c8c342a6SMilanka Ringwald#!/usr/bin/env python3
2c8c342a6SMilanka Ringwaldimport os, sys, getopt, re, pickle
3c8c342a6SMilanka Ringwaldimport subprocess
4c8c342a6SMilanka Ringwald
5c8c342a6SMilanka Ringwaldclass State:
6*d7ef0676SMilanka Ringwald    SearchTitle = 0
7*d7ef0676SMilanka Ringwald    SearchEndTitle = 1
8*d7ef0676SMilanka Ringwald    SearchStartAPI = 2
9*d7ef0676SMilanka Ringwald    SearchEndAPI = 3
10*d7ef0676SMilanka Ringwald    DoneAPI = 4
11c8c342a6SMilanka Ringwald
12*d7ef0676SMilanka Ringwaldapi_files = []
13c8c342a6SMilanka Ringwaldfunctions = {}
14c8c342a6SMilanka Ringwaldtypedefs = {}
15c8c342a6SMilanka Ringwald
16c8c342a6SMilanka Ringwaldapi_header = """
17c8c342a6SMilanka Ringwald
18c8c342a6SMilanka Ringwald## API_TITLE API {#sec:API_LABLEAPIAppendix}
19c8c342a6SMilanka Ringwald
20c8c342a6SMilanka Ringwald"""
21c8c342a6SMilanka Ringwald
22c8c342a6SMilanka Ringwaldapi_ending = """
23c8c342a6SMilanka Ringwald"""
24c8c342a6SMilanka Ringwald
25c8c342a6SMilanka Ringwaldcode_ref = """GITHUBFPATH#LLINENR"""
26c8c342a6SMilanka Ringwald
27c8c342a6SMilanka Ringwald
28*d7ef0676SMilanka Ringwalddef isEndOfComment(line):
29*d7ef0676SMilanka Ringwald    return re.match('\s*\*/.*', line)
30*d7ef0676SMilanka Ringwald
31*d7ef0676SMilanka Ringwalddef isStartOfComment(line):
32*d7ef0676SMilanka Ringwald    return re.match('\s*\/\*/.*', line)
33*d7ef0676SMilanka Ringwald
34*d7ef0676SMilanka Ringwalddef isTypedefStart(line):
35*d7ef0676SMilanka Ringwald    return re.match('.*typedef\s+struct.*', line)
36*d7ef0676SMilanka Ringwald
37c8c342a6SMilanka Ringwalddef codeReference(fname, githuburl, filepath, linenr):
38c8c342a6SMilanka Ringwald    global code_ref
39c8c342a6SMilanka Ringwald    ref = code_ref.replace("GITHUB", githuburl)
40c8c342a6SMilanka Ringwald    ref = ref.replace("FPATH", filepath)
41c8c342a6SMilanka Ringwald    ref = ref.replace("LINENR", str(linenr))
42c8c342a6SMilanka Ringwald    return ref
43c8c342a6SMilanka Ringwald
44c8c342a6SMilanka Ringwald
45*d7ef0676SMilanka Ringwalddef writeAPI(fout, fin, mk_codeidentation):
46c8c342a6SMilanka Ringwald    state = State.SearchStartAPI
47*d7ef0676SMilanka Ringwald
48c8c342a6SMilanka Ringwald    for line in fin:
49c8c342a6SMilanka Ringwald        if state == State.SearchStartAPI:
50c8c342a6SMilanka Ringwald            parts = re.match('.*API_START.*',line)
51c8c342a6SMilanka Ringwald            if parts:
52c8c342a6SMilanka Ringwald                state = State.SearchEndAPI
53c8c342a6SMilanka Ringwald            continue
54c8c342a6SMilanka Ringwald
55c8c342a6SMilanka Ringwald        if state == State.SearchEndAPI:
56c8c342a6SMilanka Ringwald            parts = re.match('.*API_END.*',line)
57c8c342a6SMilanka Ringwald            if parts:
58c8c342a6SMilanka Ringwald                state = State.DoneAPI
59c8c342a6SMilanka Ringwald                continue
60c8c342a6SMilanka Ringwald            fout.write(mk_codeidentation + line)
61c8c342a6SMilanka Ringwald            continue
62c8c342a6SMilanka Ringwald
63c8c342a6SMilanka Ringwald
64c8c342a6SMilanka Ringwaldlinenr = 0
65c8c342a6SMilanka RingwaldtypedefFound = 0
66c8c342a6SMilanka Ringwaldmultiline_function_def = 0
67c8c342a6SMilanka Ringwaldstate = State.SearchStartAPI
68c8c342a6SMilanka Ringwald
69*d7ef0676SMilanka Ringwalddef createIndex(fin, api_filename, api_title, api_lable, githuburl):
70*d7ef0676SMilanka Ringwald    global typedefs, functions
71*d7ef0676SMilanka Ringwald    global linenr, multiline_function_def, typedefFound, state
72*d7ef0676SMilanka Ringwald
73*d7ef0676SMilanka Ringwald
74c8c342a6SMilanka Ringwald    for line in fin:
75c8c342a6SMilanka Ringwald        if state == State.DoneAPI:
76c8c342a6SMilanka Ringwald            continue
77c8c342a6SMilanka Ringwald
78c8c342a6SMilanka Ringwald        linenr = linenr + 1
79c8c342a6SMilanka Ringwald
80c8c342a6SMilanka Ringwald        if state == State.SearchStartAPI:
81c8c342a6SMilanka Ringwald            parts = re.match('.*API_START.*',line)
82c8c342a6SMilanka Ringwald            if parts:
83c8c342a6SMilanka Ringwald                state = State.SearchEndAPI
84c8c342a6SMilanka Ringwald            continue
85c8c342a6SMilanka Ringwald
86c8c342a6SMilanka Ringwald        if state == State.SearchEndAPI:
87c8c342a6SMilanka Ringwald            parts = re.match('.*API_END.*',line)
88c8c342a6SMilanka Ringwald            if parts:
89c8c342a6SMilanka Ringwald                state = State.DoneAPI
90c8c342a6SMilanka Ringwald                continue
91c8c342a6SMilanka Ringwald
92c8c342a6SMilanka Ringwald        if multiline_function_def:
93c8c342a6SMilanka Ringwald            function_end = re.match('.*;\n', line)
94c8c342a6SMilanka Ringwald            if function_end:
95c8c342a6SMilanka Ringwald                multiline_function_def = 0
96c8c342a6SMilanka Ringwald            continue
97c8c342a6SMilanka Ringwald
98c8c342a6SMilanka Ringwald        param = re.match(".*@brief.*", line)
99c8c342a6SMilanka Ringwald        if param:
100c8c342a6SMilanka Ringwald            continue
101c8c342a6SMilanka Ringwald        param = re.match(".*@param.*", line)
102c8c342a6SMilanka Ringwald        if param:
103c8c342a6SMilanka Ringwald            continue
104c8c342a6SMilanka Ringwald        param = re.match(".*@return.*", line)
105c8c342a6SMilanka Ringwald        if param:
106c8c342a6SMilanka Ringwald            continue
107c8c342a6SMilanka Ringwald
108c8c342a6SMilanka Ringwald        # search typedef struct begin
109*d7ef0676SMilanka Ringwald        if isTypedefStart(line):
110c8c342a6SMilanka Ringwald            typedefFound = 1
111c8c342a6SMilanka Ringwald
112c8c342a6SMilanka Ringwald        # search typedef struct end
113c8c342a6SMilanka Ringwald        if typedefFound:
114c8c342a6SMilanka Ringwald            typedef = re.match('}\s*(.*);\n', line)
115c8c342a6SMilanka Ringwald            if typedef:
116c8c342a6SMilanka Ringwald                typedefFound = 0
117*d7ef0676SMilanka Ringwald                typedefs[typedef.group(1)] = codeReference(typedef.group(1), githuburl, api_filename, linenr)
118c8c342a6SMilanka Ringwald            continue
119c8c342a6SMilanka Ringwald
120c8c342a6SMilanka Ringwald        ref_function =  re.match('.*typedef\s+void\s+\(\s*\*\s*(.*?)\)\(.*', line)
121c8c342a6SMilanka Ringwald        if ref_function:
122*d7ef0676SMilanka Ringwald            functions[ref_function.group(1)] = codeReference(ref_function.group(1), githuburl, api_filename, linenr)
123c8c342a6SMilanka Ringwald            continue
124c8c342a6SMilanka Ringwald
125*d7ef0676SMilanka Ringwald
126*d7ef0676SMilanka Ringwald        one_line_function_definition = re.match('(.*?)\s*\(.*\(*.*;\n', line)
127*d7ef0676SMilanka Ringwald        if one_line_function_definition:
128*d7ef0676SMilanka Ringwald            parts = one_line_function_definition.group(1).split(" ");
129c8c342a6SMilanka Ringwald            name = parts[len(parts)-1]
130c8c342a6SMilanka Ringwald            if len(name) == 0:
131c8c342a6SMilanka Ringwald                print(parts);
132c8c342a6SMilanka Ringwald                sys.exit(10)
133*d7ef0676SMilanka Ringwald            functions[name] = codeReference( name, githuburl, api_filename, linenr)
134c8c342a6SMilanka Ringwald            continue
135c8c342a6SMilanka Ringwald
136*d7ef0676SMilanka Ringwald        multi_line_function_definition = re.match('.(.*?)\s*\(.*\(*.*', line)
137*d7ef0676SMilanka Ringwald        if multi_line_function_definition:
138*d7ef0676SMilanka Ringwald            parts = multi_line_function_definition.group(1).split(" ");
139*d7ef0676SMilanka Ringwald
140*d7ef0676SMilanka Ringwald            name = parts[len(parts)-1]
141c8c342a6SMilanka Ringwald            if len(name) == 0:
142c8c342a6SMilanka Ringwald                print(parts);
143c8c342a6SMilanka Ringwald                sys.exit(10)
144c8c342a6SMilanka Ringwald            multiline_function_def = 1
145*d7ef0676SMilanka Ringwald            functions[name] = codeReference(name, githuburl, api_filename, linenr)
146c8c342a6SMilanka Ringwald
147c8c342a6SMilanka Ringwald
148*d7ef0676SMilanka Ringwalddef findTitle(fin):
149*d7ef0676SMilanka Ringwald    title = None
150*d7ef0676SMilanka Ringwald    desc = ""
151*d7ef0676SMilanka Ringwald    state = State.SearchTitle
152*d7ef0676SMilanka Ringwald
153*d7ef0676SMilanka Ringwald    for line in fin:
154*d7ef0676SMilanka Ringwald        if state == State.SearchTitle:
155*d7ef0676SMilanka Ringwald            if isStartOfComment(line):
156*d7ef0676SMilanka Ringwald                continue
157*d7ef0676SMilanka Ringwald
158*d7ef0676SMilanka Ringwald            parts = re.match('.*(@title)(.*)', line)
159*d7ef0676SMilanka Ringwald            if parts:
160*d7ef0676SMilanka Ringwald                title = parts.group(2).strip()
161*d7ef0676SMilanka Ringwald                state = State.SearchEndTitle
162*d7ef0676SMilanka Ringwald                continue
163*d7ef0676SMilanka Ringwald
164*d7ef0676SMilanka Ringwald        if state == State.SearchEndTitle:
165*d7ef0676SMilanka Ringwald            if (isEndOfComment(line)):
166*d7ef0676SMilanka Ringwald                state = State.DoneAPI
167*d7ef0676SMilanka Ringwald                break
168*d7ef0676SMilanka Ringwald
169*d7ef0676SMilanka Ringwald            parts = re.match('(\s*\*\s*)(.*\n)',line)
170*d7ef0676SMilanka Ringwald            if parts:
171*d7ef0676SMilanka Ringwald                desc = desc + parts.group(2)
172*d7ef0676SMilanka Ringwald    return title, desc
173*d7ef0676SMilanka Ringwald
174c8c342a6SMilanka Ringwalddef main(argv):
175*d7ef0676SMilanka Ringwald    global linenr, multiline_function_def, typedefFound, state
176*d7ef0676SMilanka Ringwald
177c8c342a6SMilanka Ringwald    mk_codeidentation = "    "
178c8c342a6SMilanka Ringwald    git_branch_name = "master"
179c8c342a6SMilanka Ringwald    btstackfolder = "../../"
180c8c342a6SMilanka Ringwald    githuburl  = "https://github.com/bluekitchen/btstack/blob/master/"
181c8c342a6SMilanka Ringwald    markdownfolder = "docs-markdown/"
182c8c342a6SMilanka Ringwald
183c8c342a6SMilanka Ringwald    cmd = 'markdown_create_apis.py [-r <root_btstackfolder>] [-g <githuburl>] [-o <output_markdownfolder>]'
184c8c342a6SMilanka Ringwald    try:
185c8c342a6SMilanka Ringwald        opts, args = getopt.getopt(argv,"r:g:o:",["rfolder=","github=","ofolder="])
186c8c342a6SMilanka Ringwald    except getopt.GetoptError:
187c8c342a6SMilanka Ringwald        print (cmd)
188c8c342a6SMilanka Ringwald        sys.exit(2)
189c8c342a6SMilanka Ringwald    for opt, arg in opts:
190c8c342a6SMilanka Ringwald        if opt == '-h':
191c8c342a6SMilanka Ringwald            print (cmd)
192c8c342a6SMilanka Ringwald            sys.exit()
193c8c342a6SMilanka Ringwald        elif opt in ("-r", "--rfolder"):
194c8c342a6SMilanka Ringwald            btstackfolder = arg
195c8c342a6SMilanka Ringwald        elif opt in ("-g", "--github"):
196c8c342a6SMilanka Ringwald            githuburl = arg
197c8c342a6SMilanka Ringwald        elif opt in ("-o", "--ofolder"):
198c8c342a6SMilanka Ringwald            markdownfolder = arg
199c8c342a6SMilanka Ringwald
200c8c342a6SMilanka Ringwald    apifile   = markdownfolder + "appendix/apis.md"
201c8c342a6SMilanka Ringwald    # indexfile = markdownfolder + "api_index.md"
202*d7ef0676SMilanka Ringwald    btstack_srcfolder = btstackfolder + "src/"
203c8c342a6SMilanka Ringwald
204c8c342a6SMilanka Ringwald    try:
205c8c342a6SMilanka Ringwald        output = subprocess.check_output("git symbolic-ref --short HEAD", stderr=subprocess.STDOUT, timeout=3, shell=True)
206c8c342a6SMilanka Ringwald        git_branch_name = output.decode().rstrip()
207c8c342a6SMilanka Ringwald    except subprocess.CalledProcessError as exc:
208c8c342a6SMilanka Ringwald        print('GIT branch name: failed to get, use default value \"%s\""  ', git_branch_name, exc.returncode, exc.output)
209c8c342a6SMilanka Ringwald    else:
210c8c342a6SMilanka Ringwald        print ('GIT branch name :  %s' % git_branch_name)
211c8c342a6SMilanka Ringwald
212c8c342a6SMilanka Ringwald    githuburl = githuburl + git_branch_name
213c8c342a6SMilanka Ringwald
214*d7ef0676SMilanka Ringwald    print ('BTstack src folder is : ' + btstack_srcfolder)
215c8c342a6SMilanka Ringwald    print ('API file is       : ' + apifile)
216c8c342a6SMilanka Ringwald    print ('Github URL is    : ' +  githuburl)
217c8c342a6SMilanka Ringwald    # print ('Index file is     : ' + indexfile)
218c8c342a6SMilanka Ringwald
219*d7ef0676SMilanka Ringwald
220*d7ef0676SMilanka Ringwald    for root, dirs, files in os.walk(btstack_srcfolder, topdown=True):
221*d7ef0676SMilanka Ringwald        for f in files:
222*d7ef0676SMilanka Ringwald            if not f.endswith(".h"):
223*d7ef0676SMilanka Ringwald                continue
224*d7ef0676SMilanka Ringwald            api_files.append(root + "/" + f)
225*d7ef0676SMilanka Ringwald
226*d7ef0676SMilanka Ringwald    api_files.sort()
227*d7ef0676SMilanka Ringwald
228*d7ef0676SMilanka Ringwald    print(api_files)
229*d7ef0676SMilanka Ringwald
230*d7ef0676SMilanka Ringwald    with open(apifile, 'w') as fout:
231*d7ef0676SMilanka Ringwald        fout.write("#\n\n")
232*d7ef0676SMilanka Ringwald
233*d7ef0676SMilanka Ringwald        for api_filename in api_files:
234*d7ef0676SMilanka Ringwald            api_title = None
235*d7ef0676SMilanka Ringwald            api_lable = None
236*d7ef0676SMilanka Ringwald
237*d7ef0676SMilanka Ringwald            print(api_filename)
238*d7ef0676SMilanka Ringwald
239*d7ef0676SMilanka Ringwald            with open(api_filename, 'r') as fin:
240*d7ef0676SMilanka Ringwald                api_title, api_desc = findTitle(fin)
241*d7ef0676SMilanka Ringwald                if api_title:
242*d7ef0676SMilanka Ringwald                    api_lable = f[:-2]
243*d7ef0676SMilanka Ringwald
244*d7ef0676SMilanka Ringwald                    title = api_header.replace("API_TITLE", api_title).replace("API_LABLE", api_lable)
245*d7ef0676SMilanka Ringwald                    fout.write(title)
246*d7ef0676SMilanka Ringwald                    fout.write(api_desc)
247*d7ef0676SMilanka Ringwald
248*d7ef0676SMilanka Ringwald                    writeAPI(fout, fin, mk_codeidentation)
249*d7ef0676SMilanka Ringwald                fin.close()
250*d7ef0676SMilanka Ringwald
251*d7ef0676SMilanka Ringwald            if api_title:
252*d7ef0676SMilanka Ringwald
253*d7ef0676SMilanka Ringwald                linenr = 0
254*d7ef0676SMilanka Ringwald                typedefFound = 0
255*d7ef0676SMilanka Ringwald                multiline_function_def = 0
256*d7ef0676SMilanka Ringwald                state = State.SearchStartAPI
257*d7ef0676SMilanka Ringwald
258*d7ef0676SMilanka Ringwald                with open(api_filename, 'r') as fin:
259*d7ef0676SMilanka Ringwald                    createIndex(fin, api_filename, api_title, api_lable, githuburl)
260*d7ef0676SMilanka Ringwald                    fin.close()
261c8c342a6SMilanka Ringwald
262c8c342a6SMilanka Ringwald    for function in functions:
263c8c342a6SMilanka Ringwald        parts = function.split(' ')
264c8c342a6SMilanka Ringwald        if (len(parts) > 1):
265c8c342a6SMilanka Ringwald            print (parts)
266c8c342a6SMilanka Ringwald
267c8c342a6SMilanka Ringwald    references = functions.copy()
268c8c342a6SMilanka Ringwald    references.update(typedefs)
269c8c342a6SMilanka Ringwald
270c8c342a6SMilanka Ringwald    # with open(indexfile, 'w') as fout:
271c8c342a6SMilanka Ringwald    #     for function, reference in references.items():
272c8c342a6SMilanka Ringwald    #         fout.write("[" + function + "](" + reference + ")\n")
273c8c342a6SMilanka Ringwald
274c8c342a6SMilanka Ringwald    pickle.dump(references, open("references.p", "wb" ) )
275c8c342a6SMilanka Ringwald
276c8c342a6SMilanka Ringwaldif __name__ == "__main__":
277c8c342a6SMilanka Ringwald   main(sys.argv[1:])
278