X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Ftools%2Fvppapigen%2Fvppapigen.py;fp=src%2Ftools%2Fvppapigen%2Fvppapigen.py;h=b80dd4d9f7d35971d7081e588644143ef9908a16;hb=a51f9b3747d3e065b4bc7bb46aea8df11719b6cd;hp=da008231a32cb347ed719d52a8fef0340a5037ac;hpb=86ffb6b232d5ebce03cf53249fa1514384f31cce;p=vpp.git diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py index da008231a32..b80dd4d9f7d 100755 --- a/src/tools/vppapigen/vppapigen.py +++ b/src/tools/vppapigen/vppapigen.py @@ -58,6 +58,7 @@ class VPPAPILexer(object): 'define': 'DEFINE', 'typedef': 'TYPEDEF', 'enum': 'ENUM', + 'enumflag': 'ENUMFLAG', 'typeonly': 'TYPEONLY', 'manual_print': 'MANUAL_PRINT', 'manual_endian': 'MANUAL_ENDIAN', @@ -182,7 +183,16 @@ def vla_is_last_check(name, block): return vla -class Service(): +class Processable: + type = "" + + def process(self, result): # -> Dict + result[self.type].append(self) + + +class Service(Processable): + type = 'Service' + def __init__(self, caller, reply, events=None, stream_message=None, stream=False): self.caller = caller @@ -192,10 +202,11 @@ class Service(): self.events = [] if events is None else events -class Typedef(): +class Typedef(Processable): + type = 'Typedef' + def __init__(self, name, flags, block): self.name = name - self.type = 'Typedef' self.flags = flags self.block = block self.crc = str(block).encode() @@ -211,14 +222,18 @@ class Typedef(): self.vla = vla_is_last_check(name, block) vla_mark_length_field(self.block) + def process(self, result): + result['types'].append(self) + def __repr__(self): return self.name + str(self.flags) + str(self.block) -class Using(): +class Using(Processable): + type = 'Using' + def __init__(self, name, flags, alias): self.name = name - self.type = 'Using' self.vla = False self.block = [] self.manual_print = True @@ -248,13 +263,17 @@ class Using(): self.crc = str(self.block).encode() global_type_add(name, self) + def process(self, result): # -> Dict + result['types'].append(self) + def __repr__(self): return self.name + str(self.alias) -class Union(): +class Union(Processable): + type = 'Union' + def __init__(self, name, flags, block): - self.type = 'Union' self.manual_print = False self.manual_endian = False self.name = name @@ -271,14 +290,18 @@ class Union(): global_type_add(name, self) + def process(self, result): + result['types'].append(self) + def __repr__(self): return str(self.block) -class Define(): +class Define(Processable): + type = 'Define' + def __init__(self, name, flags, block): self.name = name - self.type = 'Define' self.flags = flags self.block = block self.dont_trace = False @@ -313,16 +336,31 @@ class Define(): self.crc = str(block).encode() + def autoreply_block(self, name, parent): + block = [Field('u32', 'context'), + Field('i32', 'retval')] + # inherit the parent's options + for k, v in parent.options.items(): + block.append(Option(k, v)) + return Define(name + '_reply', [], block) + + def process(self, result): # -> Dict + tname = self.__class__.__name__ + result[tname].append(self) + if self.autoreply: + result[tname].append(self.autoreply_block(self.name, self)) + def __repr__(self): return self.name + str(self.flags) + str(self.block) -class Enum(): +class Enum(Processable): + type = 'Enum' + def __init__(self, name, block, enumtype='u32'): self.name = name self.enumtype = enumtype self.vla = False - self.type = 'Enum' self.manual_print = False count = 0 @@ -350,12 +388,30 @@ class Enum(): self.crc = str(block3).encode() global_type_add(name, self) + def process(self, result): + result['types'].append(self) + def __repr__(self): return self.name + str(self.block) -class Import(): +class EnumFlag(Enum): + type = 'EnumFlag' + + def __init__(self, name, block, enumtype='u32'): + super(EnumFlag, self).__init__(name, block, enumtype) + + for b in self.block: + if bin(b[1])[2:].count("1") > 1: + raise TypeError("%s is not a flag enum. No element in a " + "flag enum may have more than a " + "single bit set." % self.name) + + +class Import(Processable): + type = 'Import' _initialized = False + def __new__(cls, *args, **kwargs): if args[0] not in seen_imports: instance = super().__new__(cls) @@ -383,13 +439,17 @@ class Import(): return self.filename -class Option(): +class Option(Processable): + type = 'Option' + def __init__(self, option, value=None): - self.type = 'Option' self.option = option self.value = value self.crc = str(option).encode() + def process(self, result): # -> Dict + result[self.type][self.option] = self.value + def __repr__(self): return str(self.option) @@ -397,9 +457,10 @@ class Option(): return self.option[index] -class Array(): +class Array(Processable): + type = 'Array' + def __init__(self, fieldtype, name, length, modern_vla=False): - self.type = 'Array' self.fieldtype = fieldtype self.fieldname = name self.modern_vla = modern_vla @@ -417,9 +478,12 @@ class Array(): self.lengthfield]) -class Field(): +class Field(Processable): + type = 'Field' + def __init__(self, fieldtype, name, limit=None): - self.type = 'Field' + # limit field has been expanded to an options dict. + self.fieldtype = fieldtype self.is_lengthfield = False @@ -437,18 +501,28 @@ class Field(): return str([self.fieldtype, self.fieldname]) -class Counter(): +class Counter(Processable): + type = 'Counter' + def __init__(self, path, counter): - self.type = 'Counter' self.name = path self.block = counter + def process(self, result): # -> Dict + result['Counters'].append(self) + + +class Paths(Processable): + type = 'Paths' -class Paths(): def __init__(self, pathset): - self.type = 'Paths' self.paths = pathset + def __repr__(self): + return "%s(paths=%s)" % ( + self.__class__.__name__, self.paths + ) + class Coord(object): """ Coordinates of a syntactic element. Consists of: @@ -523,6 +597,7 @@ class VPPAPIParser(object): | option | import | enum + | enumflag | union | service | paths @@ -643,6 +718,17 @@ class VPPAPIParser(object): else: p[0] = Enum(p[2], p[4]) + def p_enumflag(self, p): + '''enumflag : ENUMFLAG ID '{' enum_statements '}' ';' ''' + p[0] = EnumFlag(p[2], p[4]) + + def p_enumflag_type(self, p): + ''' enumflag : ENUMFLAG ID ':' enum_size '{' enum_statements '}' ';' ''' # noqa : E502 + if len(p) == 9: + p[0] = EnumFlag(p[2], p[6], enumtype=p[4]) + else: + p[0] = EnumFlag(p[2], p[4]) + def p_enum_size(self, p): ''' enum_size : U8 | U16 @@ -902,14 +988,6 @@ class VPPAPI(): print('File not found: {}'.format(filename), file=sys.stderr) sys.exit(2) - def autoreply_block(self, name, parent): - block = [Field('u32', 'context'), - Field('i32', 'retval')] - # inherhit the parent's options - for k, v in parent.options.items(): - block.append(Option(k, v)) - return Define(name + '_reply', [], block) - def process(self, objs): s = {} s['Option'] = {} @@ -921,32 +999,17 @@ class VPPAPI(): s['Paths'] = [] crc = 0 for o in objs: - tname = o.__class__.__name__ try: crc = binascii.crc32(o.crc, crc) & 0xffffffff except AttributeError: pass - if isinstance(o, Define): - s[tname].append(o) - if o.autoreply: - s[tname].append(self.autoreply_block(o.name, o)) - elif isinstance(o, Option): - s[tname][o.option] = o.value - elif type(o) is list: + + if type(o) is list: for o2 in o: if isinstance(o2, Service): - s['Service'].append(o2) - elif isinstance(o, (Enum, Typedef, Union, Using)): - s['types'].append(o) - elif isinstance(o, Counter): - s['Counters'].append(o) - elif isinstance(o, Paths): - s['Paths'].append(o) + o2.process(s) else: - if tname not in s: - raise ValueError('Unknown class type: {} {}' - .format(tname, o)) - s[tname].append(o) + o.process(s) msgs = {d.name: d for d in s['Define']} svcs = {s.caller: s for s in s['Service']} @@ -1021,7 +1084,7 @@ class VPPAPI(): return s - def process_imports(self, objs, in_import, result): + def process_imports(self, objs, in_import, result): # -> List for o in objs: # Only allow the following object types from imported file if in_import and not isinstance(o, (Enum, Import, Typedef,