对mc可以使用this["m_" + index]的变量名称方式,

package com.jnj.rsc.action; import com.jnj.rsc.service.RscConfigService; import com.jnj.rsc.utils.RscUtil; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import weaver.conn.RecordSet; import weaver.general.BaseBean; import weaver.general.Util; import weaver.interfaces.workflow.action.Action; import weaver.soa.workflow.request.RequestInfo; import weaver.workflow.workflow.WorkflowComInfo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Wf_5 调用 * * 1.MDRIM拉取相关数据,获取material * 2.把materialnumber,Physical Mf, Approved Manufacturer Sites传给Machine Learning * 3.Machine Learning返回值写入到:score->ML result, expectation->ML message * 4.ML result拼接后回写到明细表1 Single PM Data */ public class Wf_5_CallMlByMdrim_Action extends BaseBean implements Action { private final static String ACTION_NAME = " Wf_5_CallMlByMdrim_Action V2 "; private String apiUrl; public String getApiUrl() { return apiUrl; } public void setApiUrl(String apiUrl) { this.apiUrl = apiUrl; } @Override public String execute(RequestInfo requestInfo) { WorkflowComInfo workflowComInfo = new WorkflowComInfo(); int requestid = Util.getIntValue(requestInfo.getRequestid()); try { this.writeLog("************** " + ACTION_NAME + " start , requestId: " + requestid); String workflowId = requestInfo.getWorkflowid(); int formid = Util.getIntValue(workflowComInfo.getFormId(workflowId), 0); String mainTablename = "formtable_main_" + (formid * -1); RecordSet rs = new RecordSet(); RecordSet innerRs = new RecordSet(); RecordSet updateRs = new RecordSet(); String sql = "select * from " + mainTablename + " where requestid = '" + requestid + "'"; this.writeLog(ACTION_NAME + " action main sql:" + sql); rs.executeQuery(sql); String mainId = ""; if (rs.next()) { mainId = Util.null2String(rs.getString("id")); } //MDRIM拉取相关数据,获取material String dt1Sql = "select id, market, approvedmanufacturersites, sapmaterialnumber, registrationlicensenumberforra, registrationlicenseissuedatefo, localproductcode, mdrimuniquelicenseid,localbusinessunit from " + mainTablename + "_dt1 where mainid = '" + mainId + "'"; // this.writeLog(ACTION_NAME + " action main dt1Sql:" + dt1Sql); rs.execute(dt1Sql); String insertSql = "insert into " + mainTablename + "_dt2 (mainid, dt1_uuid,countryId, catalognumber, materialnumber, physicalmf, approvedmanufacturersites,sapmaterialnumber,localbusinessunit, mdrimSeq, mdrimuniquelicenseid, localproductcode) values (?,?,?,?,?,?,?,?,?,?,?,?)"; List<List> batchParamList = new ArrayList<List>(); Map<String, Map<String, String>> linIdAndProCodeMap = new HashMap<>(); JSONArray dt1DataArray = new JSONArray(); while (rs.next()) { String uuid = Util.null2String(rs.getString("id")); String countryId = Util.null2String(rs.getString("market")); String approvedmanufacturersites = Util.null2String(rs.getString("approvedmanufacturersites")); String sapmaterialnumber = Util.null2String(rs.getString("sapmaterialnumber")); String registrationlicensenumberforra = Util.null2String(rs.getString("registrationlicensenumberforra")); String registrationlicenseissuedatefo = Util.null2String(rs.getString("registrationlicenseissuedatefo")); String localproductcode = Util.null2String(rs.getString("localproductcode")); String mdrimuniquelicenseid = Util.null2String(rs.getString("mdrimuniquelicenseid")); String localBusinessUnit = Util.null2String(rs.getString("localbusinessunit")); if ("".equals(mdrimuniquelicenseid)){ continue; } JSONObject linIdObj = new JSONObject(); linIdObj.put("uuid", uuid); linIdObj.put("countryId", countryId); linIdObj.put("approvedmanufacturersites", approvedmanufacturersites); linIdObj.put("sapmaterialnumber", sapmaterialnumber); linIdObj.put("registrationlicensenumberforra", registrationlicensenumberforra); linIdObj.put("registrationlicenseissuedatefo", registrationlicenseissuedatefo); linIdObj.put("localproductcode", localproductcode); linIdObj.put("mdrimuniquelicenseid", mdrimuniquelicenseid); linIdObj.put("localbusinessunit", localBusinessUnit); dt1DataArray.add(linIdObj); Map<String, String> productCodeMap = linIdAndProCodeMap.get(mdrimuniquelicenseid); if (productCodeMap == null){ productCodeMap = new HashMap<>(); } productCodeMap.put(localproductcode, ""); linIdAndProCodeMap.put(mdrimuniquelicenseid, productCodeMap); } Map<String, JSONObject> canInputMap = new HashMap<>(); StringBuffer sber = new StringBuffer(); String linId = ""; for (Map.Entry<String, Map<String, String>> entry : linIdAndProCodeMap.entrySet()) { sber.delete(0, sber.length()); linId = entry.getKey(); for (Map.Entry<String, String> p : entry.getValue().entrySet()) { if (sber.toString().length() == 0){ sber.append(p.getKey()); } else { sber.append(","); sber.append(p.getKey()); } } //按 linId 和 sber分组去调用Mdrim接口 callMdrim(sber, linId, dt1DataArray, canInputMap); this.writeLog(ACTION_NAME + " action sber :" + sber.toString()); this.writeLog(ACTION_NAME + " action linId :" + linId); this.writeLog(ACTION_NAME + " action dt1DataArray size :" + dt1DataArray.size()); this.writeLog(ACTION_NAME + " action canInputMap size :" + canInputMap.size()); } //2.有两个同样的,合并 3.加流水号存一下 mdrimSeq ,然后Call ML int mdrimSeq = 0; for (Map.Entry<String, JSONObject> m : canInputMap.entrySet()) { mdrimSeq++; JSONObject value = m.getValue(); List<Object> paramlist = new ArrayList<Object>(); paramlist.add(mainId); paramlist.add(Util.null2String(value.getString("uuid"))); paramlist.add(Util.null2String(value.getString("countryId"))); paramlist.add(Util.null2String(value.getString("p_Catalog_Number"))); //->catalognumber paramlist.add(Util.null2String(value.getString("p_Material_Number")));//DOTO Can ship col1 col2 col3 paramlist.add(Util.null2String(value.getString("p_Physical_Manufacturer"))); //->physicalmf paramlist.add(Util.null2String(value.getString("approvedmanufacturersites"))); paramlist.add(Util.null2String(value.getString("sapmaterialnumber"))); paramlist.add(Util.null2String(value.getString("localbusinessunit"))); paramlist.add(mdrimSeq); paramlist.add(Util.null2String(value.getString("mdrimuniquelicenseid"))); paramlist.add(Util.null2String(value.getString("localproductcode"))); batchParamList.add(paramlist); } if (batchParamList.size() > 0) { updateRs.execute("delete from " + mainTablename + "_dt2 where mainid=" + mainId); updateRs.executeBatchSql(insertSql, batchParamList); } else { return failureInfo(requestInfo, requestid, "Mdrim数据不存在"); } //把materialnumber,Physical Mf, Approved Manufacturer Sites传给Machine Learning String dt2Sql = "select mdrimSeq,physicalmf,approvedmanufacturersites from " + mainTablename + "_dt2 where mainid = '" + mainId + "'"; rs.execute(dt2Sql); this.writeLog(ACTION_NAME + " ,,,dt2Sql rs count : " + rs.getCounts()); JSONArray data = new JSONArray(); while (rs.next()) { JSONObject jsonObject = new JSONObject(); jsonObject.put("Id", Util.null2String(rs.getString("mdrimSeq"))); jsonObject.put("Physical Manufacturer", Util.null2String(rs.getString("physicalmf"))); String approvedmanufacturersites = Util.null2String(rs.getString("approvedmanufacturersites")).replaceAll(" ", " "); approvedmanufacturersites = approvedmanufacturersites.replaceAll("(\\\\r\\\\n|\\\\n|\\\\n\\\\r)", " "); approvedmanufacturersites = approvedmanufacturersites.replaceAll("<br>", ""); approvedmanufacturersites = approvedmanufacturersites.replaceAll("<br/>", ""); jsonObject.put("License PM", approvedmanufacturersites); data.add(jsonObject); } //Machine Learning请求参数 JSONObject params = new JSONObject(); JSONObject inputsObj = new JSONObject(); inputsObj.put("Data", data); params.put("inputs", inputsObj); Integer pLen = params.toString().length(); // this.writeLog(ACTION_NAME + " ,,,len : " + pLen); // int ps = 500; // int page = pLen / ps; // int i = 0; // if (pLen <= ps) { // this.writeLog(ACTION_NAME + " ,,,resultObj last: " + params.toString()); // } else { // for (i = 0; i < page; i++) { // this.writeLog(ACTION_NAME + " ,,,resultObj " + i + " : " + params.toString().substring(i * ps, (i + 1) * 500)); // } // this.writeLog(ACTION_NAME + " ,,,resultObj last: " + params.toString().substring((i - 1) * 500)); // } //Call ML String result = RscUtil.httpsPost(getApiUrl(), params.toString()); this.writeLog(ACTION_NAME + " ,,,result : " + result.length()); if (!"".equals(result)) { JSONObject resultObj = JSONObject.fromObject(result); Object outputs = resultObj.get("outputs"); if (outputs != null) { JSONObject resultsObj = JSONObject.fromObject(outputs.toString()); JSONArray resultsArray = JSONArray.fromObject(resultsObj.get("Results").toString()); List<List> batchUpdateList = new ArrayList<List>(); for (int j = 0; j < resultsArray.size(); j++) { JSONObject obj = (JSONObject) resultsArray.get(j); List<Object> paramlist = new ArrayList<Object>(); paramlist.add(obj.getString("max_similarity_score")); paramlist.add(obj.getString("pm_expectation")); paramlist.add(obj.getString("pm_expectation")); paramlist.add(mainId); paramlist.add(obj.getString("Id")); batchUpdateList.add(paramlist); } String updateSql = "update " + mainTablename + "_dt2 set mlresult=?,mlmessage=?,mlreference=? where mainid=? and mdrimSeq=?"; updateRs.executeBatchSql(updateSql, batchUpdateList); } } //ML result拼接后回写到明细表1 Single PM Data String dt2GroupSql = "select sapmaterialnumber, mdrimuniquelicenseid from " + mainTablename + "_dt2 where mainid = '" + mainId + "' group by sapmaterialnumber, mdrimuniquelicenseid"; rs.execute(dt2GroupSql); Map<String, String> materialnumberMap = new HashMap<>(); while (rs.next()) { String materialnumber = Util.null2String(rs.getString("sapmaterialnumber")); String mdrimuniquelicenseid = Util.null2String(rs.getString("mdrimuniquelicenseid")); materialnumberMap.put(mdrimuniquelicenseid + "@" + materialnumber, materialnumber); } this.writeLog(ACTION_NAME + " ,,,materialnumberMap size : " + materialnumberMap.size()); List<List> batchUpdateList = new ArrayList<List>(); for (Map.Entry<String, String> entry : materialnumberMap.entrySet()) { String[] keys = entry.getKey().split("@"); String dt2MaterialSql = "select distinct materialnumber,mlreference,localbusinessunit,mdrimuniquelicenseid,localproductcode" + " from " + mainTablename + "_dt2 where mainid = '" + mainId + "' and sapmaterialnumber='" + keys[1] + "' and mdrimuniquelicenseid='" + keys[0] + "'"; rs.execute(dt2MaterialSql); StringBuffer pingjieBf = new StringBuffer(); int flag = 0; String modeCode1 = ""; String modeCode2 = ""; String modeCode3 = ""; String modeCode4 = ""; String modeCode5 = ""; int count = rs.getCounts(); while (rs.next()) { flag++; String materialnumber = Util.null2String(rs.getString("materialnumber")); String mlreference = Util.null2String(rs.getString("mlreference")); String localBusinessUnit = Util.null2String(rs.getString("localbusinessunit")); String mdrimuniquelicenseid = Util.null2String(rs.getString("mdrimuniquelicenseid")); String localproductcode = Util.null2String(rs.getString("localproductcode")); boolean c = false; if (materialnumber.indexOf("-") > 0){ String r = materialnumber.substring(materialnumber.length()-3, materialnumber.length()-2); this.writeLog(ACTION_NAME + " action r :" + r); String endStr = materialnumber.substring(materialnumber.length() -1); c = RscUtil.isNumeric(endStr); } if (c) { String[] mnArray = materialnumber.split("-"); int len = mnArray.length; //start // if (num > 1) { if (flag == 1) { modeCode1 = mnArray[len - 1]; } if (flag == 2) { modeCode2 = mnArray[len - 1]; } if (flag == 3) { modeCode3 = mnArray[len - 1]; } if (flag == 4) { modeCode4 = mnArray[len - 1]; } if (flag == 5) { modeCode5 = mnArray[len - 1]; } // } //end if (!"".equals(pingjieBf.toString())) { pingjieBf.append("|"); } pingjieBf.append(mnArray[len - 1]); pingjieBf.append(":"); pingjieBf.append(mlreference); } //没有拆除modeCode1,动态取modeCode1,modified at 2022-2-21 if ("".equals(modeCode1) && "".equals(modeCode2) && "".equals(modeCode3) && "".equals(modeCode4) && "".equals(modeCode5)){ innerRs.execute("select dummymodcode from uf_rsc_bu where id=" + localBusinessUnit); if (innerRs.next()){ modeCode1 = Util.null2String(innerRs.getString("dummymodcode")); } } if ("".equals(modeCode1)){ return failureInfo(requestInfo, requestid, "提示:modeCode1获取失败,请检查"); } //不拆的逻辑,modified at 2022-2-21 if (pingjieBf.toString().length() == 0){ pingjieBf.append(modeCode1 + ":" + mlreference); } List<Object> paramlist = new ArrayList<Object>(); paramlist.add(pingjieBf.toString()); paramlist.add(modeCode1); paramlist.add(modeCode2); paramlist.add(modeCode3); paramlist.add(modeCode4); paramlist.add(modeCode5); paramlist.add(mainId); paramlist.add(mdrimuniquelicenseid); paramlist.add(localproductcode); batchUpdateList.add(paramlist); } } this.writeLog(ACTION_NAME + " action batchUpdateList size:" + batchUpdateList.size()); String pingjieUpdateSql = "update " + mainTablename + "_dt1 set chinalabelphysicalmanufacturer=?,modcode1=?,modcode2=?,modcode3=?,modcode4=?,modcode5=? where mainid=? and mdrimuniquelicenseid=? and localproductcode=?"; if (batchUpdateList.size() > 0) { updateRs.executeBatchSql(pingjieUpdateSql, batchUpdateList); } } catch (Exception e){ this.writeLog("*************** " + ACTION_NAME + " Exception:" + e.getMessage()); return failureInfo(requestInfo, requestid, "提示:" + ACTION_NAME + "异常"); } return Action.SUCCESS; } public void callMdrim(StringBuffer sber, String linId, JSONArray dt1DataArray, Map<String, JSONObject> canInputMap) throws Exception { //Map<String, String> headerMap = new HashMap<>(); // headerMap.put("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImM0NGM4OTllLTExMWYtNDE2MC1hOTI3LTk5OWE5YmFlZTRhNCIsInV1aWQiOiIxMjQ5ODFlNC01OTQzLTQ5ODEtOWZlOS0xYmU2YzU2YTlkNTciLCJpYXQiOjE2MzcyOTA2OTYsImV4cCI6MTY0NzY1ODY5Nn0.uSs-7p8xqM64S45iqmnUpxGeNmBOFWu-u2zDm_6I1i4"); // headerMap.put("Content-Type", "application/json"); JSONObject mdrimParams = new JSONObject(); mdrimParams.put("prd_code", sber.toString()); RscConfigService rscConfigService = new RscConfigService(); String mdrimApiUrlFranchisedata = rscConfigService.getSystemConfigValue("MDRIM_API_URL_Franchisedata"); String authorization = rscConfigService.getSystemConfigValue("MDRIM_API_Authorization"); this.writeLog(ACTION_NAME + " action mdrimParams :" + mdrimParams.toString()); mdrimApiUrlFranchisedata = mdrimApiUrlFranchisedata + linId; this.writeLog(ACTION_NAME + " action mdrimApiUrlFranchisedata:" + mdrimApiUrlFranchisedata); this.writeLog(ACTION_NAME + " action authorization:" + authorization); String api3UrlResult = RscUtil.httpsPostCallMdrim(mdrimApiUrlFranchisedata, authorization, mdrimParams.toString()); this.writeLog(ACTION_NAME + " action api3UrlResult:" + api3UrlResult); if (RscUtil.isJsonObject(api3UrlResult)) { JSONObject data = JSONObject.fromObject(api3UrlResult); String state = data.getString("state"); if ("S".equals(state)) { JSONArray dataArray = JSONArray.fromObject(data.getString("content")); for (int i = 0; i < dataArray.size(); i++) { JSONObject dataObj = (JSONObject) dataArray.get(i); for (int p = 0; p < dt1DataArray.size(); p++){ JSONObject productObj = (JSONObject) dt1DataArray.get(p); if (dataObj.get("l_LicenseID").equals(productObj.get("mdrimuniquelicenseid")) && dataObj.get("p_Local_Product_Code").equals(productObj.get("localproductcode"))){ //1. ship col1 col2 all NO NO ,就不插入 p_import_the_manufacturers_labelled_products_as_is p_Is_the_additional_relabeling_repackaging_setup_completed String productAs = Util.null2String(dataObj.getString("p_import_the_manufacturers_labelled_products_as_is")); String completed = Util.null2String(dataObj.getString("p_Is_the_additional_relabeling_repackaging_setup_completed")); if (productAs.toLowerCase().startsWith("no") && completed.toLowerCase().startsWith("no")){ continue; } this.writeLog(ACTION_NAME + " action dataObj:" + dataObj.toString()); String key = Util.null2String(dataObj.getString("l_LicenseID")) + "_" + Util.null2String(dataObj.getString("p_Local_Product_Code")) + "_" + Util.null2String(dataObj.getString("p_Material_Number")); this.writeLog(ACTION_NAME + " action key:" + key); JSONObject existObj = canInputMap.get(key); if (existObj == null){ existObj = new JSONObject(); existObj.put("uuid", Util.null2String(productObj.getString("uuid"))); existObj.put("countryId", Util.null2String(productObj.getString("countryId"))); existObj.put("p_Catalog_Number", Util.null2String(dataObj.getString("p_Catalog_Number")));//->catalognumber existObj.put("p_Material_Number", Util.null2String(dataObj.getString("p_Material_Number")));//DOTO Can ship col1 col2 col3 existObj.put("p_Physical_Manufacturer", Util.null2String(dataObj.getString("p_Physical_Manufacturer")));//->physicalmf existObj.put("approvedmanufacturersites", Util.null2String(productObj.getString("approvedmanufacturersites"))); existObj.put("sapmaterialnumber", Util.null2String(productObj.getString("sapmaterialnumber"))); existObj.put("localbusinessunit", Util.null2String(productObj.getString("localbusinessunit"))); existObj.put("mdrimuniquelicenseid", Util.null2String(dataObj.getString("l_LicenseID"))); existObj.put("localproductcode", Util.null2String(dataObj.getString("p_Local_Product_Code"))); } else { String pm = existObj.getString("p_Physical_Manufacturer") + "|" + Util.null2String(dataObj.getString("p_Physical_Manufacturer")); existObj.put("p_Physical_Manufacturer", pm);//|分隔合并 } canInputMap.put(key, existObj); } } } } } } public String failureInfo(RequestInfo requestInfo, Integer requestid, String msg){ requestInfo.getRequestManager().setMessageid("111" + requestid + "222"); requestInfo.getRequestManager().setMessagecontent(msg); return Action.FAILURE_AND_CONTINUE; } }这个代码怎么给mod code1进行赋值的
09-27
import tkinter as tk from tkinter import filedialog import os import re import sys from elftools.elf.elffile import ELFFile import subprocess import json # 确定应用程序是脚本文件还是被冻结的exe if getattr(sys, 'frozen', False): # 获取应用程序exe的路径 pathorigin = os.path.dirname(sys.executable) elif __file__: # 获取脚本程序的路径 pathorigin = os.path.dirname(__file__) #--寻找当前路径下的path_config文件 path_config_path = os.path.join(pathorigin, 'path_config.json') print(path_config_path) # config_path = config_path.replace('\\','\\\\') # 读取JSON文件并加载为字典 with open(path_config_path, 'r', encoding='utf-8') as f:# ConfigPath_dict = json.load(f) A2LUpdata_fold = ConfigPath_dict['A2LUpdata_fold'] def parseDwarfOutput(elfFileName,path11):#根据elf生成dwarf path = os.path.dirname(os.path.abspath(__file__)) #print(path) ps = subprocess.Popen(path11 + "\\objdump --dwarf=info " + elfFileName, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) dwarf = ps.communicate()[0].decode('latin-1') #print with open(os.path.join(A2LUpdata_fold, 'dwarf_info1.txt'), "w", encoding='utf-8') as dwarfFile: dwarfFile.write(dwarf) def extract_type11_10(s): # 使用 . 分割字符串 parts = s.split('.') # 检查是否正好有三部分 if len(parts) == 3: third_part = parts[2]#------这里进行a.b.c[x]形式的判断 if ('[' not in parts[0]): # 检查第三部分是否包含 [ if '[' in third_part: # 找到 [ 的位置 left_bracket_index = third_part.find('[') # 找到 ] 的位置 right_bracket_index = third_part.find(']', left_bracket_index) # 提取 [ 左边和 [] 中间的内容 if left_bracket_index != -1 and right_bracket_index != -1: content_before_bracket = third_part[:left_bracket_index] content_inside_brackets = third_part[left_bracket_index + 1:right_bracket_index] return '10',parts[0],parts[1],content_before_bracket, content_inside_brackets if(('[' not in parts[0]) and ('[' not in parts[1]) and ('[' not in parts[2])): return '11',parts[0],parts[1],parts[2],None return None,None,None,None,None def extract_components9(input_string):#A[X].B[Y].C,匹配出ABCXY # 定义正则表达式 pattern = r"^([^\[\]]+)\[([^\[\]]+)\]\.([^\[\]]+)\[([^\[\]]+)\]\.([^\[\]]+)$" flag = 0 A = 'null' B = 'null' C = 'null' X = 'null' Y = 'null' # 匹配字符串 match = re.match(pattern, input_string) if match: # 提取匹配的组 A = match.group(1) X = match.group(2) B = match.group(3) Y = match.group(4) C = match.group(5) flag = 9 return flag,A, B, C, X, Y def extract_components(s): # 统计 '.' 和 '[' 的数量 dot_count = s.count('.') bracket_count = s.count('[') a = 'null' x = 'null' b = 'null' c = 'null' y = 'null' flag = 'null' flag,a, b, c, x, y = extract_components9(s) # 如果存在两个 '.' if flag == 9: flag = 9 elif dot_count == 2: # 匹配 a[x].b.c[y] 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\.([^\[\].]+)\.([^\[\].]+)\[([^\[\]]+)\]$', s) if match: a, x, b, c, y = match.groups() flag = '8' # 如果存在两个 '[' elif bracket_count == 2: # 匹配 a[x][y].b 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\[([^\[\]]+)\]\.([^\[\].]+)$', s) if match: a, x, y, b = match.groups() flag = '6' # 其他情况(默认匹配 a[x].b 格式) else: # 匹配 a[x].b 格式 match = re.match(r'^([^\[\].]+)\[([^\[\]]+)\]\.([^\[\].]+)$', s) if match: a, x, b = match.groups() flag = '5' return a,x,b,c,y,flag def check_bracket_before_first_dot(s): # 找到第一个 '.' 的位置 dot_index = s.find('.') # 如果不存在 '.',直接返回标志位 0 if dot_index == -1: return 0 # 检查第一个 '.' 之前是否有 '[' if '[' in s[:dot_index]: return 1 # 标志位为 1 else: return 0 # 标志位为 0 def parse_name(name): flag = 'null' a = 'null' b = 'null' x = 'null' y = 'null' c = 'null' d = 'null' z = 'null' # 定义正则表达式匹配规则 type,result1,result2,result3,result4 = extract_type11_10(name) if type: flag = type a = result1 b = result2 x = result3 y = result4 elif(check_bracket_before_first_dot(name)): a,b,c,d,x,flag = extract_components(name) else: pattern = re.compile(r'^([^\[\].]+)(?:\.([^\[\].]+))?(?:\[([^\[\]]+)\])?(?:\[([^\[\]]+)\])?(?:\.([^\[\].]+))?(?:\.([^\[\].]+))?(?:\[([^\[\]]+)\])?$') # 匹配字符串 match = pattern.match(name) if not match: return None # 提取各部分 a = match.group(1) b = match.group(2) x = match.group(3) y = match.group(4) c = match.group(5) d = match.group(6) z = match.group(7) # 根据提取结果确定 flag if not b and not x and not y and not c and not d and not z: flag = 1 # 情况 1: a elif b and not x and not y and not c and not d and not z: flag = 2 # 情况 2: a.b elif x and not b and not y and not c and not d and not z: flag = 3 # 情况 3: a[x] elif b and x and not y and not c and not d and not z: flag = 4 # 情况 4: a.b[x] elif x and b and not y and not c and not d and not z: flag = 5 # 情况 5: a[x].b elif x and y and b and not c and not d and not z: flag = 6 # 情况 6: a[x][y].b elif b and x and c and not y and not d and not z: flag = 7 # 情况 7: a.b[x].c elif x and b and c and y and not d and not z: flag = 8 # 情况 8: a[x].b.c[y] else: flag = 0 # 未知情况 # 返回结果 return flag,a,b,x,y,c,d,z def structgetaddr(structname,vname,classes,it_dict,list11):#(结构体作为主型)a.b类型,获取a.b的地址 address = '0' currenttype = '0' skipflag = 0 for cla in classes:#找到结构体名 if skipflag == 1: break if(structname == cla.name):#找到了结构体 initaddr = cla.address#找到结构体的初始地址 for dit in it_dict.keys():#找到了键的索引 if skipflag == 1: break if(dit == cla.type):#找到了键的索引 for va in list11:#这个列表里面都是字典,字典里面都是列表,列表中还是字典list11这里有问题????? #print(va.keys()) if skipflag == 1: break for structnum,value0 in va.items(): if skipflag == 1: break if(structnum == it_dict[dit]):#如果找到的结构体编号等于索引字典的值 for list12 in value0:#这里面都是列表,列表中的内容都是字典 if skipflag == 1: break for keylist12,valuelist12 in list12.items(): if skipflag == 1: break if(vname == keylist12):#找到了这个变量 address = str(hex(int(initaddr, 16) + int(valuelist12[1], 10))) currenttype = valuelist12[0] skipflag = 1 break return address,currenttype def arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11):#(二维数组作为主型)二维数组,获取a[x][y]的地址 address0 = '' address = '0' currenttype = '0' skipflag = 0 for cla in classes:#变量的结构体都是统一的 if skipflag == 1: break if(first_part == cla.name):#到这里就是找到了变量名,找到了数组名,数组是直接,变量到数组结构 address0 = cla.address#找到初始地址 for iarray in arrayclasslist11:#对所有的数组出手 if(iarray.name == cla.type):#找到匿名地址----------- #数组类---------------这一块没有找匿名就直接找数组了,数组没有匿名哦 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux layernum = (int(iarray.golist[1]) + 1)*int(uint) nowlayer = int(int(second_part))*layernum addresslayer = nowlayer + (int(third_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype def arraygetaddr1(first_part,second_part,classes,arrayclasslist11):#(一维数组作为主型)一维数组,获取a[x]的地址 address0 = '' address = '0' currenttype = '0' skipflag = 0 for cla in classes:#变量的结构体都是统一的 if skipflag == 1: break if(first_part == cla.name):#到这里就是找到了数组名 address0 = cla.address for iarray in arrayclasslist11:#数组类 if skipflag == 1: break if(cla.type == iarray.name):#类型地址等于数组的编号 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux #layernum = (int(iarray.golist[1]) + 1)*uint #nowlayer = int(second_part+1)*layernum addresslayer = (int(second_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype def Sonstructgetaddr(searchtypename,vname,classes,it_dict,list11,arrayclasslist11,anydict):#(结构体作为子型)a.b类型,获取a.b的地址 initaddr = '0' address = '0' currenttype = '0' skipflag = 0 for dit in it_dict.keys():#找到了键的索引 if skipflag == 1: break if(dit == searchtypename):#通过数据类型找到结构体匿名 for va in list11:#这个列表里面都是字典,字典里面都是列表,列表中还是字典list11这里有问题????? #print(va.keys()) if skipflag == 1: break for structnum,value0 in va.items(): if skipflag == 1: break if(structnum == it_dict[dit]):#通过结构体匿名找到结构体 for list12 in value0:#这里面都是列表,列表中的内容都是字典 for keylist12,valuelist12 in list12.items(): if(vname == keylist12):#找到了结构体的这个成员 address = str(hex(int(initaddr, 16) + int(valuelist12[1], 10))) currenttype = valuelist12[0] skipflag = 1 break return address,currenttype#这里实际上就找到了结构体的这个成员相对于上一级的偏移 def Sonarraygetaddr(searchtype,second_part,third_part,classes,arrayclasslist11,anydict):#(二维数组作为子型)二维数组,获取a[x][y]的地址 address0 = '0' address = '0' currenttype = '0' skipflag = 0 for iarray in arrayclasslist11:#对所有的数组出手 if skipflag == 1: break if(iarray.name == searchtype):#找到匿名地址----------- #数组类---------------这一块没有找匿名就直接找数组了,数组没有匿名哦 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux layernum = (int(iarray.golist[1]) + 1)*int(uint) nowlayer = int(int(second_part))*layernum addresslayer = nowlayer + (int(third_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype#实际上的偏移 def Sonarraygetaddr1(searchtype,second_part,classes,arrayclasslist11,anydict):#(一维数组作为子型)一维数组,获取a[x]的地址 address0 = '0' address = '0' currenttype = '0' skipflag = 0 for iarray in arrayclasslist11:#数组类 if skipflag == 1: break if(searchtype == iarray.name):#类型地址等于数组的编号 allnum = int(iarray.numtotal)#总数 sonmux = 1 for son in iarray.golist: sonmux = sonmux*(int(son) + 1)#得到数组的总大小 uint = allnum/sonmux #layernum = (int(iarray.golist[1]) + 1)*uint #nowlayer = int(second_part+1)*layernum addresslayer = (int(second_part))*int(uint) address1 = hex(int(address0,16) + int(str(addresslayer),10)) address = str(address1) currenttype = iarray.searvh skipflag = 1 break return address,currenttype#实际上的偏移 #---------------------对于elf生成需要对结构体和数组进行处理的文件 def dwarfdo(dwarfaddr):#根据dwarf文件生成需要的文件 # 正则表达式 structure_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_structure_type\)') member_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_member\)') name_pattern = re.compile(r'^\s*<[0-9a-f]+>\s+DW_AT_name\s+.*:\s+(.*)') offset_pattern = re.compile(r'DW_OP_plus_uconst:\s*(\d+)') Stop_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\sAbbrev\sNumber:\s0') #------- typedef_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_typedef\)')#找到匿名变量 searchvalue_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') #找打匿名变量的信息 # 存储结果 #----- var_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_variable\)') varname_pattern = re.compile(r'^\s*<[0-9a-f]+>\s+DW_AT_name\s+.*:\s+(.*)') vartype_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') varaddr_pattern = re.compile(r'\(DW_OP_addr:\s*([0-9a-f]+)\)') #-----存储数组 array_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组,type已经有正则表达式了 arraysearch_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>') #找到数组到匿名的索引 arrayinfo_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组结构信息 arrnumnum_pattern = re.compile(r'DW_AT_upper_bound\s*:\s*(\d+)')#找到数组的结构大小0-x,0-y,0-z basepattern_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\sAbbrev\sNumber:\s')#找到基本数据类型这个直接用search basenumpattern_pattern = re.compile(r'DW_AT_byte_size\s*:\s*(\d+)')#找到基础数据类型的大小-这个也用search # baseupper_pattern = re.compile(r'DW_AT_upper_bound\s*:\s*(\d+)')# #-----------------------匹配任意的编号到数据类型的索引 anytypehead_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:\s*Abbrev\sNumber:')#search匹配任意头 anytypeend_pattern = re.compile(r'^\s*<[0-9a-f]+>\s*DW_AT_type\s*:\s<0x([0-9a-f]+)>')#match匹配整个 #-----------------------匹配任意的编号到数据类型的索引 class ALLClass: def __init__(self, name: str, type: str, address: str): self.name = name #结构体变量名称 self.type = type #结构体类型索引 self.address = address #结构体地址 class ALLClassArray: def __init__(self, name: str, numtotal: str, searvh:str,golist):#记录出来名字,总大小,深度,单位大小---- #------注意基本单位并不是真正的基本单位,这里只有找到单位大小就可以了 self.name = name #数组名称 self.numtotal = numtotal #数组总大小 self.searvh = searvh #到匿名变量的索引 self.golist = golist #结构列表 classes = [] #----- results = {} current_structure = None current_member = None StartFlag = 0 StartFlag2 = 0 stopflag = 0 searchvalue_flag = 0#寻找匿名索引值得标志位 alone_dict = {} all_dict = {} list001 = []#列表里面全都是字典,字典的键是结构体名,字典的值是列表,列表里面是变量名对应偏移量的字典 listson = []#子表 #----- listypedef = []#用于存储中间索引的列表 it_dict = {}#用于存储中间索引的字典 #----- arraystart = 0 startflag = 0 arrayclass = {}#存储数组的基本大小--这个似乎不用了 arrayclasslist11 = []#存储编号,大小,索引,数组结构 numstart = 0 namemallstart = 0 searchstart = 0 #--------匹配任意DIE的类型 anydict = {} anyheadflag = 0 #--------匹配任意DIE的类型 # 逐行处理# #1,需求,寻找编号与对应的变量、偏移已经完成 #2,需求,构建索引结构体名的索引字典已经完成 #3,需求,构建一个类,类的内容分别是编号,名字,地址,类型已经完成 with open(dwarfaddr, 'r', encoding='utf-8') as file: lines = file.readlines() # 读取所有行到列表中 for line in lines: line = line.rstrip() # 去除行尾的空白字符 #---------匹配结构体内部变量 #---------匹配结构体内部变量 structure_match = structure_pattern.match(line) member_match = member_pattern.match(line) name_match = name_pattern.match(line) offset_match = offset_pattern.search(line) stop_match = Stop_pattern.match(line) #---------匹配索引 typedef_match = typedef_pattern.match(line) searchvalue_match = searchvalue_pattern.match(line) #---------匹配结构体变量 var_match = var_pattern.match(line) varname_match = varname_pattern.match(line) vartype_match = vartype_pattern.match(line) varaddr_match = varaddr_pattern.search(line) #---------数组处理 # array_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_array_type\)')#找到数组,type已经有正则表达式了 # arrayclass_pattern = re.compile(r'^\s*<\d+><([0-9a-f]+)>:.*\(DW_TAG_base_type\)')#找到基本数据类型 # arrnum_pattern = re.compile(r'DW_AT_byte_size\s*:\s*(\d+)')#找到基础数据类型的大小 # array_match = array_pattern.match(line) # arrayclass_match = arrayclass_pattern.match(line) # arrnum_match = arrnum_pattern.search(line) array_match = array_pattern.match(line) arraysearch_match = arraysearch_pattern.match(line) arrayinfo_match = arrayinfo_pattern.match(line) arrnumnum_match = arrnumnum_pattern.search(line) basepattern_match = basepattern_pattern.search(line) basenumpattern_match = basenumpattern_pattern.search(line) #------------------------------------匹配任意的数据类型 anytypehead_match = anytypehead_pattern.search(line) anytypeend_match = anytypeend_pattern.match(line) #------------------------------------匹配任意的数据类型 if structure_match:#当前是结构体定义处,提取编号 current_structure = structure_match.group(1) #results[current_structure] = {} StartFlag = 1 listson = [] stopflag = 1 cuttent_array = [] # 匹配成员 # elif member_match and (StartFlag == 1):#遇到成员,提取成员名与偏移 # current_member = member_match.group(1)#标记出遇到结构体的成员了 #doit #StartFlag2 = 1 #print(current_member) elif StartFlag and name_match: # print(name_match.group(1))#获取变量名 current_name = name_match.group(1) elif StartFlag and anytypeend_match: cruuenttype = anytypeend_match.group(1) cuttent_array.append(cruuenttype) elif StartFlag and offset_match: #print(offset_match.group(1))#获取上面变量名对应的偏移 current_offset = offset_match.group(1) cuttent_array.append(current_offset) alone_dict = {current_name: cuttent_array}#到这里取出一对,就建立一个字典,变量名是键偏移量是值 listson.append(alone_dict)#增加一个偏移 cuttent_array = [] elif stop_match and stopflag:#到这种时候,就代表一个结构体的内容处理完成了,接下来整理数据就好了 all_dict = {current_structure: listson} # for i in listson: # print(i) list001.append(all_dict) StartFlag = 0#处理完成标志 stopflag = 0 #这一部分是编号变量名的 #下面一部分是编号结构体名的 if typedef_match:#遇到了匿名索引 typedef_name = typedef_match.group(1)#找到匿名索引的键 searchvalue_flag = 1 elif searchvalue_flag and searchvalue_match:#找到了键,现在要找值 typedef_value = searchvalue_match.group(1) #my_dict = {typedef_name,typedef_value} it_dict[typedef_name] = typedef_value #listypedef.append(my_dict) searchvalue_flag = 0 #这一步是为了构建一个列表,列表里面有许多类,用来索引结构体的名称 if var_match: startflag = 1 elif startflag and varname_match: varname = varname_match.group(1) #print(varname) elif startflag and vartype_match: vartype = vartype_match.group(1) #print(vartype) elif startflag and varaddr_match: varaddr = varaddr_match.group(1) #print(varaddr) classes.append(ALLClass(varname,vartype,varaddr)) startflag = 0 #这里进行数组的处理找到数组中间索引-----------------找到数组变量,数组地址,数组大小,数组索引。深度, #print(line) if array_match:#找到array的DIE name = array_match.group(1)#记录数组编号 arraystart = 1#遇到数组才开始 namemallstart = 1 searchstart = 1 list004 = []#列表为空 #似乎不需要增加新的逻辑,因为每个数组与结构都是一一对应的 elif namemallstart and arraystart and basenumpattern_match:#这个大小是总大小,与数组在一起就一起记录 namemall = basenumpattern_match.group(1)#找到数组总大小并记录 namemallstart = 0 elif searchstart and arraystart and arraysearch_match:#找到找到数组到匿名变量的索引 searvh = arraysearch_match.group(1) searchstart = 0 elif arraystart and arrnumnum_match:#从这里开始记录数组结构 go = arrnumnum_match.group(1)#记录数据的结构 list004.append(go) elif arraystart and stop_match:#到停止的时候就收集信息,收集编号名称,总大小 arrayclasslist11.append(ALLClassArray(name,namemall,searvh,list004)) arraystart = 0# namemallstart = 0 searchstart = 0 #----------------到这里把数组的array块的DIE给解决了 # ---------------------------------------------这里解决数组的基础数据信息 # if basepattern_pattern:#可以索引出来大小的时候 # numhead = basepattern_pattern.group(1) # numstart = 1 # elif numstart and basenumpattern_pattern: # numend = basenumpattern_pattern.group(1) if anytypehead_match:#匹配到编号头, <2><9cb3f4>: anyhead = anytypehead_match.group(1) anyheadflag = 1 elif anyheadflag and anytypeend_match:#匹配到编号尾, <9cb3fc> DW_AT_type : <0x9cadba> anytype = anytypeend_match.group(1)# anydict[anyhead] = anytype anyheadflag = 0 return list001,it_dict,classes,arrayclasslist11,anydict def Getaddressfromelf(input_string,dict,classes):#直接从ELF里的MAP使用简单变量的,变量名与地址的对应关系更新地址-0923类型 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' for line in lines: skipflag = 0 name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_match = re.search(name_pattern, line) #print(name_match.group(1)) address_match = re.search(address_pattern, line) address_match1 = re.search(address_pattern1, line) if(address_match): address_match = address_match elif(address_match1): address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(1) result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '')): #print(line) b = address_match.group(1)# + ' ' + '/*' # print(dict[Address]) # if(Address in dict.keys()): # temp = dict[Address] # # print(temp) # temp = int(temp,16) # temp = hex(temp) # new_b = str(temp)# + ' ' + '/*' # line = line.replace(b,new_b) #print(dict[Address]) for cla in classes:#变量的结构体都是统一的 if(Address == cla.name):#到这里就是找到了数组名 address0 = cla.address temp = address0 # print(temp) temp = int(temp,16) temp = hex(temp) new_b = str(temp)# + ' ' + '/*' line = line.replace(b,new_b) result_lines.append(line) #print(line) elif not line.strip(): Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelf1227(input_string,dict,classes):#直接从ELF里的MAP使用简单变量的,变量名与地址的对应关系更新地址--1127类型 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' for line in lines: # name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 # address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 # address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_pattern = re.compile(r'\s*/begin\s(CHARACTERISTIC|MEASUREMENT)\s(\S+)\s"')#匹配约定组与预定组的名字 address_pattern = re.compile(r'0xFE([0-9A-F]+)')#匹配地址 name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) # address_pattern11 = re.compile(r'0xFE([0-9A-F]+)') # if(name_match): # address_match = address_match # elif(address_match1): # address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(2) # if(Address == 'ADAS_bAutDrvCtlActv_E'): # print('doit') result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '')): #print(line) b = 'FE' + address_match.group(1) b1 = 'fe' + address_match.group(1) # print(dict[Address]) # if(Address in dict.keys()): # temp = dict[Address] # # print(temp) # temp = int(temp,16) # temp = hex(temp).upper()[2:] # new_b = str(temp) # line = line.replace(b,new_b) # line = line.replace(b1,new_b) for cla in classes:#变量的结构体都是统一的 if(Address == cla.name):#到这里就是找到了数组名 address0 = cla.address temp = address0 # print(temp) temp = int(temp,16) temp = hex(temp).upper()[2:] new_b = str(temp)# + ' ' + '/*' line = line.replace(b,new_b) line = line.replace(b1,new_b) #print(dict[Address]) result_lines.append(line) #print(line) elif not line.strip(): Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelfplus(input_string,list11,it_dict,classes,arrayclasslist11,dict,anydict):#从elf获取地址,处理结构体,数组0923 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' flagvar = 'null' for line in lines: name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) address_match1 = re.search(address_pattern1, line) if(address_match): address_match = address_match elif(address_match1): address_match = address_match1 if('TeBTRCTR_e_SysBatteryMode' in line): print('test') if name_match:#在这里对不同的数据结构,采用不同的数据处理方式 #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(1)#Address就是名字 flagvar = 'null' # if('TeBTRCTR_e_SysBatteryMode' in Address): # print('test') # if 'TeBTRCTR_e_SysBatteryMode' in line: # print('this') flagvar,vara,varb,varx,vary,varc,vard,varz = parse_name(Address)#提取出数据类型,与各类型数据的情况 flagvar = str(flagvar) # 1,a-----flag,a一般形式已经处理过了 # 2,a.b-----flag,a,b # 3,a[x]-----flag,a,x---这里其实是二维数组 # 4,a.b[x]----flag,a,b,x # 5,a[x].b----flag,a,b,c # 6,a[x][y].b---flag,a,b,x,c # 7,a.b[x].c---flag,a,b,x,c # 8,a[x].b.c[y]---flag,a,b,c,d,x # 9, a[x].b[y].c---flag,a,b,c,d,x # 10,a.b.c[x]--- # result_lines.append(line) # print(line) # print(Address) # 提取 ECU Address 后面的字符串 elif(address_match and (Address != '') and (flagvar != 'null') ):#正是数据处理行,并且能识别出数据类型 #print(line) address = '' if(flagvar == '2'):#最普通的结构体类型,a.b类型,对应a.b,a.b[x] structname,vname = vara,varb#= Address.split('.')#分离出来变量 address,currenttype = structgetaddr(structname,vname,classes,it_dict,list11)#结构体更新出来了 #address = int(address,16) address = str(address).upper()[2:] #print(dict[Address]) #result_lines.append(line) # elif(flagvar == 2):#这种是最普通的多维数组类型,A[X][X],最多处理二维数组,后面增加通用处理功能 # address = ''#由于在a2l里面,数组只保留到次一级,二维数组只处理a[x][y].c类型 # if(re.search(r'\._\d+_\._(\d+)', Address)):#当前是二维数组 # first_part = Address.split('._')[0]#第一部分是名字 # second_part = re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 # third_part = re.search(r'\._\d+_\._(\d+)', Address)#2,1中的1 # #address0 = ''#首地址就从map里面找了,不用dwarf # address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) # address = str(address).upper()[2:] elif(flagvar == '3'):#a[x]形式,对应a[x][y],third_part默认赋值0 first_part = vara#Address.split('._')[0]#第一部分是名字 second_part = varx#re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 #third_part = re.search(r'\._\d+\._(\d+)', Address)#2,1中的1 #address0 = ''#首地址就从map里面找了,不用dwarf third_part = '0' address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11)#要用二维数组的处理方式 #address = int(address,16) address = str(address).upper()[2:] elif(flagvar == '4'):#a.b[x]形式,对应a.b[x][y],third_part默认赋值0 initaddress = '' structname = vara arrayname = varb array1dex = varx third_part = '0' address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr(currenttype,array1dex,third_part,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '5'):#a[x].b,对应a[x].b和a[x],b[y] first_part = vara second_part = varb vname = varc address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '6'):#a[x][y].b二维主,对应a[x][y].b与a[x][y].b[z] first_part = vara second_part = varb third_part = varx vname = varc address,searchtype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '7'):#a.b[x].c,对应a.b[x].c与a.b[x].c[z]结构体主,数组与结构体辅a.b,b[x],t.c initaddress = '' structname = vara arrayname = varb array1dex = varx vname = varc address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr1(currenttype,array1dex,classes,arrayclasslist11,anydict) plus1address,currenttype = Sonstructgetaddr(currenttype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plus1address,16))).upper()[2:] elif(flagvar == '8'):#a[x].b.c[y]类型数组a[x]为主,这里其实就是a[x].b.c结构体数组,结构体里面同样有结构体 first_part = vara second_part = varb vname = varc vname1 = vard five_name = varx address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress1,currenttype = Sonstructgetaddr(currenttype,vname1,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plusaddress1,16))).upper()[2:] elif(flagvar == '9'):#a[x].b[y].c类型 first_part = vara second_part = varb vname = varc vname1 = varx five_name = vard # print(vara) # print(varb) # print(varc) # print(vard) # print(varx) address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress1,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr1(currenttype,vname1,classes,arrayclasslist11,anydict) plusaddress3,currenttype = Sonstructgetaddr(currenttype,five_name,classes,it_dict,list11,arrayclasslist11,anydict) #CurrentTypenameDict[Address] = Ftypedict[currenttype] address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16) + int(plusaddress3,16))).upper()[2:] elif(flagvar == '10'):#a.b.c[y],实际对应a.b.c[y][z]形式 First_part = vara Second_part = varb Third_part = varx Four_part = vary third_partarray = '0' address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr(currenttype,Four_part,third_partarray,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16))).upper()[2:] elif(flagvar == '11'):#a.b.c,实际对应a.b.c First_part = vara Second_part = varb Third_part = varx address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16))).upper()[2:] if(address != ''):#确实把地址给更新掉了 b = address_match.group(1)#+ ' ' + '/*'#需要替代的 new_b = address# + ' ' + '/*'#新的 line = line.replace(b,new_b) result_lines.append(line) elif not line.strip():#空行代表进入到了下一个处理 Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def Getaddressfromelfplus1227(input_string,list11,it_dict,classes,arrayclasslist11,dict,anydict):#从elf获取地址,处理结构体与数组,1227 # 提取 Name 后面的字符串 lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] Address = '' flagvar = 'null' for line in lines: # name_pattern = r'\s+/\*\s+Name\s+\*/\s+([^\s]+)'#获取名字 # address_pattern = r'\s+/\*\s*ECU\s+Address\s+\*/\s+([^\s]+)'#获取地址 # address_pattern1 = r'\s+ECU_ADDRESS\s+(\S+)\s+([^\s]+)' # name_match = re.search(name_pattern, line) # address_match = re.search(address_pattern, line) # address_match1 = re.search(address_pattern1, line) name_pattern = re.compile(r'\s*/begin\s(CHARACTERISTIC|MEASUREMENT)\s(\S+)\s"')#匹配约定组与预定组的名字 address_pattern = re.compile(r'0xFE([0-9A-F]+)')#匹配地址 name_match = re.search(name_pattern, line) address_match = re.search(address_pattern, line) # if(address_match): # address_match = address_match # elif(address_match1): # address_match = address_match1 if name_match: #print("Name Extracted:", name_match.group(1)) # 输出: Name Extracted: ABC123 Address = name_match.group(2) flagvar = 'null' if('testvar5[1].usCurrentHBStatus' in Address): print('test') flagvar,vara,varb,varx,vary,varc,vard,varz = parse_name(Address)#提取出数据类型,与各类型数据的情况 flagvar = str(flagvar) if 'STRUCTtest[1].test1111[1].ucProtectCnt' == Address: print(flagvar) print(vara) print(varb) print(varx) print(varc) print(vard) # if ('._' in Address):#结构体是1,数组是2,普通是0,0已经处理过了,这里就不再处理了 # flagtype = 2 # elif('.' in Address): # flagtype = 1 # else: # flagtype = 0 # result_lines.append(line) # # print(line) # # print(Address) # # 提取 ECU Address 后面的字符串 #print(line) result_lines.append(line) elif(address_match and (Address != '') and (flagvar != 'null') ): address = '' if(flagvar == '2'):#最普通的结构体类型,a.b structname,vname = vara,varb#= Address.split('.')#分离出来变量 address,currenttype = structgetaddr(structname,vname,classes,it_dict,list11)#结构体更新出来了 #address = int(address,16)#本身就是16进制 address = str(address).upper()[2:] #print(dict[Address]) #result_lines.append(line) # elif(flagvar == 2):#这种是最普通的多维数组类型,A[X][X],最多处理二维数组,后面增加通用处理功能 # address = ''#由于在a2l里面,数组只保留到次一级,二维数组只处理a[x][y].c类型 # if(re.search(r'\._\d+_\._(\d+)', Address)):#当前是二维数组 # first_part = Address.split('._')[0]#第一部分是名字 # second_part = re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 # third_part = re.search(r'\._\d+_\._(\d+)', Address)#2,1中的1 # #address0 = ''#首地址就从map里面找了,不用dwarf # address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) # address = str(address).upper()[2:] elif(flagvar == '3'):#当前是二维数组a[x][y] first_part = vara#Address.split('._')[0]#第一部分是名字 second_part = varx#re.search(r'\._(\d+)', Address)#第二部分是2,1,中的2 #third_part = re.search(r'\._\d+\._(\d+)', Address)#2,1中的1 #address0 = ''#首地址就从map里面找了,不用dwarf third_part = '0' address,currenttype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11)#实际一维数组 #address = int(address,16) address = str(address).upper()[2:] elif(flagvar == '4'):#a.b[x]主结构体与副数组 initaddress = '' structname = vara arrayname = varb array1dex = varx third_part = '0' address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr(currenttype,array1dex,third_part,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '5'):#a[x].b数据类型 first_part = vara second_part = varb vname = varc address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '6'):#a[x][y].b二维主,结构体辅 first_part = vara second_part = varb third_part = varx vname = varc address,searchtype = arraygetaddr(first_part,second_part,third_part,classes,arrayclasslist11) plusaddress,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16))).upper()[2:] elif(flagvar == '7'):#a.b[x].c,结构体主,数组与结构体辅a.b,b[x],t.c initaddress = '' structname = vara arrayname = varb array1dex = varx vname = varc#17b04c8是什么鬼,似乎sonarrayaddr1有问题 address,currenttype = structgetaddr(structname,arrayname,classes,it_dict,list11)#主结构体的地址与当前成员的类型 plusaddress,currenttype = Sonarraygetaddr1(currenttype,array1dex,classes,arrayclasslist11,anydict) plus1address,currenttype = Sonstructgetaddr(currenttype,vname,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plus1address,16))).upper()[2:] elif(flagvar == '8'):#a[x].b.c[y]类型数组a[x]为主,这里其实就是a[x].b.c结构体数组,结构体里面同样有结构体 first_part = vara second_part = varb vname = varc vname1 = vard five_name = varx address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress,currenttype81 = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress1,currenttype = Sonstructgetaddr(currenttype81,vname1,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress,16) + int(plusaddress1,16))).upper()[2:] elif(flagvar == '9'):#a[x].b[y].c类型 first_part = vara second_part = varb vname = varc vname1 = varx five_name = vard # print(vara) # print(varb) # print(varc) # print(vard) # print(varx) address,searchtype = arraygetaddr1(first_part,second_part,classes,arrayclasslist11)#初始地址 plusaddress1,currenttype = Sonstructgetaddr(searchtype,vname,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr1(currenttype,vname1,classes,arrayclasslist11,anydict) plusaddress3,currenttype = Sonstructgetaddr(currenttype,five_name,classes,it_dict,list11,arrayclasslist11,anydict) #CurrentTypenameDict[Address] = Ftypedict[currenttype] address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16) + int(plusaddress3,16))).upper()[2:] elif(flagvar == '10'):#a.b.c[y],实际对应a.b.c[y][z]形式 First_part = vara Second_part = varb Third_part = varx Four_part = vary third_partarray = '0' address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) plusaddress2,currenttype = Sonarraygetaddr(currenttype,Four_part,third_partarray,classes,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16) + int(plusaddress2,16))).upper()[2:] elif(flagvar == '11'):#a.b.c,实际对应a.b.c First_part = vara Second_part = varb Third_part = varx address,searchtype = structgetaddr(First_part,Second_part,classes,it_dict,list11) plusaddress1,currenttype = Sonstructgetaddr(searchtype,Third_part,classes,it_dict,list11,arrayclasslist11,anydict) address = str(hex(int(address,16) + int(plusaddress1,16))).upper()[2:] if(address != ''):#确实把地址给更新掉了 b = 'FE' + address_match.group(1)# + ' ' + '/*'#需要替代的 b1 = 'fe' + address_match.group(1)# + ' ' + '/*'#需要替代的 new_b = address# + ' ' + '/*'#新的 line = line.replace(b,new_b) line = line.replace(b1,new_b) result_lines.append(line) elif not line.strip():#空行代表进入到了下一个处理 Address = '' result_lines.append(line) else: result_lines.append(line) return '\n'.join(result_lines) def get_variable_addresses(elf_file):#读取ELF文件,获取变量名与地址的字典 variable_addresses = {} with open(elf_file, 'rb') as f: elffile = ELFFile(f) # 获取符号表 symtab = elffile.get_section_by_name('.symtab') if symtab is None: print("No symbol table found.") return variable_addresses # 遍历符号表 for symbol in symtab.iter_symbols(): # 过滤出变量(通常类型为STT_OBJECT) if symbol['st_info']['type'] == 'STT_OBJECT': if(symbol.name == '_Rte_NAP_VeOUT_NAP_ICCNapTimeSetToEE_sig_VeOUT_NAP_ICCNapTimeSetToEE_sig'): print("success1111111111") variable_name = symbol.name[1:] variable_address = str(symbol['st_value']) print(variable_address) variable_addresses[variable_name] = variable_address return variable_addresses def replace_header_with_a2ml(code_str, head_str): # 查找 /begin MODULE 和 /end MODULE 之间的内容 begin_header_tag = ' /begin MODULE ModuleName' end_header_tag = ' /begin MOD_COMMON' # 找到 /begin MODULE 的起始位置 start_index = code_str.find(begin_header_tag) if start_index == -1: raise ValueError("The string 'code_str' does not contain '/begin MODULE'") # 找到 /end MODULE 的结束位置 end_index = code_str.find(end_header_tag, start_index) if end_index == -1: raise ValueError("The string 'code_str' does not contain '/end MODULE' after '/begin MODULE'") end_index += len(end_header_tag) # 查找 /begin A2ML 到最后一个 /end IF_DATA 之间的内容 begin_a2ml_tag = '/begin A2ML' end_if_data_tag = '/end IF_DATA' a2ml_start_index = head_str.find(begin_a2ml_tag) if a2ml_start_index == -1: raise ValueError("The string 'head_str' does not contain '/begin A2ML'") a2ml_end_index = head_str.rfind(end_if_data_tag, a2ml_start_index) if a2ml_end_index == -1 or a2ml_end_index < a2ml_start_index: raise ValueError("The string 'head_str' does not contain a valid '/end IF_DATA' after '/begin A2ML'") a2ml_end_index += len(end_if_data_tag) # 替换 code_str 中找到的内容为 head_str 中的相应部分 replaced_code = ( code_str[:start_index] + # code_str 中 /begin MODULE 之前的部分 begin_header_tag + '\n' + head_str[a2ml_start_index:a2ml_end_index] + # head_str 中的 A2ML 部分 end_header_tag + '\n' + code_str[end_index:] # code_str 中 /end MODULE 之后的部分 ) return replaced_code def process_string(input_string, offset_hex):#偏移函数 # 将偏移量转换为整数 offset = int(offset_hex,16) # 定义正则表达式模式 begin_pattern = re.compile(r'\s*/begin\s+CHARACTERISTIC')# address_pattern = re.compile(r'ECU\s+Address\s+[^0x]*?\s+(0x[\dA-Fa-f]+)') address_pattern11 = re.compile(r'0xFE([0-9A-F]+)') lines = input_string.split('\n') # 将字符串按行分割 result_lines = [] in_characteristic_section = False current_address = None for line in lines: # if ('VALUE 0xFEXFDD81AFBC15 Scalar_BOOLEAN 0 tvi_TqVectInf_FD_CM_boolea' in line): # print(';') stripped_line = line.rstrip() # 去除行尾的空白字符 if begin_pattern.search(stripped_line): in_characteristic_section = True result_lines.append(stripped_line) # 保留这行 continue if not stripped_line: # 遇到空行,退出特性部分处理 in_characteristic_section = False result_lines.append('') # 保留空行 continue if in_characteristic_section:#空行用于识别各块 address_match = re.search(address_pattern11, stripped_line)#行 if address_match: # 提取地址并转换为整数 current_address_hex = 'FE' + address_match.group(1) current_address = int(current_address_hex, 16) # 计算新地址并格式化为十六进制字符串 new_address = hex(current_address + offset - 0x100000000).upper()[2:] # 去除'0x'并转换为大写FEXXXX # 替换地址并构建新行 #current_address_hex = current_address_hex new_line = stripped_line.replace(current_address_hex, new_address) result_lines.append(new_line) else: # 如果不是地址行,则直接添加 result_lines.append(stripped_line) else: # 如果不在特性部分,则直接添加未处理的行 result_lines.append(stripped_line) return '\n'.join(result_lines) def select_folder():#打开窗口获取文件1 # root = tk.Tk() # root.withdraw() # 隐藏主窗口 # folder_selected = filedialog.askdirectory() folder_selected = A2LUpdata_fold print(folder_selected) if folder_selected: Code,ElfFile = process_folder(folder_selected) return Code,folder_selected,ElfFile def process_folder(folder_path,):#打开窗口获取文件2 head_content = None code_content = None for filename in os.listdir(folder_path): ElfFile = '1' if filename.endswith('.a2l') and ('master' in filename):#这个是Head with open(os.path.join(folder_path, filename), 'r', encoding='utf-8') as file: head_content = file.read() elif filename.endswith('.a2l') and 'Output_All' in filename:#这个是Code # 假设只存在两个 .a2l 文件,且其中一个包含 'head',则另一个即为 'Code' with open(os.path.join(folder_path, filename), 'r', encoding='utf-8') as file: code_content = file.read() elif filename.endswith('.elf'): ElfFile = os.path.join(folder_path, filename) if code_content:#head_content and #Head = head_content Code = code_content return Code,ElfFile #print("Head content:", Head) #print("Code content:", Code) print("success!") else: print("Failed to read all required files.") # 运行选择文件夹的函数 def resolve_dictionary(d): changed = True while changed: changed = False for key in d: value = d[key] if value in d and d[value] != value: # 检查值是否是其他键,并且不是自引用 d[key] = d[value] changed = True return d #主函数从这里开始 current_script_dir = 'F:\\' Head = '' Code = '' Code ,current_script_dir ,ElfFile = select_folder()#获取原始A2L文件,其中Head是要添加的头文件 # print(ElfFile) ElfFile = ElfFile.replace("/", "\\") ElfFile = ElfFile.replace("\\", "\\\\") ##################################################################### config_path = os.path.join(pathorigin, 'path_config.json') print(config_path) # config_path = config_path.replace('\\','\\\\') # 读取JSON文件并加载为字典 with open(config_path, 'r', encoding='utf-8') as f: pathdict = json.load(f) ElfFile = pathdict['elf_path'] ##################################################################### address_dict = get_variable_addresses(ElfFile)#从ELF里面提取出map,对于普通变量,构建变量名-地址的索引 for key,value in address_dict.items(): print(key) parseDwarfOutput(ElfFile,pathorigin)#生成编译文件dwarf list11,it_dict1,classes,arrayclasslist11,anydict = dwarfdo(os.path.join(A2LUpdata_fold, 'dwarf_info1.txt'))#找到了所有需要进行(少了一个数组) #处理dwarf生成结果 # for struct in list11:#遍历所有的结构体,这个list疑似出问题 # for structnum,value0 in struct.items(): # if('169abc4' == structnum):#结构体编号 # print('1')# # print(structnum) # for member in value0:#在这里寻找指定的成员 # # for i in i2.values(): # for key,value in member.items(): # print(key) # print(value) # 打印结果 #for var_name, address in address_dict.items(): # print(type(var_name)) # print(type(address)) # print(var_name) # print(address) # print(f"Variable: {var_name}, Address: 0x{address:x}") # print(address_dict['apa_AccrPedlArbn_FD_B']) #------------------------------------------------------------------------------------# #这里做一个操作,实现typedef正确识别 it_dict = resolve_dictionary(it_dict1) #------------------------------------------------------------------------------------# New_Code = Getaddressfromelf(Code,address_dict,classes)#普通的变量在这里更新地址 #0923类型 New_Code = Getaddressfromelf1227(New_Code,address_dict,classes)#普通的变量在这里更新地址 #1227类型 New_Code = Getaddressfromelfplus(New_Code,list11,it_dict,classes,arrayclasslist11,address_dict,anydict)#普通的结构体与普通的 #多维数组,在这里更新地址----0923类型的 New_Code = Getaddressfromelfplus1227(New_Code,list11,it_dict,classes,arrayclasslist11,address_dict,anydict) #多维数组,在这里更新地址----1227类型的 #3处,更新地址与偏移------------------------------------------------------------- offset_hex = "0x2180000"#偏移量 #New_Code = replace_header_with_a2ml(New_Code, Head)#这一步进行头文件的合并 # 调用函数并打印结果 #New_Code = process_string(New_Code, offset_hex)#更新好的地址,在这里进行偏移 #print(New_Code) # result = New_Code # ------------删除编译信息 # file_path = os.path.join(current_script_dir, 'dwarf_info1.txt') # if os.path.exists(file_path): # # 删除文件 # os.remove(file_path) # print(f"文件 {file_path} 已删除") # else: # print(f"文件 {file_path} 不存在") # ------------删除编译信息 New_Code = New_Code.replace('ECU_ADDRESS FE','ECU_ADDRESS 0xFE') # 获取当前脚本的目录 result = New_Code #current_script_dir = os.path.dirname(os.path.realpath(__file__)) # 构造目标文件的路径(与当前脚本同路径,文件名为 output.a2l) output_file_path = os.path.join(A2LUpdata_fold, 'Output_All.a2l') # 将字符串内容写入到目标文件中 with open(output_file_path, 'w', encoding='utf-8') as output_file: output_file.write(result) print(f"A2L content has been saved to {output_file_path}")
09-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

银狐游戏开发资源2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值