X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Ftools%2Fvppapigen%2Fvppapigen.py;h=ae2b0b1ba40c5496e947f358bbcc7b7237f91112;hb=72d8758fdc2266b9f4cd53063da2d23f0855c1df;hp=9d04ec24cfcd1f1be0dcc5b025121627f0a437b3;hpb=9ce6a21aaa76cd40c95ebbcb5fc6e48a8f5dfdb9;p=vpp.git diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py index 9d04ec24cfc..ae2b0b1ba40 100755 --- a/src/tools/vppapigen/vppapigen.py +++ b/src/tools/vppapigen/vppapigen.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 from __future__ import print_function import ply.lex as lex @@ -122,22 +122,30 @@ class VPPAPILexer(object): t_ignore = ' \t' +# +# Side-effect: Sets global_crc +# +def crc_block(block): + global global_crc + s = str(block).encode() + global_crc = binascii.crc32(s, global_crc) + return binascii.crc32(s) & 0xffffffff + + class Service(): - def __init__(self, caller, reply, events=[], stream=False): + def __init__(self, caller, reply, events=None, stream=False): self.caller = caller self.reply = reply self.stream = stream - self.events = events + self.events = [] if events is None else events class Typedef(): def __init__(self, name, flags, block): - global global_crc self.name = name self.flags = flags self.block = block - self.crc = binascii.crc32(str(block)) & 0xffffffff - global_crc = binascii.crc32(str(block), global_crc) + self.crc = crc_block(block) self.manual_print = False self.manual_endian = False for f in flags: @@ -151,6 +159,25 @@ class Typedef(): return self.name + str(self.flags) + str(self.block) +class Using(): + def __init__(self, name, alias): + global global_crc + self.name = name + + if isinstance(alias, Array): + a = { 'type': alias.fieldtype, # noqa: E201 + 'length': alias.length } # noqa: E202 + else: + a = { 'type': alias.fieldtype } # noqa: E201,E202 + self.alias = a + self.crc = binascii.crc32(str(alias).encode()) & 0xffffffff + global_crc = binascii.crc32(str(alias).encode(), global_crc) + global_type_add(name) + + def __repr__(self): + return self.name + str(self.alias) + + class Union(): def __init__(self, name, block): self.type = 'Union' @@ -159,8 +186,7 @@ class Union(): global global_crc self.name = name self.block = block - self.crc = binascii.crc32(str(block)) & 0xffffffff - global_crc = binascii.crc32(str(block), global_crc) + self.crc = crc_block(block) global_type_add(name) def __repr__(self): @@ -169,12 +195,10 @@ class Union(): class Define(): def __init__(self, name, flags, block): - global global_crc self.name = name self.flags = flags self.block = block - self.crc = binascii.crc32(str(block)) & 0xffffffff - global_crc = binascii.crc32(str(block), global_crc) + self.crc = crc_block(block) self.dont_trace = False self.manual_print = False self.manual_endian = False @@ -202,7 +226,6 @@ class Define(): class Enum(): def __init__(self, name, block, enumtype='u32'): - global global_crc self.name = name self.enumtype = enumtype @@ -215,8 +238,7 @@ class Enum(): block[i] = [b, count] self.block = block - self.crc = binascii.crc32(str(block)) & 0xffffffff - global_crc = binascii.crc32(str(block), global_crc) + self.crc = crc_block(block) global_type_add(name) def __repr__(self): @@ -235,8 +257,12 @@ class Import(): f = os.path.join(dir, filename) if os.path.exists(f): break - with open(f) as fd: - self.result = parser.parse_file(fd, None) + if sys.version[0] == '2': + with open(f) as fd: + self.result = parser.parse_file(fd, None) + else: + with open(f, encoding='utf-8') as fd: + self.result = parser.parse_file(fd, None) def __repr__(self): return self.filename @@ -244,10 +270,8 @@ class Import(): class Option(): def __init__(self, option): - global global_crc self.option = option - self.crc = binascii.crc32(str(option)) & 0xffffffff - global_crc = binascii.crc32(str(option), global_crc) + self.crc = crc_block(option) def __repr__(self): return str(self.option) @@ -274,10 +298,11 @@ class Array(): class Field(): - def __init__(self, fieldtype, name): + def __init__(self, fieldtype, name, limit=None): self.type = 'Field' self.fieldtype = fieldtype self.fieldname = name + self.limit = limit def __repr__(self): return str([self.fieldtype, self.fieldname]) @@ -457,6 +482,10 @@ class VPPAPIParser(object): '''typedef : TYPEDEF ID '{' block_statements_opt '}' ';' ''' p[0] = Typedef(p[2], [], p[4]) + def p_typedef_alias(self, p): + '''typedef : TYPEDEF declaration ''' + p[0] = Using(p[2].fieldname, p[2]) + def p_block_statements_opt(self, p): '''block_statements_opt : block_statements ''' p[0] = p[1] @@ -476,7 +505,7 @@ class VPPAPIParser(object): def p_enum_statements(self, p): '''enum_statements : enum_statement - | enum_statements enum_statement''' + | enum_statements enum_statement''' if len(p) == 2: p[0] = [p[1]] else: @@ -491,11 +520,16 @@ class VPPAPIParser(object): p[0] = p[1] def p_declaration(self, p): - '''declaration : type_specifier ID ';' ''' - if len(p) != 4: + '''declaration : type_specifier ID ';' + | type_specifier ID '[' ID '=' assignee ']' ';' ''' + if len(p) == 9: + p[0] = Field(p[1], p[2], {p[4]: p[6]}) + elif len(p) == 4: + p[0] = Field(p[1], p[2]) + else: self._parse_error('ERROR') self.fields.append(p[2]) - p[0] = Field(p[1], p[2]) + def p_declaration_array(self, p): '''declaration : type_specifier ID '[' NUM ']' ';' @@ -594,6 +628,7 @@ class VPPAPI(object): s['Service'] = [] s['types'] = [] s['Import'] = [] + s['Alias'] = {} for o in objs: tname = o.__class__.__name__ if isinstance(o, Define): @@ -606,11 +641,16 @@ class VPPAPI(object): for o2 in o: if isinstance(o2, Service): s['Service'].append(o2) - elif isinstance(o, Enum) or isinstance(o, Typedef) or isinstance(o, Union): + elif (isinstance(o, Enum) or + isinstance(o, Typedef) or + isinstance(o, Union)): s['types'].append(o) + elif isinstance(o, Using): + s['Alias'][o.name] = o.alias else: if tname not in s: - raise ValueError('Unknown class type: {} {}'.format(tname, o)) + raise ValueError('Unknown class type: {} {}' + .format(tname, o)) s[tname].append(o) msgs = {d.name: d for d in s['Define']} @@ -656,7 +696,7 @@ class VPPAPI(object): continue if d[:-5]+'_details' in msgs: s['Service'].append(Service(d, d[:-5]+'_details', - stream=True)) + stream=True)) else: raise ValueError('{} missing details message' .format(d)) @@ -686,13 +726,15 @@ class VPPAPI(object): if in_import and not (isinstance(o, Enum) or isinstance(o, Union) or isinstance(o, Typedef) or - isinstance(o, Import)): + isinstance(o, Import) or + isinstance(o, Using)): continue if isinstance(o, Import): self.process_imports(o.result, True, result) else: result.append(o) + # Add message ids to each message. def add_msg_id(s): for o in s: @@ -720,10 +762,20 @@ def main(): cliparser = argparse.ArgumentParser(description='VPP API generator') cliparser.add_argument('--pluginpath', default=""), cliparser.add_argument('--includedir', action='append'), - cliparser.add_argument('--input', type=argparse.FileType('r'), - default=sys.stdin) - cliparser.add_argument('--output', nargs='?', type=argparse.FileType('w'), - default=sys.stdout) + if sys.version[0] == '2': + cliparser.add_argument('--input', type=argparse.FileType('r'), + default=sys.stdin) + cliparser.add_argument('--output', nargs='?', + type=argparse.FileType('w'), + default=sys.stdout) + + else: + cliparser.add_argument('--input', + type=argparse.FileType('r', encoding='UTF-8'), + default=sys.stdin) + cliparser.add_argument('--output', nargs='?', + type=argparse.FileType('w', encoding='UTF-8'), + default=sys.stdout) cliparser.add_argument('output_module', nargs='?', default='C') cliparser.add_argument('--debug', action='store_true') @@ -774,7 +826,7 @@ def main(): # # Generate representation # - import imp + from importlib.machinery import SourceFileLoader # Default path pluginpath = '' @@ -785,18 +837,21 @@ def main(): '/../share/vpp/') for c in cand: c += '/' - if os.path.isfile('{}vppapigen_{}.py'.format(c, args.output_module.lower())): + if os.path.isfile('{}vppapigen_{}.py' + .format(c, args.output_module.lower())): pluginpath = c break else: pluginpath = args.pluginpath + '/' if pluginpath == '': raise Exception('Output plugin not found') - module_path = '{}vppapigen_{}.py'.format(pluginpath, args.output_module.lower()) + module_path = '{}vppapigen_{}.py'.format(pluginpath, + args.output_module.lower()) try: - plugin = imp.load_source(args.output_module, module_path) - except Exception, err: + plugin = SourceFileLoader(args.output_module, + module_path).load_module() + except Exception as err: raise Exception('Error importing output plugin: {}, {}' .format(module_path, err))