tools/generate-wire.py: simplify printwire routines, fix ... handling.

We make them return bool, and always use names `cursor` and `plen` in
callers, for simplicity.

Also, `...` means "loop until finished" not "loop this many bytes".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-03-23 10:01:14 +10:30
parent 12c7b156c5
commit 88de64a580
5 changed files with 53 additions and 48 deletions

View File

@@ -180,7 +180,7 @@ find_print_record_type(u64 type,
return NULL; return NULL;
} }
void printwire_tlvs(const char *fieldname, const u8 **cursor, size_t *plen, bool printwire_tlvs(const char *fieldname, const u8 **cursor, size_t *plen,
const struct tlv_print_record_type types[], const struct tlv_print_record_type types[],
size_t num_types) size_t num_types)
{ {
@@ -212,10 +212,11 @@ void printwire_tlvs(const char *fieldname, const u8 **cursor, size_t *plen,
printf("**TYPE #%"PRIu64" UNKNOWN for TLV %s**\n", type, fieldname); printf("**TYPE #%"PRIu64" UNKNOWN for TLV %s**\n", type, fieldname);
*plen -= length; *plen -= length;
} }
return; return true;
fail: fail:
printf("**TRUNCATED TLV %s**\n", fieldname); printf("**TRUNCATED TLV %s**\n", fieldname);
return false;
} }
#define PRINTWIRE_TYPE_TO_STRING(T, N) \ #define PRINTWIRE_TYPE_TO_STRING(T, N) \

View File

@@ -9,7 +9,7 @@
struct tlv_print_record_type { struct tlv_print_record_type {
u64 type; u64 type;
void (*print)(const char *tlv_name, const u8 **cursor, size_t *plen); bool (*print)(const char *tlv_name, const u8 **cursor, size_t *plen);
}; };
typedef u64 bigsize; typedef u64 bigsize;
@@ -21,7 +21,7 @@ void printwire_u16(const char *fieldname, const u16 *v);
void printwire_u32(const char *fieldname, const u32 *v); void printwire_u32(const char *fieldname, const u32 *v);
void printwire_u64(const char *fieldname, const u64 *v); void printwire_u64(const char *fieldname, const u64 *v);
void printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len); void printwire_u8_array(const char *fieldname, const u8 **cursor, size_t *plen, size_t len);
void printwire_tlvs(const char *tlv_name, const u8 **cursor, size_t *plen, bool printwire_tlvs(const char *tlv_name, const u8 **cursor, size_t *plen,
const struct tlv_print_record_type types[], size_t num_types); const struct tlv_print_record_type types[], size_t num_types);
void printwire_bitcoin_blkid(const char *fieldname, const struct bitcoin_blkid *bitcoin_blkid); void printwire_bitcoin_blkid(const char *fieldname, const struct bitcoin_blkid *bitcoin_blkid);

View File

@@ -9,18 +9,18 @@
${i} ${i}
% endfor % endfor
void print${options.enum_name}_message(const u8 *msg); bool print${options.enum_name}_message(const u8 *msg);
void print${options.enum_name}_tlv_message(const char *tlv_name, const u8 *msg); bool print${options.enum_name}_tlv_message(const char *tlv_name, const u8 *msg);
% for msg in messages: % for msg in messages:
void printwire_${msg.name}(const char *fieldname, const u8 *cursor); bool printwire_${msg.name}(const char *fieldname, const u8 *cursor);
% endfor % endfor
% if options.expose_subtypes: % if options.expose_subtypes:
% for subtype in subtypes: % for subtype in subtypes:
void printwire_${subtype.name}(const char *fieldname, const u8 **cursor, size_t *plen); bool printwire_${subtype.name}(const char *fieldname, const u8 **cursor, size_t *plen);
% endfor % endfor
% endif % endif
#endif /* LIGHTNING_${idem} */ #endif /* LIGHTNING_${idem} */

View File

