interface: add api test file
[vpp.git] / src / vpp-api / vapi / vapi_c_gen.py
index eb1006d..1a5665e 100755 (executable)
@@ -1,22 +1,31 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
 import argparse
 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 "vapi_type_%s" % 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)
+        if self.type.get_c_name() == 'vl_api_string_t':
+            if self.len:
+                return "u8 %s[%d];" % (self.name, self.len)
+            else:
+                return "vl_api_string_t %s;" % (self.name)
         else:
-            return "%s %s" % (self.type.get_c_name(), self.name)
+            if self.len is not None and type(self.len) != dict:
+                return "%s %s[%d];" % (self.type.get_c_name(), self.name, self.len)
+            else:
+                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:
+        if self.len is not None and type(self.len) != dict:
             if self.len > 0:
                 return "do { unsigned i; for (i = 0; i < %d; ++i) { %s } }"\
                     " while(0);" % (
@@ -37,7 +46,7 @@ class CField(Field):
         return self.type.get_swap_to_be_code(struct, "%s" % var)
 
     def get_swap_to_host_code(self, struct, var):
-        if self.len is not None:
+        if self.len is not None and type(self.len) != dict:
             if self.len > 0:
                 return "do { unsigned i; for (i = 0; i < %d; ++i) { %s } }"\
                     " while(0);" % (
@@ -95,12 +104,25 @@ class CField(Field):
         return result
 
 
+class CAlias(CField):
+    def get_c_name(self):
+        return "vapi_type_%s" % self.name
+
+    def get_c_def(self):
+        if self.len is not None:
+            return "typedef %s vapi_type_%s[%d];" % (
+                self.type.get_c_name(), self.name, self.len)
+        else:
+            return "typedef %s vapi_type_%s;" % (
+                self.type.get_c_name(), self.name)
+
+
 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):
@@ -131,6 +153,12 @@ class CSimpleType (SimpleType):
         'i64': 'be64toh', 'u64': 'be64toh',
     }
 
+    __packed = "__attribute__((packed))"
+    pack_dict = {
+        'i8':  __packed, 'u8':  __packed,
+        'i16': __packed, 'u16': __packed,
+    }
+
     def get_c_name(self):
         return self.name
 
@@ -140,6 +168,9 @@ class CSimpleType (SimpleType):
     def get_swap_to_host_func_name(self):
         return self.swap_to_host_dict[self.name]
 
+    def get_packed_string(self):
+        return self.pack_dict[self.name]
+
     def get_swap_to_be_code(self, struct, var, cast=None):
         x = "%s%s" % (struct, var)
         return "%s = %s%s(%s);" % (x,
@@ -156,18 +187,22 @@ class CSimpleType (SimpleType):
         try:
             self.get_swap_to_host_func_name()
             return True
-        except:
+        except KeyError:
             pass
         return False
 
+    def get_packed(self):
+        return self.pack_dict.get(self.name, "")
+
 
 class CEnum(Enum):
     def get_c_name(self):
         return "vapi_enum_%s" % self.name
 
     def get_c_def(self):
-        return "typedef enum {\n%s\n} %s;" % (
+        return "typedef enum {\n%s\n} %s %s;" % (
             "\n".join(["  %s = %s," % (i, j) for i, j in self.value_pairs]),
+            self.type.get_packed(),
             self.get_c_name()
         )
 
@@ -335,8 +370,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 +644,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)
@@ -655,7 +691,7 @@ def gen_json_unified_header(parser, logger, j, io, name):
     orig_stdout = sys.stdout
     sys.stdout = io
     include_guard = "__included_%s" % (
-        j.replace(".", "_").replace("/", "_").replace("-", "_"))
+        j.replace(".", "_").replace("/", "_").replace("-", "_").replace("+", "_"))
     print("#ifndef %s" % include_guard)
     print("#define %s" % include_guard)
     print("")
@@ -669,12 +705,12 @@ def gen_json_unified_header(parser, logger, j, io, name):
     print("#ifdef __cplusplus")
     print("extern \"C\" {")
     print("#endif")
-    if name == "vpe.api.vapi.h":
+    if name == "memclnt.api.vapi.h":
         print("")
         print("static inline vapi_error_e vapi_send_with_control_ping "
               "(vapi_ctx_t ctx, void * msg, u32 context);")
     else:
-        print("#include <vapi/vpe.api.vapi.h>")
+        print("#include <vapi/vlib.api.vapi.h>")
     print("")
     for m in parser.messages_by_json[j].values():
         print("extern vapi_msg_id_t %s;" % m.get_msg_id_name())
@@ -694,12 +730,14 @@ def gen_json_unified_header(parser, logger, j, io, name):
         emit_definition(parser, j, emitted, u)
     for t in parser.types_by_json[j]:
         emit_definition(parser, j, emitted, t)
+    for a in parser.aliases_by_json[j]:
+        emit_definition(parser, j, emitted, a)
     for m in parser.messages_by_json[j].values():
         emit_definition(parser, j, emitted, m)
 
     print("")
 
-    if name == "vpe.api.vapi.h":
+    if name == "vlib.api.vapi.h":
         print("%s" % vapi_send_with_control_ping)
         print("")
 
@@ -765,7 +803,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