X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvpp-api%2Fvapi%2Fvapi_c_gen.py;h=445790d10599475df3bff5e7f6b917511feae02c;hb=4c64b6edc86f7732f4a160b948b3386e4021a265;hp=2bc1eef87e537fb1a4cadf61bba6b1a6b80a12cc;hpb=8f2a4eafeaa439432107563033728e09665c16d9;p=vpp.git diff --git a/src/vpp-api/vapi/vapi_c_gen.py b/src/vpp-api/vapi/vapi_c_gen.py index 2bc1eef87e5..445790d1059 100755 --- a/src/vpp-api/vapi/vapi_c_gen.py +++ b/src/vpp-api/vapi/vapi_c_gen.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python2 import argparse import os @@ -9,14 +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().__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) @@ -26,7 +18,7 @@ class CField(Field): def get_swap_to_be_code(self, struct, var): if self.len is not None: if self.len > 0: - return "do { int i; for (i = 0; i < %d; ++i) { %s } }"\ + return "do { unsigned i; for (i = 0; i < %d; ++i) { %s } }"\ " while(0);" % ( self.len, self.type.get_swap_to_be_code(struct, "%s[i]" % var)) @@ -38,7 +30,7 @@ class CField(Field): else: nelem_field = "%s%s" % (struct, self.nelem_field.name) return ( - "do { int i; for (i = 0; i < %s; ++i) { %s } }" + "do { unsigned i; for (i = 0; i < %s; ++i) { %s } }" " while(0);" % (nelem_field, self.type.get_swap_to_be_code( struct, "%s[i]" % var))) @@ -47,14 +39,14 @@ class CField(Field): def get_swap_to_host_code(self, struct, var): if self.len is not None: if self.len > 0: - return "do { int i; for (i = 0; i < %d; ++i) { %s } }"\ + return "do { unsigned i; for (i = 0; i < %d; ++i) { %s } }"\ " while(0);" % ( self.len, self.type.get_swap_to_host_code(struct, "%s[i]" % var)) else: # nelem_field already swapped to host here... return ( - "do { int i; for (i = 0; i < %s%s; ++i) { %s } }" + "do { unsigned i; for (i = 0; i < %s%s; ++i) { %s } }" " while(0);" % (struct, self.nelem_field.name, self.type.get_swap_to_host_code( @@ -66,9 +58,13 @@ class CField(Field): class CStruct(Struct): - def __init__(self, name, fields): - super().__init__(name, fields) + def duplicate_barrier(func): + def func_wrapper(self): + name = self.get_c_name() + return "#ifndef defined_{}\n#define defined_{}\n{}\n#endif".format(name, name, func(self)) + return func_wrapper + @duplicate_barrier def get_c_def(self): return "\n".join([ "typedef struct __attribute__((__packed__)) {", @@ -91,9 +87,6 @@ class CSimpleType (SimpleType): 'i64': 'be64toh', 'u64': 'be64toh', } - def __init__(self, name): - super().__init__(name) - def get_c_name(self): return self.name @@ -121,9 +114,6 @@ class CSimpleType (SimpleType): class CStructType (StructType, CStruct): - def __init__(self, definition, typedict, field_class): - super().__init__(definition, typedict, field_class) - def get_c_name(self): return "vapi_type_%s" % self.name @@ -173,8 +163,9 @@ class CStructType (StructType, CStruct): class CMessage (Message): def __init__(self, logger, definition, typedict, struct_type_class, simple_type_class, field_class): - super().__init__(logger, definition, typedict, struct_type_class, - simple_type_class, field_class) + super(CMessage, self).__init__(logger, definition, typedict, + struct_type_class, simple_type_class, + field_class) self.payload_members = [ " %s" % p.get_c_def() for p in self.fields @@ -199,14 +190,17 @@ class CMessage (Message): def get_alloc_func_name(self): return "vapi_alloc_%s" % self.name + def get_alloc_vla_param_names(self): + return [self.get_alloc_func_vla_field_length_name(f) + for f in self.fields + if f.nelem_field is not None] + def get_alloc_func_decl(self): return "%s* %s(struct vapi_ctx_s *ctx%s)" % ( self.get_c_name(), self.get_alloc_func_name(), - "".join([", size_t %s" % - self.get_alloc_func_vla_field_length_name(f) - for f in self.fields - if f.nelem_field is not None])) + "".join([", size_t %s" % n for n in + self.get_alloc_vla_param_names()])) def get_alloc_func_def(self): extra = [] @@ -228,7 +222,8 @@ class CMessage (Message): for f in self.fields if f.nelem_field is not None ])), - " msg = vapi_msg_alloc(ctx, size);", + " /* cast here required to play nicely with C++ world ... */", + " msg = (%s*)vapi_msg_alloc(ctx, size);" % self.get_c_name(), " if (!msg) {", " return NULL;", " }", @@ -265,6 +260,13 @@ class CMessage (Message): "}", ]) + def duplicate_barrier(func): + def func_wrapper(self): + name = self.get_payload_struct_name() + return "#ifndef defined_{}\n#define defined_{}\n{}\n#endif".format(name, name, func(self)) + return func_wrapper + + @duplicate_barrier def get_c_def(self): if self.has_payload(): return "\n".join([ @@ -441,7 +443,7 @@ class CMessage (Message): def get_event_cb_func_decl(self): if not self.is_reply(): raise Exception( - "Cannot register event callback for non-reply function") + "Cannot register event callback for non-reply message") if self.has_payload(): return "\n".join([ "void vapi_set_%s_event_cb (" % @@ -498,11 +500,11 @@ class CMessage (Message): ' offsetof(%s, context),' % self.header.get_c_name() if has_context else ' 0,', (' offsetof(%s, payload),' % self.get_c_name()) - if self.has_payload() else '-1,', + if self.has_payload() else ' VAPI_INVALID_MSG_ID,', ' sizeof(%s),' % self.get_c_name(), ' (generic_swap_fn_t)%s,' % self.get_swap_to_be_func_name(), ' (generic_swap_fn_t)%s,' % self.get_swap_to_host_func_name(), - ' ~0,', + ' VAPI_INVALID_MSG_ID,', ' };', '', ' %s = vapi_register_msg(&%s);' % @@ -529,8 +531,9 @@ vapi_send_with_control_ping (vapi_ctx_t ctx, void *msg, u32 context) """ -def gen_json_header(parser, logger, j, io): - logger.info("Generating header `%s'" % io.name) +def gen_json_unified_header(parser, logger, j, io, name): + d, f = os.path.split(j) + logger.info("Generating header `%s'" % name) orig_stdout = sys.stdout sys.stdout = io include_guard = "__included_%s" % ( @@ -538,144 +541,35 @@ def gen_json_header(parser, logger, j, io): print("#ifndef %s" % include_guard) print("#define %s" % include_guard) print("") - print("#include ") - print("") - if io.name == "vpe.api.vapi.h": - print("static inline vapi_error_e vapi_send_with_control_ping " - "(vapi_ctx_t ctx, void * msg, u32 context);") - print("") - for m in parser.messages_by_json[j].values(): - print("extern vapi_msg_id_t %s;" % m.get_msg_id_name()) - print("") - for t in parser.types_by_json[j].values(): - try: - print("%s" % t.get_c_def()) - print("") - except: - pass - for t in parser.types_by_json[j].values(): - print("%s;" % t.get_swap_to_be_func_decl()) - print("") - print("%s;" % t.get_swap_to_host_func_decl()) - print("") - for m in parser.messages_by_json[j].values(): - print("%s" % m.get_c_def()) - print("") - for m in parser.messages_by_json[j].values(): - if not m.is_reply(): - print("%s;" % m.get_alloc_func_decl()) - print("") - print("%s;" % m.get_op_func_decl()) - if m.has_payload(): - print("%s;" % m.get_swap_payload_to_be_func_decl()) - print("") - print("%s;" % m.get_swap_payload_to_host_func_decl()) - print("") - print("%s;" % m.get_calc_msg_size_func_decl()) - print("") - print("%s;" % m.get_swap_to_host_func_decl()) - print("") - print("%s;" % m.get_swap_to_be_func_decl()) - print("") - for m in parser.messages_by_json[j].values(): - if not m.is_reply(): - continue - print("%s;" % m.get_event_cb_func_decl()) - print("") - - if io.name == "vpe.api.vapi.h": - print("%s" % vapi_send_with_control_ping) - print("") - - print("#endif") - sys.stdout = orig_stdout - - -def gen_json_code(parser, logger, j, io): - logger.info("Generating code `%s'" % io.name) - orig_stdout = sys.stdout - sys.stdout = io - print("#include <%s>" % json_to_header_name(j)) print("#include ") print("#include ") print("#include ") - print("#include ") - print("#include ") - print("") - for t in parser.types_by_json[j].values(): - print("%s" % t.get_swap_to_be_func_def()) - print("") - print("%s" % t.get_swap_to_host_func_def()) - print("") - for m in parser.messages_by_json[j].values(): - if m.has_payload(): - print("%s" % m.get_swap_payload_to_be_func_def()) - print("") - print("%s" % m.get_swap_payload_to_host_func_def()) - print("") - print("%s" % m.get_calc_msg_size_func_def()) - print("") - print("%s" % m.get_swap_to_be_func_def()) - print("") - print("%s" % m.get_swap_to_host_func_def()) - print("") - for m in parser.messages_by_json[j].values(): - if m.is_reply(): - continue - print("%s" % m.get_alloc_func_def()) - print("") - print("%s" % m.get_op_func_def()) - print("") - print("") - for m in parser.messages_by_json[j].values(): - print("%s" % m.get_c_constructor()) - print("") - print("") - for m in parser.messages_by_json[j].values(): - if not m.is_reply(): - continue - print("%s;" % m.get_event_cb_func_def()) - print("") - print("") - for m in parser.messages_by_json[j].values(): - print("vapi_msg_id_t %s;" % m.get_msg_id_name()) - sys.stdout = orig_stdout - - -def gen_json_unified_header(parser, logger, j, io): - logger.info("Generating header `%s'" % io.name) - orig_stdout = sys.stdout - sys.stdout = io - include_guard = "__included_%s" % ( - j.replace(".", "_").replace("/", "_").replace("-", "_")) - print("#ifndef %s" % include_guard) - print("#define %s" % include_guard) + print("#include ") + print("#include ") + print("#include ") print("") - print("#include ") - print("#include ") - print("#include ") - print("#include ") - print("#include ") - print("#include ") - if io.name == "vpe.api.vapi.h": + print("#ifdef __cplusplus") + print("extern \"C\" {") + print("#endif") + if name == "vpe.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 ") + print("#include ") print("") for m in parser.messages_by_json[j].values(): print("extern vapi_msg_id_t %s;" % m.get_msg_id_name()) print("") print("#define DEFINE_VAPI_MSG_IDS_%s\\" % - j.replace(".", "_").replace("/", "_").replace("-", "_").upper()) + f.replace(".", "_").replace("/", "_").replace("-", "_").upper()) print("\\\n".join([ " vapi_msg_id_t %s;" % m.get_msg_id_name() for m in parser.messages_by_json[j].values() ])) print("") print("") - for t in parser.types_by_json[j].values(): + for t in parser.types_by_json[j]: try: print("%s" % t.get_c_def()) print("") @@ -687,10 +581,13 @@ def gen_json_unified_header(parser, logger, j, io): print("") function_attrs = "static inline " - for t in parser.types_by_json[j].values(): + for t in parser.types_by_json[j]: + print("#ifndef defined_inline_%s" % t.get_c_name()) + print("#define defined_inline_%s" % t.get_c_name()) print("%s%s" % (function_attrs, t.get_swap_to_be_func_def())) print("") print("%s%s" % (function_attrs, t.get_swap_to_host_func_def())) + print("#endif") print("") for m in parser.messages_by_json[j].values(): if m.has_payload(): @@ -725,46 +622,37 @@ def gen_json_unified_header(parser, logger, j, io): print("") print("") - if io.name == "vpe.api.vapi.h": + if name == "vpe.api.vapi.h": print("%s" % vapi_send_with_control_ping) print("") + print("#ifdef __cplusplus") + print("}") + print("#endif") + print("") print("#endif") sys.stdout = orig_stdout -def json_to_header_name(json_name): +def json_to_c_header_name(json_name): if json_name.endswith(".json"): return "%s.vapi.h" % os.path.splitext(json_name)[0] raise Exception("Unexpected json name `%s'!" % json_name) -def json_to_code_name(json_name): - if json_name.endswith(".json"): - return "%s.vapi.c" % os.path.splitext(json_name)[0] - raise Exception("Unexpected json name `%s'!" % json_name) - - -def gen_c_headers_and_code(parser, logger, prefix): - if prefix == "" or prefix is None: - prefix = "" - else: - prefix = "%s/" % prefix - for j in parser.json_files: - with open('%s%s' % (prefix, json_to_header_name(j)), "w") as io: - gen_json_header(parser, logger, j, io) - with open('%s%s' % (prefix, json_to_code_name(j)), "w") as io: - gen_json_code(parser, logger, j, io) - - -def gen_c_unified_headers(parser, logger, prefix): +def gen_c_unified_headers(parser, logger, prefix, remove_path): if prefix == "" or prefix is None: prefix = "" else: prefix = "%s/" % prefix for j in parser.json_files: - with open('%s%s' % (prefix, json_to_header_name(j)), "w") as io: - gen_json_unified_header(parser, logger, j, io) + if remove_path: + d, f = os.path.split(j) + else: + f = j + with open('%s%s' % (prefix, json_to_c_header_name(f)), "w") as io: + gen_json_unified_header( + parser, logger, j, io, json_to_c_header_name(f)) if __name__ == '__main__': @@ -784,12 +672,14 @@ if __name__ == '__main__': logger = logging.getLogger("VAPI C GEN") logger.setLevel(log_level) - argparser = argparse.ArgumentParser(description="VPP JSON API parser") + argparser = argparse.ArgumentParser(description="VPP C API generator") argparser.add_argument('files', metavar='api-file', action='append', type=str, help='json api file' '(may be specified multiple times)') argparser.add_argument('--prefix', action='store', default=None, help='path prefix') + argparser.add_argument('--remove-path', action='store_true', + help='remove path from filename') args = argparser.parse_args() jsonparser = JsonParser(logger, args.files, @@ -803,7 +693,7 @@ if __name__ == '__main__': # Damjan), to avoid symbol version issues in .so # gen_c_headers_and_code(jsonparser, logger, args.prefix) - gen_c_unified_headers(jsonparser, logger, args.prefix) + gen_c_unified_headers(jsonparser, logger, args.prefix, args.remove_path) for e in jsonparser.exceptions: - logger.error(e) + logger.warning(e)