From 64000eabedf2a964cc46db41d4903997b86af0ee Mon Sep 17 00:00:00 2001 From: Matthias Bolte Date: Wed, 15 Jun 2011 15:38:31 +0200 Subject: [PATCH] remote generator: Handle struct returning functions better The position of the struct parameter in the function signature differs. Instead of hardcoding the handling for this add an annotation to the .x file to define the position. --- daemon/remote_generator.pl | 42 ++++++++++++++++++++---------------- src/remote/remote_protocol.x | 23 ++++++++++++-------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl index ce35ebe5f5..351866b4cb 100755 --- a/daemon/remote_generator.pl +++ b/daemon/remote_generator.pl @@ -95,8 +95,9 @@ while () { $collect_args_members = 1; $collect_ret_members = 0; $last_name = $name; - } elsif (/^struct ${structprefix}_(.*)_ret/) { + } elsif (/^struct ${structprefix}_(.*)_ret\s+{(.*)$/) { $name = $1; + $flags = $2; $ProcName = name_to_ProcName ($name); if (exists $calls{$name}) { @@ -112,6 +113,14 @@ while () { } } + if ($flags ne "" and ($opt_b or $opt_k)) { + if (!($flags =~ m/^\s*\/\*\s*insert@(\d+)\s*\*\/\s*$/)) { + die "invalid generator flags for $calls{$name}->{ret}"; + } + + $calls{$name}->{ret_offset} = int($1); + } + $collect_args_members = 0; $collect_ret_members = 1; $last_name = $name; @@ -668,29 +677,26 @@ elsif ($opt_b) { # select struct type for multi-return-value functions if ($multi_ret) { - if (! @args_list) { + if (!(defined $call->{ret_offset})) { + die "multi-return-value without insert@ annotation: $call->{ret}"; + } + + if (!@args_list) { push(@args_list, "conn"); } my $struct_name = $call->{ProcName}; $struct_name =~ s/Get//; - if ($call->{ProcName} eq "DomainGetBlockInfo") { - # SPECIAL: virDomainGetBlockInfo has flags parameter after - # the struct parameter in its signature - my $flags = pop(@args_list); - push(@args_list, "&tmp"); - push(@args_list, $flags); - } elsif ($call->{ProcName} eq "DomainBlockStats" || - $call->{ProcName} eq "DomainInterfaceStats") { + splice(@args_list, $call->{ret_offset}, 0, ("&tmp")); + + if ($call->{ProcName} eq "DomainBlockStats" || + $call->{ProcName} eq "DomainInterfaceStats") { # SPECIAL: virDomainBlockStats and virDomainInterfaceStats # have a 'Struct' suffix on the actual struct name # and take the struct size as additional argument $struct_name .= "Struct"; - push(@args_list, "&tmp"); - push(@args_list, "sizeof tmp"); - } else { - push(@args_list, "&tmp"); + splice(@args_list, $call->{ret_offset} + 1, 0, ("sizeof tmp")); } push(@vars_list, "vir$struct_name tmp"); @@ -1012,14 +1018,14 @@ elsif ($opt_k) { " xdr_free((xdrproc_t)xdr_$call->{args}, (char *)&args);\n" . " goto done;\n" . " }"); - } elsif ($args_member =~ m/^(unsigned )?int (\S+);\s*\/\*\s*call-by-reference\s*\*\//) { - my $type_name = $1; $type_name .= "int *"; + } elsif ($args_member =~ m/^((?:unsigned )?int) (\S+);\s*\/\*\s*call-by-reference\s*\*\//) { + my $type_name = "$1 *"; my $arg_name = $2; push(@args_list, "$type_name $arg_name"); push(@setters_list, "args.$arg_name = *$arg_name;"); - } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) { - my $type_name = $1; $type_name .= "int"; + } elsif ($args_member =~ m/^((?:unsigned )?int) (\S+);/) { + my $type_name = $1; my $arg_name = $2; push(@args_list, "$type_name $arg_name"); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 0dd8b09aff..2b9784ba3c 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -352,7 +352,12 @@ struct remote_node_get_memory_stats { * * 'remote_CALL_ret' members that are filled via call-by-reference must be * annotated with a insert@ comment to indicate the offset in the - * parameter list of the function to be called. */ + * parameter list of the function to be called. + * + * If the 'remote_CALL_ret' maps to a struct in the public API then it is + * also filled via call-by-reference and must be annotated with a + * insert@ comment to indicate the offset in the parameter list of + * the function to be called. */ struct remote_open_args { /* NB. "name" might be NULL although in practice you can't @@ -409,7 +414,7 @@ struct remote_get_max_vcpus_ret { int max_vcpus; }; -struct remote_node_get_info_ret { +struct remote_node_get_info_ret { /* insert@1 */ char model[32]; unsigned hyper memory; int cpus; @@ -537,7 +542,7 @@ struct remote_domain_block_stats_args { remote_nonnull_string path; }; -struct remote_domain_block_stats_ret { +struct remote_domain_block_stats_ret { /* insert@2 */ hyper rd_req; hyper rd_bytes; hyper wr_req; @@ -550,7 +555,7 @@ struct remote_domain_interface_stats_args { remote_nonnull_string path; }; -struct remote_domain_interface_stats_ret { +struct remote_domain_interface_stats_ret { /* insert@2 */ hyper rx_bytes; hyper rx_packets; hyper rx_errs; @@ -605,7 +610,7 @@ struct remote_domain_get_block_info_args { unsigned int flags; }; -struct remote_domain_get_block_info_ret { +struct remote_domain_get_block_info_ret { /* insert@2 */ unsigned hyper allocation; unsigned hyper capacity; unsigned hyper physical; @@ -713,7 +718,7 @@ struct remote_domain_get_info_args { remote_nonnull_domain dom; }; -struct remote_domain_get_info_ret { +struct remote_domain_get_info_ret { /* insert@1 */ unsigned char state; unsigned hyper maxMem; unsigned hyper memory; @@ -1400,7 +1405,7 @@ struct remote_storage_pool_get_info_args { remote_nonnull_storage_pool pool; }; -struct remote_storage_pool_get_info_ret { +struct remote_storage_pool_get_info_ret { /* insert@1 */ unsigned char state; unsigned hyper capacity; unsigned hyper allocation; @@ -1510,7 +1515,7 @@ struct remote_storage_vol_get_info_args { remote_nonnull_storage_vol vol; }; -struct remote_storage_vol_get_info_ret { +struct remote_storage_vol_get_info_ret { /* insert@1 */ char type; unsigned hyper capacity; unsigned hyper allocation; @@ -1827,7 +1832,7 @@ struct remote_domain_get_job_info_args { remote_nonnull_domain dom; }; -struct remote_domain_get_job_info_ret { +struct remote_domain_get_job_info_ret { /* insert@1 */ int type; unsigned hyper timeElapsed;