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