diff options
Diffstat (limited to 'src/tools/vppapigen/vppapigen_c.py')
-rwxr-xr-x | src/tools/vppapigen/vppapigen_c.py | 124 |
1 files changed, 55 insertions, 69 deletions
diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py index fb7de0a023f..3cd52df1ad0 100755 --- a/src/tools/vppapigen/vppapigen_c.py +++ b/src/tools/vppapigen/vppapigen_c.py @@ -171,14 +171,10 @@ class ToJSON: write(" {\n") # What is length field doing here? write( - ' u8 *s = format(0, "0x%U", format_hex_bytes, ' + ' char *s = format_c_string(0, "0x%U", format_hex_bytes_no_wrap, ' "&a->{n}, {lfield});\n".format(n=o.fieldname, lfield=lfield) ) - write( - ' cJSON_AddStringToObject(o, "{n}", (char *)s);\n'.format( - n=o.fieldname - ) - ) + write(' cJSON_AddStringToObject(o, "{n}", s);\n'.format(n=o.fieldname)) write(" vec_free(s);\n") write(" }\n") return @@ -275,8 +271,12 @@ class ToJSON: "(vl_api_{name}_t *a) {{\n".format(name=o.name) ) - write(' u8 *s = format(0, "%U", format_vl_api_{}_t, a);\n'.format(o.name)) - write(" cJSON *o = cJSON_CreateString((char *)s);\n") + write( + ' char *s = format_c_string(0, "%U", format_vl_api_{}_t, a);\n'.format( + o.name + ) + ) + write(" cJSON *o = cJSON_CreateString(s);\n") write(" vec_free(s);\n") write(" return o;\n") write("}\n") @@ -365,7 +365,7 @@ class FromJSON: write(" char *p = cJSON_GetStringValue(item);\n") write(" size_t plen = strlen(p);\n") write( - " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen, {msgsize});\n".format( + " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen);\n".format( msgvar=msgvar, msgsize=msgsize ) ) @@ -434,7 +434,7 @@ class FromJSON: cJSON *array = cJSON_GetObjectItem(o, "{n}"); int size = cJSON_GetArraySize(array); {lfield} = size; - {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size, {msgsize}); + {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size); {t} *d = (void *){realloc} + {msgsize}; {msgsize} += sizeof({t}) * size; for (i = 0; i < size; i++) {{ @@ -461,12 +461,12 @@ class FromJSON: write( " {realloc} = cJSON_realloc({realloc}, {msgsize} + " - "vec_len(s), {msgsize});\n".format( + "vec_len(s));\n".format( msgvar=msgvar, msgsize=msgsize, realloc=realloc ) ) write( - " memcpy((void *){realloc} + {msgsize}, s, " + " clib_memcpy((void *){realloc} + {msgsize}, s, " "vec_len(s));\n".format(realloc=realloc, msgsize=msgsize) ) write(" {msgsize} += vec_len(s);\n".format(msgsize=msgsize)) @@ -1143,20 +1143,22 @@ ENDIAN_STRINGS = { } -def get_endian_string(o, type): +def get_endian_string(fieldtype): """Return proper endian string conversion function""" - try: - if o.to_network: - return ENDIAN_STRINGS[type].replace("net_to_host", "host_to_net") - except: - pass - return ENDIAN_STRINGS[type] + return ENDIAN_STRINGS[fieldtype] + +def get_lengthfield_type(fieldname, block): + """Return the type of the length field""" + for o in block: + if o.fieldname == fieldname: + return o.fieldtype + return None -def endianfun_array(o): + +def endianfun_array(o, block): """Generate endian functions for arrays""" forloop = """\ - {comment} ASSERT((u32){length} <= (u32)VL_API_MAX_ARRAY_SIZE); for (i = 0; i < {length}; i++) {{ a->{name}[i] = {format}(a->{name}[i]); @@ -1165,33 +1167,32 @@ def endianfun_array(o): forloop_format = """\ for (i = 0; i < {length}; i++) {{ - {type}_endian(&a->{name}[i]); + {type}_endian(&a->{name}[i], to_net); }} """ - to_network_comment = "" - try: - if o.to_network: - to_network_comment = """/* - * Array fields processed first to handle variable length arrays and size - * field endian conversion in the proper order for to-network messages. - * Message fields have been sorted by type in the code generator, thus fields - * in this generated code may be converted in a different order than specified - * in the *.api file. - */""" - except: - pass - output = "" if o.fieldtype == "u8" or o.fieldtype == "string" or o.fieldtype == "bool": output += " /* a->{n} = a->{n} (no-op) */\n".format(n=o.fieldname) else: - lfield = "a->" + o.lengthfield if o.lengthfield else o.length + # lfield = "a->" + o.lengthfield if o.lengthfield else o.length + if o.lengthfield: + fieldtype = get_lengthfield_type(o.lengthfield, block) + if fieldtype == "u8": + output += f" u32 count = a->{o.lengthfield};\n" + else: + output += ( + f" u32 count = to_net ? {get_endian_string(fieldtype)}(a->{o.lengthfield}) : " + f"a->{o.lengthfield};\n" + ) + lfield = "count" + else: + lfield = o.length + if o.fieldtype in ENDIAN_STRINGS: output += forloop.format( - comment=to_network_comment, length=lfield, - format=get_endian_string(o, o.fieldtype), + format=get_endian_string(o.fieldtype), name=o.fieldname, ) else: @@ -1204,11 +1205,11 @@ def endianfun_array(o): NO_ENDIAN_CONVERSION = {"client_index": None} -def endianfun_obj(o): +def endianfun_obj(o, block): """Generate endian conversion function for type""" output = "" if o.type == "Array": - return endianfun_array(o) + return endianfun_array(o, block) if o.type != "Field": output += ' s = format(s, "\\n{} {} {} (print not implemented");\n'.format( o.type, o.fieldtype, o.fieldname @@ -1219,10 +1220,10 @@ def endianfun_obj(o): return output if o.fieldtype in ENDIAN_STRINGS: output += " a->{name} = {format}(a->{name});\n".format( - name=o.fieldname, format=get_endian_string(o, o.fieldtype) + name=o.fieldname, format=get_endian_string(o.fieldtype) ) elif o.fieldtype.startswith("vl_api_"): - output += " {type}_endian(&a->{name});\n".format( + output += " {type}_endian(&a->{name}, to_net);\n".format( type=o.fieldtype, name=o.fieldname ) else: @@ -1254,23 +1255,16 @@ def endianfun(objs, modulename): output = output.format(module=modulename) signature = """\ -static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a) +static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a, bool to_net) {{ int i __attribute__((unused)); """ for t in objs: - # Outbound (to network) messages are identified by message nomenclature - # i.e. message names ending with these suffixes are 'to network' - if t.name.endswith("_reply") or t.name.endswith("_details"): - t.to_network = True - else: - t.to_network = False - if t.__class__.__name__ == "Enum" or t.__class__.__name__ == "EnumFlag": output += signature.format(name=t.name) if t.enumtype in ENDIAN_STRINGS: - output += " *a = {}(*a);\n".format(get_endian_string(t, t.enumtype)) + output += " *a = {}(*a);\n".format(get_endian_string(t.enumtype)) else: output += " /* a->{name} = a->{name} (no-op) */\n".format( name=t.name @@ -1291,7 +1285,7 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a) ) elif t.alias["type"] in FORMAT_STRINGS: output += " *a = {}(*a);\n".format( - get_endian_string(t, t.alias["type"]) + get_endian_string(t.alias["type"]) ) else: output += " /* Not Implemented yet {} */".format(t.name) @@ -1300,16 +1294,8 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a) output += signature.format(name=t.name) - # For outbound (to network) messages: - # some arrays have dynamic length -- iterate over - # them before changing endianness for the length field - # by making the Array types show up first - if t.to_network: - t.block.sort(key=lambda x: x.type) - for o in t.block: - o.to_network = t.to_network - output += endianfun_obj(o) + output += endianfun_obj(o, t.block) output += "}\n\n" output += "\n#endif" @@ -1375,7 +1361,7 @@ static inline uword vl_api_{name}_t_calc_size (vl_api_{name}_t *a) ) lf = m[0] if lf.fieldtype in ENDIAN_STRINGS: - output += f" + {get_endian_string(b, lf.fieldtype)}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])" + output += f" + {get_endian_string(lf.fieldtype)}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])" elif lf.fieldtype == "u8": output += ( f" + a->{b.lengthfield} * sizeof(a->{b.fieldname}[0])" @@ -1852,7 +1838,7 @@ api_{n} (cJSON *o) }} mp->_vl_msg_id = vac_get_msg_index(VL_API_{N}_CRC); - vl_api_{n}_t_endian(mp); + vl_api_{n}_t_endian(mp, 1); vac_write((char *)mp, len); cJSON_free(mp); @@ -1867,7 +1853,7 @@ api_{n} (cJSON *o) return 0; }} vl_api_{r}_t *rmp = (vl_api_{r}_t *)p; - vl_api_{r}_t_endian(rmp); + vl_api_{r}_t_endian(rmp, 0); return vl_api_{r}_t_tojson(rmp); }} @@ -1885,7 +1871,7 @@ api_{n} (cJSON *o) return 0; }} mp->_vl_msg_id = msg_id; - vl_api_{n}_t_endian(mp); + vl_api_{n}_t_endian(mp, 1); vac_write((char *)mp, len); cJSON_free(mp); @@ -1919,7 +1905,7 @@ api_{n} (cJSON *o) return 0; }} vl_api_{r}_t *rmp = (vl_api_{r}_t *)p; - vl_api_{r}_t_endian(rmp); + vl_api_{r}_t_endian(rmp, 0); cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp)); }} }} @@ -1941,7 +1927,7 @@ api_{n} (cJSON *o) }} mp->_vl_msg_id = msg_id; - vl_api_{n}_t_endian(mp); + vl_api_{n}_t_endian(mp, 1); vac_write((char *)mp, len); cJSON_free(mp); @@ -1962,14 +1948,14 @@ api_{n} (cJSON *o) u16 msg_id = ntohs(*((u16 *)p)); if (msg_id == reply_msg_id) {{ vl_api_{r}_t *rmp = (vl_api_{r}_t *)p; - vl_api_{r}_t_endian(rmp); + vl_api_{r}_t_endian(rmp, 0); cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp)); break; }} if (msg_id == details_msg_id) {{ vl_api_{d}_t *rmp = (vl_api_{d}_t *)p; - vl_api_{d}_t_endian(rmp); + vl_api_{d}_t_endian(rmp, 0); cJSON_AddItemToArray(reply, vl_api_{d}_t_tojson(rmp)); }} }} |