diff --git a/doc/manual/markdown_create_apis.py b/doc/manual/markdown_create_apis.py index fb16ac20b..295d87ea3 100755 --- a/doc/manual/markdown_create_apis.py +++ b/doc/manual/markdown_create_apis.py @@ -3,79 +3,13 @@ import os, sys, getopt, re, pickle import subprocess class State: - SearchStartAPI = 0 - SearchEndAPI = 1 - DoneAPI = 2 - -# [file_name, api_title, api_label] -apis = [ - ["src/ad_parser.h", "AD Data (Advertisements and EIR) Parser", "advParser"], - ["src/btstack_chipset.h","BTstack Chipset","btMemory"], - ["src/btstack_control.h","BTstack Hardware Control","btControl"], - ["src/btstack_event.h","HCI Event Getter","btEvent"], - ["src/btstack_linked_list.h","BTstack Linked List","btList"], - ["src/btstack_memory.h","BTstack Memory Management","btMemory"], - ["src/btstack_run_loop.h", "Run Loop", "runLoop"], - ["src/btstack_tlv.h", "Tag Value Length Persistent Storage (TLV)", "tlv"], - ["src/btstack_util.h", "Common Utils", "btUtil"], - ["src/btstack_hid.h", "HID", "hid"], - ["src/gap.h", "GAP", "gap"], - ["src/hci.h", "HCI", "hci"], - ["src/hci_dump.h","HCI Logging","hciTrace"], - ["src/hci_transport.h","HCI Transport","hciTransport"], - ["src/l2cap.h", "L2CAP", "l2cap"], - - ["src/ble/att_db_util.h", "ATT Database", "attDb"], - ["src/ble/att_server.h", "ATT Server", "attServer"], - ["src/ble/gatt_client.h", "GATT Client", "gattClient"], - ["src/ble/le_device_db.h", "Device Database", "leDeviceDb"], - ["src/ble/le_device_db_tlv.h", "Device Database TLV", "leDeviceDbTLV"], - ["src/ble/sm.h", "Security Manager", "sm"], - - ["src/ble/gatt-service/ancs_client.h", "ANCS Client", "ancsClient"], - ["src/ble/gatt-service/battery_service_client.h", "Battery Service Client", "gattclient_battery"], - ["src/ble/gatt-service/battery_service_server.h", "Battery Service Server", "batteryServiceServer"], - ["src/ble/gatt-service/cycling_power_service_server.h", "Cycling Power Service Server", "cyclingPowerServiceServer"], - ["src/ble/gatt-service/cycling_speed_and_cadence_service_server.h", "Cycling Speed and Cadence Service Server", "cyclingSpeedCadenceServiceServer"], - ["src/ble/gatt-service/device_information_service_client.h", "Device Information Service Client", "gattclient_device_information"], - ["src/ble/gatt-service/device_information_service_server.h", "Device Information Service Server", "deviceInformationServiceServer"], - ["src/ble/gatt-service/heart_rate_service_server.h", "Heart Rate Service Server", "heartRateServiceServer"], - ["src/ble/gatt-service/hids_device.h", "HID Device Service Server", "hidsDevice"], - ["src/ble/gatt-service/mesh_provisioning_service_server.h", "Mesh Provisioning Service Server", "meshProvisioningServiceServer"], - ["src/ble/gatt-service/mesh_proxy_service_server.h", "Mesh Proxy Service Server", "meshProxyServiceServer"], - ["src/ble/gatt-service/nordic_spp_service_server.h", "Nordic SPP Service Server", "nordicSppServiceServer"], - ["src/ble/gatt-service/scan_parameters_service_client.h", "Scan Parameters Service Client", "scanParametersServiceClient"], - ["src/ble/gatt-service/ublox_spp_service_server.h", "u-blox SPP Service Server", "ubloxSppServiceServer"], - - ["src/classic/a2dp_sink.h", "A2DP Sink", "a2dpSink"], - ["src/classic/a2dp_source.h", "A2DP Source", "a2dpSource"], - ["src/classic/avdtp_sink.h", "AVDTP Sink", "avdtpSink"], - ["src/classic/avdtp_source.h", "AVDTP Source", "avdtpSource"], - ["src/classic/avrcp_browsing_controller.h", "AVRCP Browsing Controller", "avrcpBrowsingController"], - ["src/classic/avrcp_browsing_target.h", "AVRCP Browsing Target", "avrcpBrowsingTarget"], - ["src/classic/avrcp_controller.h", "AVRCP Controller", "avrcpController"], - ["src/classic/avrcp_target.h", "AVRCP Target", "avrcpTarget"], - ["src/classic/bnep.h", "BNEP", "bnep"], - ["src/classic/btstack_link_key_db.h","Link Key DB","lkDb"], - ["src/classic/btstack_sbc.h", "SBC", "sbc"], - ["src/classic/device_id_server.h", "Device ID Server", "deviceIdServer"], - ["src/classic/gatt_sdp.h", "GATT SDP", "gattSdp"], - ["src/classic/goep_client.h", "GOEP Client", "goepClient"], - ["src/classic/hfp_ag.h","HFP Audio Gateway","hfpAG"], - ["src/classic/hfp_hf.h","HFP Hands-Free","hfpHF"], - ["src/classic/hid_device.h", "HID Device", "hidDevice"], - ["src/classic/hid_host.h", "HID Host", "hidHost"], - ["src/classic/hsp_ag.h","HSP Audio Gateway","hspAG"], - ["src/classic/hsp_hs.h","HSP Headset","hspHS"], - ["src/classic/pan.h", "PAN", "pan"], - ["src/classic/pbap_client.h", "PBAP Client", "pbapClient"], - ["src/classic/rfcomm.h", "RFCOMM", "rfcomm"], - ["src/classic/sdp_client.h", "SDP Client", "sdpClient"], - ["src/classic/sdp_client_rfcomm.h", "SDP RFCOMM Query", "sdpQueries"], - ["src/classic/sdp_server.h", "SDP Server", "sdpSrv"], - ["src/classic/sdp_util.h","SDP Utils", "sdpUtil"], -] + SearchTitle = 0 + SearchEndTitle = 1 + SearchStartAPI = 2 + SearchEndAPI = 3 + DoneAPI = 4 +api_files = [] functions = {} typedefs = {} @@ -91,6 +25,15 @@ api_ending = """ code_ref = """GITHUBFPATH#LLINENR""" +def isEndOfComment(line): + return re.match('\s*\*/.*', line) + +def isStartOfComment(line): + return re.match('\s*\/\*/.*', line) + +def isTypedefStart(line): + return re.match('.*typedef\s+struct.*', line) + def codeReference(fname, githuburl, filepath, linenr): global code_ref ref = code_ref.replace("GITHUB", githuburl) @@ -99,123 +42,138 @@ def codeReference(fname, githuburl, filepath, linenr): return ref -def writeAPI(apifile, btstackfolder, apis, mk_codeidentation): - with open(apifile, 'w') as fout: - fout.write("#\n\n") - for api_tuple in apis: - api_filename = btstackfolder + api_tuple[0] - api_title = api_tuple[1] - api_lable = api_tuple[2] - - title = api_header.replace("API_TITLE", api_title).replace("API_LABLE", api_lable) - fout.write(title) - - state = State.SearchStartAPI - with open(api_filename, 'r') as fin: - for line in fin: - if state == State.SearchStartAPI: - parts = re.match('.*API_START.*',line) - if parts: - state = State.SearchEndAPI - continue - - if state == State.SearchEndAPI: - parts = re.match('.*API_END.*',line) - if parts: - state = State.DoneAPI - continue - fout.write(mk_codeidentation + line) - continue - - -def createIndex(btstackfolder, apis, githuburl): - global typedefs, functions +def writeAPI(fout, fin, mk_codeidentation): + state = State.SearchStartAPI - for api_tuple in apis: - api_filename = btstackfolder + api_tuple[0] - api_title = api_tuple[1] - api_lable = api_tuple[2] + for line in fin: + if state == State.SearchStartAPI: + parts = re.match('.*API_START.*',line) + if parts: + state = State.SearchEndAPI + continue + + if state == State.SearchEndAPI: + parts = re.match('.*API_END.*',line) + if parts: + state = State.DoneAPI + continue + fout.write(mk_codeidentation + line) + continue - linenr = 0 - with open(api_filename, 'r') as fin: - typedefFound = 0 - multiline_function_def = 0 - state = State.SearchStartAPI - - for line in fin: - if state == State.DoneAPI: - continue - linenr = linenr + 1 - - if state == State.SearchStartAPI: - parts = re.match('.*API_START.*',line) - if parts: - state = State.SearchEndAPI - continue - - if state == State.SearchEndAPI: - parts = re.match('.*API_END.*',line) - if parts: - state = State.DoneAPI - continue +linenr = 0 +typedefFound = 0 +multiline_function_def = 0 +state = State.SearchStartAPI - if multiline_function_def: - function_end = re.match('.*;\n', line) - if function_end: - multiline_function_def = 0 - continue +def createIndex(fin, api_filename, api_title, api_lable, githuburl): + global typedefs, functions + global linenr, multiline_function_def, typedefFound, state + + + for line in fin: + if state == State.DoneAPI: + continue - param = re.match(".*@brief.*", line) - if param: - continue - param = re.match(".*@param.*", line) - if param: - continue - param = re.match(".*@return.*", line) - if param: - continue - - # search typedef struct begin - typedef = re.match('.*typedef\s+struct.*', line) - if typedef: - typedefFound = 1 - - # search typedef struct end - if typedefFound: - typedef = re.match('}\s*(.*);\n', line) - if typedef: - typedefFound = 0 - typedefs[typedef.group(1)] = codeReference(typedef.group(1), githuburl, api_tuple[0], linenr) - continue + linenr = linenr + 1 + + if state == State.SearchStartAPI: + parts = re.match('.*API_START.*',line) + if parts: + state = State.SearchEndAPI + continue + + if state == State.SearchEndAPI: + parts = re.match('.*API_END.*',line) + if parts: + state = State.DoneAPI + continue - ref_function = re.match('.*typedef\s+void\s+\(\s*\*\s*(.*?)\)\(.*', line) - if ref_function: - functions[ref_function.group(1)] = codeReference(ref_function.group(1), githuburl, api_tuple[0], linenr) - continue + if multiline_function_def: + function_end = re.match('.*;\n', line) + if function_end: + multiline_function_def = 0 + continue - function = re.match('(.*?)\s*\(.*\(*.*;\n', line) - if function: - parts = function.group(1).split(" "); - name = parts[len(parts)-1] - if len(name) == 0: - print(parts); - sys.exit(10) - functions[name] = codeReference( name, githuburl, api_tuple[0], linenr) - continue + param = re.match(".*@brief.*", line) + if param: + continue + param = re.match(".*@param.*", line) + if param: + continue + param = re.match(".*@return.*", line) + if param: + continue + + # search typedef struct begin + if isTypedefStart(line): + typedefFound = 1 + + # search typedef struct end + if typedefFound: + typedef = re.match('}\s*(.*);\n', line) + if typedef: + typedefFound = 0 + typedefs[typedef.group(1)] = codeReference(typedef.group(1), githuburl, api_filename, linenr) + continue - function = re.match('.(.*?)\s*\(.*\(*.*', line) - if function: - if len(name) == 0: - print(parts); - sys.exit(10) - parts = function.group(1).split(" "); - name = parts[len(parts)-1] - multiline_function_def = 1 - functions[name] = codeReference(name, githuburl, api_tuple[0], linenr) + ref_function = re.match('.*typedef\s+void\s+\(\s*\*\s*(.*?)\)\(.*', line) + if ref_function: + functions[ref_function.group(1)] = codeReference(ref_function.group(1), githuburl, api_filename, linenr) + continue + + + one_line_function_definition = re.match('(.*?)\s*\(.*\(*.*;\n', line) + if one_line_function_definition: + parts = one_line_function_definition.group(1).split(" "); + name = parts[len(parts)-1] + if len(name) == 0: + print(parts); + sys.exit(10) + functions[name] = codeReference( name, githuburl, api_filename, linenr) + continue + + multi_line_function_definition = re.match('.(.*?)\s*\(.*\(*.*', line) + if multi_line_function_definition: + parts = multi_line_function_definition.group(1).split(" "); + + name = parts[len(parts)-1] + if len(name) == 0: + print(parts); + sys.exit(10) + multiline_function_def = 1 + functions[name] = codeReference(name, githuburl, api_filename, linenr) + + +def findTitle(fin): + title = None + desc = "" + state = State.SearchTitle + + for line in fin: + if state == State.SearchTitle: + if isStartOfComment(line): + continue + + parts = re.match('.*(@title)(.*)', line) + if parts: + title = parts.group(2).strip() + state = State.SearchEndTitle + continue + + if state == State.SearchEndTitle: + if (isEndOfComment(line)): + state = State.DoneAPI + break + + parts = re.match('(\s*\*\s*)(.*\n)',line) + if parts: + desc = desc + parts.group(2) + return title, desc - def main(argv): + global linenr, multiline_function_def, typedefFound, state + mk_codeidentation = " " git_branch_name = "master" btstackfolder = "../../" @@ -241,6 +199,7 @@ def main(argv): apifile = markdownfolder + "appendix/apis.md" # indexfile = markdownfolder + "api_index.md" + btstack_srcfolder = btstackfolder + "src/" try: output = subprocess.check_output("git symbolic-ref --short HEAD", stderr=subprocess.STDOUT, timeout=3, shell=True) @@ -252,13 +211,53 @@ def main(argv): githuburl = githuburl + git_branch_name - print ('BTstack folder is : ' + btstackfolder) + print ('BTstack src folder is : ' + btstack_srcfolder) print ('API file is : ' + apifile) print ('Github URL is : ' + githuburl) # print ('Index file is : ' + indexfile) - writeAPI(apifile, btstackfolder, apis, mk_codeidentation) - createIndex(btstackfolder, apis, githuburl) + + for root, dirs, files in os.walk(btstack_srcfolder, topdown=True): + for f in files: + if not f.endswith(".h"): + continue + api_files.append(root + "/" + f) + + api_files.sort() + + print(api_files) + + with open(apifile, 'w') as fout: + fout.write("#\n\n") + + for api_filename in api_files: + api_title = None + api_lable = None + + print(api_filename) + + with open(api_filename, 'r') as fin: + api_title, api_desc = findTitle(fin) + if api_title: + api_lable = f[:-2] + + title = api_header.replace("API_TITLE", api_title).replace("API_LABLE", api_lable) + fout.write(title) + fout.write(api_desc) + + writeAPI(fout, fin, mk_codeidentation) + fin.close() + + if api_title: + + linenr = 0 + typedefFound = 0 + multiline_function_def = 0 + state = State.SearchStartAPI + + with open(api_filename, 'r') as fin: + createIndex(fin, api_filename, api_title, api_lable, githuburl) + fin.close() for function in functions: parts = function.split(' ')