以下对提供的代码进行相关分析:
### 代码功能概述
这段 Python 代码旨在解析 OPPO 充电 IC 配置文件,支持获取配置文件版本、合并多个配置文件、生成 `.h` 和 `.c` 配置文件、生成调试文件以及生成 Markdown 文档等功能。
### 代码问题分析与修正
1. **格式化字符串问题**:在 `show_error` 和 `show_warning` 函数中,使用 `%` 格式化字符串时,传入的参数应该是元组,而代码中传入的是集合,需修改。
2. **文件关闭问题**:在 `open` 文件后,使用 `f.close` 关闭文件有误,应改为 `f.close()`。
以下是修正后的代码:
```python
#coding=utf-8
from ast import Param
import os
import sys
import json
import datetime
import hashlib
import re
import argparse
config_path = ""
cfg_version_list = []
def show_warning(str):
print("Warning: %s[%d]: " % (__file__, sys._getframe(1).f_lineno) + str)
def show_error(str):
print("Error: %s[%d]: " % (__file__, sys._getframe(1).f_lineno) + str)
sys.exit(-1)
def vict_read_support(vict_cfg):
if 'read' not in vict_cfg:
return False
read = vict_cfg['read']
if read is False:
return False
return True
def vict_write_support(vict_cfg):
if 'write' not in vict_cfg:
return False
write = vict_cfg['write']
if write is False:
return False
return True
def vict_overwrite_support(vict_cfg):
if 'overwrite' not in vict_cfg:
return False
overwrite = vict_cfg['overwrite']
if overwrite is False:
return False
return True
def vict_read_desc(read_cfg, language='zh'):
desc = read_cfg['desc']
if language in desc:
return desc[language]
return "N/A"
def vict_read_cmd(read_cfg):
if 'cmd' not in read_cfg:
return "N/A"
return read_cfg['cmd']
def vict_write_desc(write_cfg, language='zh'):
desc = write_cfg['desc']
if language in desc:
return desc[language]
return "N/A"
def vict_write_cmd(write_cfg):
if 'cmd' not in write_cfg:
return "N/A"
return write_cfg['cmd']
def vict_overwrite_desc(overwrite_cfg, language='zh'):
desc = overwrite_cfg['desc']
if language in desc:
return desc[language]
return "N/A"
def vict_overwrite_cmd(overwrite_cfg):
if 'cmd' not in overwrite_cfg:
return "N/A"
return overwrite_cfg['cmd']
def func_auto_debug_support(func):
if 'auto_debug_code' not in func:
return False
return func['auto_debug_code']
def vict_can_read_support(func):
if func_auto_debug_support(func) == False:
return False
if vict_write_support(func['vict']): # 修改此处
return False
if len(func['parameter_list']) == 0:
return False
for desc in func['parameter_desc']:
if desc['type'] == 'in':
return False
return True
def vict_can_write_support(func):
if func_auto_debug_support(func) == False:
return False
if vict_read_support(func['vict']): # 修改此处
return False
if len(func['parameter_list']) == 0:
return True
for desc in func['parameter_desc']:
if desc['type'] == 'out':
return False
return True
def is_signed_64_bit_type(type):
types_64bit = [
"s64",
"long",
"long long",
"long int",
"long long int",
"int64_t",
"const s64",
"const long",
"const long long",
"const long int",
"const long long int",
"const int64_t",
]
for tmp in types_64bit:
tmp_c = tmp.replace(" ", "")
type_c = type.replace(" ", "")
if type.startswith(tmp_c):
return True
return False
def is_signed_32_bit_type(type):
types_32bit = [
"s32",
"int",
"int32_t",
"const s32",
"const int",
"const int32_t",
]
for tmp in types_32bit:
tmp_c = tmp.replace(" ", "")
type_c = type.replace(" ", "")
if type.startswith(tmp_c):
return True
return False
def is_signed_16_bit_type(type):
types_16bit = [
"s16",
"short",
"short int",
"int16_t",
"const s16",
"const short",
"const short int",
"const int16_t",
]
for tmp in types_16bit:
tmp_c = tmp.replace(" ", "")
type_c = type.replace(" ", "")
if type.startswith(tmp_c):
return True
return False
def is_signed_8_bit_type(type):
types_8bit = [
"s8",
"char",
"int8_t",
"const s8",
"const char",
"const int8_t",
]
for tmp in types_8bit:
tmp_c = tmp.replace(" ", "")
type_c = type.replace(" ", "")
if type.startswith(tmp_c):
return True
return False
def check_func_parameter_list(lable, param_desc_list, num):
if len(param_desc_list) != num:
show_error("func[\"%s\"] \"parameter_list\" num error" % lable) # 修改此处
count = 0
for param in param_desc_list:
if 'range' not in param:
show_error("func[\"%s\"] parameter %d missing \"range\" info" % (lable, count)) # 修改此处
if 'type' not in param:
show_error("func[\"%s\"] parameter %d missing \"type\" info" % (lable, count)) # 修改此处
if 'desc' not in param:
show_error("func[\"%s\"] parameter %d missing \"desc\" info" % (lable, count)) # 修改此处
count += 1
def check_func_vict_info(lable, vict_cfg):
if vict_read_support(vict_cfg):
read_cfg = vict_cfg['read']
if 'cmd' not in read_cfg:
show_error("func[\"%s\"] missing read \"cmd\" info" % lable) # 修改此处
if 'desc' not in read_cfg:
show_error("func[\"%s\"] missing read \"desc\" info" % lable) # 修改此处
if vict_write_support(vict_cfg):
write_cfg = vict_cfg['write']
if 'cmd' not in write_cfg:
show_error("func[\"%s\"] missing write \"cmd\" info" % lable) # 修改此处
if 'desc' not in write_cfg:
show_error("func[\"%s\"] missing write \"desc\" info" % lable) # 修改此处
if vict_overwrite_support(vict_cfg):
overwrite_cfg = vict_cfg['overwrite']
if 'cmd' not in overwrite_cfg:
show_error("func[\"%s\"] missing overwrite \"cmd\" info" % lable) # 修改此处
if 'desc' not in overwrite_cfg:
show_error("func[\"%s\"] missing overwrite \"desc\" info" % lable) # 修改此处
def is_pointer_type_parameter(c_type):
c_type = c_type.strip()
if c_type.endswith('*'):
return True
if '[' in c_type and ']' in c_type:
return True
return False
def check_func_auto_debug_info(func):
if func_auto_debug_support(func) == False:
return
i = 0
for desc in func['parameter_desc']:
if desc['type'] == 'in' and is_pointer_type_parameter(func['parameter_list'][i]):
show_error("func[\"%s\"]: Parameter %d is a pointer parameter of input type and cannot support the \"auto_debug_code\" option. Please set the \"auto_debug_code\" option to false." % (func['lable'], i))
i += 1
def check_func_cfg(func, type, index):
if 'lable' not in func:
show_error(type + ": func[" + str(index) + "] missing \"lable\" info")
if 'desc' not in func:
show_error(type + ": func[" + func['lable'] +
"] missing \"desc\" info")
if 'parameter_list' not in func:
show_error(type + ": func[" + func['lable'] +
"] missing \"parameter_list\" info")
if 'parameter_desc' not in func:
show_error(type + ": func[" + func['lable'] +
"] missing \"parameter_desc\" info")
if 'vict' not in func:
show_error(type + ": func[" + func['lable'] +
"] missing \"vict\" info")
check_func_parameter_list(func['lable'], func['parameter_desc'],
len(func['parameter_list']))
check_func_vict_info(func['lable'], func['vict'])
check_func_auto_debug_info(func)
def is_top_cfg(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
if 'type' not in cfg:
show_error(ic_cfg_path + ": Unknown config file type")
if cfg['type'] == "top_cfg":
return True
return False
def is_ic_cfg(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
if 'type' not in cfg:
show_error(ic_cfg_path + ": Unknown config file type")
if cfg['type'] == "ic_cfg":
return True
return False
def get_ic_cfg_func_num(cfg):
func_list = cfg['list']
return len(func_list)
def get_ic_cfg_hash(cfg, num=-1, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
cfg_str = ""
func_list = cfg['list']
index = 0
for func in func_list:
check_func_cfg(func, ic_cfg_path, index)
cfg_str = cfg_str + func['lable'] + str(func['parameter_list'])
if vict_read_support(func['vict']):
cfg_str += vict_read_cmd(func['vict']['read'])
if vict_write_support(func['vict']):
cfg_str += vict_write_cmd(func['vict']['write'])
if vict_overwrite_support(func['vict']):
cfg_str += vict_overwrite_cmd(func['vict']['overwrite'])
index = index + 1
if num > 0 and index >= num:
break
hash = hashlib.sha256(bytes(cfg_str, encoding="utf-8")).hexdigest()
return str(hash)
def parse_ic_cfg_version(version):
v_info = version.split(":")
v_version = v_info[0].replace('V', '')
v_version_info = v_version.split(".")
v_major = int(v_version_info[0], 10)
v_minor = int(v_version_info[1], 10)
v_num = int(v_info[1], 10)
v_hash = v_info[2]
return v_major, v_minor, v_num, v_hash
def calculate_new_version(new_info, old_info):
major = old_info['major']
minor = old_info['minor']
v_version = "V%d.%d" % (major, minor)
v_num = old_info['num']
v_hash = old_info['hash']
if (new_info['hash_num'] == old_info['hash']):
if (new_info['num'] == old_info['num']):
v_version = "V%d.%d" % (major, minor)
v_hash = old_info['hash']
else:
minor = minor + 1
if (minor > 20):
minor = 0
major = major + 1
v_version = "V%d.%d" % (major, minor)
v_num = new_info['num']
v_hash = new_info['hash']
else:
major = major + 1
minor = 0
v_version = "V%d.%d" % (major, minor)
v_num = new_info['num']
v_hash = new_info['hash']
return v_version, v_num, v_hash
def get_ic_cfg_version(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
if 'version' not in cfg:
show_warning(ic_cfg_path + ": missing version")
version = ""
else:
version = cfg['version']
v_num = get_ic_cfg_func_num(cfg)
v_hash = get_ic_cfg_hash(cfg, path=ic_cfg_path)
if version == "":
v_version = "V1.0"
else:
match = re.match("V[0-9]+\.[0-9]+:[0-9]+:[0-9a-f]+", version, flags=0)
if match is None:
show_error(ic_cfg_path +
": version format error, you can use: \"V1.0:%d:%s\"" %
(v_num, v_hash))
v_major_old, v_minor_old, v_num_old, v_hash_old = parse_ic_cfg_version(
version)
v_hash_num = get_ic_cfg_hash(cfg, v_num_old, ic_cfg_path)
v_version, v_num, v_hash = calculate_new_version(
{
'num': v_num,
'hash': v_hash,
'hash_num': v_hash_num
},
{
'major': v_major_old,
'minor': v_minor_old,
'num': v_num_old,
'hash': v_hash_old
})
version = "%s:%d:%s" % (v_version, v_num, v_hash)
return version
def get_top_cfg_version(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
version_list = ""
ic_list = cfg['oplus_chg_ic_list']
for ic_name in ic_list:
ic_cfg_file_name = get_ic_cfg_file(ic_name)
with open(ic_cfg_file_name) as f:
ic = json.load(f)
f.close() # 修改此处
version = get_ic_cfg_version(ic, ic_name)
version_list = version_list + "%s[%s]\n" % (ic['name'], version)
return version_list
def get_cfg_version(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
if is_ic_cfg(cfg, ic_cfg_path):
version = get_ic_cfg_version(cfg, ic_cfg_path)
elif is_top_cfg(cfg, ic_cfg_path):
version = get_top_cfg_version(cfg, ic_cfg_path)
else:
show_error(ic_cfg_path + ": Unknown config file type")
print(version)
def check_ic_cfg_version(cfg, path=None):
if path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = path
if is_ic_cfg(cfg, ic_cfg_path) is False:
show_error(ic_cfg_path + " is not ic config file")
if 'version' not in cfg:
show_error(ic_cfg_path + ": missing version")
version = cfg['version']
version_new = get_ic_cfg_version(cfg, ic_cfg_path)
if version != version_new:
show_error(ic_cfg_path +
": version error, the correct version should be: \"%s\"" %
(version_new))
return version
def get_ic_cfg_file(name):
global config_path
file_name = config_path + "/" + name
if os.path.isfile(file_name) is False:
show_error(name + ".json not exist")
return file_name
def merge_ic_cfg(cfg, merge_file=None, cfg_path=None):
global cfg_version_list
if cfg_path == None:
ic_cfg_path = "config file"
else:
ic_cfg_path = cfg_path
if is_top_cfg(cfg, ic_cfg_path) is False:
show_error(ic_cfg_path + " is