diff --git a/tools/check_typed_item_calls.py b/tools/check_typed_item_calls.py index 52e6943625..c909ca694c 100755 --- a/tools/check_typed_item_calls.py +++ b/tools/check_typed_item_calls.py @@ -52,34 +52,66 @@ class Call: # A check for a particular API function. class APICheck: - def __init__(self, fun_name, allowed_types): + def __init__(self, fun_name, allowed_types, positive_length=False): self.fun_name = fun_name self.allowed_types = allowed_types + self.positive_length = positive_length self.calls = [] if fun_name.startswith('ptvcursor'): # RE captures function name + 1st 2 args (always ptvc + hfindex) self.p = re.compile('.*' + self.fun_name + '\(([a-zA-Z0-9_]+),\s*([a-zA-Z0-9_]+)') elif fun_name.find('add_bitmask') == -1: - # RE captures function name + 1st 2 args (always tree + hfindex) - self.p = re.compile('.*' + self.fun_name + '\(([a-zA-Z0-9_]+),\s*([a-zA-Z0-9_]+)') + # Normal case. + # RE captures function name + 1st 2 args (always tree + hfindex + length) + self.p = re.compile('.*' + self.fun_name + '\(([a-zA-Z0-9_]+),\s*([a-zA-Z0-9_]+),\s*[a-zA-Z0-9_]+,\s*[a-zA-Z0-9_]+,\s*([a-zA-Z0-9_]+)') else: + # _add_bitmask functions. # RE captures function name + 1st + 4th args (always tree + hfindex) self.p = re.compile('.*' + self.fun_name + '\(([a-zA-Z0-9_]+),\s*[a-zA-Z0-9_]+,\s*[a-zA-Z0-9_]+,\s*([a-zA-Z0-9_]+)') self.file = None + def find_calls(self, file): self.file = file self.calls = [] + with open(file, 'r') as f: - for line_number, line in enumerate(f, start=1): - m = self.p.match(line) - if m: - self.calls.append(Call(m.group(2), line_number=line_number)) + contents = f.read() + lines = contents.splitlines() + total_lines = len(lines) + line_number = 1 + for line in lines: + # Want to check this, and next few lines + to_check = lines[line_number-1] + # Nothing to check if function name isn't in it + if to_check.find(self.fun_name) != -1: + # Ok, add the next file lines before trying RE + for i in range(1, 4): + if line_number+i < total_lines: + to_check += lines[line_number-1+i] + m = self.p.match(to_check) + if m: + # Add call. We have length if re had 3 groups. + num_groups = self.p.groups + self.calls.append(Call(m.group(2), + line_number=line_number, + length=(m.group(3) if (num_groups==3) else None))) + line_number += 1 + + def check_against_items(self, items): + global errors_found for call in self.calls: + if self.positive_length and call.length != None: + if call.length != -1 and call.length <= 0: + print('Error: ' + self.fun_name + '(.., ' + call.hf_name + ', ...) called at ' + + self.file + ':' + str(call.line_number) + + ' with length ' + str(call.length) + ' - must be > 0 or -1') + # Inc global count of issues found. + errors_found += 1 if call.hf_name in items: if not items[call.hf_name].item_type in self.allowed_types: # Report this issue. @@ -88,7 +120,6 @@ class APICheck: ' with type ' + items[call.hf_name].item_type) print(' (allowed types are', self.allowed_types, ')\n') # Inc global count of issues found. - global errors_found errors_found += 1 @@ -139,6 +170,7 @@ class ProtoTreeAddItemCheck(APICheck): with open(file, 'r') as f: # TODO: would be better to just iterate over those found in whole file, # but extra effort would be needed to still know line number. + # TODO: See what APICheck does above.. for line_number, line in enumerate(f, start=1): m = self.p.match(line) if m: @@ -389,15 +421,15 @@ class Item: # These are APIs in proto.c that check a set of types at runtime and can print '.. is not of type ..' to the console # if the type is not suitable. apiChecks = [] -apiChecks.append(APICheck('proto_tree_add_item_ret_uint', { 'FT_CHAR', 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32'})) +apiChecks.append(APICheck('proto_tree_add_item_ret_uint', { 'FT_CHAR', 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32'}, positive_length=True)) apiChecks.append(APICheck('proto_tree_add_item_ret_int', { 'FT_INT8', 'FT_INT16', 'FT_INT24', 'FT_INT32'})) -apiChecks.append(APICheck('ptvcursor_add_ret_uint', { 'FT_CHAR', 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32'})) -apiChecks.append(APICheck('ptvcursor_add_ret_int', { 'FT_INT8', 'FT_INT16', 'FT_INT24', 'FT_INT32'})) +apiChecks.append(APICheck('ptvcursor_add_ret_uint', { 'FT_CHAR', 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32'}, positive_length=True)) +apiChecks.append(APICheck('ptvcursor_add_ret_int', { 'FT_INT8', 'FT_INT16', 'FT_INT24', 'FT_INT32'}, positive_length=True)) apiChecks.append(APICheck('ptvcursor_add_ret_string', { 'FT_STRING', 'FT_STRINGZ', 'FT_UINT_STRING', 'FT_STRINGZPAD', 'FT_STRINGZTRUNC'})) -apiChecks.append(APICheck('ptvcursor_add_ret_boolean', { 'FT_BOOLEAN'})) -apiChecks.append(APICheck('proto_tree_add_item_ret_uint64', { 'FT_UINT40', 'FT_UINT48', 'FT_UINT56', 'FT_UINT64'})) -apiChecks.append(APICheck('proto_tree_add_item_ret_int64', { 'FT_INT40', 'FT_INT48', 'FT_INT56', 'FT_INT64'})) -apiChecks.append(APICheck('proto_tree_add_item_ret_boolean', { 'FT_BOOLEAN'})) +apiChecks.append(APICheck('ptvcursor_add_ret_boolean', { 'FT_BOOLEAN'}, positive_length=True)) +apiChecks.append(APICheck('proto_tree_add_item_ret_uint64', { 'FT_UINT40', 'FT_UINT48', 'FT_UINT56', 'FT_UINT64'}, positive_length=True)) +apiChecks.append(APICheck('proto_tree_add_item_ret_int64', { 'FT_INT40', 'FT_INT48', 'FT_INT56', 'FT_INT64'}, positive_length=True)) +apiChecks.append(APICheck('proto_tree_add_item_ret_boolean', { 'FT_BOOLEAN'}, positive_length=True)) apiChecks.append(APICheck('proto_tree_add_item_ret_string_and_length', { 'FT_STRING', 'FT_STRINGZ', 'FT_UINT_STRING', 'FT_STRINGZPAD', 'FT_STRINGZTRUNC'})) apiChecks.append(APICheck('proto_tree_add_item_ret_display_string_and_length', { 'FT_STRING', 'FT_STRINGZ', 'FT_UINT_STRING', 'FT_STRINGZPAD', 'FT_STRINGZTRUNC', 'FT_BYTES', 'FT_UINT_BYTES'})) @@ -435,6 +467,7 @@ apiChecks.append(APICheck('proto_tree_add_ascii_7bits_item', { 'FT_STRING'})) apiChecks.append(APICheck('proto_tree_add_checksum', { 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32'})) apiChecks.append(APICheck('proto_tree_add_int64_bits_format_value', { 'FT_INT40', 'FT_INT48', 'FT_INT56', 'FT_INT64'})) +# TODO: add proto_tree_add_bytes_item, proto_tree_add_time_item ? bitmask_types = { 'FT_CHAR', 'FT_UINT8', 'FT_UINT16', 'FT_UINT24', 'FT_UINT32', 'FT_INT8', 'FT_INT16', 'FT_INT24', 'FT_INT32', @@ -488,7 +521,6 @@ def isGeneratedFile(filename): line.find('This filter was automatically generated') != -1 or line.find('This file is auto generated, do not edit!') != -1): - f_read.close() return True lines_tested = lines_tested + 1