@@ -13,87 +13,85 @@ ${i}
% endfor % endfor
% if enum_sets: % if enum_sets:
void print${options.enum_name}_message(const u8 *msg) bool print${options.enum_name}_message(const u8 *msg)
{ {
switch ((enum ${options.enum_name})fromwire_peektype(msg)) { switch ((enum ${options.enum_name})fromwire_peektype(msg)) {
% for msg in enum_sets[0]['set']: % for msg in enum_sets[0]['set']:
case ${msg.enum_name()}: case ${msg.enum_name()}:
printf("${msg.enum_name()}:\n"); printf("${msg.enum_name()}:\n");
printwire_${msg.name}("${msg.name}", msg); return printwire_${msg.name}("${msg.name}", msg);
return;
% endfor % endfor
} }
printf("UNKNOWN: %s\\n", tal_hex(msg, msg)); printf("UNKNOWN: %s\\n", tal_hex(msg, msg));
return false;
} }
% endif % endif
## 'component' for 'truncate check ## 'component' for 'truncate check
<%def name="truncate_check(nested=False)"> <%def name="truncate_check()">
if (!${ '*' if nested else '' }cursor) { if (!*cursor) {
printf("**TRUNCATED**\n"); printf("**TRUNCATED**\n");
return; return false;
} }
</%def> \ </%def> \
## definition for printing field sets ## definition for printing field sets
<%def name="print_fieldset(fields, nested, cursor, plen)"> <%def name="print_fieldset(fields)">
% for f in fields: % for f in fields:
% if f.is_extension(): % if f.is_extension():
if (plen <= 0) if (*plen == 0)
return; return true;
printf("(${','.join(f.extension_names)}):"); printf("(${','.join(f.extension_names)}):");
% endif % endif
% if f.len_field_of: % if f.len_field_of:
${f.type_obj.type_name()} ${f.name} = fromwire_${f.type_obj.name}(${cursor}, ${plen});${truncate_check(nested)} <% continue %> \ ${f.type_obj.type_name()} ${f.name} = fromwire_${f.type_obj.name}(cursor, plen);${truncate_check()} <% continue %> \
% endif % endif
printf("${f.name}="); printf("${f.name}=");
% if f.type_obj.is_tlv(): % if f.type_obj.is_tlv():
printwire_tlvs(tal_fmt(NULL, "%s.${f.name}", fieldname), ${cursor}, ${plen}, print_tlvs_${f.type_obj.tlv.name}, ARRAY_SIZE(print_tlvs_${f.type_obj.tlv.name})); printwire_tlvs(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen, print_tlvs_${f.type_obj.tlv.name}, ARRAY_SIZE(print_tlvs_${f.type_obj.tlv.name}));
% elif f.is_array() or f.is_varlen(): % elif f.is_array() or f.is_varlen():
% if f.type_obj.has_array_helper(): % if f.type_obj.has_array_helper():
printwire_${f.type_obj.name}_array(tal_fmt(NULL, "%s.${f.name}", fieldname), ${cursor}, ${plen}, ${f.size('*' + plen)}); printwire_${f.type_obj.name}_array(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen, ${f.size('*plen')});
% else: % else:
printf("["); printf("[");
% if f.is_implicit_len(): % if f.is_implicit_len():
for (size_t i = 0; i < *${plen}; i++) { while (*plen) {
% else: % else:
for (size_t i = 0; i < ${f.size()}; i++) { for (size_t i = 0; i < ${f.size()}; i++) {
% endif % endif
printf("{\n");
% if f.type_obj.is_subtype() or f.type_obj.is_varsize(): % if f.type_obj.is_subtype() or f.type_obj.is_varsize():
printf("{\n"); printf("{\n");
printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), ${cursor}, ${plen}); printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen);
printf("}\n"); printf("}\n");
% else: % else:
${f.type_obj.type_name()} v; ${f.type_obj.type_name()} v;
% if f.type_obj.is_assignable(): % if f.type_obj.is_assignable():
v = fromwire_${f.type_obj.name}(${cursor}, ${plen}); v = fromwire_${f.type_obj.name}(cursor, plen);
% else: % else:
fromwire_${f.type_obj.name}(${cursor}, ${plen}, &v); fromwire_${f.type_obj.name}(cursor, plen, &v);
% endif % endif
if (!*cursor) { ${truncate_check()}
printf("**TRUNCATED**\n");
return;
}
<% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %>\ <% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %>\
printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &v); printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &v);
% endif % endif
} }
printf("]"); printf("]");
% endif % endif
${truncate_check(nested)} \ ${truncate_check()} \
% elif f.type_obj.is_subtype() or f.type_obj.is_varsize(): % elif f.type_obj.is_subtype() or f.type_obj.is_varsize():
printf("{\n"); printf("{\n");
printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), ${cursor}, ${plen}); printwire_${f.type_obj.name}(tal_fmt(NULL, "%s.${f.name}", fieldname), cursor, plen);
printf("}\n"); printf("}\n");
% else: % else:
% if f.type_obj.is_assignable(): % if f.type_obj.is_assignable():
${f.type_obj.type_name()} ${f.name} = fromwire_${f.type_obj.name}(${cursor}, ${plen}); ${f.type_obj.type_name()} ${f.name} = fromwire_${f.type_obj.name}(cursor, plen);
% else: % else:
${f.type_obj.type_name()} ${f.name}; ${f.type_obj.type_name()} ${f.name};
fromwire_${f.type_obj.name}(${cursor}, ${plen}, &${f.name}); fromwire_${f.type_obj.name}(cursor, plen, &${f.name});
% endif % endif
<% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %> <% typename = f.type_obj.name if not f.type_obj.is_truncated() else f.type_obj.name[1:] %>
printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &${f.name}); ${truncate_check(nested)} \ printwire_${typename}(tal_fmt(NULL, "%s.${f.name}", fieldname), &${f.name}); ${truncate_check()} \
% endif % endif
% endfor % endfor
</%def> \ </%def> \
@@ -103,18 +101,20 @@ ${truncate_check(nested)} \
<% <%
static = '' if options.expose_subtypes else 'static ' static = '' if options.expose_subtypes else 'static '
%>\ %>\
${static}void printwire_${subtype.name}(const char *fieldname, const u8 **cursor, size_t *plen) ${static}bool printwire_${subtype.name}(const char *fieldname, const u8 **cursor, size_t *plen)
{ {
${print_fieldset(subtype.fields.values(), True, 'cursor', 'plen')} ${print_fieldset(subtype.fields.values())}
return true;
} }
% endfor % endfor
% for tlv in tlvs.values(): % for tlv in tlvs.values():
% for msg in tlv.messages.values(): % for msg in tlv.messages.values():
static void printwire_${msg.struct_name()}(const char *fieldname, const u8 **cursor, size_t *plen) static bool printwire_${msg.struct_name()}(const char *fieldname, const u8 **cursor, size_t *plen)
{ {
printf("(msg_name=%s)\n", "${msg.name}"); printf("(msg_name=%s)\n", "${msg.name}");
${print_fieldset(msg.fields.values(), True, 'cursor', 'plen')} ${print_fieldset(msg.fields.values())}
return true;
} }
% endfor % endfor
@@ -125,29 +125,33 @@ static const struct tlv_print_record_type print_tlvs_${tlv.name}[] = {
}; };
% endfor % endfor
% for msg in messages: % for msg in messages:
void printwire_${msg.name}(const char *fieldname, const u8 *cursor) bool printwire_${msg.name}(const char *fieldname, const u8 *msg)
{ {
size_t msglen = tal_count(msg);
const u8 **cursor = &msg;
size_t *plen = &msglen;
size_t plen = tal_count(cursor); if (fromwire_u16(cursor, plen) != ${msg.enum_name()}) {
if (fromwire_u16(&cursor, &plen) != ${msg.enum_name()}) {
printf("WRONG TYPE?!\n"); printf("WRONG TYPE?!\n");
return; return false;
} }
${print_fieldset(msg.fields.values(), False, '&cursor', '&plen')} ${print_fieldset(msg.fields.values())}
## Length check ## Length check
if (plen != 0) if (*plen != 0)
printf("EXTRA: %s\n", tal_hexstr(NULL, cursor, plen)); printf("EXTRA: %s\n", tal_hexstr(NULL, *cursor, *plen));
return *cursor != NULL;
} }
% endfor % endfor
% if bool(tlvs): % if bool(tlvs):
void print${options.enum_name}_tlv_message(const char *tlv_name, const u8 *msg) { bool print${options.enum_name}_tlv_message(const char *tlv_name, const u8 *msg) {
size_t plen = tal_count(msg); size_t len = tal_count(msg);
% for tlv in tlvs.values(): % for tlv in tlvs.values():
if (strcmp(tlv_name, "${tlv.name}") == 0) { if (strcmp(tlv_name, "${tlv.name}") == 0) {
printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_${tlv.name}, ARRAY_SIZE(print_tlvs_${tlv.name})); return printwire_tlvs(tlv_name, &msg, &len, print_tlvs_${tlv.name}, ARRAY_SIZE(print_tlvs_${tlv.name}));
} }
% endfor % endfor
return false;
} }
% endif % endif

View File

@@ -14,7 +14,7 @@ int fromwire_peektype(const u8 *cursor UNNEEDED)
void printwire_amount_msat(const char *fieldname UNNEEDED, const struct amount_msat *msat UNNEEDED) void printwire_amount_msat(const char *fieldname UNNEEDED, const struct amount_msat *msat UNNEEDED)
{ fprintf(stderr, "printwire_amount_msat called!\n"); abort(); } { fprintf(stderr, "printwire_amount_msat called!\n"); abort(); }
/* Generated stub for printwire_tlvs */ /* Generated stub for printwire_tlvs */
void printwire_tlvs(const char *tlv_name UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED, bool printwire_tlvs(const char *tlv_name UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED,
const struct tlv_print_record_type types[] UNNEEDED, size_t num_types UNNEEDED) const struct tlv_print_record_type types[] UNNEEDED, size_t num_types UNNEEDED)
{ fprintf(stderr, "printwire_tlvs called!\n"); abort(); } { fprintf(stderr, "printwire_tlvs called!\n"); abort(); }
/* Generated stub for printwire_u16 */ /* Generated stub for printwire_u16 */