diff options
Diffstat (limited to 'gr-utils/python/modtool/tools/parser_cc_block.py')
-rw-r--r-- | gr-utils/python/modtool/tools/parser_cc_block.py | 223 |
1 files changed, 0 insertions, 223 deletions
diff --git a/gr-utils/python/modtool/tools/parser_cc_block.py b/gr-utils/python/modtool/tools/parser_cc_block.py deleted file mode 100644 index 81c10f0cdc..0000000000 --- a/gr-utils/python/modtool/tools/parser_cc_block.py +++ /dev/null @@ -1,223 +0,0 @@ -# -# Copyright 2013, 2018 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# -''' A parser for blocks written in C++ ''' - -from __future__ import print_function -from __future__ import absolute_import -from __future__ import unicode_literals - -import re -import sys -import logging - -logger = logging.getLogger(__name__) - -def dummy_translator(the_type, default_v=None): - """ Doesn't really translate. """ - return the_type - -class ParserCCBlock(object): - """ Class to read blocks written in C++ """ - def __init__(self, filename_cc, filename_h, blockname, version, type_trans=dummy_translator): - with open(filename_cc) as f: - self.code_cc = f.read() - with open(filename_h) as f: - self.code_h = f.read() - self.blockname = blockname - self.type_trans = type_trans - self.version = version - - def read_io_signature(self): - """ Scans a .cc file for an IO signature. """ - def _figure_out_iotype_and_vlen(iosigcall, typestr): - """ From a type identifier, returns the data type. - E.g., for sizeof(int), it will return 'int'. - Returns a list! """ - if 'gr::io_signature::makev' in iosigcall: - logger.error('tbi') - raise ValueError - return {'type': [_typestr_to_iotype(x) for x in typestr.split(',')], - 'vlen': [_typestr_to_vlen(x) for x in typestr.split(',')] - } - def _typestr_to_iotype(typestr): - """ Convert a type string (e.g. sizeof(int) * vlen) to the type (e.g. 'int'). """ - type_match = re.search(r'sizeof\s*\(([^)]*)\)', typestr) - if type_match is None: - return self.type_trans('char') - return self.type_trans(type_match.group(1)) - def _typestr_to_vlen(typestr): - """ From a type identifier, returns the vector length of the block's - input/out. E.g., for 'sizeof(int) * 10', it returns 10. For - 'sizeof(int)', it returns '1'. For 'sizeof(int) * vlen', it returns - the string vlen. """ - # Catch fringe case where no sizeof() is given - if typestr.find('sizeof') == -1: - return typestr - if typestr.find('*') == -1: - return '1' - vlen_parts = typestr.split('*') - for fac in vlen_parts: - if fac.find('sizeof') != -1: - vlen_parts.remove(fac) - if len(vlen_parts) == 1: - return vlen_parts[0].strip() - elif len(vlen_parts) > 1: - return '*'.join(vlen_parts).strip() - iosig = {} - iosig_regex = r'(?P<incall>gr::io_signature::make[23v]?)\s*\(\s*(?P<inmin>[^,]+),\s*(?P<inmax>[^,]+),' + \ - r'\s*(?P<intype>(\([^\)]*\)|[^)])+)\),\s*' + \ - r'(?P<outcall>gr::io_signature::make[23v]?)\s*\(\s*(?P<outmin>[^,]+),\s*(?P<outmax>[^,]+),' + \ - r'\s*(?P<outtype>(\([^\)]*\)|[^)])+)\)' - iosig_match = re.compile(iosig_regex, re.MULTILINE).search(self.code_cc) - try: - iosig['in'] = _figure_out_iotype_and_vlen(iosig_match.group('incall'), - iosig_match.group('intype')) - iosig['in']['min_ports'] = iosig_match.group('inmin') - iosig['in']['max_ports'] = iosig_match.group('inmax') - except Exception: - logger.error("Error: Can't parse input signature.") - try: - iosig['out'] = _figure_out_iotype_and_vlen(iosig_match.group('outcall'), - iosig_match.group('outtype')) - iosig['out']['min_ports'] = iosig_match.group('outmin') - iosig['out']['max_ports'] = iosig_match.group('outmax') - except Exception: - logger.error("Error: Can't parse output signature.") - return iosig - - - def read_params(self): - """ Read the parameters required to initialize the block """ - def _scan_param_list(start_idx): - """ Go through a parameter list and return a tuple each: - (type, name, default_value). Python's re just doesn't cut - it for C++ code :( """ - i = start_idx - c = self.code_h - if c[i] != '(': - raise ValueError - i += 1 - - param_list = [] - read_state = 'type' - in_string = False - parens_count = 0 # Counts () - brackets_count = 0 # Counts <> - end_of_list = False - this_type = '' - this_name = '' - this_defv = '' - WHITESPACE = ' \t\n\r\f\v' - while not end_of_list: - # Keep track of (), stop when reaching final closing parens - if not in_string: - if c[i] == ')': - if parens_count == 0: - if read_state == 'type' and len(this_type): - raise ValueError( - 'Found closing parentheses before finishing ' - 'last argument (this is how far I got: {})'.format \ - (str(param_list)) - ) - if len(this_type): - param_list.append((this_type, this_name, this_defv)) - end_of_list = True - break - else: - parens_count -= 1 - elif c[i] == '(': - parens_count += 1 - # Parameter type (int, const std::string, std::vector<gr_complex>, unsigned long ...) - if read_state == 'type': - if c[i] == '<': - brackets_count += 1 - if c[i] == '>': - brackets_count -= 1 - if c[i] == '&': - i += 1 - continue - if c[i] in WHITESPACE and brackets_count == 0: - while c[i] in WHITESPACE: - i += 1 - continue - if this_type == 'const' or this_type == '': # Ignore this - this_type = '' - elif this_type == 'unsigned': # Continue - this_type += ' ' - continue - else: - read_state = 'name' - continue - this_type += c[i] - i += 1 - continue - # Parameter name - if read_state == 'name': - if c[i] == '&' or c[i] in WHITESPACE: - i += 1 - elif c[i] == '=': - if parens_count != 0: - raise ValueError( - 'While parsing argument {} ({}): name finished but no closing parentheses.'.format \ - (len(param_list)+1, this_type + ' ' + this_name) - ) - read_state = 'defv' - i += 1 - elif c[i] == ',': - if parens_count: - raise ValueError( - 'While parsing argument {} ({}): name finished but no closing parentheses.'.format \ - (len(param_list)+1, this_type + ' ' + this_name) - ) - read_state = 'defv' - else: - this_name += c[i] - i += 1 - continue - # Default value - if read_state == 'defv': - if in_string: - if c[i] == '"' and c[i-1] != '\\': - in_string = False - else: - this_defv += c[i] - elif c[i] == ',': - if parens_count: - raise ValueError( - 'While parsing argument {} ({}): default value finished but no closing parentheses.'.format \ - (len(param_list)+1, this_type + ' ' + this_name) - ) - read_state = 'type' - param_list.append((this_type, this_name, this_defv)) - this_type = '' - this_name = '' - this_defv = '' - else: - this_defv += c[i] - i += 1 - continue - return param_list - # Go, go, go! - if self.version in ('37', '38'): - make_regex = r'static\s+sptr\s+make\s*' - else: - make_regex = r'(?<=_API)\s+\w+_sptr\s+\w+_make_\w+\s*' - make_match = re.compile(make_regex, re.MULTILINE).search(self.code_h) - try: - params_list = _scan_param_list(make_match.end(0)) - except ValueError as ve: - logger.error("Can't parse the argument list: ", ve.args[0]) - sys.exit(0) - params = [] - for plist in params_list: - params.append({'type': self.type_trans(plist[0], plist[2]), - 'key': plist[1], - 'default': plist[2], - 'in_constructor': True}) - return params |