From 8b6b5ab7dba7cb5fe738c887e27c65bee6a2f600 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Thu, 3 May 2018 14:27:42 +0200 Subject: [PATCH] VAPI: support VLAs in type definitions Change-Id: I8d54415972d6644190857175b0e895c5319ce7b6 Signed-off-by: Klement Sekera --- src/vpp-api/vapi/vapi_c_gen.py | 18 --------- src/vpp-api/vapi/vapi_cpp_gen.py | 24 ++---------- src/vpp-api/vapi/vapi_json_parser.py | 74 ++++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/vpp-api/vapi/vapi_c_gen.py b/src/vpp-api/vapi/vapi_c_gen.py index eaa22c5bc03..b85f1e9d248 100755 --- a/src/vpp-api/vapi/vapi_c_gen.py +++ b/src/vpp-api/vapi/vapi_c_gen.py @@ -9,15 +9,6 @@ from vapi_json_parser import Field, Struct, Message, JsonParser,\ class CField(Field): - def __init__( - self, - field_name, - field_type, - array_len=None, - nelem_field=None): - super(CField, self).__init__( - field_name, field_type, array_len, nelem_field) - def get_c_def(self): if self.len is not None: return "%s %s[%d]" % (self.type.get_c_name(), self.name, self.len) @@ -67,9 +58,6 @@ class CField(Field): class CStruct(Struct): - def __init__(self, name, fields): - super(CStruct, self).__init__(name, fields) - def duplicate_barrier(func): def func_wrapper(self): name = self.get_c_name() @@ -99,9 +87,6 @@ class CSimpleType (SimpleType): 'i64': 'be64toh', 'u64': 'be64toh', } - def __init__(self, name): - super(CSimpleType, self).__init__(name) - def get_c_name(self): return self.name @@ -129,9 +114,6 @@ class CSimpleType (SimpleType): class CStructType (StructType, CStruct): - def __init__(self, definition, typedict, field_class): - super(CStructType, self).__init__(definition, typedict, field_class) - def get_c_name(self): return "vapi_type_%s" % self.name diff --git a/src/vpp-api/vapi/vapi_cpp_gen.py b/src/vpp-api/vapi/vapi_cpp_gen.py index 3010f3e1919..e83e151a879 100755 --- a/src/vpp-api/vapi/vapi_cpp_gen.py +++ b/src/vpp-api/vapi/vapi_cpp_gen.py @@ -10,38 +10,22 @@ from vapi_json_parser import JsonParser class CppField(CField): - def __init__( - self, - field_name, - field_type, - array_len=None, - nelem_field=None): - super(CppField, self).__init__( - field_name, field_type, array_len, nelem_field) + pass class CppStruct(CStruct): - def __init__(self, name, fields): - super(CppStruct, self).__init__(name, fields) + pass class CppSimpleType (CSimpleType): - def __init__(self, name): - super(CppSimpleType, self).__init__(name) + pass class CppStructType (CStructType, CppStruct): - def __init__(self, definition, typedict, field_class): - super(CppStructType, self).__init__(definition, typedict, field_class) + pass class CppMessage (CMessage): - def __init__(self, logger, definition, typedict, - struct_type_class, simple_type_class, field_class): - super(CppMessage, self).__init__( - logger, definition, typedict, struct_type_class, - simple_type_class, field_class) - def get_swap_to_be_template_instantiation(self): return "\n".join([ "template <> inline void vapi_swap_to_be<%s>(%s *msg)" % diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py index b52b95be6dc..0da2a5e32b3 100644 --- a/src/vpp-api/vapi/vapi_json_parser.py +++ b/src/vpp-api/vapi/vapi_json_parser.py @@ -63,20 +63,20 @@ class SimpleType (Type): return self.name -def get_msg_header_defs(struct_type_class, field_class, typedict): +def get_msg_header_defs(struct_type_class, field_class, typedict, logger): return [ struct_type_class(['msg_header1_t', ['u16', '_vl_msg_id'], ['u32', 'context'], ], - typedict, field_class + typedict, field_class, logger ), struct_type_class(['msg_header2_t', ['u16', '_vl_msg_id'], ['u32', 'client_index'], ['u32', 'context'], ], - typedict, field_class + typedict, field_class, logger ), ] @@ -107,7 +107,7 @@ class Message(object): self.header = None fields = [] for header in get_msg_header_defs(struct_type_class, field_class, - typedict): + typedict, logger): logger.debug("Probing header `%s'" % header.name) if header.is_part_of_def(m[1:]): self.header = header @@ -137,6 +137,7 @@ class Message(object): "While parsing message `%s': could not find " "type by magic name `%s' nor by mundane name " "`%s'" % (name, field_type, mundane_field_type)) + logger.debug("Parsing message field `%s'" % field) if len(field) == 2: if self.header is not None and\ self.header.has_field(field[1]): @@ -187,8 +188,9 @@ class Message(object): class StructType (Type, Struct): - def __init__(self, definition, typedict, field_class): + def __init__(self, definition, typedict, field_class, logger): t = definition + logger.debug("Parsing struct definition `%s'" % t) name = t[0] fields = [] for field in t[1:]: @@ -207,6 +209,7 @@ class StructType (Type, Struct): "While parsing message `%s': could not find " "type by magic name `%s' nor by mundane name " "`%s'" % (name, field_type, mundane_field_type)) + logger.debug("Parsing type field `%s'" % field) if len(field) == 2: p = field_class(field_name=field[1], field_type=field_type) @@ -217,10 +220,25 @@ class StructType (Type, Struct): p = field_class(field_name=field[1], field_type=field_type, array_len=field[2]) + elif len(field) == 4: + nelem_field = None + for f in fields: + if f.name == field[3]: + nelem_field = f + if nelem_field is None: + raise ParseError( + "While parsing message `%s': couldn't find " + "variable length array `%s' member containing " + "the actual length `%s'" % ( + name, field[1], field[3])) + p = field_class(field_name=field[1], + field_type=field_type, + array_len=field[2], + nelem_field=nelem_field) else: raise ParseError( - "Don't know how to parse type definition for " - "type `%s': `%s'" % (t, t[1:])) + "Don't know how to parse field `%s' of type definition " + "for type `%s'" % (field, t)) fields.append(p) Type.__init__(self, name) Struct.__init__(self, name, fields) @@ -283,7 +301,8 @@ class JsonParser(object): for t in j['types']: try: type_ = self.struct_type_class(t, self.types, - self.field_class) + self.field_class, + self.logger) if type_.name in self.types: raise ParseError("Duplicate type `%s'" % type_.name) except ParseError as e: @@ -292,19 +311,32 @@ class JsonParser(object): self.types[type_.name] = type_ self.types_by_json[path].append(type_) self.logger.debug("Parsed type: %s" % type_) - for m in j['messages']: - try: - msg = self.message_class(self.logger, m, self.types, - self.struct_type_class, - self.simple_type_class, - self.field_class) - if msg.name in self.messages: - raise ParseError("Duplicate message `%s'" % msg.name) - except ParseError as e: - self.exceptions.append(e) - continue - self.messages[msg.name] = msg - self.messages_by_json[path][msg.name] = msg + prev_length = len(self.messages) + processed = [] + while True: + exceptions = [] + for m in j['messages']: + if m in processed: + continue + try: + msg = self.message_class(self.logger, m, self.types, + self.struct_type_class, + self.simple_type_class, + self.field_class) + if msg.name in self.messages: + raise ParseError( + "Duplicate message `%s'" % msg.name) + except ParseError as e: + exceptions.append(e) + continue + self.messages[msg.name] = msg + self.messages_by_json[path][msg.name] = msg + processed.append(m) + if prev_length == len(self.messages): + # cannot make forward progress ... + self.exceptions.extend(exceptions) + break + prev_length = len(self.messages) def get_reply(self, message): if self.messages[message].is_dump(): -- 2.16.6