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