Allow specifying the output filename for rpcgen; based on work by jmansion; patch from Zack Weinberg.

svn:r1335
This commit is contained in:
Niels Provos 2009-07-03 17:31:17 +00:00
parent bbcc54ef9c
commit fbb181d1aa
2 changed files with 77 additions and 36 deletions

View File

@ -38,6 +38,7 @@ Changes in 2.0.2-alpha:
o Set truncated flag correctly in evdns server replies. o Set truncated flag correctly in evdns server replies.
o Raise RpcGenError in event_rpcgen.py; from jmanison and Zack Weinberg o Raise RpcGenError in event_rpcgen.py; from jmanison and Zack Weinberg
o Fix preamble of rpcgen-generated files to rely on event2 includes; based on work by jmansion; patch from Zack Weinberg. o Fix preamble of rpcgen-generated files to rely on event2 includes; based on work by jmansion; patch from Zack Weinberg.
o Allow specifying the output filename for rpcgen; based on work by jmansion; patch from Zack Weinberg.
Changes in 2.0.1-alpha: Changes in 2.0.1-alpha:

View File

@ -1539,11 +1539,10 @@ class CCodeGenerator:
guard = self.GuardName(name) guard = self.GuardName(name)
return '#endif /* %s */' % guard return '#endif /* %s */' % guard
def BodyPreamble(self, name): def BodyPreamble(self, name, header_file):
global _NAME global _NAME
global _VERSION global _VERSION
header_file = '.'.join(name.split('.')[:-1]) + '.gen.h'
slash = header_file.rfind('/') slash = header_file.rfind('/')
if slash != -1: if slash != -1:
header_file = header_file[slash+1:] header_file = header_file[slash+1:]
@ -1573,7 +1572,7 @@ class CCodeGenerator:
return pre return pre
def HeaderFilename(self, filename): def HeaderFilename(self, filename):
return '.'.join(filename.split('.')[:-1]) + '.gen.h' return '.'.join(filename.split('.')[:-1]) + '.h'
def CodeFilename(self, filename): def CodeFilename(self, filename):
return '.'.join(filename.split('.')[:-1]) + '.gen.c' return '.'.join(filename.split('.')[:-1]) + '.gen.c'
@ -1599,51 +1598,92 @@ class CCodeGenerator:
def EntryArray(self, entry): def EntryArray(self, entry):
return EntryArray(entry) return EntryArray(entry)
def Generate(factory, filename): class Usage(RpcGenError):
ext = filename.split('.')[-1] def __init__(self, argv0):
if ext != 'rpc': RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]"
raise RpcGenError('Unrecognized file extension: %s' % ext) % argv0)
print >>sys.stderr, 'Reading \"%s\"' % filename class CommandLine:
def __init__(self, argv):
self.filename = None
self.header_file = None
self.impl_file = None
self.factory = CCodeGenerator()
fp = open(filename, 'r') if len(argv) < 2 or len(argv) > 4:
entities = Parse(factory, fp) raise Usage(argv[0])
fp.close()
header_file = factory.HeaderFilename(filename) self.filename = argv[1].replace('\\', '/')
impl_file = factory.CodeFilename(filename) if len(argv) == 3:
self.impl_file = argv[2].replace('\\', '/')
if len(argv) == 4:
self.header_file = argv[2].replace('\\', '/')
self.impl_file = argv[3].replace('\\', '/')
print >>sys.stderr, '... creating "%s"' % header_file if not self.filename:
header_fp = open(header_file, 'w') raise Usage(argv[0])
print >>header_fp, factory.HeaderPreamble(filename)
# Create forward declarations: allows other structs to reference if not self.impl_file:
# each other self.impl_file = self.factory.CodeFilename(self.filename)
for entry in entities:
entry.PrintForwardDeclaration(header_fp)
print >>header_fp, ''
for entry in entities: if not self.header_file:
entry.PrintTags(header_fp) self.header_file = self.factory.HeaderFilename(self.impl_file)
entry.PrintDeclaration(header_fp)
print >>header_fp, factory.HeaderPostamble(filename)
header_fp.close()
print >>sys.stderr, '... creating "%s"' % impl_file if not self.impl_file.endswith('.c'):
impl_fp = open(impl_file, 'w') raise RpcGenError("can only generate C implementation files")
print >>impl_fp, factory.BodyPreamble(filename) if not self.header_file.endswith('.h'):
for entry in entities: raise RpcGenError("can only generate C header files")
entry.PrintCode(impl_fp)
impl_fp.close() def run(self):
filename = self.filename
header_file = self.header_file
impl_file = self.impl_file
factory = self.factory
print >>sys.stderr, 'Reading \"%s\"' % filename
fp = open(filename, 'r')
entities = Parse(factory, fp)
fp.close()
print >>sys.stderr, '... creating "%s"' % header_file
header_fp = open(header_file, 'w')
print >>header_fp, factory.HeaderPreamble(filename)
# Create forward declarations: allows other structs to reference
# each other
for entry in entities:
entry.PrintForwardDeclaration(header_fp)
print >>header_fp, ''
for entry in entities:
entry.PrintTags(header_fp)
entry.PrintDeclaration(header_fp)
print >>header_fp, factory.HeaderPostamble(filename)
header_fp.close()
print >>sys.stderr, '... creating "%s"' % impl_file
impl_fp = open(impl_file, 'w')
print >>impl_fp, factory.BodyPreamble(filename, header_file)
for entry in entities:
entry.PrintCode(impl_fp)
impl_fp.close()
if __name__ == '__main__': if __name__ == '__main__':
try: try:
if len(sys.argv) < 2 or not sys.argv[1]: CommandLine(sys.argv).run()
raise RpcGenError('Need RPC description file as first argument.')
Generate(CCodeGenerator(), sys.argv[1])
sys.exit(0) sys.exit(0)
except RpcGenError, e: except RpcGenError, e:
print >>sys.stderr, e print >>sys.stderr, e
sys.exit(1) sys.exit(1)
except EnvironmentError, e:
if e.filename and e.strerror:
print >>sys.stderr, "%s: %s" % (e.filename, e.strerror)
sys.exit(1)
elif e.strerror:
print >> sys.stderr, e.strerror
sys.exit(1)
else:
raise