X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvpp-api%2Fvapi%2Fvapi_json_parser.py;h=58a75777f11535d9e3f894ceb90d7c4032abd6fd;hb=d0df49f2;hp=1e17c7a5b5a953b5206a3e6e8b4a497c86dd048c;hpb=dc15be2ca7c51772b00e4c5548934a35aa7e4add;p=vpp.git diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py index 1e17c7a5b5a..58a75777f11 100644 --- a/src/vpp-api/vapi/vapi_json_parser.py +++ b/src/vpp-api/vapi/vapi_json_parser.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python2 import json @@ -22,7 +22,7 @@ def remove_magic(what): return what -class Field: +class Field(object): def __init__( self, @@ -46,47 +46,53 @@ class Field: (self.name, self.type, self.nelem_field)) -class Type: +class Type(object): def __init__(self, name): self.name = name + def __str__(self): + return self.name + class SimpleType (Type): def __init__(self, name): - super().__init__(name) + super(SimpleType, self).__init__(name) def __str__(self): 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 ), ] -class Struct: +class Struct(object): def __init__(self, name, fields): self.name = name self.fields = fields self.field_names = [n.name for n in self.fields] + def __str__(self): + return "[%s]" % "], [".join([str(f) for f in self.fields]) + -class Message: +class Message(object): def __init__(self, logger, definition, typedict, struct_type_class, simple_type_class, field_class): @@ -101,7 +107,7 @@ class Message: 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 @@ -123,7 +129,15 @@ class Message: if field_type in typedict: field_type = typedict[field_type] else: - field_type = typedict[remove_magic(field_type)] + mundane_field_type = remove_magic(field_type) + if mundane_field_type in typedict: + field_type = typedict[mundane_field_type] + else: + raise ParseError( + "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]): @@ -174,32 +188,65 @@ class Message: 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:]: if len(field) == 1 and 'crc' in field: self.crc = field['crc'] continue - elif len(field) == 2: + field_type = field[0] + if field_type in typedict: + field_type = typedict[field_type] + else: + mundane_field_type = remove_magic(field_type) + if mundane_field_type in typedict: + field_type = typedict[mundane_field_type] + else: + raise ParseError( + "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=typedict[field[0]]) + field_type=field_type) elif len(field) == 3: if field[2] == 0: raise ParseError("While parsing type `%s': array `%s' has " "variable length" % (name, field[1])) p = field_class(field_name=field[1], - field_type=typedict[field[0]], + 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) + def __str__(self): + return "StructType(%s, %s)" % (Type.__str__(self), + Struct.__str__(self)) + def has_field(self, name): return name in self.field_names @@ -217,7 +264,7 @@ class StructType (Type, Struct): return True -class JsonParser: +class JsonParser(object): def __init__(self, logger, files, simple_type_class=SimpleType, struct_type_class=StructType, field_class=Field, message_class=Message): @@ -247,34 +294,49 @@ class JsonParser: def parse_json_file(self, path): self.logger.info("Parsing json api file: `%s'" % path) self.json_files.append(path) - self.types_by_json[path] = {} + self.types_by_json[path] = [] self.messages_by_json[path] = {} with open(path) as f: j = json.load(f) 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: self.exceptions.append(e) continue self.types[type_.name] = type_ - self.types_by_json[path][type_.name] = 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 + self.types_by_json[path].append(type_) + self.logger.debug("Parsed type: %s" % type_) + 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(): @@ -285,7 +347,6 @@ class JsonParser: if len(self.messages) == 0: for e in self.exceptions: self.logger.error(e) - raise Exception("No messages parsed.") for jn, j in self.messages_by_json.items(): remove = [] for n, m in j.items():