Browse Source

tools/generate-wire.py: simple scheme to autoindent.

I verified that the generated files don't change.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
232b330284
  1. 173
      tools/generate-wire.py

173
tools/generate-wire.py

@ -249,6 +249,43 @@ printwire_impl_templ = """void printwire_{name}(const char *fieldname, const u8
""" """
class CCode(object):
"""Simple class to create indented C code"""
def __init__(self):
self.indent = 1
self.single_indent = False
self.code = []
def append(self, lines):
for line in lines.split('\n'):
# Let us to the indenting please!
assert '\t' not in line
# Special case: } by itself is pre-unindented.
if line == '}':
self.indent -= 1
self.code.append("\t" * self.indent + line)
continue
self.code.append("\t" * self.indent + line)
if self.single_indent:
self.indent -= 1
self.single_indent = False
if line.endswith('{'):
self.indent += 1
elif line.endswith('}'):
self.indent -= 1
elif line.startswith('for') or line.startswith('if'):
self.indent += 1
self.single_indent = True
def __str__(self):
assert self.indent == 1
assert not self.single_indent
return '\n'.join(self.code)
class Message(object): class Message(object):
def __init__(self, name, enum, comments): def __init__(self, name, enum, comments):
self.name = name self.name = name
@ -288,19 +325,19 @@ class Message(object):
def print_fromwire_array(self, subcalls, basetype, f, name, num_elems): def print_fromwire_array(self, subcalls, basetype, f, name, num_elems):
if f.has_array_helper(): if f.has_array_helper():
subcalls.append('\tfromwire_{}_array(&cursor, &plen, {}, {});' subcalls.append('fromwire_{}_array(&cursor, &plen, {}, {});'
.format(basetype, name, num_elems)) .format(basetype, name, num_elems))
else: else:
subcalls.append('\tfor (size_t i = 0; i < {}; i++)' subcalls.append('for (size_t i = 0; i < {}; i++)'
.format(num_elems)) .format(num_elems))
if f.fieldtype.is_assignable(): if f.fieldtype.is_assignable():
subcalls.append('\t\t({})[i] = fromwire_{}(&cursor, &plen);' subcalls.append('({})[i] = fromwire_{}(&cursor, &plen);'
.format(name, basetype)) .format(name, basetype))
elif basetype in varlen_structs: elif basetype in varlen_structs:
subcalls.append('\t\t({})[i] = fromwire_{}(ctx, &cursor, &plen);' subcalls.append('({})[i] = fromwire_{}(ctx, &cursor, &plen);'
.format(name, basetype)) .format(name, basetype))
else: else:
subcalls.append('\t\tfromwire_{}(&cursor, &plen, {} + i);' subcalls.append('fromwire_{}(&cursor, &plen, {} + i);'
.format(basetype, name)) .format(basetype, name))
def print_fromwire(self, is_header): def print_fromwire(self, is_header):
@ -327,53 +364,53 @@ class Message(object):
template = fromwire_header_templ if is_header else fromwire_impl_templ template = fromwire_header_templ if is_header else fromwire_impl_templ
fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var] fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var]
subcalls = [] subcalls = CCode()
for f in self.fields: for f in self.fields:
basetype = f.basetype() basetype = f.basetype()
for c in f.comments: for c in f.comments:
subcalls.append('\t/*{} */'.format(c)) subcalls.append('/*{} */'.format(c))
if f.is_padding(): if f.is_padding():
subcalls.append('\tfromwire_pad(&cursor, &plen, {});' subcalls.append('fromwire_pad(&cursor, &plen, {});'
.format(f.num_elems)) .format(f.num_elems))
elif f.is_array(): elif f.is_array():
self.print_fromwire_array(subcalls, basetype, f, f.name, self.print_fromwire_array(subcalls, basetype, f, f.name,
f.num_elems) f.num_elems)
elif f.is_variable_size(): elif f.is_variable_size():
subcalls.append("\t//2nd case {name}".format(name=f.name)) subcalls.append("//2nd case {name}".format(name=f.name))
typename = f.fieldtype.name typename = f.fieldtype.name
# If structs are varlen, need array of ptrs to them. # If structs are varlen, need array of ptrs to them.
if basetype in varlen_structs: if basetype in varlen_structs:
typename += ' *' typename += ' *'
subcalls.append('\t*{} = {} ? tal_arr(ctx, {}, {}) : NULL;' subcalls.append('*{} = {} ? tal_arr(ctx, {}, {}) : NULL;'
.format(f.name, f.lenvar, typename, f.lenvar)) .format(f.name, f.lenvar, typename, f.lenvar))
self.print_fromwire_array(subcalls, basetype, f, '*' + f.name, self.print_fromwire_array(subcalls, basetype, f, '*' + f.name,
f.lenvar) f.lenvar)
else: else:
if f.optional: if f.optional:
subcalls.append("\tif (!fromwire_bool(&cursor, &plen))\n" subcalls.append("if (!fromwire_bool(&cursor, &plen))\n"
"\t\t*{} = NULL;\n" "*{} = NULL;\n"
"\telse {{\n" "else {{\n"
"\t\t*{} = tal(ctx, {});\n" "*{} = tal(ctx, {});\n"
"\t\tfromwire_{}(&cursor, &plen, *{});\n" "fromwire_{}(&cursor, &plen, *{});\n"
"\t}}" "}}"
.format(f.name, f.name, f.fieldtype.name, .format(f.name, f.name, f.fieldtype.name,
basetype, f.name)) basetype, f.name))
elif f.is_assignable(): elif f.is_assignable():
subcalls.append("\t//3th case {name}".format(name=f.name)) subcalls.append("//3th case {name}".format(name=f.name))
if f.is_len_var: if f.is_len_var:
subcalls.append('\t{} = fromwire_{}(&cursor, &plen);' subcalls.append('{} = fromwire_{}(&cursor, &plen);'
.format(f.name, basetype)) .format(f.name, basetype))
else: else:
subcalls.append('\t*{} = fromwire_{}(&cursor, &plen);' subcalls.append('*{} = fromwire_{}(&cursor, &plen);'
.format(f.name, basetype)) .format(f.name, basetype))
elif basetype in varlen_structs: elif basetype in varlen_structs:
subcalls.append('\t*{} = fromwire_{}(ctx, &cursor, &plen);' subcalls.append('*{} = fromwire_{}(ctx, &cursor, &plen);'
.format(f.name, basetype)) .format(f.name, basetype))
else: else:
subcalls.append('\tfromwire_{}(&cursor, &plen, {});' subcalls.append('fromwire_{}(&cursor, &plen, {});'
.format(basetype, f.name)) .format(basetype, f.name))
return template.format( return template.format(
@ -382,21 +419,21 @@ class Message(object):
args=''.join(args), args=''.join(args),
fields=''.join(fields), fields=''.join(fields),
enum=self.enum, enum=self.enum,
subcalls='\n'.join(subcalls) subcalls=str(subcalls)
) )
def print_towire_array(self, subcalls, basetype, f, num_elems): def print_towire_array(self, subcalls, basetype, f, num_elems):
if f.has_array_helper(): if f.has_array_helper():
subcalls.append('\ttowire_{}_array(&p, {}, {});' subcalls.append('towire_{}_array(&p, {}, {});'
.format(basetype, f.name, num_elems)) .format(basetype, f.name, num_elems))
else: else:
subcalls.append('\tfor (size_t i = 0; i < {}; i++)' subcalls.append('for (size_t i = 0; i < {}; i++)'
.format(num_elems)) .format(num_elems))
if f.fieldtype.is_assignable() or basetype in varlen_structs: if f.fieldtype.is_assignable() or basetype in varlen_structs:
subcalls.append('\t\ttowire_{}(&p, {}[i]);' subcalls.append('towire_{}(&p, {}[i]);'
.format(basetype, f.name)) .format(basetype, f.name))
else: else:
subcalls.append('\t\ttowire_{}(&p, {} + i);' subcalls.append('towire_{}(&p, {} + i);'
.format(basetype, f.name)) .format(basetype, f.name))
def print_towire(self, is_header): def print_towire(self, is_header):
@ -421,7 +458,7 @@ class Message(object):
f.fieldtype.name, f.name, f.lenvar_for.name f.fieldtype.name, f.name, f.lenvar_for.name
)) ))
subcalls = [] subcalls = CCode()
for f in self.fields: for f in self.fields:
basetype = f.fieldtype.name basetype = f.fieldtype.name
if basetype.startswith('struct '): if basetype.startswith('struct '):
@ -430,10 +467,10 @@ class Message(object):
basetype = basetype[5:] basetype = basetype[5:]
for c in f.comments: for c in f.comments:
subcalls.append('\t/*{} */'.format(c)) subcalls.append('/*{} */'.format(c))
if f.is_padding(): if f.is_padding():
subcalls.append('\ttowire_pad(&p, {});' subcalls.append('towire_pad(&p, {});'
.format(f.num_elems)) .format(f.num_elems))
elif f.is_array(): elif f.is_array():
self.print_towire_array(subcalls, basetype, f, f.num_elems) self.print_towire_array(subcalls, basetype, f, f.num_elems)
@ -441,14 +478,14 @@ class Message(object):
self.print_towire_array(subcalls, basetype, f, f.lenvar) self.print_towire_array(subcalls, basetype, f, f.lenvar)
else: else:
if f.optional: if f.optional:
subcalls.append("\tif (!{})\n" subcalls.append("if (!{})\n"
"\t\ttowire_bool(&p, false);\n" "towire_bool(&p, false);\n"
"\telse {{\n" "else {{\n"
"\t\ttowire_bool(&p, true);\n" "towire_bool(&p, true);\n"
"\t\ttowire_{}(&p, {});\n" "towire_{}(&p, {});\n"
"\t}}".format(f.name, basetype, f.name)) "}}".format(f.name, basetype, f.name))
else: else:
subcalls.append('\ttowire_{}(&p, {});' subcalls.append('towire_{}(&p, {});'
.format(basetype, f.name)) .format(basetype, f.name))
return template.format( return template.format(
@ -456,62 +493,62 @@ class Message(object):
args=''.join(args), args=''.join(args),
enumname=self.enum.name, enumname=self.enum.name,
field_decls='\n'.join(field_decls), field_decls='\n'.join(field_decls),
subcalls='\n'.join(subcalls), subcalls=str(subcalls),
) )
def add_truncate_check(self, subcalls, indent='\t'): def add_truncate_check(self, subcalls):
# Report if truncated, otherwise print. # Report if truncated, otherwise print.
subcalls.append(indent + 'if (!cursor) {') subcalls.append('if (!cursor) {\n'
subcalls.append(indent + '\tprintf("**TRUNCATED**\\n");') 'printf("**TRUNCATED**\\n");\n'
subcalls.append(indent + '\treturn;') 'return;\n'
subcalls.append(indent + '}') '}')
def print_printwire_array(self, subcalls, basetype, f, num_elems): def print_printwire_array(self, subcalls, basetype, f, num_elems):
if f.has_array_helper(): if f.has_array_helper():
subcalls.append('\tprintwire_{}_array(tal_fmt(NULL, "%s.{}", fieldname), &cursor, &plen, {});' subcalls.append('printwire_{}_array(tal_fmt(NULL, "%s.{}", fieldname), &cursor, &plen, {});'
.format(basetype, f.name, num_elems)) .format(basetype, f.name, num_elems))
else: else:
subcalls.append('\tprintf("[");') subcalls.append('printf("[");')
subcalls.append('\tfor (size_t i = 0; i < {}; i++) {{' subcalls.append('for (size_t i = 0; i < {}; i++) {{'
.format(num_elems)) .format(num_elems))
subcalls.append('\t\t{} v;'.format(f.fieldtype.name)) subcalls.append('{} v;'.format(f.fieldtype.name))
if f.fieldtype.is_assignable(): if f.fieldtype.is_assignable():
subcalls.append('\t\tv = fromwire_{}(&cursor, plen);' subcalls.append('v = fromwire_{}(&cursor, plen);'
.format(f.fieldtype.name, basetype)) .format(f.fieldtype.name, basetype))
else: else:
# We don't handle this yet! # We don't handle this yet!
assert(basetype not in varlen_structs) assert(basetype not in varlen_structs)
subcalls.append('\t\tfromwire_{}(&cursor, &plen, &v);' subcalls.append('fromwire_{}(&cursor, &plen, &v);'
.format(basetype)) .format(basetype))
self.add_truncate_check(subcalls, indent='\t\t') self.add_truncate_check(subcalls)
subcalls.append('\t\tprintwire_{}(tal_fmt(NULL, "%s.{}", fieldname), &v);' subcalls.append('printwire_{}(tal_fmt(NULL, "%s.{}", fieldname), &v);'
.format(basetype, f.name)) .format(basetype, f.name))
subcalls.append('\t}') subcalls.append('}')
subcalls.append('\tprintf("]");') subcalls.append('printf("]");')
def print_printwire(self, is_header): def print_printwire(self, is_header):
template = printwire_header_templ if is_header else printwire_impl_templ template = printwire_header_templ if is_header else printwire_impl_templ
fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var] fields = ['\t{} {};\n'.format(f.fieldtype.name, f.name) for f in self.fields if f.is_len_var]
subcalls = [] subcalls = CCode()
for f in self.fields: for f in self.fields:
basetype = f.basetype() basetype = f.basetype()
for c in f.comments: for c in f.comments:
subcalls.append('\t/*{} */'.format(c)) subcalls.append('/*{} */'.format(c))
if f.is_len_var: if f.is_len_var:
subcalls.append('\t{} {} = fromwire_{}(&cursor, &plen);' subcalls.append('{} {} = fromwire_{}(&cursor, &plen);'
.format(f.fieldtype.name, f.name, basetype)) .format(f.fieldtype.name, f.name, basetype))
self.add_truncate_check(subcalls) self.add_truncate_check(subcalls)
continue continue
subcalls.append('\tprintf("{}=");'.format(f.name)) subcalls.append('printf("{}=");'.format(f.name))
if f.is_padding(): if f.is_padding():
subcalls.append('\tprintwire_pad(tal_fmt(NULL, "%s.{}", fieldname), &cursor, &plen, {});' subcalls.append('printwire_pad(tal_fmt(NULL, "%s.{}", fieldname), &cursor, &plen, {});'
.format(f.name, f.num_elems)) .format(f.name, f.num_elems))
self.add_truncate_check(subcalls) self.add_truncate_check(subcalls)
elif f.is_array(): elif f.is_array():
@ -521,35 +558,33 @@ class Message(object):
self.print_printwire_array(subcalls, basetype, f, f.lenvar) self.print_printwire_array(subcalls, basetype, f, f.lenvar)
self.add_truncate_check(subcalls) self.add_truncate_check(subcalls)
else: else:
indent = '\t'
if f.optional: if f.optional:
subcalls.append("\tif (fromwire_bool(&cursor, &plen)) {") subcalls.append("if (fromwire_bool(&cursor, &plen)) {")
indent += '\t'
if f.is_assignable(): if f.is_assignable():
subcalls.append(indent + '{} {} = fromwire_{}(&cursor, &plen);' subcalls.append('{} {} = fromwire_{}(&cursor, &plen);'
.format(f.fieldtype.name, f.name, basetype)) .format(f.fieldtype.name, f.name, basetype))
else: else:
# Don't handle these yet. # Don't handle these yet.
assert(basetype not in varlen_structs) assert(basetype not in varlen_structs)
subcalls.append(indent + '{} {};'. subcalls.append('{} {};'.
format(f.fieldtype.name, f.name)) format(f.fieldtype.name, f.name))
subcalls.append(indent + 'fromwire_{}(&cursor, &plen, &{});' subcalls.append('fromwire_{}(&cursor, &plen, &{});'
.format(basetype, f.name)) .format(basetype, f.name))
self.add_truncate_check(subcalls, indent=indent) self.add_truncate_check(subcalls)
subcalls.append(indent + 'printwire_{}(tal_fmt(NULL, "%s.{}", fieldname), &{});' subcalls.append('printwire_{}(tal_fmt(NULL, "%s.{}", fieldname), &{});'
.format(basetype, f.name, f.name)) .format(basetype, f.name, f.name))
if f.optional: if f.optional:
subcalls.append("\t} else {") subcalls.append("} else {")
self.add_truncate_check(subcalls, indent='\t\t') self.add_truncate_check(subcalls)
subcalls.append("\t}") subcalls.append("}")
return template.format( return template.format(
name=self.name, name=self.name,
fields=''.join(fields), fields=''.join(fields),
enum=self.enum, enum=self.enum,
subcalls='\n'.join(subcalls) subcalls=str(subcalls)
) )

Loading…
Cancel
Save