2007-06-11 15:47:01 +04:00
#!/usr/bin/perl -w
#
# This script parses remote_protocol.x and produces lots of boilerplate
# code for both ends of the remote connection.
#
# By Richard Jones <rjones@redhat.com>
use strict ;
use Getopt::Std ;
# Command line options.
2008-12-05 01:03:24 +03:00
our ( $ opt_p , $ opt_t , $ opt_a , $ opt_r , $ opt_d ) ;
getopts ( 'ptard' ) ;
2007-06-11 15:47:01 +04:00
# Convert name_of_call to NameOfCall.
sub name_to_ProcName {
my $ name = shift ;
my @ elems = split /_/ , $ name ;
@ elems = map ucfirst , @ elems ;
join "" , @ elems
}
# Read the input file (usually remote_protocol.x) and form an
# opinion about the name, args and return type of each RPC.
2008-12-05 01:03:24 +03:00
my ( $ name , $ ProcName , $ id , % calls , @ calls ) ;
# REMOTE_PROC_CLOSE has no args or ret.
$ calls { close } = {
name = > "close" ,
ProcName = > "Close" ,
UC_NAME = > "CLOSE" ,
args = > "void" ,
ret = > "void" ,
} ;
2007-06-11 15:47:01 +04:00
while ( < > ) {
if ( /^struct remote_(.*)_args/ ) {
$ name = $ 1 ;
$ ProcName = name_to_ProcName ( $ name ) ;
die "duplicate definition of remote_${name}_args"
if exists $ calls { $ name } ;
$ calls { $ name } = {
name = > $ name ,
ProcName = > $ ProcName ,
UC_NAME = > uc $ name ,
args = > "remote_${name}_args" ,
ret = > "void" ,
} ;
} elsif ( /^struct remote_(.*)_ret/ ) {
$ name = $ 1 ;
$ ProcName = name_to_ProcName ( $ name ) ;
if ( exists $ calls { $ name } ) {
$ calls { $ name } - > { ret } = "remote_${name}_ret" ;
} else {
$ calls { $ name } = {
name = > $ name ,
ProcName = > $ ProcName ,
UC_NAME = > uc $ name ,
args = > "void" ,
ret = > "remote_${name}_ret"
}
}
2009-07-10 15:38:41 +04:00
} elsif ( /^struct remote_(.*)_msg/ ) {
$ name = $ 1 ;
$ ProcName = name_to_ProcName ( $ name ) ;
$ calls { $ name } = {
name = > $ name ,
ProcName = > $ ProcName ,
UC_NAME = > uc $ name ,
msg = > "remote_${name}_msg"
}
2008-12-05 01:03:24 +03:00
} elsif ( /^\s*REMOTE_PROC_(.*?)\s+=\s+(\d+),?$/ ) {
$ name = lc $ 1 ;
$ id = $ 2 ;
$ ProcName = name_to_ProcName ( $ name ) ;
$ calls [ $ id ] = $ calls { $ name } ;
2007-06-11 15:47:01 +04:00
}
}
#----------------------------------------------------------------------
# Output
print << __EOF__ ;
/ * Automatically generated by remote_generate_stubs . pl .
* Do not edit this file . Any changes you make will be lost .
* /
__EOF__
# Debugging.
if ( $ opt_d ) {
my @ keys = sort ( keys % calls ) ;
foreach ( @ keys ) {
print "$_:\n" ;
2008-05-22 19:20:25 +04:00
print " name $calls{$_}->{name} ($calls{$_}->{ProcName})\n" ;
print " $calls{$_}->{args} -> $calls{$_}->{ret}\n" ;
2007-06-11 15:47:01 +04:00
}
}
# Prototypes for dispatch functions ("remote_dispatch_prototypes.h").
2008-12-05 01:03:24 +03:00
elsif ( $ opt_p ) {
2007-06-11 15:47:01 +04:00
my @ keys = sort ( keys % calls ) ;
foreach ( @ keys ) {
2009-07-10 15:38:41 +04:00
# Skip things which are REMOTE_MESSAGE
next if $ calls { $ _ } - > { msg } ;
2008-12-05 01:16:40 +03:00
print "static int remoteDispatch$calls{$_}->{ProcName}(\n" ;
print " struct qemud_server *server,\n" ;
print " struct qemud_client *client,\n" ;
print " virConnectPtr conn,\n" ;
print " remote_error *err,\n" ;
print " $calls{$_}->{args} *args,\n" ;
print " $calls{$_}->{ret} *ret);\n" ;
2007-06-11 15:47:01 +04:00
}
}
2008-12-05 01:03:24 +03:00
# Union of all arg types
# ("remote_dispatch_args.h").
elsif ( $ opt_a ) {
for ( $ id = 0 ; $ id <= $# calls ; $ id + + ) {
if ( defined $ calls [ $ id ] &&
2009-07-10 15:38:41 +04:00
! $ calls [ $ id ] - > { msg } &&
2008-12-05 01:03:24 +03:00
$ calls [ $ id ] - > { args } ne "void" ) {
print " $calls[$id]->{args} val_$calls[$id]->{args};\n" ;
2007-06-11 15:47:01 +04:00
}
}
}
2008-12-05 01:03:24 +03:00
# Union of all arg types
# ("remote_dispatch_ret.h").
elsif ( $ opt_r ) {
for ( $ id = 0 ; $ id <= $# calls ; $ id + + ) {
if ( defined $ calls [ $ id ] &&
2009-07-10 15:38:41 +04:00
! $ calls [ $ id ] - > { msg } &&
2008-12-05 01:03:24 +03:00
$ calls [ $ id ] - > { ret } ne "void" ) {
print " $calls[$id]->{ret} val_$calls[$id]->{ret};\n" ;
2007-06-11 15:47:01 +04:00
}
}
}
2008-12-05 01:03:24 +03:00
# Inside the switch statement, prepare the 'fn', 'args_filter', etc
# ("remote_dispatch_table.h").
elsif ( $ opt_t ) {
for ( $ id = 0 ; $ id <= $# calls ; $ id + + ) {
2009-07-10 15:38:41 +04:00
if ( defined $ calls [ $ id ] && ! $ calls [ $ id ] - > { msg } ) {
2008-12-05 01:03:24 +03:00
print "{ /* $calls[$id]->{ProcName} => $id */\n" ;
print " .fn = (dispatch_fn) remoteDispatch$calls[$id]->{ProcName},\n" ;
if ( $ calls [ $ id ] - > { args } ne "void" ) {
print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n" ;
} else {
print " .args_filter = (xdrproc_t) xdr_void,\n" ;
}
if ( $ calls [ $ id ] - > { ret } ne "void" ) {
print " .ret_filter = (xdrproc_t) xdr_$calls[$id]->{ret},\n" ;
} else {
print " .ret_filter = (xdrproc_t) xdr_void,\n" ;
}
print "},\n" ;
2007-06-11 15:47:01 +04:00
} else {
2009-07-10 15:38:41 +04:00
if ( $ calls [ $ id ] - > { msg } ) {
print "{ /* Async event $calls[$id]->{ProcName} => $id */\n" ;
} else {
print "{ /* (unused) => $id */\n" ;
}
2008-12-05 01:03:24 +03:00
print " .fn = NULL,\n" ;
print " .args_filter = (xdrproc_t) xdr_void,\n" ;
print " .ret_filter = (xdrproc_t) xdr_void,\n" ;
print "},\n" ;
2007-06-11 15:47:01 +04:00
}
}
}