feat(esp8266): Add esp-idf error number description

Commit ID: f49e2afe
This commit is contained in:
dongheng
2019-03-21 17:23:30 +08:00
parent 8378b1af6c
commit 050fb6a63f
5 changed files with 538 additions and 40 deletions

View File

@ -40,17 +40,18 @@ import textwrap
import functools
# list files here which should not be parsed
ignore_files = [ 'components/mdns/test_afl_fuzz_host/esp32_compat.h' ]
ignore_files = ['components/mdns/test_afl_fuzz_host/esp32_compat.h']
# add directories here which should not be parsed
ignore_dirs = ( 'examples' )
ignore_dirs = ('examples')
# macros from here have higher priorities in case of collisions
priority_headers = [ 'components/esp32/include/esp_err.h' ]
priority_headers = ['components/esp32/include/esp_err.h']
err_dict = collections.defaultdict(list) # identified errors are stored here; mapped by the error code
rev_err_dict = dict() # map of error string to error code
unproc_list = list() # errors with unknown codes which depend on other errors
err_dict = collections.defaultdict(list) #identified errors are stored here; mapped by the error code
rev_err_dict = dict() #map of error string to error code
unproc_list = list() #errors with unknown codes which depend on other errors
class ErrItem(object):
"""
@ -62,13 +63,14 @@ class ErrItem(object):
- rel_str - (optional) error string which is a base for the error
- rel_off - (optional) offset in relation to the base error
"""
def __init__(self, name, file, include_as = None, comment = "", rel_str = "", rel_off = 0):
def __init__(self, name, file, include_as=None, comment="", rel_str="", rel_off=0):
self.name = name
self.file = file
self.include_as = include_as
self.comment = comment
self.rel_str = rel_str
self.rel_off = rel_off
def __str__(self):
ret = self.name + " from " + self.file
if (self.rel_str != ""):
@ -76,6 +78,7 @@ class ErrItem(object):
if self.comment != "":
ret += " // " + self.comment
return ret
def __cmp__(self, other):
if self.file in priority_headers and other.file not in priority_headers:
return -1
@ -99,6 +102,7 @@ class ErrItem(object):
else:
return 0
class InputError(RuntimeError):
"""
Represents and error on the input
@ -106,6 +110,7 @@ class InputError(RuntimeError):
def __init__(self, p, e):
super(InputError, self).__init__(p + ": " + e)
def process(line, idf_path, include_as):
"""
Process a line of text from file idf_path (relative to IDF project).
@ -129,18 +134,18 @@ def process(line, idf_path, include_as):
m = re.search(r'/\*!<(.+?(?=\*/))', todo_str)
if m:
comment = m.group(1).strip()
todo_str = todo_str[:m.start()].strip() # keep just the part before the comment
todo_str = todo_str[:m.start()].strip() # keep just the part before the comment
# identify possible parentheses ()
m = re.search(r'\((.+)\)', todo_str)
if m:
todo_str = m.group(1) #keep what is inside the parentheses
todo_str = m.group(1) # keep what is inside the parentheses
# identify BASE error code, e.g. from the form BASE + 0x01
m = re.search(r'\s*(\w+)\s*\+(.+)', todo_str)
if m:
related = m.group(1) # BASE
todo_str = m.group(2) # keep and process only what is after "BASE +"
related = m.group(1) # BASE
todo_str = m.group(2) # keep and process only what is after "BASE +"
# try to match a hexadecimal number
m = re.search(r'0x([0-9A-Fa-f]+)', todo_str)
@ -153,8 +158,8 @@ def process(line, idf_path, include_as):
num = int(m.group(1), 10)
elif re.match(r'\w+', todo_str):
# It is possible that there is no number, e.g. #define ERROR BASE
related = todo_str # BASE error
num = 0 # (BASE + 0)
related = todo_str # BASE error
num = 0 # (BASE + 0)
else:
raise InputError(idf_path, "Cannot parse line %s" % line)
@ -168,6 +173,7 @@ def process(line, idf_path, include_as):
# Store the information available now and compute the error code later
unproc_list.append(ErrItem(words[1], idf_path, include_as, comment, related, num))
def process_remaining_errors():
"""
Create errors which could not be processed before because the error code
@ -180,7 +186,6 @@ def process_remaining_errors():
for item in unproc_list:
if item.rel_str in rev_err_dict:
base_num = rev_err_dict[item.rel_str]
base = err_dict[base_num][0]
num = base_num + item.rel_off
err_dict[num].append(ErrItem(item.name, item.file, item.include_as, item.comment))
rev_err_dict[item.name] = num
@ -189,6 +194,7 @@ def process_remaining_errors():
del unproc_list[:]
def path_to_include(path):
"""
Process the path (relative to the IDF project) in a form which can be used
@ -207,7 +213,8 @@ def path_to_include(path):
# no include in the path -> use just the filename
return os.path.basename(path)
else:
return os.sep.join(spl_path[i+1:]) # subdirectories and filename in "include"
return os.sep.join(spl_path[i + 1:]) # subdirectories and filename in "include"
def print_warning(error_list, error_code):
"""
@ -217,6 +224,7 @@ def print_warning(error_list, error_code):
for e in error_list:
print(" " + str(e))
def max_string_width():
max = 0
for k in err_dict:
@ -226,6 +234,7 @@ def max_string_width():
max = x
return max
def generate_c_output(fin, fout):
"""
Writes the output to fout based on th error dictionary err_dict and
@ -247,7 +256,7 @@ def generate_c_output(fin, fout):
include_list = list(includes)
include_list.sort()
max_width = max_string_width() + 17 + 1 # length of " ERR_TBL_IT()," with spaces is 17
max_width = max_string_width() + 17 + 1 # length of " ERR_TBL_IT()," with spaces is 17
max_decdig = max(len(str(k)) for k in err_dict)
for line in fin:
@ -271,7 +280,7 @@ def generate_c_output(fin, fout):
fout.write("# ifdef %s\n" % e.name)
fout.write(table_line)
hexnum_length = 0
if k > 0: # negative number and zero should be only ESP_FAIL and ESP_OK
if k > 0: # negative number and zero should be only ESP_FAIL and ESP_OK
hexnum = " 0x%x" % k
hexnum_length = len(hexnum)
fout.write(hexnum)
@ -280,7 +289,7 @@ def generate_c_output(fin, fout):
fout.write(" %s" % e.comment)
else:
indent = " " * (len(table_line) + hexnum_length + 1)
w = textwrap.wrap(e.comment, width=120, initial_indent = indent, subsequent_indent = indent)
w = textwrap.wrap(e.comment, width=120, initial_indent=indent, subsequent_indent=indent)
# this couldn't be done with initial_indent because there is no initial_width option
fout.write(" %s" % w[0].strip())
for i in range(1, len(w)):
@ -289,6 +298,7 @@ def generate_c_output(fin, fout):
else:
fout.write(line)
def generate_rst_output(fout):
for k in sorted(err_dict.keys()):
v = err_dict[k][0]
@ -301,6 +311,7 @@ def generate_rst_output(fout):
fout.write(': {}'.format(v.comment))
fout.write('\n\n')
def main():
if 'IDF_PATH' in os.environ:
idf_path = os.environ['IDF_PATH']
@ -308,8 +319,8 @@ def main():
idf_path = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
parser = argparse.ArgumentParser(description='ESP32 esp_err_to_name lookup generator for esp_err_t')
parser.add_argument('--c_input', help='Path to the esp_err_to_name.c.in template input.', default=idf_path + '/components/esp32/esp_err_to_name.c.in')
parser.add_argument('--c_output', help='Path to the esp_err_to_name.c output.', default=idf_path + '/components/esp32/esp_err_to_name.c')
parser.add_argument('--c_input', help='Path to the esp_err_to_name.c.in template input.', default=idf_path + '/components/esp8266/source/esp_err_to_name.c.in')
parser.add_argument('--c_output', help='Path to the esp_err_to_name.c output.', default=idf_path + '/components/esp8266/source/esp_err_to_name.c')
parser.add_argument('--rst_output', help='Generate .rst output and save it into this file')
args = parser.parse_args()
@ -348,5 +359,6 @@ def main():
with open(args.c_input, 'r', encoding='utf-8') as fin, open(args.c_output, 'w', encoding='utf-8') as fout:
generate_c_output(fin, fout)
if __name__ == "__main__":
main()