1#!/usr/bin/env python3 2import os, sys, getopt, re, pickle 3import subprocess 4 5class State: 6 SearchStartAPI = 0 7 SearchEndAPI = 1 8 DoneAPI = 2 9 10# [file_name, api_title, api_label] 11apis = [ 12 ["src/ad_parser.h", "AD Data (Advertisements and EIR) Parser", "advParser"], 13 ["src/btstack_chipset.h","BTstack Chipset","btMemory"], 14 ["src/btstack_control.h","BTstack Hardware Control","btControl"], 15 ["src/btstack_event.h","HCI Event Getter","btEvent"], 16 ["src/btstack_linked_list.h","BTstack Linked List","btList"], 17 ["src/btstack_memory.h","BTstack Memory Management","btMemory"], 18 ["src/btstack_run_loop.h", "Run Loop", "runLoop"], 19 ["src/btstack_tlv.h", "Tag Value Length Persistent Storage (TLV)", "tlv"], 20 ["src/btstack_util.h", "Common Utils", "btUtil"], 21 ["src/btstack_hid.h", "HID", "hid"], 22 ["src/gap.h", "GAP", "gap"], 23 ["src/hci.h", "HCI", "hci"], 24 ["src/hci_dump.h","HCI Logging","hciTrace"], 25 ["src/hci_transport.h","HCI Transport","hciTransport"], 26 ["src/l2cap.h", "L2CAP", "l2cap"], 27 28 ["src/ble/att_db_util.h", "ATT Database", "attDb"], 29 ["src/ble/att_server.h", "ATT Server", "attServer"], 30 ["src/ble/gatt_client.h", "GATT Client", "gattClient"], 31 ["src/ble/le_device_db.h", "Device Database", "leDeviceDb"], 32 ["src/ble/le_device_db_tlv.h", "Device Database TLV", "leDeviceDbTLV"], 33 ["src/ble/sm.h", "Security Manager", "sm"], 34 35 ["src/ble/gatt-service/ancs_client.h", "ANCS Client", "ancsClient"], 36 ["src/ble/gatt-service/battery_service_client.h", "Battery Service Client", "gattclient_battery"], 37 ["src/ble/gatt-service/battery_service_server.h", "Battery Service Server", "batteryServiceServer"], 38 ["src/ble/gatt-service/cycling_power_service_server.h", "Cycling Power Service Server", "cyclingPowerServiceServer"], 39 ["src/ble/gatt-service/cycling_speed_and_cadence_service_server.h", "Cycling Speed and Cadence Service Server", "cyclingSpeedCadenceServiceServer"], 40 ["src/ble/gatt-service/device_information_service_client.h", "Device Information Service Client", "gattclient_device_information"], 41 ["src/ble/gatt-service/device_information_service_server.h", "Device Information Service Server", "deviceInformationServiceServer"], 42 ["src/ble/gatt-service/heart_rate_service_server.h", "Heart Rate Service Server", "heartRateServiceServer"], 43 ["src/ble/gatt-service/hids_device.h", "HID Device Service Server", "hidsDevice"], 44 ["src/ble/gatt-service/mesh_provisioning_service_server.h", "Mesh Provisioning Service Server", "meshProvisioningServiceServer"], 45 ["src/ble/gatt-service/mesh_proxy_service_server.h", "Mesh Proxy Service Server", "meshProxyServiceServer"], 46 ["src/ble/gatt-service/nordic_spp_service_server.h", "Nordic SPP Service Server", "nordicSppServiceServer"], 47 ["src/ble/gatt-service/scan_parameters_service_client.h", "Scan Parameters Service Client", "scanParametersServiceClient"], 48 ["src/ble/gatt-service/ublox_spp_service_server.h", "u-blox SPP Service Server", "ubloxSppServiceServer"], 49 50 ["src/classic/a2dp_sink.h", "A2DP Sink", "a2dpSink"], 51 ["src/classic/a2dp_source.h", "A2DP Source", "a2dpSource"], 52 ["src/classic/avdtp_sink.h", "AVDTP Sink", "avdtpSink"], 53 ["src/classic/avdtp_source.h", "AVDTP Source", "avdtpSource"], 54 ["src/classic/avrcp_browsing_controller.h", "AVRCP Browsing Controller", "avrcpBrowsingController"], 55 ["src/classic/avrcp_browsing_target.h", "AVRCP Browsing Target", "avrcpBrowsingTarget"], 56 ["src/classic/avrcp_controller.h", "AVRCP Controller", "avrcpController"], 57 ["src/classic/avrcp_target.h", "AVRCP Target", "avrcpTarget"], 58 ["src/classic/bnep.h", "BNEP", "bnep"], 59 ["src/classic/btstack_link_key_db.h","Link Key DB","lkDb"], 60 ["src/classic/btstack_sbc.h", "SBC", "sbc"], 61 ["src/classic/device_id_server.h", "Device ID Server", "deviceIdServer"], 62 ["src/classic/gatt_sdp.h", "GATT SDP", "gattSdp"], 63 ["src/classic/goep_client.h", "GOEP Client", "goepClient"], 64 ["src/classic/hfp_ag.h","HFP Audio Gateway","hfpAG"], 65 ["src/classic/hfp_hf.h","HFP Hands-Free","hfpHF"], 66 ["src/classic/hid_device.h", "HID Device", "hidDevice"], 67 ["src/classic/hid_host.h", "HID Host", "hidHost"], 68 ["src/classic/hsp_ag.h","HSP Audio Gateway","hspAG"], 69 ["src/classic/hsp_hs.h","HSP Headset","hspHS"], 70 ["src/classic/pan.h", "PAN", "pan"], 71 ["src/classic/pbap_client.h", "PBAP Client", "pbapClient"], 72 ["src/classic/rfcomm.h", "RFCOMM", "rfcomm"], 73 ["src/classic/sdp_client.h", "SDP Client", "sdpClient"], 74 ["src/classic/sdp_client_rfcomm.h", "SDP RFCOMM Query", "sdpQueries"], 75 ["src/classic/sdp_server.h", "SDP Server", "sdpSrv"], 76 ["src/classic/sdp_util.h","SDP Utils", "sdpUtil"], 77] 78 79functions = {} 80typedefs = {} 81 82api_header = """ 83 84## API_TITLE API {#sec:API_LABLEAPIAppendix} 85 86""" 87 88api_ending = """ 89""" 90 91code_ref = """GITHUBFPATH#LLINENR""" 92 93 94def codeReference(fname, githuburl, filepath, linenr): 95 global code_ref 96 ref = code_ref.replace("GITHUB", githuburl) 97 ref = ref.replace("FPATH", filepath) 98 ref = ref.replace("LINENR", str(linenr)) 99 return ref 100 101 102def writeAPI(apifile, btstackfolder, apis, mk_codeidentation): 103 with open(apifile, 'w') as fout: 104 fout.write("#\n\n") 105 for api_tuple in apis: 106 api_filename = btstackfolder + api_tuple[0] 107 api_title = api_tuple[1] 108 api_lable = api_tuple[2] 109 110 title = api_header.replace("API_TITLE", api_title).replace("API_LABLE", api_lable) 111 fout.write(title) 112 113 state = State.SearchStartAPI 114 with open(api_filename, 'r') as fin: 115 for line in fin: 116 if state == State.SearchStartAPI: 117 parts = re.match('.*API_START.*',line) 118 if parts: 119 state = State.SearchEndAPI 120 continue 121 122 if state == State.SearchEndAPI: 123 parts = re.match('.*API_END.*',line) 124 if parts: 125 state = State.DoneAPI 126 continue 127 fout.write(mk_codeidentation + line) 128 continue 129 130 131def createIndex(btstackfolder, apis, githuburl): 132 global typedefs, functions 133 134 for api_tuple in apis: 135 api_filename = btstackfolder + api_tuple[0] 136 api_title = api_tuple[1] 137 api_lable = api_tuple[2] 138 139 linenr = 0 140 with open(api_filename, 'r') as fin: 141 typedefFound = 0 142 multiline_function_def = 0 143 state = State.SearchStartAPI 144 145 for line in fin: 146 if state == State.DoneAPI: 147 continue 148 149 linenr = linenr + 1 150 151 if state == State.SearchStartAPI: 152 parts = re.match('.*API_START.*',line) 153 if parts: 154 state = State.SearchEndAPI 155 continue 156 157 if state == State.SearchEndAPI: 158 parts = re.match('.*API_END.*',line) 159 if parts: 160 state = State.DoneAPI 161 continue 162 163 if multiline_function_def: 164 function_end = re.match('.*;\n', line) 165 if function_end: 166 multiline_function_def = 0 167 continue 168 169 param = re.match(".*@brief.*", line) 170 if param: 171 continue 172 param = re.match(".*@param.*", line) 173 if param: 174 continue 175 param = re.match(".*@return.*", line) 176 if param: 177 continue 178 179 # search typedef struct begin 180 typedef = re.match('.*typedef\s+struct.*', line) 181 if typedef: 182 typedefFound = 1 183 184 # search typedef struct end 185 if typedefFound: 186 typedef = re.match('}\s*(.*);\n', line) 187 if typedef: 188 typedefFound = 0 189 typedefs[typedef.group(1)] = codeReference(typedef.group(1), githuburl, api_tuple[0], linenr) 190 continue 191 192 ref_function = re.match('.*typedef\s+void\s+\(\s*\*\s*(.*?)\)\(.*', line) 193 if ref_function: 194 functions[ref_function.group(1)] = codeReference(ref_function.group(1), githuburl, api_tuple[0], linenr) 195 continue 196 197 function = re.match('(.*?)\s*\(.*\(*.*;\n', line) 198 if function: 199 parts = function.group(1).split(" "); 200 name = parts[len(parts)-1] 201 if len(name) == 0: 202 print(parts); 203 sys.exit(10) 204 functions[name] = codeReference( name, githuburl, api_tuple[0], linenr) 205 continue 206 207 function = re.match('.(.*?)\s*\(.*\(*.*', line) 208 if function: 209 if len(name) == 0: 210 print(parts); 211 sys.exit(10) 212 parts = function.group(1).split(" "); 213 name = parts[len(parts)-1] 214 multiline_function_def = 1 215 functions[name] = codeReference(name, githuburl, api_tuple[0], linenr) 216 217 218def main(argv): 219 mk_codeidentation = " " 220 git_branch_name = "master" 221 btstackfolder = "../../" 222 githuburl = "https://github.com/bluekitchen/btstack/blob/master/" 223 markdownfolder = "docs-markdown/" 224 225 cmd = 'markdown_create_apis.py [-r <root_btstackfolder>] [-g <githuburl>] [-o <output_markdownfolder>]' 226 try: 227 opts, args = getopt.getopt(argv,"r:g:o:",["rfolder=","github=","ofolder="]) 228 except getopt.GetoptError: 229 print (cmd) 230 sys.exit(2) 231 for opt, arg in opts: 232 if opt == '-h': 233 print (cmd) 234 sys.exit() 235 elif opt in ("-r", "--rfolder"): 236 btstackfolder = arg 237 elif opt in ("-g", "--github"): 238 githuburl = arg 239 elif opt in ("-o", "--ofolder"): 240 markdownfolder = arg 241 242 apifile = markdownfolder + "appendix/apis.md" 243 # indexfile = markdownfolder + "api_index.md" 244 245 try: 246 output = subprocess.check_output("git symbolic-ref --short HEAD", stderr=subprocess.STDOUT, timeout=3, shell=True) 247 git_branch_name = output.decode().rstrip() 248 except subprocess.CalledProcessError as exc: 249 print('GIT branch name: failed to get, use default value \"%s\"" ', git_branch_name, exc.returncode, exc.output) 250 else: 251 print ('GIT branch name : %s' % git_branch_name) 252 253 githuburl = githuburl + git_branch_name 254 255 print ('BTstack folder is : ' + btstackfolder) 256 print ('API file is : ' + apifile) 257 print ('Github URL is : ' + githuburl) 258 # print ('Index file is : ' + indexfile) 259 260 writeAPI(apifile, btstackfolder, apis, mk_codeidentation) 261 createIndex(btstackfolder, apis, githuburl) 262 263 for function in functions: 264 parts = function.split(' ') 265 if (len(parts) > 1): 266 print (parts) 267 268 references = functions.copy() 269 references.update(typedefs) 270 271 # with open(indexfile, 'w') as fout: 272 # for function, reference in references.items(): 273 # fout.write("[" + function + "](" + reference + ")\n") 274 275 pickle.dump(references, open("references.p", "wb" ) ) 276 277if __name__ == "__main__": 278 main(sys.argv[1:]) 279