--- /dev/null
+#
+# 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;
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;
}
-#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";
print PYOUT "#include <arpa/inet.h>\n";
print PYOUT "#include \"py_rxgen.h\"\n";
+# Declare types
foreach my $s (@structs) {
my @members = @{$s};
my $struct = shift @members;
###############################################################################
#
-# 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) {