From ed283042ae8da1f35e623dd02da1d4dbcc3647f6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 9 Jan 2014 14:59:13 +0000 Subject: [PATCH] rxgen: Extract C synchronous RPC func emitter Extract the code to emit C functions to perform synchronous RPC calls from the main rxgen script and put into its own module. Signed-off-by: David Howells --- rxgen/emit_c_sync_funcs.pm | 195 +++++++++++++++++++++++++++++++ rxgen/rxgen.pl | 229 ++----------------------------------- 2 files changed, 204 insertions(+), 220 deletions(-) create mode 100644 rxgen/emit_c_sync_funcs.pm diff --git a/rxgen/emit_c_sync_funcs.pm b/rxgen/emit_c_sync_funcs.pm new file mode 100644 index 0000000..aaa939f --- /dev/null +++ b/rxgen/emit_c_sync_funcs.pm @@ -0,0 +1,195 @@ +# +# Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. +# Written by David Howells (dhowells@redhat.com) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public Licence +# as published by the Free Software Foundation; either version +# 2 of the Licence, or (at your option) any later version. +# + +############################################################################### +# +# Emit a function to encode a request +# +############################################################################### +sub emit_func_enc_request($$$$$@) +{ + my ($func, $op, $request_size, $req_has_charptr, $reply_size, @request) = @_; + + # Function definition and arguments + print RXOUT "int rxgen_send_request_", $func, "(\n"; + print RXOUT "\tstruct rx_connection *z_conn,\n"; + print RXOUT "\tstruct rx_call *call"; + foreach my $p (@request) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + print RXOUT ",\n\t"; + print RXOUT "const " if ($type =~ "[*]"); + print RXOUT "$type $name"; + die "Array arg not supported '$name'" if ($array_size != -1); + } + print RXOUT ")\n"; + + # Function body, beginning with local variables + print RXOUT "{\n"; + if ($req_has_charptr) { + print RXOUT "\tnet_xdr_t request[", $request_size / 4, " + 1], *xdr;\n"; + print RXOUT "\tuint32_t tmp;\n"; + } else { + print RXOUT "\tnet_xdr_t request[", $request_size / 4, "], *xdr;\n"; + } + + # Marshal the data + print RXOUT "\n"; + print RXOUT "\txdr = request;\n"; + print RXOUT "\t*xdr++ = htonl($op);\n"; + foreach my $p (@request) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + if ($type eq "uint8_t" || + $type eq "uint16_t" || + $type eq "uint32_t") { + print RXOUT "\t*xdr++ = htonl($name);\n"; + } elsif ($type eq "char*") { + print RXOUT "\ttmp = strlen($name);\n"; + print RXOUT "\t*xdr++ = htonl(tmp);\n"; + print RXOUT "\txdr[tmp / 4] = 0;\n"; + print RXOUT "\tmemcpy(xdr, $name, tmp);\n"; + print RXOUT "\txdr += (tmp + 3) / 4;\n"; + } elsif ($type =~ /struct ([a-zA-Z_][a-zA-Z0-9_]*)[*]/) { + print RXOUT "\txdr = rxgen_encode_$1(xdr, $name);\n"; + } + } + + # Send the message + print RXOUT "\n"; + print RXOUT "\treturn rxrpc_send_request(z_conn, call, request, (xdr - request) * 4, $reply_size);\n"; + print RXOUT "}\n"; +} + +############################################################################### +# +# Emit a function to decode a reply +# +############################################################################### +sub emit_func_dec_reply($$$@) +{ + my ($func, $op, $reply_size, @reply) = @_; + + print RXOUT "\n"; + + # Function definition and arguments + print RXOUT "void rxgen_decode_reply_", $func, "(\n"; + print RXOUT "\tstruct rx_connection *z_conn,\n"; + print RXOUT "\tstruct rx_call *call"; + foreach my $p (@reply) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + print RXOUT ",\n\t"; + print RXOUT "$type $name"; + die "Array arg not supported '$name'" if ($array_size != -1); + } + print RXOUT ")\n"; + + # Function body, beginning with local variables + print RXOUT "{\n"; + print RXOUT "\tconst net_xdr_t *xdr;\n"; + + # Unmarshal the data + print RXOUT "\n"; + print RXOUT "\txdr = call->reply;\n"; + foreach my $p (@reply) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + if ($type eq "int8_t*" || + $type eq "int16_t*" || + $type eq "int32_t*" || + $type eq "uint8_t*" || + $type eq "uint16_t*" || + $type eq "uint32_t*") { + print RXOUT "\t*$name = ntohl(*xdr++);\n"; + } elsif ($type eq "int64_t*" || + $type eq "uint64_t*") { + print RXOUT "\t*$name = (uint64_t)ntohl(*xdr++) << 32\n"; + print RXOUT "\t\t | (uint64_t)ntohl(*xdr++);\n"; + } elsif ($type =~ /struct ([a-zA-Z_][a-zA-Z0-9_]*)[*]/) { + print RXOUT "\txdr = rxgen_decode_$1($name, xdr);\n"; + } + } + + print RXOUT "}\n"; +} + +############################################################################### +# +# Emit a function to make a simple synchronous call +# +############################################################################### +sub emit_func_simple_sync_call($$$$$@) +{ + my ($func, $request_size, $reply_size, $_request, $_reply, @params) = @_; + my @request = @{$_request}; + my @reply = @{$_reply}; + + print RXOUT "\n"; + + # Function definition and arguments + print RXOUT "int ", $func, "(\n"; + print RXOUT "\tstruct rx_connection *z_conn"; + foreach my $p (@params) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + print RXOUT ",\n\t"; + print RXOUT "const " if ($type =~ "[*]" && $dir eq "IN"); + print RXOUT "$type $name"; + die "Array arg not supported '$name'" if ($array_size != -1); + } + print RXOUT ")\n"; + + # Function body, beginning with local variables + print RXOUT "{\n"; + print RXOUT "\tstruct rx_call *call;\n"; + print RXOUT "\tint ret;\n"; + print RXOUT "\n"; + + # Allocate a call record and reply buffer + print RXOUT "\tcall = malloc(sizeof(*call) + $reply_size);\n"; + print RXOUT "\tif (!call)\n"; + print RXOUT "\t\treturn -1;\n"; + print RXOUT "\tcall->reply = (void *)call + sizeof(*call);\n"; + print RXOUT "\n"; + + # Send the request + print RXOUT "\tret = rxgen_send_request_", $func, "("; + print RXOUT "z_conn, call"; + foreach my $p (@request) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + print RXOUT ", $name"; + } + print RXOUT ");\n"; + print RXOUT "\tif (ret != 0) {\n"; + print RXOUT "\t\tfree(call);\n"; + print RXOUT "\t\treturn ret;\n"; + print RXOUT "\t}\n"; + + # Wait for the reply + print RXOUT "\tret = rxrpc_wait_for_sync_reply(z_conn, call);\n"; + print RXOUT "\tif (ret != 0) {\n"; + print RXOUT "\t\tfree(call);\n"; + print RXOUT "\t\treturn ret;\n"; + print RXOUT "\t}\n"; + print RXOUT "\n"; + + # Unmarshal the reply + if (@reply) { + print RXOUT "\trxgen_decode_reply_", $func, "("; + print RXOUT "z_conn, call"; + foreach my $p (@reply) { + my ($type, $name, $array_size, $max_size, $dir) = @{$p}; + print RXOUT ", $name"; + } + print RXOUT ");\n"; + } + + print RXOUT "\n"; + print RXOUT "\treturn 0;\n"; + print RXOUT "}\n"; +} + +1; diff --git a/rxgen/rxgen.pl b/rxgen/rxgen.pl index 22238e4..0d73803 100755 --- a/rxgen/rxgen.pl +++ b/rxgen/rxgen.pl @@ -19,6 +19,7 @@ use strict; use lib "rxgen"; use emit_c_struct; +use emit_c_sync_funcs; use emit_py_types; use emit_py_sync_funcs; use emit_py_module; @@ -166,41 +167,11 @@ while (my $line = <>) { } -#print "----------------------------------------\n"; - -#foreach $_ (sort keys %constants) { -# print $_, " -> (", $constants{$_}, ")\n"; -#} - -# foreach $_ (keys %structs) { -# print "-- ", $_, " --\n"; -# my $p = $structs{$_}; -# print $#{$p}, "\n"; -# my @members = @{$p}; -# shift @members; -# foreach my $m (@members) { -# if (@{$m}[2] eq -1) { -# print @{$m}[1], " IS ", @{$m}[0], "\n"; -# } else { -# print @{$m}[1], " IS ", @{$m}[0], "[", @{$m}[2], "]\n"; -# } -# } -# } - -# foreach $_ (keys %funcs) { -# print "-- ", $_, " --\n"; -# my $p = $funcs{$_}; -# my @members = @{$p}; -# shift @members; -# foreach my $m (@members) { -# if (@{$m}[2] eq -1) { -# print "\t", @{$m}[1], " IS ", @{$m}[0], "\n"; -# } else { -# print "\t", @{$m}[1], " IS ", @{$m}[0], "[", @{$m}[2], "]\n"; -# } -# } -# } - +############################################################################### +# +# Create the output files and emit the file prologues. +# +############################################################################### open RXOUT, ">afs_xg.c" || die "afs_xg.c"; print RXOUT "/* AUTOGENERATED */\n"; print RXOUT "#define _XOPEN_SOURCE\n"; @@ -232,6 +203,7 @@ print PYOUT "#include \"afs_py.h\"\n"; print PYOUT "#include \n"; print PYOUT "#include \"py_rxgen.h\"\n"; +# Declare types foreach my $s (@structs) { my @members = @{$s}; my $struct = shift @members; @@ -241,191 +213,8 @@ foreach my $s (@structs) { ############################################################################### # -# Emit a function to encode a request -# -############################################################################### -sub emit_func_enc_request($$$$$@) -{ - my ($func, $op, $request_size, $req_has_charptr, $reply_size, @request) = @_; - - # Function definition and arguments - print RXOUT "int rxgen_send_request_", $func, "(\n"; - print RXOUT "\tstruct rx_connection *z_conn,\n"; - print RXOUT "\tstruct rx_call *call"; - foreach my $p (@request) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - print RXOUT ",\n\t"; - print RXOUT "const " if ($type =~ "[*]"); - print RXOUT "$type $name"; - die "Array arg not supported '$name'" if ($array_size != -1); - } - print RXOUT ")\n"; - - # Function body, beginning with local variables - print RXOUT "{\n"; - if ($req_has_charptr) { - print RXOUT "\tnet_xdr_t request[", $request_size / 4, " + 1], *xdr;\n"; - print RXOUT "\tuint32_t tmp;\n"; - } else { - print RXOUT "\tnet_xdr_t request[", $request_size / 4, "], *xdr;\n"; - } - - # Marshal the data - print RXOUT "\n"; - print RXOUT "\txdr = request;\n"; - print RXOUT "\t*xdr++ = htonl($op);\n"; - foreach my $p (@request) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - if ($type eq "uint8_t" || - $type eq "uint16_t" || - $type eq "uint32_t") { - print RXOUT "\t*xdr++ = htonl($name);\n"; - } elsif ($type eq "char*") { - print RXOUT "\ttmp = strlen($name);\n"; - print RXOUT "\t*xdr++ = htonl(tmp);\n"; - print RXOUT "\txdr[tmp / 4] = 0;\n"; - print RXOUT "\tmemcpy(xdr, $name, tmp);\n"; - print RXOUT "\txdr += (tmp + 3) / 4;\n"; - } elsif ($type =~ /struct ([a-zA-Z_][a-zA-Z0-9_]*)[*]/) { - print RXOUT "\txdr = rxgen_encode_$1(xdr, $name);\n"; - } - } - - # Send the message - print RXOUT "\n"; - print RXOUT "\treturn rxrpc_send_request(z_conn, call, request, (xdr - request) * 4, $reply_size);\n"; - print RXOUT "}\n"; -} - -############################################################################### -# -# Emit a function to decode a reply -# -############################################################################### -sub emit_func_dec_reply($$$@) -{ - my ($func, $op, $reply_size, @reply) = @_; - - print RXOUT "\n"; - - # Function definition and arguments - print RXOUT "void rxgen_decode_reply_", $func, "(\n"; - print RXOUT "\tstruct rx_connection *z_conn,\n"; - print RXOUT "\tstruct rx_call *call"; - foreach my $p (@reply) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - print RXOUT ",\n\t"; - print RXOUT "$type $name"; - die "Array arg not supported '$name'" if ($array_size != -1); - } - print RXOUT ")\n"; - - # Function body, beginning with local variables - print RXOUT "{\n"; - print RXOUT "\tconst net_xdr_t *xdr;\n"; - - # Unmarshal the data - print RXOUT "\n"; - print RXOUT "\txdr = call->reply;\n"; - foreach my $p (@reply) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - if ($type eq "int8_t*" || - $type eq "int16_t*" || - $type eq "int32_t*" || - $type eq "uint8_t*" || - $type eq "uint16_t*" || - $type eq "uint32_t*") { - print RXOUT "\t*$name = ntohl(*xdr++);\n"; - } elsif ($type eq "int64_t*" || - $type eq "uint64_t*") { - print RXOUT "\t*$name = (uint64_t)ntohl(*xdr++) << 32\n"; - print RXOUT "\t\t | (uint64_t)ntohl(*xdr++);\n"; - } elsif ($type =~ /struct ([a-zA-Z_][a-zA-Z0-9_]*)[*]/) { - print RXOUT "\txdr = rxgen_decode_$1($name, xdr);\n"; - } - } - - print RXOUT "}\n"; -} - -############################################################################### -# -# Emit a function to make a simple synchronous call -# -############################################################################### -sub emit_func_simple_sync_call($$$$$@) -{ - my ($func, $request_size, $reply_size, $_request, $_reply, @params) = @_; - my @request = @{$_request}; - my @reply = @{$_reply}; - - print RXOUT "\n"; - - # Function definition and arguments - print RXOUT "int ", $func, "(\n"; - print RXOUT "\tstruct rx_connection *z_conn"; - foreach my $p (@params) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - print RXOUT ",\n\t"; - print RXOUT "const " if ($type =~ "[*]" && $dir eq "IN"); - print RXOUT "$type $name"; - die "Array arg not supported '$name'" if ($array_size != -1); - } - print RXOUT ")\n"; - - # Function body, beginning with local variables - print RXOUT "{\n"; - print RXOUT "\tstruct rx_call *call;\n"; - print RXOUT "\tint ret;\n"; - print RXOUT "\n"; - - # Allocate a call record and reply buffer - print RXOUT "\tcall = malloc(sizeof(*call) + $reply_size);\n"; - print RXOUT "\tif (!call)\n"; - print RXOUT "\t\treturn -1;\n"; - print RXOUT "\tcall->reply = (void *)call + sizeof(*call);\n"; - print RXOUT "\n"; - - # Send the request - print RXOUT "\tret = rxgen_send_request_", $func, "("; - print RXOUT "z_conn, call"; - foreach my $p (@request) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - print RXOUT ", $name"; - } - print RXOUT ");\n"; - print RXOUT "\tif (ret != 0) {\n"; - print RXOUT "\t\tfree(call);\n"; - print RXOUT "\t\treturn ret;\n"; - print RXOUT "\t}\n"; - - # Wait for the reply - print RXOUT "\tret = rxrpc_wait_for_sync_reply(z_conn, call);\n"; - print RXOUT "\tif (ret != 0) {\n"; - print RXOUT "\t\tfree(call);\n"; - print RXOUT "\t\treturn ret;\n"; - print RXOUT "\t}\n"; - print RXOUT "\n"; - - # Unmarshal the reply - if (@reply) { - print RXOUT "\trxgen_decode_reply_", $func, "("; - print RXOUT "z_conn, call"; - foreach my $p (@reply) { - my ($type, $name, $array_size, $max_size, $dir) = @{$p}; - print RXOUT ", $name"; - } - print RXOUT ");\n"; - } - - print RXOUT "\n"; - print RXOUT "\treturn 0;\n"; - print RXOUT "}\n"; -} - -############################################################################### -# -# Dump RPC call encoders and decoders +# Emit RPC call functions. For this we need to classify parameters according +# to input and output usage and work out how big the RPC messages will be. # ############################################################################### foreach $func (sort keys %funcs) { -- 2.49.0