def match_sanity_check(): count = 0 for match_v in ["of_match_v1", "of_match_v2"]: count += 1 for mm in of_g.unified[match_v][count]["members"]: key = mm["name"] if key.find("_mask") >= 0: continue if loxi_utils.skip_member_name(key): continue if key == "wildcards": continue if not key in of_match_members: print "Key %s not found in match struct, v %s" % (key, match_v) sys.exit(1) # Check oxm list and the list above for key in oxm.oxm_types: if not key in of_match_members: if not (key.find("_masked") > 0): debug("Key %s in oxm.oxm_types, not of_match_members" % key) sys.exit(1) if not key[:-7] in of_match_members: debug("Key %s in oxm.oxm_types, but %s not in of_match_members" % (key, key[:-7])) sys.exit(1) for key in of_match_members: if not key in oxm.oxm_types: debug("Key %s in of_match_members, not in oxm.oxm_types" % key) sys.exit(1) if of_match_members[key]["m_type"] != oxm.oxm_types[key]: debug("Type mismatch for key %s in oxm data: %s vs %s" % (key, of_match_members[key]["m_type"], oxm.oxm_types[key])) sys.exit(1)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)] ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)]; ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)
def match_sanity_check(): count = 0 for match_v in ["of_match_v1", "of_match_v2"]: count += 1 for mm in of_g.unified[match_v][count]["members"]: key = mm["name"] if key.find("_mask") >= 0: continue if loxi_utils.skip_member_name(key): continue if key == "wildcards": continue if not key in of_match_members: print "Key %s not found in match struct, v %s" % (key, match_v) sys.exit(1) # Generate list of OXM names from the unified classes oxm_names = [x[7:] for x in of_g.unified.keys() if x.startswith('of_oxm_') and x.find('masked') < 0 and x.find('header') < 0] # Check that all OXMs are in the match members for key in oxm_names: if not key in of_match_members: if not (key.find("_masked") > 0): debug("Key %s in OXM, not of_match_members" % key) sys.exit(1) if not key[:-7] in of_match_members: debug("Key %s in OXM, but %s not in of_match_members" % (key, key[:-7])) sys.exit(1) # Check that all match members are in the OXMs for key in of_match_members: if not key in oxm_names: debug("Key %s in of_match_members, not in OXM" % key) sys.exit(1) oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type'] if of_match_members[key]["m_type"] != oxm_type: debug("Type mismatch for key %s in oxm data: %s vs %s" % (key, of_match_members[key]["m_type"], oxm_type)) sys.exit(1)
def match_sanity_check(): count = 0 for match_v in ["of_match_v1", "of_match_v2"]: count += 1 for mm in of_g.unified[match_v][count]["members"]: key = mm["name"] if key.find("_mask") >= 0: continue if loxi_utils.skip_member_name(key): continue if key == "wildcards": continue if not key in of_match_members: print "Key %s not found in match struct, v %s" % (key, match_v) sys.exit(1) # Generate list of OXM names from the unified classes oxm_names = [ x[7:] for x in of_g.unified.keys() if x.startswith('of_oxm_') and x.find('masked') < 0 and x.find('header') < 0 ] # Check that all OXMs are in the match members for key in oxm_names: if not key in of_match_members: if not (key.find("_masked") > 0): debug("Key %s in OXM, not of_match_members" % key) sys.exit(1) if not key[:-7] in of_match_members: debug("Key %s in OXM, but %s not in of_match_members" % (key, key[:-7])) sys.exit(1) # Check that all match members are in the OXMs for key in of_match_members: if not key in oxm_names: debug("Key %s in of_match_members, not in OXM" % key) sys.exit(1) oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type'] if of_match_members[key]["m_type"] != oxm_type: debug("Type mismatch for key %s in oxm data: %s vs %s" % (key, of_match_members[key]["m_type"], oxm_type)) sys.exit(1)
def match_sanity_check(): count = 0 for match_v in ["of_match_v1", "of_match_v2"]: count += 1 for mm in of_g.unified[match_v][count]["members"]: key = mm["name"] if key.find("_mask") >= 0: continue if loxi_utils.skip_member_name(key): continue if key == "wildcards": continue if not key in of_match_members: print "Key %s not found in match struct, v %s" % (key, match_v) sys.exit(1) # Check oxm list and the list above for key in oxm.oxm_types: if not key in of_match_members: if not (key.find("_masked") > 0): debug("Key %s in oxm.oxm_types, not of_match_members" % key) sys.exit(1) if not key[:-7] in of_match_members: debug( "Key %s in oxm.oxm_types, but %s not in of_match_members" % (key, key[:-7])) sys.exit(1) for key in of_match_members: if not key in oxm.oxm_types: debug("Key %s in of_match_members, not in oxm.oxm_types" % key) sys.exit(1) if of_match_members[key]["m_type"] != oxm.oxm_types[key]: debug("Type mismatch for key %s in oxm data: %s vs %s" % (key, of_match_members[key]["m_type"], oxm.oxm_types[key])) sys.exit(1)
def gen_obj_show_c(out, name): loxi_utils.gen_c_copy_license(out) out.write(""" /** * * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen. * * Source file for object showing. * */ #define DISABLE_WARN_UNUSED_RESULT #include <loci/loci.h> #include <loci/loci_show.h> #include <loci/loci_obj_show.h> static int unknown_show(loci_writer_f writer, void* cookie, of_object_t *obj) { return writer(cookie, "Unable to print object of type %d, version %d\\n", obj->object_id, obj->version); } """) for version in of_g.of_version_range: ver_name = loxi_utils.version_to_name(version) for cls in of_g.standard_class_order: if not loxi_utils.class_in_version(cls, version): continue if cls in type_maps.inheritance_map: continue out.write(""" int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, %(cls)s_t *obj) { int out = 0; """ % dict(cls=cls, ver_name=ver_name)) members, member_types = loxi_utils.all_member_types_get(cls, version) for m_type in member_types: if loxi_utils.type_is_scalar(m_type) or m_type in \ ["of_match_t", "of_octets_t"]: # Declare instance of these out.write(" %s %s;\n" % (m_type, var_name_map(m_type))) else: out.write(""" %(m_type)s %(v_name)s; """ % dict(m_type=m_type, v_name=var_name_map(m_type))) if loxi_utils.class_is_list(m_type): base_type = loxi_utils.list_to_entry_type(m_type) out.write(" %s elt;\n int rv;\n" % base_type) for member in members: m_type = member["m_type"] m_name = member["name"] #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + m_name; if loxi_utils.skip_member_name(m_name): continue if (loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]): out.write(""" %(cls)s_%(m_name)s_get(obj, &%(v_name)s); out += writer(cookie, "%(m_name)s="); out += %(emitter)s(writer, cookie, %(v_name)s); out += writer(cookie, " "); """ % dict(cls=cls, m_name=m_name, m_type=m_type, v_name=var_name_map(m_type), emitter=emitter)) elif loxi_utils.class_is_list(m_type): sub_cls = m_type[:-2] # Trim _t elt_type = loxi_utils.list_to_entry_type(m_type) out.write(""" out += writer(cookie, "%(elt_type)s={ "); %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); %(u_type)s_ITER(&%(v_name)s, &elt, rv) { of_object_show(writer, cookie, (of_object_t *)&elt); } out += writer(cookie, "} "); """ % dict(sub_cls=sub_cls, u_type=sub_cls.upper(), v_name=var_name_map(m_type), elt_type=elt_type, cls=cls, m_name=m_name, m_type=m_type)) else: sub_cls = m_type[:-2] # Trim _t out.write(""" %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); out += %(sub_cls)s_%(ver_name)s_show(writer, cookie, &%(v_name)s); """ % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, v_name=var_name_map(m_type), ver_name=ver_name)) out.write(""" return out; } """) out.write(""" /** * Log a match entry */ int loci_show_match(loci_writer_f writer, void* cookie, of_match_t *match) { int out = 0; """) for key, entry in match.of_match_members.items(): m_type = entry["m_type"] #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + key; out.write(""" if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) { out += writer(cookie, "%(key)s active="); out += %(emitter)s(writer, cookie, match->fields.%(key)s); out += writer(cookie, "/"); out += %(emitter)s(writer, cookie, match->masks.%(key)s); out += writer(cookie, " "); } """ % dict(key=key, ku=key.upper(), emitter=emitter, m_type=m_type)) out.write(""" return out; } """) # Generate big table indexed by version and object for version in of_g.of_version_range: out.write(""" static loci_obj_show_f show_funs_v%(version)s[OF_OBJECT_COUNT] = { """ % dict(version=version)) out.write(" unknown_show, /* of_object, not a valid specific type */\n") for j, cls in enumerate(of_g.all_class_order): comma = "" if j < len(of_g.all_class_order) - 1: # Avoid ultimate comma comma = "," if (not loxi_utils.class_in_version(cls, version) or cls in type_maps.inheritance_map): out.write(" unknown_show%s\n" % comma); else: out.write(" %s_%s_show%s\n" % (cls, loxi_utils.version_to_name(version), comma)) out.write("};\n\n") out.write(""" static loci_obj_show_f *show_funs[5] = { NULL, show_funs_v1, show_funs_v2, show_funs_v3, show_funs_v4 }; int of_object_show(loci_writer_f writer, void* cookie, of_object_t *obj) { if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) { if (((obj)->version > 0) && ((obj)->version <= OF_VERSION_1_2)) { /* @fixme VERSION */ return show_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj); } else { return writer(cookie, "Bad version %d\\n", obj->version); } } return writer(cookie, "Bad object id %d\\n", obj->object_id); } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)] ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) elif version >= of_g.VERSION_1_2 and loxi_utils.cls_is_flow_mod( cls) and m_name == "instructions": # See _FLOW_MOD_INSTRUCTIONS_OFFSET match_offset = v3_match_offset_get(cls) m_offset = '%s_offset' % m_name out.write(""" { uint16_t %(m_name)s_len, %(m_name)s_offset; uint16_t match_len; buf_u16_get(buf + %(match_offset)s + 2, &match_len); %(m_name)s_offset = %(match_offset)s + OF_MATCH_BYTES(match_len); %(m_name)s_len = len - %(m_name)s_offset; """ % dict(m_name=m_name, cls=cls, match_offset=match_offset)) elif cls == "of_bsn_gentable_entry_add" and m_name == "value": continue elif cls == "of_bsn_gentable_entry_desc_stats_entry" and m_name == "value": continue elif cls == "of_bsn_gentable_entry_stats_entry" and m_name == "stats": continue else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)
def gen_obj_show_c(out, name): loxi_utils.gen_c_copy_license(out) out.write(""" /** * * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen. * * Source file for object showing. * */ #define DISABLE_WARN_UNUSED_RESULT #include <loci/loci.h> #include <loci/loci_show.h> #include <loci/loci_obj_show.h> static int unknown_show(loci_writer_f writer, void* cookie, of_object_t *obj) { return writer(cookie, "Unable to print object of type %d, version %d\\n", obj->object_id, obj->version); } """) for version in of_g.of_version_range: ver_name = loxi_utils.version_to_name(version) for cls in of_g.standard_class_order: if not loxi_utils.class_in_version(cls, version): continue if type_maps.class_is_virtual(cls): continue out.write(""" int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, of_object_t *obj) { int out = 0; """ % dict(cls=cls, ver_name=ver_name)) members, member_types = loxi_utils.all_member_types_get(cls, version) for m_type in member_types: if loxi_utils.type_is_scalar(m_type) or m_type in \ ["of_match_t", "of_octets_t"]: # Declare instance of these out.write(" %s %s;\n" % (m_type, var_name_map(m_type))) else: out.write(""" %(m_type)s %(v_name)s; """ % dict(m_type=m_type, v_name=var_name_map(m_type))) if loxi_utils.class_is_list(m_type): out.write(" of_object_t elt;\n int rv;\n") for member in members: m_type = member["m_type"] m_name = member["name"] emitter = gen_emitter(cls, m_name, m_type) if loxi_utils.skip_member_name(m_name): continue if (loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]): out.write(""" %(cls)s_%(m_name)s_get(obj, &%(v_name)s); out += writer(cookie, "%(m_name)s="); out += %(emitter)s(writer, cookie, %(v_name)s); out += writer(cookie, " "); """ % dict(cls=cls, m_name=m_name, m_type=m_type, v_name=var_name_map(m_type), emitter=emitter)) elif loxi_utils.class_is_list(m_type): sub_cls = m_type[:-2] # Trim _t elt_type = loxi_utils.list_to_entry_type(m_type) out.write(""" out += writer(cookie, "%(elt_type)s={ "); %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); %(u_type)s_ITER(&%(v_name)s, &elt, rv) { of_object_show(writer, cookie, (of_object_t *)&elt); } out += writer(cookie, "} "); """ % dict(sub_cls=sub_cls, u_type=sub_cls.upper(), v_name=var_name_map(m_type), elt_type=elt_type, cls=cls, m_name=m_name, m_type=m_type)) else: sub_cls = m_type[:-2] # Trim _t out.write(""" %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); out += of_object_show(writer, cookie, &%(v_name)s); """ % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, v_name=var_name_map(m_type), ver_name=ver_name)) out.write(""" return out; } """) out.write(""" /** * Log a match entry */ int loci_show_match(loci_writer_f writer, void* cookie, of_match_t *match) { int out = 0; """) for key, entry in match.of_match_members.items(): m_type = entry["m_type"] emitter = gen_emitter('of_match', key, m_type) out.write(""" if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) { out += writer(cookie, "%(key)s active="); out += %(emitter)s(writer, cookie, match->fields.%(key)s); out += writer(cookie, "/"); out += %(emitter)s(writer, cookie, match->masks.%(key)s); out += writer(cookie, " "); } """ % dict(key=key, ku=key.upper(), emitter=emitter, m_type=m_type)) out.write(""" return out; } """) # Generate big table indexed by version and object for version in of_g.of_version_range: out.write(""" static const loci_obj_show_f show_funs_v%(version)s[OF_OBJECT_COUNT] = { """ % dict(version=version)) out.write(" unknown_show, /* of_object, not a valid specific type */\n") for j, cls in enumerate(of_g.all_class_order): comma = "" if j < len(of_g.all_class_order) - 1: # Avoid ultimate comma comma = "," if (not loxi_utils.class_in_version(cls, version) or type_maps.class_is_virtual(cls)): out.write(" unknown_show%s\n" % comma); else: out.write(" %s_%s_show%s\n" % (cls, loxi_utils.version_to_name(version), comma)) out.write("};\n\n") out.write(""" static const loci_obj_show_f *const show_funs[] = { """) for version in of_g.of_version_range: out.write(" [%(v)d] = show_funs_v%(v)d,\n" % dict(v=version)) out.write("""\ }; int of_object_show(loci_writer_f writer, void* cookie, of_object_t *obj) { if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) { if (OF_VERSION_OKAY(obj->version)) { return show_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj); } else { return writer(cookie, "Bad version %d\\n", obj->version); } } return writer(cookie, "Bad object id %d\\n", obj->object_id); } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)]; ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) elif version >= of_g.VERSION_1_2 and loxi_utils.cls_is_flow_mod(cls) and m_name == "instructions": # See _FLOW_MOD_INSTRUCTIONS_OFFSET match_offset = v3_match_offset_get(cls) m_offset = '%s_offset' % m_name out.write(""" { uint16_t %(m_name)s_len, %(m_name)s_offset; uint16_t match_len; buf_u16_get(buf + %(match_offset)s + 2, &match_len); %(m_name)s_offset = %(match_offset)s + OF_MATCH_BYTES(match_len); %(m_name)s_len = len - %(m_name)s_offset; """ % dict(m_name=m_name, cls=cls, match_offset=match_offset)) elif cls == "of_bsn_gentable_entry_add" and m_name == "value": continue; elif cls == "of_bsn_gentable_entry_desc_stats_entry" and m_name == "value": continue; elif cls == "of_bsn_gentable_entry_stats_entry" and m_name == "stats": continue; else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)