summaryrefslogtreecommitdiffstats
path: root/src/vpp-api
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2018-11-13 12:36:56 +0100
committerFlorin Coras <florin.coras@gmail.com>2018-11-29 07:39:22 +0000
commit53fffa1db7cb04982db8977acd61b808ef60d5a8 (patch)
tree7f8c8b25b51d722cc6353c028ddad4e0ad6fcd31 /src/vpp-api
parent4f10db317382832068d67b5d19be4a696d80c19a (diff)
API: Add support for type aliases
Previously all types are compound. This adds support for aliases, so one can do things like: typedef u32 interface_index; or typedef u8 ip4_address[4]; Change-Id: I0455cad0123fc88acb491d2a3ea2725426bdb246 Signed-off-by: Ole Troan <ot@cisco.com> Signed-off-by: Klement Sekera <ksekera@cisco.com>
Diffstat (limited to 'src/vpp-api')
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_papi.py11
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_serializer.py14
-rwxr-xr-xsrc/vpp-api/vapi/vapi_c_gen.py43
-rwxr-xr-xsrc/vpp-api/vapi/vapi_cpp_gen.py9
-rw-r--r--src/vpp-api/vapi/vapi_json_parser.py33
5 files changed, 87 insertions, 23 deletions
diff --git a/src/vpp-api/python/vpp_papi/vpp_papi.py b/src/vpp-api/python/vpp_papi/vpp_papi.py
index ca4b955fd07..bd2682f5b8f 100644
--- a/src/vpp-api/python/vpp_papi/vpp_papi.py
+++ b/src/vpp-api/python/vpp_papi/vpp_papi.py
@@ -27,7 +27,7 @@ import fnmatch
import weakref
import atexit
from . vpp_serializer import VPPType, VPPEnumType, VPPUnionType, BaseTypes
-from . vpp_serializer import VPPMessage, vpp_get_type
+from . vpp_serializer import VPPMessage, vpp_get_type, VPPTypeAlias
from . vpp_format import VPPFormat
if sys.version[0] == '2':
@@ -102,13 +102,15 @@ class VPP(object):
for t in api['types']:
t[0] = 'vl_api_' + t[0] + '_t'
types[t[0]] = {'type': 'type', 'data': t}
+ for t, v in api['aliases'].items():
+ types['vl_api_' + t + '_t'] = {'type': 'alias', 'data': v}
i = 0
while True:
unresolved = {}
for k, v in types.items():
t = v['data']
- if not vpp_get_type(t[0]):
+ if not vpp_get_type(k):
if v['type'] == 'enum':
try:
VPPEnumType(t[0], t[1:])
@@ -124,6 +126,11 @@ class VPP(object):
VPPType(t[0], t[1:])
except ValueError:
unresolved[k] = v
+ elif v['type'] == 'alias':
+ try:
+ VPPTypeAlias(k, t)
+ except ValueError:
+ unresolved[k] = v
if len(unresolved) == 0:
break
if i > 3:
diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py
index bd0f73803da..a001cca565a 100644
--- a/src/vpp-api/python/vpp_papi/vpp_serializer.py
+++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py
@@ -79,7 +79,7 @@ class FixedList_u8(object):
self.packer = BaseTypes(field_type, num)
self.size = self.packer.size
- def pack(self, list, kwargs):
+ def pack(self, list, kwargs = None):
"""Packs a fixed length bytestring. Left-pads with zeros
if input data is too short."""
if not list:
@@ -277,6 +277,18 @@ class VPPUnionType(object):
return self.tuple._make(r), maxsize
+def VPPTypeAlias(name, msgdef):
+ t = vpp_get_type(msgdef['type'])
+ if not t:
+ raise ValueError()
+ if 'length' in msgdef:
+ if msgdef['length'] == 0:
+ raise ValueError()
+ types[name] = FixedList(name, msgdef['type'], msgdef['length'])
+ else:
+ types[name] = t
+
+
class VPPType(object):
# Set everything up to be able to pack / unpack
def __init__(self, name, msgdef):
diff --git a/src/vpp-api/vapi/vapi_c_gen.py b/src/vpp-api/vapi/vapi_c_gen.py
index eb1006d3a7e..9939bc0556c 100755
--- a/src/vpp-api/vapi/vapi_c_gen.py
+++ b/src/vpp-api/vapi/vapi_c_gen.py
@@ -5,15 +5,18 @@ import os
import sys
import logging
from vapi_json_parser import Field, Struct, Enum, Union, Message, JsonParser,\
- SimpleType, StructType
+ SimpleType, StructType, Alias
class CField(Field):
+ def get_c_name(self):
+ return self.name
+
def get_c_def(self):
if self.len is not None:
- return "%s %s[%d]" % (self.type.get_c_name(), self.name, self.len)
+ return "%s %s[%d];" % (self.type.get_c_name(), self.name, self.len)
else:
- return "%s %s" % (self.type.get_c_name(), self.name)
+ return "%s %s;" % (self.type.get_c_name(), self.name)
def get_swap_to_be_code(self, struct, var):
if self.len is not None:
@@ -95,12 +98,26 @@ class CField(Field):
return result
+class CAlias(CField):
+ def get_c_name(self):
+ return self.name
+
+ def get_c_def(self):
+ return "typedef %s" % super(CAlias, self).get_c_def()
+ # if self.len is not None:
+ # return "typedef %s %s[%d];" % (self.type.get_c_name(), self.name, self.len)
+ # else:
+ # return "typedef %s %s;" % (self.type.get_c_name(), self.name)
+
+ # def needs_byte_swap
+
+
class CStruct(Struct):
def get_c_def(self):
return "\n".join([
- "typedef struct __attribute__((__packed__)) {\n%s;" % (
- ";\n".join([" %s" % x.get_c_def()
- for x in self.fields])),
+ "typedef struct __attribute__((__packed__)) {\n%s" % (
+ "\n".join([" %s" % x.get_c_def()
+ for x in self.fields])),
"} %s;" % self.get_c_name()])
def get_vla_assign_code(self, prefix, path):
@@ -156,7 +173,7 @@ class CSimpleType (SimpleType):
try:
self.get_swap_to_host_func_name()
return True
- except:
+ except KeyError:
pass
return False
@@ -335,8 +352,8 @@ class CMessage (Message):
if self.has_payload():
return "\n".join([
"typedef struct __attribute__ ((__packed__)) {",
- "%s; " %
- ";\n".join(self.payload_members),
+ "%s " %
+ "\n".join(self.payload_members),
"} %s;" % self.get_payload_struct_name(),
"",
"typedef struct __attribute__ ((__packed__)) {",
@@ -609,7 +626,8 @@ def emit_definition(parser, json_file, emitted, o):
if (o not in parser.enums_by_json[json_file] and
o not in parser.types_by_json[json_file] and
o not in parser.unions_by_json[json_file] and
- o.name not in parser.messages_by_json[json_file]):
+ o.name not in parser.messages_by_json[json_file] and
+ o not in parser.aliases_by_json[json_file]):
return
guard = "defined_%s" % o.get_c_name()
print("#ifndef %s" % guard)
@@ -690,6 +708,8 @@ def gen_json_unified_header(parser, logger, j, io, name):
emitted = []
for e in parser.enums_by_json[j]:
emit_definition(parser, j, emitted, e)
+ for a in parser.aliases_by_json[j]:
+ emit_definition(parser, j, emitted, a)
for u in parser.unions_by_json[j]:
emit_definition(parser, j, emitted, u)
for t in parser.types_by_json[j]:
@@ -765,7 +785,8 @@ if __name__ == '__main__':
union_class=CUnion,
struct_type_class=CStructType,
field_class=CField,
- message_class=CMessage)
+ message_class=CMessage,
+ alias_class=CAlias)
# not using the model of having separate generated header and code files
# with generated symbols present in shared library (per discussion with
diff --git a/src/vpp-api/vapi/vapi_cpp_gen.py b/src/vpp-api/vapi/vapi_cpp_gen.py
index 6b62bc4da22..c08993dc918 100755
--- a/src/vpp-api/vapi/vapi_cpp_gen.py
+++ b/src/vpp-api/vapi/vapi_cpp_gen.py
@@ -5,7 +5,7 @@ import os
import sys
import logging
from vapi_c_gen import CField, CEnum, CStruct, CSimpleType, CStructType,\
- CMessage, json_to_c_header_name
+ CMessage, json_to_c_header_name, CAlias
from vapi_json_parser import JsonParser
@@ -21,6 +21,10 @@ class CppEnum(CEnum):
pass
+class CppAlias(CAlias):
+ pass
+
+
class CppSimpleType (CSimpleType):
pass
@@ -251,7 +255,8 @@ if __name__ == '__main__':
struct_type_class=CppStructType,
field_class=CppField,
enum_class=CppEnum,
- message_class=CppMessage)
+ message_class=CppMessage,
+ alias_class=CppAlias)
gen_cpp_headers(jsonparser, logger, args.prefix, args.gen_h_prefix,
args.remove_path)
diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py
index 39acca0b538..3eb5d3616e1 100644
--- a/src/vpp-api/vapi/vapi_json_parser.py
+++ b/src/vpp-api/vapi/vapi_json_parser.py
@@ -45,6 +45,10 @@ class Field(object):
return self.is_vla() or self.type.has_vla()
+class Alias(Field):
+ pass
+
+
class Type(object):
def __init__(self, name):
self.name = name
@@ -55,12 +59,6 @@ class Type(object):
class SimpleType (Type):
- def __init__(self, name):
- super(SimpleType, self).__init__(name)
-
- def __str__(self):
- return self.name
-
def has_vla(self):
return False
@@ -290,11 +288,12 @@ class JsonParser(object):
def __init__(self, logger, files, simple_type_class=SimpleType,
enum_class=Enum, union_class=Union,
struct_type_class=StructType, field_class=Field,
- message_class=Message):
+ message_class=Message, alias_class=Alias):
self.services = {}
self.messages = {}
self.enums = {}
self.unions = {}
+ self.aliases = {}
self.types = {
x: simple_type_class(x) for x in [
'i8', 'i16', 'i32', 'i64',
@@ -310,6 +309,7 @@ class JsonParser(object):
self.union_class = union_class
self.struct_type_class = struct_type_class
self.field_class = field_class
+ self.alias_class = alias_class
self.message_class = message_class
self.exceptions = []
@@ -317,6 +317,7 @@ class JsonParser(object):
self.types_by_json = {}
self.enums_by_json = {}
self.unions_by_json = {}
+ self.aliases_by_json = {}
self.messages_by_json = {}
self.logger = logger
for f in files:
@@ -329,6 +330,7 @@ class JsonParser(object):
self.types_by_json[path] = []
self.enums_by_json[path] = []
self.unions_by_json[path] = []
+ self.aliases_by_json[path] = []
self.messages_by_json[path] = {}
with open(path) as f:
j = json.load(f)
@@ -369,6 +371,19 @@ class JsonParser(object):
self.unions[union.name] = union
self.logger.debug("Parsed union: %s" % union)
self.unions_by_json[path].append(union)
+ for name, body in j['aliases'].iteritems():
+ if name in self.aliases:
+ progress = progress + 1
+ continue
+ if 'length' in body:
+ array_len = body['length']
+ else:
+ array_len = None
+ t = self.types[body['type']]
+ alias = self.alias_class(name, t, array_len)
+ self.aliases[name] = alias
+ self.logger.debug("Parsed alias: %s" % alias)
+ self.aliases_by_json[path].append(alias)
for t in j['types']:
if t[0] in self.types:
progress = progress + 1
@@ -429,12 +444,16 @@ class JsonParser(object):
return self.enums[name]
elif name in self.unions:
return self.unions[name]
+ elif name in self.aliases:
+ return self.aliases[name]
elif mundane_name in self.types:
return self.types[mundane_name]
elif mundane_name in self.enums:
return self.enums[mundane_name]
elif mundane_name in self.unions:
return self.unions[mundane_name]
+ elif mundane_name in self.aliases:
+ return self.aliases[mundane_name]
raise ParseError(
"Could not find type, enum or union by magic name `%s' nor by "
"mundane name `%s'" % (name, mundane_name))