+++ /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 structure encoders and decoders predeclarations
-#
-###############################################################################
-sub emit_struct_encdec_decls ($) {
- my ($struct) = @_;
-
- print RXOUT "/* ", $struct->{type}, " XDR size ", $struct->{xdr_size}, " */\n"
-}
-
-###############################################################################
-#
-# Emit structure encoders and decoders
-#
-###############################################################################
-sub emit_struct_encdec ($) {
- my ($struct) = @_;
-
- # Write out a C structure definition for this type
- print RXHDR "struct ", $struct->{type}, " {\n";
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "basic") {
- print RXHDR "\t", $m->{type}, "\t", $m->{name};
- } elsif ($m->{class} eq "struct") {
- print RXHDR "\tstruct ", $m->{type}, "\t", $m->{name};
- } elsif ($m->{class} eq "array") {
- if ($m->{elem}->{class} eq "basic") {
- print RXHDR "\t", $m->{elem}->{type}, "\t", $m->{name}, "[", $m->{dim}, "]";
- } else {
- print RXHDR "\tstruct ", $m->{elem}->{type}, "\t", $m->{name}, "[", $m->{dim}, "]";
- }
- } else {
- die $m->{where}, ": Unsupported type class '", $m->{class}, "'\n";
- }
- print RXHDR ";\n";
- }
- print RXHDR "};\n";
-
- # Write an encoding function
- print RXHDR "extern void rxgen_encode_", $struct->{type}, "(struct rx_call *call, const struct ", $struct->{type}, " *p);\n";
-
- print RXOUT "void rxgen_encode_", $struct->{type}, "(struct rx_call *call, const struct ", $struct->{type}, " *p)\n";
- print RXOUT "{\n";
-
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "array") {
- print RXOUT "\tint i;\n\n";
- last;
- }
- }
-
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "basic") {
- if ($m->{type} !~ /64/) {
- print RXOUT "\trxrpc_enc(call, p->", $m->{name}, ");\n";
- } else {
- die $m->{where}, ": No encoding for type '", $m->{type}, "'";
- }
- } elsif ($m->{class} eq "struct") {
- print RXOUT "\trxgen_encode_", $m->{type}, "(call, &p->", $m->{name}, ");\n";
- } elsif ($m->{class} eq "array") {
- print RXOUT "\tfor (i = 0; i < ", $m->{dim}, "; i++)\n";
- if ($m->{elem}->{class} eq "basic" && $m->{elem}->{type} !~ /64/) {
- print RXOUT "\t\trxrpc_enc(call, p->", $m->{name}, "[i]);\n";
- } elsif ($m->{elem}->{class} eq "struct") {
- print RXOUT "\t\trxgen_encode_", $m->{elem}->{type},
- "(call, &p->", $m->{name}, "[i]);\n";
- } else {
- die $m->{where}, ": No encoding for array type '", $m->{elem}->{type}, "'";
- }
- } else {
- die $m->{where}, "No encoding for type class '$class'";
- }
- }
-
- print RXOUT "}\n";
- print RXOUT "\n";
-
- # Write a decoding function
- print RXHDR "extern void rxgen_decode_", $struct->{type}, "(struct rx_call *call, struct ", $struct->{type}, " *p);\n";
-
- print RXOUT "void rxgen_decode_", $struct->{type}, "(struct rx_call *call, struct ", $struct->{type}, " *p)\n";
- print RXOUT "{\n";
-
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "array") {
- print RXOUT "\tint i;\n\n";
- last;
- }
- }
-
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "basic") {
- if ($m->{type} !~ /64/) {
- print RXOUT "\tp->", $m->{name}, " = rxrpc_dec(call);\n";
- } else {
- die $m->{where}, "No decoding for type '$type'";
- }
- } elsif ($m->{class} eq "struct") {
- print RXOUT "\trxgen_decode_", $m->{type}, "(call, &p->", $m->{name}, ");\n";
- } elsif ($m->{class} eq "array") {
- print RXOUT "\tfor (i = 0; i < ", $m->{dim}, "; i++)\n";
- if ($m->{elem}->{class} eq "basic" && $m->{elem}->{type} !~ /64/) {
- print RXOUT "\t\tp->", $m->{name}, "[i] = rxrpc_dec(call);\n";
- } elsif ($m->{elem}->{class} eq "struct") {
- print RXOUT "\t\trxgen_decode_", $m->{elem}->{type}, "(call, &p->", $m->{name}, "[i]);\n";
- } else {
- die $m->{where}, "No decoding for array type '$type'";
- }
- } else {
- die $m->{where}, "No decoding for type class '$class'";
- }
- }
-
- print RXOUT "}\n";
-}
-
-1;
+++ /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.
-#
-
-###############################################################################
-#
-# Calculate the C function prototypes
-#
-###############################################################################
-sub emit_func_prototype($)
-{
- my ($func) = @_;
-
- # Function prototype lists (we add commas and the closing bracket later)
- my @protos = ( "int " . $func->{name} . "(\n" );
- my @send_request_protos = ();
- my @send_response_protos = ();
- my @recv_request_protos = ();
- my @recv_response_protos = ();
-
- # Arguments to pass when sending a call or processing a reply
- my @send_args = ();
- my @recv_args = ();
-
- foreach my $p (@{$func->{params}}) {
- my @enclines = ();
- my @declines = ();
-
- if ($p->{class} eq "array") {
- die $p->{where}, ": Array arg not supported";
- } elsif ($p->{class} eq "bulk") {
- # Encode
- if ($p->{elem}->{class} eq "struct") {
- $proto = "int (*get__" . $p->{name} . ")(struct rx_call *call, void *token)";
- } else {
- $proto = "int (*get__" . $p->{name} . ")(struct rx_call *call, void *token)";
- }
- push @enclines, $proto;
- push @enclines, "void *token__" . $p->{name};
- push @enclines, "size_t nr__" . $p->{name};
- push @args, "get__" . $p->{name};
- push @args, "token__" . $p->{name};
- push @args, "nr__" . $p->{name};
-
- # Decode
- if ($p->{elem}->{class} eq "struct") {
- $proto = "int (*alloc__" . $p->{name} . ")(struct rx_call *call, void **token)";
- push @args, "alloc__" . $p->{name};
- } else {
- $proto = "int (*store__" . $p->{name} . ")(struct rx_call *call, void **token)";
- push @args, "store__" . $p->{name};
- }
- push @declines, $proto;
- push @declines, "void *token__" . $p->{name};
- push @declines, "size_t nr__" . $p->{name};
- push @args, "token__" . $p->{name};
- } elsif ($p->{class} eq "blob") {
- $proto = $p->{type} . " " . $p->{ptr} . $p->{name};
- push @enclines, "size_t nr__" . $p->{name};
- push @enclines, "const " . $proto;
-
- push @declines, "size_t nr__" . $p->{name};
- push @declines, "void *token__" . $p->{name};
- push @declines, "int (*alloc__" . $p->{name} . ")(struct rx_call *call, void **token)";
- push @args, "nr__" . $p->{name};
- push @args, $p->{name};
- push @args, "alloc__" . $p->{name};
- } else {
- my $enc_const = "";
- $enc_const = "const " if ($p->{class} ne "basic");
- $proto = "";
- $proto .= "struct " if ($p->{class} eq "struct");
- $proto .= $p->{type} . " ";
- $proto .= $p->{ptr} if ($p->{class} ne "basic");
- $proto .= $p->{name};
- push @enclines, $enc_const . $proto;
- push @declines, $proto;
- push @args, $p->{name};
- }
-
- push @send_request_protos, @enclines unless ($p->{dir} eq "OUT");
- push @recv_request_protos, @declines unless ($p->{dir} eq "OUT");
- push @send_response_protos, @enclines unless ($p->{dir} eq "IN");
- push @recv_response_protos, @declines unless ($p->{dir} eq "IN");
- push @send_args, @args unless ($p->{dir} eq "OUT");
- push @recv_args, @args unless ($p->{dir} eq "IN");
- }
-
- print RXHDR "\n";
- print RXHDR "/*\n";
- print RXHDR " * ", $func->{name}, "\n";
- print RXHDR " */\n";
-
- if (@recv_request_protos) {
- print RXHDR "struct ", $func->{name}, "_request {\n";
- foreach my $p (@recv_request_protos) {
- print RXHDR "\t$p;\n";
- }
- print RXHDR "};\n";
- }
-
- print RXHDR "\n";
- if (@recv_response_protos) {
- print RXHDR "struct ", $func->{name}, "_response {\n";
- foreach my $p (@recv_response_protos) {
- print RXHDR "\t$p;\n";
- }
- print RXHDR "};\n";
- }
-
- # # Terminate each line with a comma, excepting the last, which we terminate
- # # with a closing bracket.
- # for (my $i = 1; $i < $#protos; $i++) {
- # $protos[$i] .= ",\n";
- # }
- # $protos[$#protos] .= ")";
-
- # for (my $i = 1; $i < $#send_protos; $i++) {
- # $send_protos[$i] .= ",\n";
- # }
- # $send_protos[$#send_protos] .= ")";
-
- # for (my $i = 1; $i < $#recv_protos; $i++) {
- # $recv_protos[$i] .= ",\n";
- # }
- # $recv_protos[$#recv_protos] .= ")";
-
- $func->{protos} = \@protos;
- $func->{send_request_protos} = \@send_request_protos;
- $func->{recv_request_protos} = \@recv_request_protos;
- $func->{send_response_protos} = \@send_response_protos;
- $func->{recv_response_protos} = \@recv_response_protos;
- $func->{send_args} = \@send_args;
- $func->{recv_args} = \@recv_args;
-}
-
-###############################################################################
-#
-# Emit a function to encode a block in a way that can be used from asynchronous
-# code.
-#
-###############################################################################
-sub emit_func_encode($$$$)
-{
- my ($func, $side, $subname, $paramlist) = @_;
- my @params = @{$paramlist};
- my $ptr;
-
- if ($side eq "client") {
- my %op_id = (
- class => "opcode",
- type => "uint32_t",
- name => $func->{opcode},
- where => $func->{where},
- xdr_size => 4,
- );
- unshift @params, \%op_id;
- $ptr = "call->req.";
- } else {
- $ptr = "call->resp.";
- }
-
- # We marshal the data in a number of phases. Each phase marshals a chunk
- # of data of a certain size. A phase's size might be dependent on a
- # variable in the previous phase. Variable-sized bulk arrays are split
- # across multiple phases, with the length being at the end of the first
- # phase and the data in the second.
- my @phases = ();
- my $phase = 0;
- my $have_bulk = 0;
-
- foreach my $p (@params) {
- unless ($phase) {
- $phase = { type => "flat", size => 0, params => [] };
- push @phases, $phase;
- }
-
- if ($p->{class} eq "opcode" ||
- $p->{class} eq "basic" ||
- $p->{class} eq "struct"
- ) {
- $phase->{size} += $p->{xdr_size};
- push @{$phase->{params}}, $p;
- } elsif ($p->{class} eq "blob") {
- $have_bulk = 2;
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "blob_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "blob",
- name => $p->{name},
- elem => $p->{elem},
- params => [ $p ],
- xdr_size => $p->{xdr_size},
- size => $p->{xdr_size},
- };
- push @phases, $phase;
-
- $phase->{size} = 4;
- $phase = 0;
- } elsif ($p->{class} eq "bulk") {
- $have_bulk = 1 if ($have_bulk == 0);
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "bulk_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "bulk",
- name => $p->{name},
- elem => $p->{elem},
- params => [ $p ],
- xdr_size => $p->{xdr_size},
- size => $p->{xdr_size},
- };
- push @phases, $phase;
-
- # We don't want to be sending one object at a time if they're
- # really small.
- my $n_buf = ($p->{xdr_size} < 1020) ? int(1020 / $p->{xdr_size}) : 1;
- $n_buf *= $p->{xdr_size};
- $phase->{size} = $p->{xdr_size};
- $phase = 0;
- } else {
- die $p->{where}, "Encode array arg not supported";
- }
- }
-
- # Function definition (data gets passed in *call)
- print RXOUT "\n";
- print RXOUT "int ", $func->{name}, "_", $subname, "(\n";
- print RXOUT "\tstruct rx_connection *z_conn,\n";
- print RXOUT "\tstruct ", $func->{name}, "_", $side, "_call *call)\n";
- print RXOUT "{\n";
-
- unless (@params) {
- die if ($side eq "client");
- print RXOUT "\tcall->more_send = 0;\n";
- print RXOUT "\treturn 0;\n";
- print RXOUT "}\n";
- return;
- }
-
- # Local variables
- print RXOUT "\tunsigned phase = call->phase;\n";
-
- # Deal with each phase
- print RXOUT "\n";
- print RXOUT "select_phase:\n" if ($have_bulk);
- print RXOUT "\tswitch (phase) {\n";
-
- print RXOUT "\tcase 0:\n";
- print RXOUT "\t\tcall->more_send = 1;\n";
-
- my $phase_goto_label = 0;
- my $phix;
- for ($phix = 1; $phix <= $#phases + 1; $phix++) {
- $phase = $phases[$phix - 1];
- print RXOUT "\n";
- print RXOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- if ($phase_goto_label == $phix) {
- print RXOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
-
- # Determine how big bulk objects are
- if ($phase->{type} eq "blob") {
- my $p = $phase->{params}->[0];
- print RXOUT "\t\tcall->blob_size = ", $ptr, "nr__", $p->{name}, ";\n";
- print RXOUT "\t\tif (call->blob_size == 0)\n";
- print RXOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- print RXOUT "\t\tcall->blob_offset = 0;\n";
- } elsif ($phase->{type} eq "bulk") {
- my $p = $phase->{params}->[0];
- print RXOUT "\t\tcall->bulk_count = ", $ptr, "nr__", $p->{name}, ";\n";
- print RXOUT "\t\tif (call->bulk_count == 0)\n";
- print RXOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- print RXOUT "\t\tcall->bulk_index = 0;\n";
- }
-
- # Entry point for a phase
- print RXOUT "\t\tcall->phase = ", $phix, ";\n";
- print RXOUT "\tcase ", $phix, ":\n";
-
- # Marshal the data
- foreach my $p (@{$phase->{params}}) {
- if ($p->{type} eq "blob_size") {
- print RXOUT "\t\trxrpc_enc(call, ", $ptr, "nr__", $p->{name}, ");\n";
- $close_phase = 0;
- next;
- } elsif ($p->{type} eq "bulk_size") {
- print RXOUT "\t\trxrpc_enc(call, ", $ptr, "nr__", $p->{name}, ");\n";
- $close_phase = 0;
- next;
- }
-
- if ($p->{class} eq "bulk" && $p->{elem}->{class} eq "basic") {
- if ($p->{elem}->{xdr_size} == 4) {
- print RXOUT "\t\tif (", $ptr, "get__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- } else {
- print RXOUT "\t\tif (", $ptr, "get__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- }
- print RXOUT "\t\t\treturn -1;\n";
-
- if ($p->{elem}->{xdr_size} == 4) {
- print RXOUT "\t\trxrpc_enc(call, call->bulk_u32);\n";
- } elsif ($p->{elem}->{xdr_size} == 8) {
- print RXOUT "\t\trxrpc_enc(call, call->bulk_u64 >> 32)\n";
- print RXOUT "\t\trxrpc_enc(call, (uint32_t)call->bulk_u64)\n";
- } else {
- die;
- }
- print RXOUT "\t\tcall->bulk_index++;\n";
- } elsif ($p->{class} eq "bulk" && $p->{elem}->{class} eq "struct") {
- print RXOUT "\t\tif (", $ptr, "get__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\trxgen_encode_", $p->{type}, "(call, call->bulk_item);\n";
- print RXOUT "\t\tcall->bulk_index++;\n";
- } elsif ($p->{class} eq "bulk" && ($p->{elem}->{class} eq "string" ||
- $p->{elem}->{class} eq "opaque")) {
- print RXOUT "\t\trxrpc_enc_bytes(call, ", $ptr, $p->{name}, ", call);\n";
- print RXOUT "\t\trxrpc_enc_align(call);\n";
- } elsif ($p->{class} eq "opcode") {
- print RXOUT "\t\trxrpc_enc(call, ", $p->{name}, ");\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 4) {
- print RXOUT "\t\trxrpc_enc(call, ", $ptr, $p->{name}, ");\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 8) {
- print RXOUT "\t\trxrpc_enc(call, ", $ptr, $p->{name}, " >> 32);\n";
- print RXOUT "\t\trxrpc_enc(call, (uint32_t)", $ptr, $p->{name}, ");\n";
- } elsif ($p->{class} eq "struct") {
- print RXOUT "\t\trxgen_encode_", $p->{type}, "(call, ", $ptr, $p->{name}, ");\n";
- } else {
- die $p->{where}, ": Unsupported type in decode";
- }
-
- if ($p->{class} eq "blob") {
- print RXOUT "\t\tif (call->blob_offset < call->blob_size) {\n";
- print RXOUT "\t\t\tphase = ", $phix, ";\n";
- print RXOUT "\t\t\tgoto select_phase;\n";
- print RXOUT "\t\t}\n";
- } elsif ($p->{class} eq "bulk") {
- print RXOUT "\t\tif (call->bulk_index < call->bulk_count) {\n";
- print RXOUT "\t\t\tphase = ", $phix, ";\n";
- print RXOUT "\t\t\tgoto select_phase;\n";
- print RXOUT "\t\t}\n";
- }
- }
- }
-
- print RXOUT "\n";
- print RXOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- if ($phase_goto_label == $phix) {
- print RXOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
- print RXOUT "\t\tcall->phase = ", $phix, ";\n";
- print RXOUT "\tcase ", $phix, ":\n";
- print RXOUT "\t\tif (rxrpc_post_enc(call) < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tcall->more_send = 0;\n";
- print RXOUT "\t\tbreak;\n";
- print RXOUT "\t}\n";
-
- print RXOUT "\treturn 0;\n";
- print RXOUT "}\n";
-}
-
-###############################################################################
-#
-# Emit a function to decode a block in a way that can be used from asynchronous
-# code. The opcode is expected to have been removed from the incoming call on
-# the server side.
-#
-###############################################################################
-sub emit_func_decode($$$$)
-{
- my ($func, $side, $subname, $paramlist) = @_;
- my @params = @{$paramlist};
- my $ptr = "obj->";
-
- # We fetch the data in a number of phases. Each phase receives a chunk of
- # data of a certain size. A phase's size might be dependent on a variable
- # in the previous phase. Variable-sized bulk arrays are split across
- # multiple phases, with the length being at the end of the first phase and
- # the data in the second.
- my @phases = ();
- my $phase = 0;
- my $have_bulk = 0;
-
- foreach my $p (@params) {
- unless ($phase) {
- $phase = { type => "flat", size => 0, params => [] };
- push @phases, $phase;
- }
-
- if ($p->{class} eq "basic" ||
- $p->{class} eq "struct"
- ) {
- $phase->{size} += $p->{xdr_size};
- push @{$phase->{params}}, $p;
- } elsif ($p->{class} eq "blob") {
- $have_bulk = 1;
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "blob_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "blob",
- name => $p->{name},
- params => [ $p ],
- size => 4,
- xdr_size => $p->{xdr_size},
- };
- push @phases, $phase;
- $phase = 0;
- } elsif ($p->{class} eq "bulk") {
- $have_bulk = 1;
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "bulk_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "bulk",
- name => $p->{name},
- params => [ $p ],
- xdr_size => $p->{xdr_size},
- };
- push @phases, $phase;
-
- # We don't want to be asking recvmsg() for one object at a time if
- # they're really small.
- my $n_buf = ($p->{xdr_size} < 1020) ? int(1020 / $p->{xdr_size}) : 1;
- $n_buf *= $p->{xdr_size};
- $phase->{size} = $p->{xdr_size};
- $phase = 0;
- } else {
- die $p->{where}, "Reply array not supported";
- }
- }
-
- # Function definition and arguments
- print RXOUT "\n";
- print RXOUT "static int rxgen_decode_", $func->{name}, "_", $subname, "(struct rx_call *call)\n";
- print RXOUT "{\n";
-
- unless (@params) {
- print RXOUT "\treturn 0;\n";
- print RXOUT "}\n";
- return;
- }
-
- # Local variables
- print RXOUT "\tstruct ", $func->{name}, "_", $subname, " *obj = call->decoder_private;\n";
- print RXOUT "\tunsigned count;\n";
- print RXOUT "\tunsigned phase = call->phase;\n";
-
- # Deal with each phase
- print RXOUT "\n";
- print RXOUT "select_phase:\n" if ($have_bulk);
- print RXOUT "\tcount = call->data_count;\n";
- print RXOUT "\tswitch (phase) {\n";
-
- print RXOUT "\tcase 0:\n";
-
- my $phase_goto_label = 0;
- my $phix;
- for ($phix = 1; $phix <= $#phases + 1; $phix++) {
- print RXOUT "\n";
- print RXOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- $phase = $phases[$phix - 1];
- if ($phase_goto_label == $phix) {
- print RXOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
-
- # Determine how big bulk objects are
- if ($phase->{type} eq "blob") {
- my $p = $phase->{params}->[0];
- print RXOUT "\t\tcall->blob_size = ", $ptr, "nr__", $p->{name}, ";\n";
- print RXOUT "\t\tcall->blob_offset = UINT_MAX;\n";
- print RXOUT "\t\tif (", $ptr, "alloc__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tif (call->blob_size == 0)\n";
- print RXOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- print RXOUT "\t\tcall->blob_offset = 0;\n";
- } elsif ($phase->{type} eq "bulk") {
- my $p = $phase->{params}->[0];
- print RXOUT "\t\tcall->bulk_count = ", $ptr, "nr__", $p->{name}, ";\n";
- print RXOUT "\t\tcall->bulk_index = UINT_MAX;\n";
-
- if ($p->{elem}->{class} eq "basic") {
- print RXOUT "\t\tif (", $ptr, "store__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- } else {
- print RXOUT "\t\tif (", $ptr, "alloc__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- }
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tif (call->bulk_count == 0)\n";
- print RXOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- print RXOUT "\t\tcall->bulk_index = 0;\n";
- } else {
- print RXOUT "\t\tcall->need_size = ", $phase->{size}, ";\n"
- }
-
- # Entry point for a phase
- print RXOUT "\t\tcall->phase = ", $phix, ";\n";
- print RXOUT "\tcase ", $phix, ":\n";
-
- print RXOUT "\t\tif (count < ", $phase->{size}, ")";
- if ($phase->{type} eq "bulk" &&
- $phase->{xdr_size} <= 512
- ) {
- print RXOUT " {\n";
- print RXOUT "\t\t\tunsigned n = call->bulk_count - call->bulk_index;\n";
- print RXOUT "\t\t\tn = MIN(n, ", int(1024 / $phase->{xdr_size}), ");\n";
- print RXOUT "\t\t\tcall->need_size = n * ", $phase->{xdr_size}, ";\n";
- print RXOUT "\t\t\treturn 1;\n";
- print RXOUT "\t\t}";
- } else {
- print RXOUT "\n";
- print RXOUT "\t\t\treturn 1;\n";
- }
-
- # Unmarshal the data
- print RXOUT "\n";
- foreach my $p (@{$phase->{params}}) {
- if ($p->{type} eq "blob_size") {
- print RXOUT "\t\t", $ptr, "nr__", $p->{name}, " = rxrpc_dec(call);\n";
- next;
- } elsif ($p->{type} eq "bulk_size") {
- print RXOUT "\t\t", $ptr, "nr__", $p->{name}, " = rxrpc_dec(call);\n";
- next;
- }
-
- if ($p->{class} eq "bulk" && $p->{elem}->{class} eq "basic") {
- if ($p->{elem}->{xdr_size} == 4) {
- print RXOUT "\t\tcall->bulk_u32 = rxrpc_dec(call);\n";
- print RXOUT "\t\tif (", $ptr, "store__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- } elsif ($p->{elem}->{xdr_size} == 8) {
- print RXOUT "\t\tcall->bulk_u64 = (uint64_t)rxrpc_dec(call) << 32;\n";
- print RXOUT "\t\tcall->bulk_u64 |= (uint64_t)rxrpc_dec(call);\n";
- print RXOUT "\t\tif (", $ptr, "store__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- } else {
- die;
- }
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tcall->bulk_index++;\n";
-
- } elsif ($p->{class} eq "bulk" && $p->{elem}->{class} eq "struct") {
- print RXOUT "\t\tif (", $ptr, "alloc__", $p->{name}, "(call, &", $ptr, "token__", $p->{name}, ") < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\trxgen_decode_", $p->{type}, "(call, call->bulk_item);\n";
- print RXOUT "\t\tcall->bulk_index++;\n";
- } elsif ($p->{class} eq "blob") {
- print RXOUT "\t\trxrpc_dec_blob(call);\n";
- print RXOUT "\t\trxrpc_dec_align(call);\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 4) {
- print RXOUT "\t\t", $ptr, $p->{name}, " = rxrpc_dec(call);\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 8) {
- print RXOUT "\t\t", $ptr, $p->{name}, " = (uint64_t)rxrpc_dec(call) << 32;\n";
- print RXOUT "\t\t", $ptr, $p->{name}, " |= (uint64_t)rxrpc_dec(call);\n";
- } elsif ($p->{class} eq "struct") {
- print RXOUT "\t\trxgen_decode_", $p->{type}, "(call, ", $ptr, $p->{name}, ");\n";
- } else {
- die $p->{where}, ": Unsupported type in decode";
- }
-
- if ($p->{class} eq "blob") {
- print RXOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tif (call->blob_offset < call->blob_size) {\n";
- print RXOUT "\t\t\tphase = ", $phix, ";\n";
- print RXOUT "\t\t\tgoto select_phase;\n";
- print RXOUT "\t\t}\n";
- } elsif ($p->{class} eq "bulk") {
- print RXOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- print RXOUT "\t\tif (call->bulk_index < call->bulk_count) {\n";
- print RXOUT "\t\t\tphase = ", $phix, ";\n";
- print RXOUT "\t\t\tgoto select_phase;\n";
- print RXOUT "\t\t}\n";
- }
- }
-
- if ($phase->{type} ne "blob" && $phase->{type} ne "bulk") {
- print RXOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print RXOUT "\t\t\treturn -1;\n";
- }
- }
-
- print RXOUT "\n";
- print RXOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- if ($phase_goto_label == $phix) {
- print RXOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
- print RXOUT "\t\tcall->phase = ", $phix, ";\n";
- print RXOUT "\t\tcall->need_size = 0;\n";
- print RXOUT "\tdefault:\n";
- print RXOUT "\t\treturn 0;\n";
- print RXOUT "\t}\n";
- print RXOUT "}\n";
-}
-
-###############################################################################
-#
-# Emit a function to encode and dispatch a request or a response
-#
-###############################################################################
-sub emit_func_send($$)
-{
- my ($func, $what) = @_;
- my $params;
- my $bad_ret;
-
- # Function definition and arguments
- my @protos;
- if ($what eq "request") {
- @protos = @{$func->{send_request_protos}};
- $params = $func->{request};
- $bad_ret = "NULL";
- } else {
- @protos = @{$func->{send_response_protos}};
- $params = $func->{response};
- $bad_ret = "-1";
- }
- print RXOUT "\n";
- if ($what eq "request") {
- print RXOUT "struct rx_call *", $func->{name} . "(\n";
- print RXOUT "\tstruct rx_connection *z_conn";
- } else {
- print RXOUT "int respond_to_", $func->{name} . "(\n";
- print RXOUT "\tstruct rx_call *call";
- }
- foreach $proto (@protos) {
- print RXOUT ",\n\t", $proto;
- }
- if ($what eq "request" && @{$func->{response}}) {
- print RXOUT ",\n";
- print RXOUT "\tstruct ", $func->{name}, "_response *response";
- }
- print RXOUT ")\n";
- print RXOUT "{\n";
-
- print RXOUT "\tstruct rx_call *call;\n" if ($what eq "request");
-
- my @blob_params = grep { $_->{class} eq "blob"; } @{$params};
- my @bulk_params = grep { $_->{class} eq "bulk"; } @{$params};
-
- # Local variables
- print RXOUT "\tint ret;\n";
-
- # Check lengths
- if (@blob_params || @bulk_params) {
- print RXOUT "\n";
- print RXOUT "\tif (";
- my $first = 1;
- foreach my $p (@blob_params) {
- if ($first) {
- $first = 0;
- } else {
- print RXOUT " ||\n\t ";
- }
- print RXOUT "!", $p->{name};
- if (exists($p->{dim})) {
- print RXOUT " || nr__", $p->{name}, " > ", $p->{dim};
- }
- }
- foreach my $p (@bulk_params) {
- if ($first) {
- $first = 0;
- } else {
- print RXOUT " ||\n\t ";
- }
- print RXOUT "!get__", $p->{name};
- if (exists($p->{dim})) {
- print RXOUT " || nr__", $p->{name}, " > ", $p->{dim};
- }
- }
- print RXOUT ") {\n";
- print RXOUT "\t\terrno = EINVAL;\n";
- print RXOUT "\t\treturn ", $bad_ret, ";\n";
- print RXOUT "\t};\n";
- }
-
- # Allocate call
- if ($what eq "request") {
- print RXOUT "\n";
- print RXOUT "\tcall = rxrpc_alloc_call(z_conn, 0);\n";
- print RXOUT "\tif (!call)\n";
- print RXOUT "\t\treturn ", $bad_ret, ";\n";
- print RXOUT "\tcall->decoder = rxgen_decode_", $func->{name}, "_response;\n";
- print RXOUT "\tcall->decoder_private = response;\n" if (@{$func->{response}});
- }
-
- # Marshal the data
- print RXOUT "\n" if ($what eq "request" || @{$params});
- print RXOUT "\trxrpc_enc(call, ", $func->{opcode}, ");\n" if ($what eq "request");
- foreach my $p (@{$params}) {
- if ($p->{class} eq "basic" && $p->{type} !~ /64/) {
- print RXOUT "\trxrpc_enc(call, ", $p->{name}, ");\n";
- } elsif ($p->{class} eq "basic" && $p->{type} =~ /64/) {
- print RXOUT "\trxrpc_enc(call, (uint32_t)", $p->{name}, ");\n";
- print RXOUT "\trxrpc_enc(call, (uint32_t)(", $p->{name}, " >> 32));\n";
- } elsif ($p->{class} eq "struct") {
- print RXOUT "\trxgen_encode_", $p->{type}, "(call, ", $p->{name}, ");\n";
- } elsif ($p->{class} eq "blob") {
- print RXOUT "\trxrpc_enc_blob(call, ", $p->{name}, ", nr__", $p->{name}, ");\n";
- print RXOUT "\trxrpc_enc_align(call);\n";
- } elsif ($p->{class} eq "bulk") {
- print RXOUT "\trxrpc_enc(call, nr__", $p->{name}, ");\n";
- print RXOUT "\tcall->bulk_count = nr__", $p->{name}, ";\n";
- print RXOUT "\tfor (call->bulk_index = 0; call->bulk_index < call->bulk_count; call->bulk_index++) {\n";
- if ($p->{elem}->{class} eq "struct") {
- print RXOUT "\t\tstruct ", $p->{elem}->{type}, " x;\n";
- } else {
- print RXOUT "\t\t", $p->{elem}->{type}, " x;\n";
- }
- print RXOUT "\t\tcall->bulk_item = &x;\n";
- print RXOUT "\t\tif (get__", $p->{name}, "(call, token__", $p->{name}, ") < 0)\n";
- print RXOUT "\t\t\tgoto error;\n";
- if ($p->{elem}->{class} eq "basic" && $p->{elem}->{type} !~ /64/) {
- if ($p->{type} !~ /^u/) {
- print RXOUT "\t\trxrpc_enc(call, (u", $p->{type}, ")x);\n";
- } else {
- print RXOUT "\t\trxrpc_enc(call, x);\n";
- }
- } elsif ($p->{class} eq "basic" && $p->{type} =~ /64/) {
- print RXOUT "\t\trxrpc_enc(call, (uint32_t)", $p->{name}, ");\n";
- print RXOUT "\t\trxrpc_enc(call, (uint32_t)(", $p->{name}, " >> 32));\n";
- } elsif ($p->{elem}->{class} eq "struct") {
- print RXOUT "\t\trxgen_encode_", $p->{elem}->{type}, "(call, &x);\n";
- } else {
- die $p->{where}, "No decoding for array type '$type'";
- }
- print RXOUT "\t}\n";
- } else {
- die $p->{where}, ": Unsupported param encoding";
- }
- }
-
- print RXOUT "\tif (rxrpc_post_enc(call) < 0)\n";
- print RXOUT "\t\tgoto error;\n";
- print RXOUT "\tcall->more_send = 0;\n";
-
- # Send the message
- print RXOUT "\n";
- print RXOUT "\tret = rxrpc_send_data(call);\n";
- print RXOUT "\tif (ret < 0)\n";
- print RXOUT "\t\tgoto error;\n";
- if ($what eq "request") {
- print RXOUT "\treturn call;\n";
- } else {
- print RXOUT "\treturn 0;\n";
- }
-
- print RXOUT "\n";
- print RXOUT "error:\n";
- print RXOUT "\trxrpc_terminate_call(call, 0);\n";
- print RXOUT "\treturn ", $bad_ret, ";\n";
- print RXOUT "}\n";
-}
-
-1;
+++ /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 python module definition.
-#
-###############################################################################
-sub emit_py_module() {
- # We want an exception we can raise when we get a remote abort
- print PYHDR "extern PyObject *kafs_remote_abort;\n";
-
- print PYOUT "\n";
- print PYOUT "/*\n";
- print PYOUT " * The remote-abort exception.\n";
- print PYOUT " */\n";
- print PYOUT "PyObject *kafs_remote_abort;\n";
-
- foreach $_ (sort(keys(%packages))) {
- my $pkg = $packages{$_};
- my $codes = $pkg->{abort_codes};
- next unless (@{$codes});
- print PYOUT "PyObject *kafs_", $pkg->{name}, "_abort;\n";
- }
-
- print PYOUT "\n";
- print PYHDR "extern struct kafs_abort_list kafs_abort_map[", $abort_count, "];\n";
-
- my $index = 0;
- print PYOUT "struct kafs_abort_list kafs_abort_map[", $abort_count, "] = {\n";
- foreach my $id (sort {$a <=> $b} keys(%abort_ids)) {
- my $abort = $abort_ids{$id};
- print PYOUT "\t{ .id = ", $abort->{sym};
- print PYOUT ", .msg = \"", $abort->{msg}, "\"" if ($abort->{msg});
- print PYOUT " }, /* ", $abort->{id}, " */\n";
- $abort->{index} = $index++;
- }
- print PYOUT "};\n\n";
-
- # Emit python structure wrapper static method table
- print PYOUT "\n";
- print PYOUT "/*\n";
- print PYOUT " * The static methods.\n";
- print PYOUT " */\n";
- print PYOUT "static PyMethodDef module_methods[] = {\n";
-
- print PYOUT "\t{\"rx_new_connection\", (PyCFunction)kafs_py_rx_new_connection, METH_VARARGS, \"\" },\n";
- print PYOUT "\t{\"afs_string_to_key\", (PyCFunction)kafs_py_string_to_key, METH_VARARGS, \"\" },\n";
-
- foreach my $def (@py_func_defs) {
- print PYOUT "\t{\"", $def->{name}, "\", (PyCFunction)", $def->{c_func}, ", METH_VARARGS,";
- print PYOUT " \"", $def->{doc}, "\" },\n";
- }
-
- print PYOUT "\t{}\n";
- print PYOUT "};\n";
-
- # Emit python structure wrapper loader
- print PYOUT "\n";
-
- print PYOUT "static PyModuleDef kafs_module = {\n";
- print PYOUT "\t.m_base = PyModuleDef_HEAD_INIT,\n";
- print PYOUT "\t.m_name = \"kafs\",\n";
- print PYOUT "\t.m_doc = \"AFS stuff.\",\n";
- print PYOUT "\t.m_size = -1,\n";
- print PYOUT "\t.m_methods = module_methods,\n";
- print PYOUT "};\n";
-
- print PYHDR "\n";
- print PYHDR "extern PyObject *pykafs_load_wrappers(void);\n";
-
- print PYOUT "\n";
- print PYOUT "PyObject *pykafs_load_wrappers(void)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *m;\n";
-
- # Load types
- if (@py_type_defs) {
- print PYOUT "\tif (";
- print PYOUT "PyType_Ready(&py_rx_connectionType) < 0 ||\n\t ";
- print PYOUT "PyType_Ready(&py_rx_split_infoType) < 0";
- my $first = 0;
- foreach my $def (@py_type_defs) {
- print PYOUT " ||\n\t " unless ($first);
- print PYOUT "PyType_Ready(&", $def->{c_type}, ") < 0";
- $first = 0;
- }
- print PYOUT ")\n";
- print PYOUT "\t\treturn NULL;\n";
- }
-
- print PYOUT "\n";
- print PYOUT "\tm = PyModule_Create(&kafs_module);\n";
- print PYOUT "\tif (!m)\n";
- print PYOUT "\t\treturn NULL;\n";
-
- if (%constants) {
- print PYOUT "\n";
- foreach my $c (sort grep /^[^0-9]/, keys %constants) {
- print PYOUT "\tPyModule_AddIntConstant(m, \"$c\", $c);\n";
- }
- }
-
- if (@py_type_defs) {
- print PYOUT "\n";
- foreach my $def (@py_type_defs) {
- print PYOUT "\tPy_INCREF(&", $def->{c_type}, ");\n";
- print PYOUT "\tPyModule_AddObject(m, \"", $def->{name}, "\", (PyObject *)&", $def->{c_type}, ");\n";
- }
- }
-
- # Emit a base remote abort class that all others can be subclassed off
- print PYOUT "\n";
- print PYOUT "\tkafs_remote_abort = PyErr_NewException(\"kafs.RemoteAbort\", NULL, NULL);\n";
- print PYOUT "\tif (!kafs_remote_abort)\n";
- print PYOUT "\t\treturn NULL;\n";
- print PYOUT "\tPy_INCREF(kafs_remote_abort);\n";
- print PYOUT "\tPyModule_AddObject(m, \"RemoteAbort\", kafs_remote_abort);\n";
-
- foreach $_ (sort(keys(%packages))) {
- my $pkg = $packages{$_};
- my $abort_codes = $pkg->{abort_codes};
- next unless (@{$abort_codes});
-
- my $pkg_abort = $pkg->{name} . "Abort";
- my $pkg_sym = "kafs_" . $pkg->{name} . "_abort";
-
- print PYOUT "\n";
- print PYOUT "\t", $pkg_sym, " = PyErr_NewException(\"kafs.", $pkg_abort, "\", kafs_remote_abort, NULL);\n";
- print PYOUT "\tif (!", $pkg_sym, ")\n";
- print PYOUT "\t\treturn NULL;\n";
- print PYOUT "\tPy_INCREF(", $pkg_sym, ");\n";
- print PYOUT "\tPyModule_AddObject(m, \"", $pkg_abort, "\", ", $pkg_sym, ");\n";
-
- foreach my $abort (sort { $a->{id} <=> $b->{id}; } @{$abort_codes}) {
- my $abort_name = "Abort" . $abort->{sym};
- my $abort_var = "kafs_abort_map[" . $abort->{index} . "].obj";
-
- print PYOUT "\n";
- print PYOUT "\t", $abort_var, " = PyErr_NewException(\"kafs.", $abort_name, "\", ", $pkg_sym, ", NULL);\n";
- print PYOUT "\tif (!", $abort_var, ")\n";
- print PYOUT "\t\treturn NULL;\n";
- print PYOUT "\tPy_INCREF(", $abort_var, ");\n";
- print PYOUT "\tPyModule_AddObject(m, \"", $abort_name, "\", ", $abort_var, ");\n";
- }
- }
-
- print PYOUT "\n";
- print PYOUT "\treturn m;\n";
- print PYOUT "}\n";
-}
-
-1;
+++ /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.
-#
-
-my %bulk_get_helpers = ();
-my %bulk_set_helpers = ();
-
-###############################################################################
-#
-# Emit python objects to represent received parameter sets and received
-# response sets for RPC calls.
-#
-###############################################################################
-sub emit_py_func_param_object($$) {
- my ($func, $set) = @_;
-
- my $struct_req = "py_" . $func->{name}. "_". $set;
- my @basic = ();
- my @complex = ();
- my $params = ();
- my $division = "";
-
- push @py_type_defs, {
- name => $func->{name} . "_" . $set,
- c_type => $struct_req . "Type",
- };
-
- if ($set eq "request") {
- $params = $func->{request};
- $division = "calls";
- } else {
- $params = $func->{response};
- $division = "responses";
- }
-
- # Define a C structure to hold the python object header and the data.
- print PYHDR "\n";
- print PYHDR "struct ", $struct_req, " {\n";
- print PYHDR "\tstruct py_rx_", $set, " common;\n";
- if (@{$params}) {
- my $have_opaque = 0;
- print PYHDR "\tstruct {\n";
- foreach my $p (@{$params}) {
- if ($p->{class} eq "basic") {
- push @basic, $p;
- print PYHDR "\t\t", $p->{type}, "\t", $p->{name}, ";\n";
- } else {
- push @complex, $p;
- print PYHDR "\t\tPyObject\t*", $p->{name}, ";\n";
- }
- $have_opaque = 1 if ($p->{class} eq "blob" && $p->{elem}->{class} eq "opaque");
- }
- print PYHDR "\t} x;\n";
- print PYHDR "\tPy_buffer dec_buf;\n" if ($have_opaque);
- }
- print PYHDR "};\n";
-
- # We need to have a new function if the object is to be allocatable by the
- # Python interpreter
- print PYOUT "\n";
- print PYOUT "static PyObject *\n";
- print PYOUT $struct_req, "_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *obj;\n";
- print PYOUT "\n";
- print PYOUT "\tobj = subtype->tp_alloc(subtype, 1);\n";
- if (@{$params}) {
- print PYOUT "\tif (obj) {\n";
- print PYOUT "\t\tstruct ", $struct_req, " *self = (struct ", $struct_req, " *)obj;\n";
- print PYOUT "\t\tmemset(&self->x, 0, sizeof(self->x));\n";
- print PYOUT "\t}\n";
- }
- print PYOUT "\treturn obj;\n";
- print PYOUT "}\n";
-
- # We have to have a deallocation function
- print PYOUT "\n";
- print PYOUT "static void ", $struct_req, "_dealloc(struct ", $struct_req, " *self)\n";
- print PYOUT "{\n";
- foreach my $p (@complex) {
- print PYOUT "\tPy_XDECREF(self->x.", $p->{name}, ");\n";
- }
- print PYOUT "\tPy_TYPE(self)->tp_free((PyObject *)self);\n";
- print PYOUT "}\n";
-
- # All elements are made directly accessible to the Python interpreter,
- # either as integer types or as object types.
- if (@{$params}) {
- print PYOUT "\n";
- print PYOUT "static PyMemberDef ", $struct_req, "_members[] = {\n";
- foreach my $p (@{$params}) {
- print PYOUT "\t{ \"", $p->{name}, "\", ";
- if ($p->{class} eq "blob") { print PYOUT "T_OBJECT_EX";
- } elsif ($p->{class} eq "bulk") { print PYOUT "T_OBJECT_EX";
- } elsif ($p->{type} eq "char" ) { print PYOUT "T_CHAR";
- } elsif ($p->{type} eq "int8_t" ) { print PYOUT "T_BYTE";
- } elsif ($p->{type} eq "int16_t" ) { print PYOUT "T_SHORT";
- } elsif ($p->{type} eq "int32_t" ) { print PYOUT "T_INT";
- } elsif ($p->{type} eq "int64_t" ) { print PYOUT "T_LONGLONG";
- } elsif ($p->{type} eq "uint8_t" ) { print PYOUT "T_UBYTE";
- } elsif ($p->{type} eq "uint16_t") { print PYOUT "T_USHORT";
- } elsif ($p->{type} eq "uint32_t") { print PYOUT "T_UINT";
- } elsif ($p->{type} eq "uint64_t") { print PYOUT "T_ULONGLONG";
- } else {
- print PYOUT "T_OBJECT_EX";
- }
- print PYOUT ", offsetof(struct ", $struct_req, ", x.", $p->{name}, "), 0, \"\"},\n";
- }
- print PYOUT "\t{}\n";
- print PYOUT "};\n";
- }
-
- # Emit the Python type definition
- print PYOUT "\n";
- print PYOUT "static PyTypeObject ", $struct_req, "Type = {\n";
- print PYOUT "\tPyVarObject_HEAD_INIT(NULL, 0)\n";
- print PYOUT "\t\"kafs.", $func->{name}, "_", $set, "\",\t\t/*tp_name*/\n";
- print PYOUT "\tsizeof(struct ", $struct_req, "),\t/*tp_basicsize*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_itemsize*/\n";
- print PYOUT "\t(destructor)", $struct_req, "_dealloc, /*tp_dealloc*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_print*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_getattr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_setattr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_compare*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_repr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_number*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_sequence*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_mapping*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_hash */\n";
- print PYOUT "\t0,\t\t\t\t/*tp_call */\n";
- print PYOUT "\t0,\t\t\t\t/*tp_str*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_getattro*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_setattro*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_buffer*/\n";
- print PYOUT "\tPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n";
- print PYOUT "\t\"\",\t\t\t\t/* tp_doc */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_traverse */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_clear */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_richcompare */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_weaklistoffset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_iter */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_iternext */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_methods */\n";
- if (@{$params}) {
- print PYOUT "\t", $struct_req, "_members,\n";
- } else {
- print PYOUT "\t0,\t\t\t\t/* tp_members */\n";
- }
- print PYOUT "\t0,\t\t\t\t/* tp_getset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_base */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_dict */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_descr_get */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_descr_set */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_dictoffset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_init */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_alloc */\n";
- print PYOUT "\t", $struct_req, "_new,\n";
- print PYOUT "};\n";
-}
-
-###############################################################################
-#
-# Emit functions to help deal with bulk lists
-#
-###############################################################################
-sub emit_py_func_bulk_helper($)
-{
- my ($func) = @_;
-
- foreach my $p (@{$func->{params}}) {
- next if ($p->{class} ne "bulk");
-
- # Data encoding
- if (!exists $bulk_get_helpers{$p->{type}}) {
- $bulk_get_helpers{$p->{type}} = 1;
-
- print PYOUT "\n";
- print PYOUT "static __attribute__((unused))\n";
- print PYOUT "int py_encode_bulk_", $p->{type}, "(struct rx_call *call, PyObject *list)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *item;\n";
- print PYOUT "\tunsigned count, i;\n";
- print PYOUT "\n";
- print PYOUT "\tcount = PyList_Size(list);\n";
- print PYOUT "\trxrpc_enc(call, count);\n";
- print PYOUT "\n";
- print PYOUT "\tfor (i = 0; i < count; i++) {\n";
- print PYOUT "\t\titem = PyList_GetItem(list, i);\n";
- print PYOUT "\t\tif (!item)\n";
- print PYOUT "\t\t\treturn -1;\n";
-
- print PYOUT "\n";
- if ($p->{elem}->{class} eq "basic") {
- print PYOUT "\t\tif (!PyLong_Check(item)) {\n";
- print PYOUT "\t\t\tPyErr_SetString(PyExc_TypeError, \"Expected list of ", $p->{type}, "\");\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\t}\n";
- } else {
- print PYOUT "\t\tif (py_premarshal_", $p->{type}, "(item))\n";
- print PYOUT "\t\t\treturn -1;\n";
- }
-
- if ($p->{elem}->{class} eq "basic") {
- if ($p->{elem}->{type} eq "int64_t") {
- print PYOUT "\t\tuint64_t x = PyLong_AsLongLong(item);\n";
- print PYOUT "\t\trxrpc_enc(call, x >> 32);\n";
- print PYOUT "\t\trxrpc_enc(call, x);\n";
- } elsif ($p->{elem}->{type} eq "uint64_t") {
- print PYOUT "\t\tuint64_t x = PyLong_AsUnsignedLongLong(item);\n";
- print PYOUT "\t\trxrpc_enc(call, x >> 32);\n";
- print PYOUT "\t\trxrpc_enc(call, x);\n";
- } elsif ($p->{elem}->{type} =~ /^int/) {
- print PYOUT "\t\trxrpc_enc(call, PyLong_AsLong(item));\n";
- } elsif ($p->{elem}->{type} =~ /^uint|^char/) {
- print PYOUT "\t\trxrpc_enc(call, PyLong_AsUnsignedLong(item));\n";
- }
- } else {
- print PYOUT "\t\trxgen_encode_", $p->{type}, "(call, &((struct py_", $p->{type}, " *)item)->x);\n";
- }
- print PYOUT "\t}\n";
- print PYOUT "\treturn 0;\n";
- print PYOUT "}\n";
- }
- }
-}
-
-###############################################################################
-#
-# Emit a python wrapper function to make a simple synchronous call
-#
-###############################################################################
-sub emit_py_func_simple_sync_call($)
-{
- my ($func) = @_;
-
- push @py_func_defs, {
- name => $func->{name},
- c_func => "kafs_" . $func->{name},
- doc => "",
- };
-
- print PYOUT "\n";
- print PYOUT "PyObject *\n";
- print PYOUT "kafs_", $func->{name}, "(PyObject *_self, PyObject *args)\n";
- print PYOUT "{\n";
-
- # Local variable declarations representing parameters to send
- print PYOUT "\tstruct rx_call *call;\n";
- print PYOUT "\tstruct py_rx_connection *z_conn;\n";
- print PYOUT "\tstruct py_", $func->{name}, "_response *response;\n";
- foreach my $p (@{$func->{request}}) {
- if ($p->{class} eq "blob") {
- print PYOUT "\tPy_buffer param_", $p->{name}, ";\n";
- } elsif ($p->{class} eq "basic") {
- print PYOUT "\t", $p->{type}, " param_", $p->{name}, ";\n";
- } elsif ($p->{class} eq "struct") {
- print PYOUT "\tstruct py_", $p->{type}, " *param_", $p->{name}, ";\n";
- } elsif ($p->{class} eq "bulk") {
- print PYOUT "\tPyObject *param_", $p->{name}, ";\n"
- unless ($p->{dir} eq "OUT");
- } else {
- die $p->{where}, ": Unsupported type \"", $p->{type}, "\"";
- }
- }
-
- print PYOUT "\tPyObject *split_callback, *split_info;\n" if ($func->{split});
- print PYOUT "\tPyObject *res = NULL;\n";
- print PYOUT "\tint ret;\n";
-
- # Make use of the tuple parser to extract the arguments and check their
- # types for us.
- print PYOUT "\n";
- print PYOUT "\tif (!PyArg_ParseTuple(args, \"O!";
-
- foreach my $p (@{$func->{request}}) {
- if ($p->{class} eq "bulk") { print PYOUT "O!";
- } elsif ($p->{type} eq "int8_t") { print PYOUT "B";
- } elsif ($p->{type} eq "int16_t") { print PYOUT "h";
- } elsif ($p->{type} eq "int32_t") { print PYOUT "i";
- } elsif ($p->{type} eq "int64_t") { print PYOUT "L";
- } elsif ($p->{type} eq "uint8_t") { print PYOUT "b";
- } elsif ($p->{type} eq "uint16_t") { print PYOUT "H";
- } elsif ($p->{type} eq "uint32_t") { print PYOUT "I";
- } elsif ($p->{type} eq "uint64_t") { print PYOUT "K";
- } elsif ($p->{class} eq "struct") { print PYOUT "O!";
- } elsif ($p->{class} eq "blob" && $p->{elem}->{class} eq "string") {
- print PYOUT "s*";
- } elsif ($p->{class} eq "blob" && $p->{elem}->{class} eq "opaque") {
- print PYOUT "z*";
- } else {
- die $p->{where}, ": No py parse for param";
- }
- }
-
- print PYOUT "O" if ($func->{split});
- print PYOUT "\",\n";
- print PYOUT "\t\t\t &py_rx_connectionType, &z_conn";
-
- foreach my $p (@{$func->{request}}) {
- print PYOUT ",\n";
- print PYOUT "\t\t\t ";
- if ($p->{class} eq "basic") {
- print PYOUT "¶m_", $p->{name};
- } elsif ($p->{class} eq "struct") {
- print PYOUT "&py_", $p->{type}, "Type, ¶m_", $p->{name};
- } elsif ($p->{class} eq "blob") {
- print PYOUT "¶m_", $p->{name};
- } elsif ($p->{class} eq "bulk") {
- print PYOUT "&PyList_Type, ¶m_", $p->{name};
- } else {
- die $p->{where}, ": Unsupported type \"", $p->{type}, "\"";
- }
- }
- print PYOUT ",\n\t\t\t &split_callback" if ($func->{split});
- print PYOUT "))\n";
- print PYOUT "\t\treturn NULL;\n";
-
- if ($func->{split}) {
- print PYOUT "\n";
- print PYOUT "\tsplit_info = py_rxgen_split_client_prepare();\n";
- print PYOUT "\tif (!split_info)\n";
- print PYOUT "\t\treturn NULL;\n";
- }
-
- print PYOUT "\n";
- print PYOUT "\tcall = rxrpc_alloc_call(z_conn->x, 0);\n";
- print PYOUT "\tif (!call) {\n";
- print PYOUT "\t\tPy_XDECREF(split_info);\n" if ($func->{split});
- print PYOUT "\t\treturn PyErr_NoMemory();\n";
- print PYOUT "\t}\n";
- print PYOUT "\tcall->decoder_cleanup = py_rxgen_decoder_cleanup;\n";
- print PYOUT "\tpy_rxgen_split_client_set(call, split_callback, split_info);\n"
- if ($func->{split});
-
- # Marshal the arguments
- print PYOUT "\n";
- print PYOUT "\trxrpc_enc(call, ", $func->{opcode}, ");\n";
- foreach my $p (@{$func->{request}}) {
- if ($p->{class} eq "blob") {
- my $dim = -1;
- $dim = $p->{dim} if exists $p->{dim};
- print PYOUT "\tif (py_enc_buffer(call, ¶m_", $p->{name}, ", ", $dim, ") < 0) {\n";
- print PYOUT "\t\trxrpc_terminate_call(call, EINVAL);\n";
- print PYOUT "\t\treturn NULL;\n";
- print PYOUT "\t}\n";
- } elsif ($p->{class} eq "bulk") {
- print PYOUT "\tif (py_encode_bulk_", $p->{type}, "(call, param_", $p->{name}, ") < 0)\n";
- print PYOUT "\t\tgoto error;\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 4) {
- print PYOUT "\trxrpc_enc(call, param_", $p->{name}, ");\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 8) {
- print PYOUT "\trxrpc_enc(call, param_", $p->{name}, " >> 32);\n";
- print PYOUT "\trxrpc_enc(call, param_", $p->{name}, ");\n";
- } elsif ($p->{class} eq "struct") {
- print PYOUT "\tif (py_premarshal_", $p->{type}, "((PyObject *)param_", $p->{name}, ")) {\n";
- print PYOUT "\t\trxrpc_terminate_call(call, EINVAL);\n";
- print PYOUT "\t\treturn NULL;\n";
- print PYOUT "\t}\n";
- print PYOUT "\trxgen_encode_", $p->{type}, "(call, ¶m_", $p->{name}, "->x);\n";
- } else {
- die $p->{where}, ": Unsupported type in decode";
- }
- }
-
- print PYOUT "\tif (rxrpc_post_enc(call) < 0)\n";
- print PYOUT "\t\tgoto error_no_res;\n";
-
- # Allocate a reply object
- print PYOUT "\n";
- print PYOUT "\tres = _PyObject_New(&py_", $func->{name}, "_responseType);\n";
- print PYOUT "\tresponse = (struct py_", $func->{name}, "_response *)res;\n";
- print PYOUT "\tif (!response)\n";
- print PYOUT "\t\tgoto enomem;\n";
- print PYOUT "\tmemset(&response->x, 0, sizeof(response->x));\n"
- if (@{$func->{response}});
- print PYOUT "\tcall->decoder = py_", $func->{name}, "_decode_response;\n";
- print PYOUT "\tcall->decoder_private = response;\n";
-
- # Transmit the split data
- if ($func->{split}) {
- print PYOUT "\tif (py_rxgen_split_transmit(call) < 0)\n";
- print PYOUT "\t\tgoto error_no_res;\n";
- } else {
- print PYOUT "\tcall->more_send = 0;\n";
-
- # Make the call
- print PYOUT "\n";
- print PYOUT "\tret = rxrpc_send_data(call);\n";
- print PYOUT "\tif (ret == -1)\n";
- print PYOUT "\t\tgoto error;\n";
- }
-
- # Wait for the reply
- #
- # If we're dealing with a split function or are in asynchronous mode, we
- # need to return the call here.
- #
- print PYOUT "\n";
- print PYOUT "\tret = rxrpc_run_sync_call(call);\n";
- print PYOUT "\tif (ret == -1)\n";
- print PYOUT "\t\tgoto error;\n";
-
- # Successful return
- print PYOUT "\n";
- print PYOUT "\trxrpc_terminate_call(call, 0);\n";
- print PYOUT "\treturn res;\n";
-
- # Error cleanups
- print PYOUT "\n";
- print PYOUT "error:\n";
- print PYOUT "\tPy_XDECREF(res);\n";
- print PYOUT "error_no_res:\n";
- print PYOUT "\tif (errno == ENOMEM)\n";
- print PYOUT "enomem:\n";
- print PYOUT "\t\tres = PyErr_NoMemory();\n";
- print PYOUT "\telse if (errno == ECONNABORTED)\n";
- print PYOUT "\t\tres = py_rxgen_received_abort(call);\n";
- print PYOUT "\telse\n";
- print PYOUT "\t\tres = PyErr_SetFromErrno(PyExc_IOError);\n";
- print PYOUT "\trxrpc_terminate_call(call, ENOMEM);\n";
- print PYOUT "\treturn res;\n";
-
- # End the function
- print PYOUT "}\n";
-}
-
-###############################################################################
-#
-# Emit a function to decode a block into a python object in a way that can be
-# used from asynchronous code. The opcode is expected to have been removed
-# from the incoming call on the server side.
-#
-###############################################################################
-sub emit_py_func_decode($$$$)
-{
- my ($func, $side, $subname, $paramlist) = @_;
- my @params = @{$paramlist};
- my $ptr;
-
- $ptr = "obj->";
-
- # We fetch the data in a number of phases. Each phase receives a chunk of
- # data of a certain size. A phase's size might be dependent on a variable
- # in the previous phase. Variable-sized bulk arrays are split across
- # multiple phases, with the length being at the end of the first phase and
- # the data in the second.
- #
- # We also need to interpolate a phase to deal with decoding split-op
- # auxiliary data. This comes last when decoding the request and first when
- # decoding the response.
- #
- my @phases = ();
- my $phase = 0;
- my $have_bulk = 0;
- my $want_item = 0;
-
- if ($func->{split} && $subname eq "response") {
- $phase = {
- type => "split",
- size => "py_rxgen_split_receive(call)",
- params => []
- };
- push @phases, $phase;
- $phase = 0;
- $have_bulk = 1;
- }
-
- foreach my $p (@params) {
- unless ($phase) {
- $phase = { type => "flat", size => 0, params => [] };
- push @phases, $phase;
- }
-
- if ($p->{class} eq "basic" ||
- $p->{class} eq "struct"
- ) {
- $phase->{size} += $p->{xdr_size};
- push @{$phase->{params}}, $p;
- } elsif ($p->{class} eq "blob") {
- $have_bulk = 1;
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "blob_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "blob",
- name => $p->{name},
- params => [ $p ],
- xdr_size => $p->{xdr_size},
- };
- push @phases, $phase;
-
- # We don't want to be asking recvmsg() for one object at a time if
- # they're really small.
- $phase->{size} = $p->{xdr_size};
- $phase = 0;
- } elsif ($p->{class} eq "bulk") {
- $have_bulk = 1;
-
- # Bulk objects begin with an element count
- $phase->{elem_count} = $phase->{size};
- $phase->{size} += 4;
-
- my %pseudoparam = (
- class => "basic",
- type => "bulk_size",
- name => $p->{name},
- elem => $p->{elem},
- where => $p->{where},
- xdr_size => $p->{xdr_size},
- );
- push @{$phase->{params}}, \%pseudoparam;
-
- # Create a new phase
- $phase = {
- type => "bulk",
- name => $p->{name},
- params => [ $p ],
- xdr_size => $p->{xdr_size},
- };
- push @phases, $phase;
-
- $want_item = 1;
-
- # We don't want to be asking recvmsg() for one object at a time if
- # they're really small.
- $phase->{size} = $p->{xdr_size};
- $phase = 0;
- } else {
- die $p->{where}, "Reply array not supported";
- }
- }
-
- if ($func->{split} && $subname eq "request") {
- $phase = {
- type => "split",
- size => "py_rxgen_split_receive(call)",
- params => []
- };
- push @phases, $phase;
- $phase = 0;
- $have_bulk = 1;
- }
-
- # Function definition and arguments
- print PYOUT "\n";
- print PYOUT "int py_", $func->{name}, "_decode_", $subname, "(struct rx_call *call)\n";
- print PYOUT "{\n";
-
- unless (@params || $func->{split}) {
- print PYOUT "\treturn 0;\n";
- print PYOUT "}\n";
- return;
- }
-
- # Local variables
- print PYOUT "\tstruct py_", $func->{name}, "_", $subname, " *obj = call->decoder_private;\n"
- if (@params);
- print PYOUT "\tPyObject *item;\n" if ($want_item);
- print PYOUT "\tunsigned phase = call->phase;\n";
- print PYOUT "\tunsigned count;\n";
-
- # Deal with each phase
- print PYOUT "\n";
- print PYOUT "select_phase:\n" if ($have_bulk);
- print PYOUT "\tcount = call->data_count;\n";
- #print PYOUT "\tprintf(\"-- Phase %u (%u) --\\n\", phase, count);\n";
- print PYOUT "\tswitch (phase) {\n";
-
- print PYOUT "\tcase 0:\n";
-
- my $phase_goto_label = 0;
- my $phix;
- for ($phix = 1; $phix <= $#phases + 1; $phix++) {
- print PYOUT "\n";
- print PYOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- $phase = $phases[$phix - 1];
- if ($phase_goto_label == $phix) {
- print PYOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
-
- # Determine how big bulk objects are
- if ($phase->{type} eq "blob") {
- my $p = $phase->{params}->[0];
- if ($p->{elem}->{class} eq "string") {
- print PYOUT "\t\tswitch (py_dec_init_string(call, &obj->x.", $p->{name}, ")) {\n";
- } elsif ($p->{elem}->{class} eq "opaque") {
- print PYOUT "\t\tobj->x.", $p->{name}, " = PyByteArray_FromStringAndSize(\"\", 0);\n";
- print PYOUT "\t\tif (!obj->x.", $p->{name}, ")\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tif (PyByteArray_Resize(obj->x.", $p->{name}, ", call->blob_size) == -1)\n";
- print PYOUT "\t\t\treturn -1;\n";
-
- print PYOUT "\t\tswitch (py_dec_init_opaque(call, obj->x.", $p->{name}, ")) {\n";
- } else {
- die;
- }
- print PYOUT "\t\tcase -1: return -1;\n";
- print PYOUT "\t\tcase 0: goto phase_", $phix + 1, ";\n";
- print PYOUT "\t\tcase 1: break;\n";
- print PYOUT "\t\t}\n";
- $phase_goto_label = $phix + 1;
- } elsif ($phase->{type} eq "bulk") {
- my $p = $phase->{params}->[0];
- if ($p->{elem}->{class} eq "basic" ||
- $p->{elem}->{class} eq "struct") {
- print PYOUT "\t\tobj->x.", $p->{name}, " = PyList_New(call->bulk_count);\n";
- print PYOUT "\t\tif (!obj->x.", $p->{name}, ")\n";
- print PYOUT "\t\t\treturn -1;\n";
- } else {
- die;
- }
-
- print PYOUT "\t\tif (call->bulk_count == 0)\n";
- print PYOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- print PYOUT "\t\tcall->bulk_index = 0;\n";
- }
-
- # Entry point for a phase
- if ($phase->{type} eq "split") {
- print PYOUT "\t\tif (py_rxgen_split_receive(call, 1) < 0)\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tif (call->need_size == 0)\n";
- print PYOUT "\t\t\tgoto phase_", $phix + 1, ";\n";
- $phase_goto_label = $phix + 1;
- }
- print PYOUT "\t\tcall->phase = ", $phix, ";\n";
- print PYOUT "\tcase ", $phix, ":\n";
-
- if ($phase->{type} ne "split") {
- print PYOUT "\t\tcall->need_size = ", $phase->{size}, ";\n";
- print PYOUT "\t\tif (count < call->need_size)\n";
- print PYOUT "\t\t\treturn 1;\n";
- } else {
- print PYOUT "\t\tif (call->need_size == UINT_MAX ? count == 0 : count < call->need_size) {\n";
- #print PYOUT "\t\t\tprintf(\"NEED %u (phase %u)\\n\", call->need_size, phase);\n";
- print PYOUT "\t\t\treturn 1;\n";
- print PYOUT "\t\t}\n";
- }
-
- # Unmarshal the data
- print PYOUT "\n";
- foreach my $p (@{$phase->{params}}) {
- if ($p->{type} eq "blob_size") {
- print PYOUT "\t\tcall->blob_size = rxrpc_dec(call);\n";
- next;
- } elsif ($p->{type} eq "bulk_size") {
- print PYOUT "\t\tcall->bulk_count = rxrpc_dec(call);\n";
- next;
- }
-
- if ($p->{class} eq "bulk") {
- if ($p->{elem}->{class} eq "struct") {
- print PYOUT "\t\titem = py_decode_", $p->{type}, "(call);\n";
- } elsif ($p->{elem}->{xdr_size} == 4 && $p->{type} =~ /^u/) {
- print PYOUT "\t\titem = PyLong_FromUnsignedLong((", $p->{type}, ")rxrpc_dec(call));\n";
- } elsif ($p->{elem}->{xdr_size} == 4) {
- print PYOUT "\t\titem = PyLong_FromLong((", $p->{type}, ")rxrpc_dec(call));\n";
- } elsif ($p->{elem}->{xdr_size} == 8 && $p->{type} =~ /^u/) {
- print PYOUT "\t\tcall->bulk_u64 = (uint64_t)rxrpc_dec(call) << 32;\n";
- print PYOUT "\t\tcall->bulk_u64 |= (uint64_t)rxrpc_dec(call);\n";
- print PYOUT "\t\titem = PyLong_FromUnsignedLongLong(call->bulk_u64);\n";
- } elsif ($p->{elem}->{xdr_size} == 8) {
- print PYOUT "\t\tcall->bulk_s64 = (int64_t)rxrpc_dec(call) << 32;\n";
- print PYOUT "\t\tcall->bulk_s64 |= (int64_t)rxrpc_dec(call);\n";
- print PYOUT "\t\titem = PyLong_FromLongLong(call->bulk_s64);\n";
- } else {
- die;
- }
-
- print PYOUT "\t\tif (!item)\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tif (PyList_SetItem(obj->x.", $p->{name}, ", call->bulk_index, item) < 0)\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tcall->bulk_index++;\n";
-
- } elsif ($p->{class} eq "blob") {
- if ($p->{elem}->{class} eq "string") {
- print PYOUT "\t\tswitch (py_dec_into_string(call)) {\n";
- } else {
- print PYOUT "\t\tswitch (py_dec_into_buffer(call)) {\n";
- }
- print PYOUT "\t\tcase -1: return -1;\n";
- print PYOUT "\t\tcase 0: break;\n";
- print PYOUT "\t\tcase 1: phase = ", $phix, "; goto select_phase;\n";
- print PYOUT "\t\t}\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 4) {
- print PYOUT "\t\tobj->x.", $p->{name}, " = (", $p->{type}, ")rxrpc_dec(call);\n";
- } elsif ($p->{class} eq "basic" && $p->{xdr_size} == 8) {
- print PYOUT "\t\tobj->x.", $p->{name}, " = (", $p->{type}, ")rxrpc_dec(call) << 32;\n";
- print PYOUT "\t\tobj->x.", $p->{name}, " |= (", $p->{type}, ")rxrpc_dec(call) << 32;\n";
- } elsif ($p->{class} eq "struct") {
- print PYOUT "\t\tobj->x.", $p->{name}, " = py_decode_", $p->{type}, "(call);\n";
- } else {
- die $p->{where}, ": Unsupported type in decode";
- }
-
- if ($p->{class} eq "blob" && $p->{elem}->{class} eq "string") {
- print PYOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tif (call->blob_offset < call->blob_size) {\n";
- print PYOUT "\t\t\tphase = ", $phix, ";\n";
- print PYOUT "\t\t\tgoto select_phase;\n";
- print PYOUT "\t\t}\n";
- } elsif ($p->{class} eq "bulk") {
- print PYOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print PYOUT "\t\t\treturn -1;\n";
- print PYOUT "\t\tif (call->bulk_index < call->bulk_count) {\n";
- print PYOUT "\t\t\tphase = ", $phix, ";\n";
- print PYOUT "\t\t\tgoto select_phase;\n";
- print PYOUT "\t\t}\n";
- }
- }
-
- if ($phase->{type} eq "split") {
- print PYOUT "\t\tswitch (py_rxgen_split_receive(call, 0)) {\n";
- print PYOUT "\t\tcase -1: return -1;\n";
- print PYOUT "\t\tcase 0: break;\n";
- print PYOUT "\t\tcase 1: phase = ", $phix, "; goto select_phase;\n";
- print PYOUT "\t\t}\n";
- #print PYOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- #print PYOUT "\t\t\treturn -1;\n";
- #print PYOUT "\t\tif (call->need_size != 0) {\n";
- #print PYOUT "\t\t\tphase = ", $phix, ";\n";
- #print PYOUT "\t\t\tgoto select_phase;\n";
- #print PYOUT "\t\t}\n";
- }
-
- if ($phase->{type} ne "bulk" && $phase->{type} ne "blob") {
- print PYOUT "\t\tif (rxrpc_post_dec(call) < 0)\n";
- print PYOUT "\t\t\treturn -1;\n";
- }
- }
-
- print PYOUT "\n";
- print PYOUT "\t\t/* --- Phase ", $phix, " --- */\n";
- if ($phase_goto_label == $phix) {
- print PYOUT "\tphase_", $phix, ":\n";
- $phase_goto_label = 0;
- }
- print PYOUT "\t\tcall->phase = ", $phix, ";\n";
- print PYOUT "\t\tcall->need_size = 0;\n";
- print PYOUT "\tdefault:\n";
- print PYOUT "\t\treturn 0;\n";
- print PYOUT "\t}\n";
-
- print PYOUT "}\n";
-}
-
-1;
+++ /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 python type wrapper declarations
-#
-###############################################################################
-sub emit_py_type_wrapper_decls($) {
- my ($s) = @_;
-
- print PYOUT "static PyTypeObject py_", $s->{type}, "Type;\n";
-}
-
-###############################################################################
-#
-# Emit python type wrappers for C structs.
-#
-###############################################################################
-sub emit_py_type_wrapper($) {
- my ($struct) = @_;
-
- push @py_type_defs, {
- name => $struct->{type},
- c_type => "py_" . $struct->{type} . "Type",
- };
-
- # Divide the struct members into single ints, single structs, char arrays
- # (strings) and other arrays
- my @single_ints = ();
- my @single_structs = ();
- my @char_arrays = ();
- my @arrays = ();
- foreach my $m (@{$struct->{members}}) {
- if ($m->{class} eq "array" && $m->{elem}->{type} eq "char") {
- push @char_arrays, $m;
- } elsif ($m->{class} eq "basic") {
- push @single_ints, $m;
- } elsif ($m->{class} eq "struct") {
- push @single_structs, $m;
- } elsif ($m->{class} eq "array") {
- push @arrays, $m;
- } else {
- die $m->{where}, ": Unsupported struct member type";
- }
- }
-
- # Write a python wrapper struct
- #
- # We have a copy of the raw struct and we also have caches for python
- # objects for non-integer, non-array bits of the struct. We populate the
- # caches when these bits are called for and then fold their contents back
- # into the raw struct when we're about to marshal it.
- #
- print PYHDR "\n";
- print PYHDR "struct py_", $struct->{type}, " {\n";
- print PYHDR "\tPyObject_HEAD\n";
- print PYHDR "\tstruct ", $struct->{type}, " x;\n";
- if ($#single_structs + $#arrays > -2) {
- print PYHDR "\tstruct {\n";
- foreach my $m (@single_structs, @arrays) {
- print PYHDR "\t\tPyObject *", $m->{name}, ";\n";
- }
- print PYHDR "\t} c;\n";
- }
- print PYHDR "};\n";
-
- # We need to have a new function if the object is to be allocatable by the
- # Python interpreter
- print PYOUT "\n";
- print PYOUT "static PyObject *\n";
- print PYOUT "py_", $struct->{type}, "_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)\n";
- print PYOUT "{\n";
- print PYOUT "\treturn subtype->tp_alloc(subtype, 1);\n;";
- print PYOUT "}\n";
-
- # We have to have a deallocation function
- print PYOUT "\n";
- print PYOUT "static void\n";
- print PYOUT "py_", $struct->{type}, "_dealloc(struct py_", $struct->{type}, " *self)\n";
- print PYOUT "{\n";
- foreach my $m (@single_structs, @arrays) {
- print PYOUT "\tPy_XDECREF(self->c.", $m->{name}, ");\n";
- }
- print PYOUT "\tPy_TYPE(self)->tp_free((PyObject *)self);\n";
- print PYOUT "}\n";
-
- # Any integer non-array elements are made directly accessible to the Python
- # interpreter
- if (@single_ints) {
- print PYOUT "\n";
- print PYOUT "static PyMemberDef py_", $struct->{type}, "_members[] = {\n";
- foreach my $m (@single_ints) {
- print PYOUT "\t{ \"", $m->{name}, "\", ";
- if ($m->{type} eq "char") { print PYOUT "T_CHAR";
- } elsif ($m->{type} eq "int8_t") { print PYOUT "T_BYTE";
- } elsif ($m->{type} eq "int16_t") { print PYOUT "T_SHORT";
- } elsif ($m->{type} eq "int32_t") { print PYOUT "T_INT";
- } elsif ($m->{type} eq "int64_t") { print PYOUT "T_LONGLONG";
- } elsif ($m->{type} eq "uint8_t") { print PYOUT "T_UBYTE";
- } elsif ($m->{type} eq "uint16_t") { print PYOUT "T_USHORT";
- } elsif ($m->{type} eq "uint32_t") { print PYOUT "T_UINT";
- } elsif ($m->{type} eq "uint64_t") { print PYOUT "T_ULONGLONG";
- } else {
- die $m->{where}, ": Unsupported type \"", $m->{type}, "\"";
- }
- print PYOUT ", offsetof(struct py_", $struct->{type}, ", x.", $m->{name}, "), 0, \"\"},\n";
- }
- print PYOUT "\t{}\n";
- print PYOUT "};\n";
- }
-
- # Non-single integer elements need to be turned into their respective
- # Python types and returned.
-
- # Array elements have to be accessed through ->tp_[sg]etattro() as
- # tuples (int[]/uint[]/struct[]) or strings (char[])
- if ($#single_structs + $#arrays + $#char_arrays > -3) {
- # The attribute get function
- print PYOUT "\n";
- print PYOUT "static PyObject *\n";
- print PYOUT "py_", $struct->{type}, "_getattro(PyObject *_self, PyObject *name)\n";
- print PYOUT "{\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)_self;\n";
- print PYOUT "\n";
- print PYOUT "\tif (PyUnicode_Check(name)) {\n";
-
- foreach my $m (@char_arrays, @single_structs, @arrays) {
- print PYOUT "\t\tif (PyUnicode_CompareWithASCIIString(name, \"", $m->{name}, "\") == 0)\n";
- if ($m->{class} eq "struct") {
- print PYOUT "\t\t\treturn py_rxgen_get_struct(&self->x.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\t\t py_data_to_", $m->{type}, ");\n";
- } elsif ($m->{class} ne "array") {
- die $m->{where}, ": Unsupported type class \"", $m->{class}, "\"";
- } elsif ($m->{elem}->{class} eq "struct") {
- print PYOUT "\t\t\treturn py_rxgen_get_structs(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t sizeof(struct ", $m->{elem}->{type}, "),\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\t\t py_data_to_", $m->{elem}->{type}, ");\n";
- } elsif ($m->{elem}->{class} ne "basic") {
- die $m->{where}, ": Unsupported array type class \"", $m->{elem}->{class}, "\"";
- } elsif ($m->{elem}->{type} eq "char") {
- print PYOUT "\t\t\treturn py_rxgen_get_string(&self->x.", $m->{name}, ", ", $m->{dim}, ");\n";
- } elsif ($m->{elem}->{type} eq "uint8_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_uint8(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } elsif ($m->{elem}->{type} eq "uint16_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_uint16(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } elsif ($m->{elem}->{type} eq "uint32_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_uint32(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } elsif ($m->{elem}->{type} eq "int8_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_int8(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } elsif ($m->{elem}->{type} eq "int16_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_int16(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } elsif ($m->{elem}->{type} eq "int32_t") {
- print PYOUT "\t\t\treturn py_rxgen_get_int32(&self->x.", $m->{name}, ", ", $m->{dim}, ",\n";
- print PYOUT "\t\t\t\t\t\t &self->c.", $m->{name}, ");\n";
- } else {
- die $m->{where}, ": Unsupported array type \"", $m->{elem}->{type}, "\"";
- }
- }
-
- print PYOUT "\t}\n";
- print PYOUT "\n";
- print PYOUT "\treturn PyObject_GenericGetAttr(_self, name);\n";
- print PYOUT "}\n";
- print PYOUT "\n";
-
- # The attribute set function
- print PYOUT "static int\n";
- print PYOUT "py_", $struct->{type}, "_setattro(PyObject *_self, PyObject *name, PyObject *val)\n";
- print PYOUT "{\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)_self;\n";
- print PYOUT "\n";
- print PYOUT "\tif (PyUnicode_Check(name)) {\n";
-
- foreach my $m (@char_arrays, @single_structs, @arrays) {
- print PYOUT "\t\tif (PyUnicode_CompareWithASCIIString(name, \"", $m->{name}, "\") == 0)\n";
- if ($m->{class} eq "struct") {
- print PYOUT "\t\t\treturn py_rxgen_set_struct(&self->c.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\t\t &py_", $m->{type}, "Type, val);\n";
- } elsif ($m->{class} ne "array") {
- die $m->{where}, ": Unsupported type class \"", $m->{class}, "\"";
- } elsif ($m->{elem}->{type} eq "char") {
- print PYOUT "\t\t\treturn py_rxgen_set_string(&self->x.", $m->{name}, ", ", $m->{dim}, ", val);\n";
- } elsif ($m->{elem}->{class} eq "basic" ||
- $m->{elem}->{class} eq "struct") {
- print PYOUT "\t\t\treturn py_rxgen_set_array(", $m->{dim}, ", &self->c.", $m->{name}, ", val);\n";
- } else {
- die $m->{where}, ": Unsupported array type \"", $m->{elem}->{type}, "\"";
- }
- }
-
- print PYOUT "\t}\n";
- print PYOUT "\n";
- print PYOUT "\treturn PyObject_GenericSetAttr(_self, name, val);\n";
- print PYOUT "}\n";
- print PYOUT "\n";
- }
-
- # Emit the Python type definition
- print PYOUT "static PyTypeObject py_", $struct->{type}, "Type = {\n";
- print PYOUT "\tPyVarObject_HEAD_INIT(NULL, 0)\n";
- print PYOUT "\t\"kafs.", $struct->{type}, "\",\t\t/*tp_name*/\n";
- print PYOUT "\tsizeof(struct py_", $struct->{type}, "),\t/*tp_basicsize*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_itemsize*/\n";
- print PYOUT "\t(destructor)py_", $struct->{type}, "_dealloc, /*tp_dealloc*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_print*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_getattr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_setattr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_compare*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_repr*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_number*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_sequence*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_as_mapping*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_hash */\n";
- print PYOUT "\t0,\t\t\t\t/*tp_call*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_str*/\n";
- if ($#single_structs + $#arrays + $#char_arrays > -3) {
- print PYOUT "\tpy_", $struct->{type}, "_getattro,\n";
- print PYOUT "\tpy_", $struct->{type}, "_setattro,\n";
- } else {
- print PYOUT "\t0,\t\t\t\t/*tp_getattro*/\n";
- print PYOUT "\t0,\t\t\t\t/*tp_setattro*/\n";
- }
- print PYOUT "\t0,\t\t\t\t/*tp_as_buffer*/\n";
- print PYOUT "\tPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/\n";
- if (@comments) {
- print PYOUT "\t";
- foreach my $c (@comments) {
- $c =~ s/\s+$//;
- $c =~ s/^\s+//;
- next if ($c eq "/*" || $c eq "*/");
- $c =~ s/^[*] //;
- $c =~ s/^[*]$//;
- print PYOUT "\n\t\t\"", $c, "\\n\"";
- }
- print PYOUT ",\n";
- } else {
- print PYOUT "\t\"\",\t\t\t/* tp_doc */\n";
- }
- print PYOUT "\t0,\t\t\t\t/* tp_traverse */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_clear */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_richcompare */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_weaklistoffset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_iter */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_iternext */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_methods */\n";
- if (@single_ints) {
- print PYOUT "\tpy_", $struct->{type}, "_members,\n";
- } else {
- print PYOUT "\t0,\t\t\t/* tp_members */\n";
- }
- print PYOUT "\t0,\t\t\t\t/* tp_getset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_base */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_dict */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_descr_get */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_descr_set */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_dictoffset */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_init */\n";
- print PYOUT "\t0,\t\t\t\t/* tp_alloc */\n";
- print PYOUT "\tpy_", $struct->{type}, "_new,\n";
- print PYOUT "};\n";
-
- # Emit a function to allocate such a type
- print PYHDR "extern PyObject *kafs_new_py_", $struct->{type}, "(PyObject *, PyObject *);\n";
-
- print PYOUT "\n";
- print PYOUT "PyObject *\n";
- print PYOUT "kafs_new_py_", $struct->{type}, "(PyObject *_self, PyObject *args)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *obj = _PyObject_New(&py_", $struct->{type}, "Type);\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)obj;\n";
- print PYOUT "\tif (!obj)\n";
- print PYOUT "\t\treturn PyExc_MemoryError;\n";
- print PYOUT "\tmemset(&self->x, 0, sizeof(self->x));\n";
- if ($#single_structs + $#arrays > -2) {
- print PYOUT "\tmemset(&self->c, 0, sizeof(self->c));\n";
- }
- print PYOUT "\treturn obj;\n";
- print PYOUT "}\n";
-
- # Emit a function to create an object of this type from raw data
- print PYHDR "extern PyObject *py_data_to_", $struct->{type}, "(const void *);\n";
-
- print PYOUT "\n";
- print PYOUT "PyObject *py_data_to_", $struct->{type}, "(const void *data)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *obj = _PyObject_New(&py_", $struct->{type}, "Type);\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)obj;\n";
- print PYOUT "\tif (!obj)\n";
- print PYOUT "\t\treturn PyExc_MemoryError;\n";
- print PYOUT "\tmemcpy(&self->x, data, sizeof(self->x));\n";
- if ($#single_structs + $#arrays > -2) {
- print PYOUT "\tmemset(&self->c, 0, sizeof(self->c));\n";
- }
- print PYOUT "\treturn obj;\n";
- print PYOUT "}\n";
-
- # Emit a function to unmarshal on object of this type.
- print PYOUT "\n";
- print PYOUT "PyObject *py_decode_", $struct->{type}, "(struct rx_call *call)\n";
- print PYOUT "{\n";
- print PYOUT "\tPyObject *obj = _PyObject_New(&py_", $struct->{type}, "Type);\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)obj;\n";
- print PYOUT "\tif (!obj)\n";
- print PYOUT "\t\treturn PyExc_MemoryError;\n";
- print PYOUT "\trxgen_decode_", $struct->{type}, "(call, &self->x);\n";
- if ($#single_structs + $#arrays > -2) {
- print PYOUT "\tmemset(&self->c, 0, sizeof(self->c));\n";
- }
- print PYOUT "\treturn obj;\n";
- print PYOUT "}\n";
-
- # Emit a function to premarshal such a type. This checks the Python object
- # type and folds the contents of the cached Python objects into their raw
- # fields.
- #
- print PYHDR "extern int py_premarshal_", $struct->{type}, "(PyObject *);\n";
-
- print PYOUT "\n";
- print PYOUT "int py_premarshal_", $struct->{type}, "(PyObject *_self)\n";
- print PYOUT "{\n";
- print PYOUT "\tstruct py_", $struct->{type}, " *self = (struct py_", $struct->{type}, " *)_self;\n";
-
- # Check that the type we've been given is the right one
- print PYOUT "\n";
- print PYOUT "\tif (!PyObject_TypeCheck(self, &py_", $struct->{type}, "Type)) {\n";
- print PYOUT "\t\tPyErr_Format(PyExc_TypeError, \"Expected object of type ", $struct->{type}, "\");\n";
- print PYOUT "\t\treturn -1;\n";
- print PYOUT "\t}\n";
-
- if ($#single_structs + $#arrays > -2) {
- print PYOUT "\n";
- my $first = 1;
- foreach my $m (@single_structs, @arrays) {
- if ($first) {
- print PYOUT "\tif (";
- $first = 0;
- } else {
- print PYOUT " ||\n";
- print PYOUT "\t ";
- }
-
- if ($m->{class} eq "struct") {
- print PYOUT "py_rxgen_premarshal_struct(&self->x.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t sizeof(struct ", $m->{type}, "),\n";
- print PYOUT "\t\t\t\t offsetof(struct py_", $m->{type}, ", x),\n";
- print PYOUT "\t\t\t\t self->c.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t py_premarshal_", $m->{type}, ") < 0";
- } elsif ($m->{class} ne "array") {
- die $m->{where}, ": Unsupported type class \"", $m->{class}, "\"";
- } elsif ($m->{elem}->{class} eq "struct") {
- print PYOUT "py_rxgen_premarshal_structs(&self->x.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\t", $m->{dim}, ", sizeof(struct ", $m->{elem}->{type}, "),\n";
- print PYOUT "\t\t\t\t\toffsetof(struct py_", $m->{elem}->{type}, ", x),\n";
- print PYOUT "\t\t\t\t\tself->c.", $m->{name}, ",\n";
- print PYOUT "\t\t\t\t\tpy_premarshal_", $m->{elem}->{type}, ") < 0";
- } elsif ($m->{elem}->{class} ne "basic") {
- die $m->{where}, ": Unsupported array type class \"", $m->{elem}->{class}, "\"";
- } elsif ($m->{elem}->{type} eq "uint8_t") {
- print PYOUT "py_rxgen_premarshal_uint8(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } elsif ($m->{elem}->{type} eq "uint16_t") {
- print PYOUT "py_rxgen_premarshal_uint16(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } elsif ($m->{elem}->{type} eq "uint32_t") {
- print PYOUT "py_rxgen_premarshal_uint32(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } elsif ($m->{elem}->{type} eq "int8_t") {
- print PYOUT "py_rxgen_premarshal_int8(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } elsif ($m->{elem}->{type} eq "int16_t") {
- print PYOUT "py_rxgen_premarshal_int16(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } elsif ($m->{elem}->{type} eq "int32_t") {
- print PYOUT "py_rxgen_premarshal_int32(&self->x.", $m->{name}, ", ", $m->{dim}, ", self->c.", $m->{name}, ") < 0";
- } else {
- die $m->{where}, ": Unsupported array type \"", $m->{elem}->{type}, "\"";
- }
- }
-
- print PYOUT ")\n";
- print PYOUT "\t\treturn -1;\n";
- }
-
- print PYOUT "\treturn 0;\n";
- print PYOUT "}\n";
-}
-
-1;
+++ /dev/null
-#!/usr/bin/perl -w
-#
-# Tool for processing an RxRPC-based RPC API definition in a C header file to
-# produce (un)marshalling code and RPC functions to implement that API.
-#
-# It also produces a python module containing wrappers for the types, RPC
-# functions and constants in the API definition.
-#
-#
-# 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.
-#
-
-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;
-
-die "Need list of xg files to process\n" if ($#ARGV < 0);
-
-our @structs = (); # Structure definitions
-our %struct_sizes = (); # Structure sizes
-our @funcs = (); # Functions in declaration order
-our %func_names = (); # Function name uniquifier
-our %constants = (); # Constants
-our %packages = (); # Packages
-our $abort_codes = (); # Abort codes
-our %abort_syms = (); # Abort symbol to code map
-our %abort_ids = (); # Abort code to symbol map
-our $abort_count = 0; # Number of abort codes
-our @py_type_defs = (); # Python type definitions
-our @py_func_defs = (); # Python function definitions
-
-$constants{RXRPC_SECURITY_PLAIN} = { name => "RXRPC_SECURITY_PLAIN", val => 0 };
-$constants{RXRPC_SECURITY_AUTH} = { name => "RXRPC_SECURITY_AUTH", val => 1 };
-$constants{RXRPC_SECURITY_ENCRYPT} = { name => "RXRPC_SECURITY_ENCRYPT", val => 2 };
-
-#
-# Divide the lines from the files up into typed collections
-#
-my $pkg = 0;
-my $struct = 0;
-my $func = 0;
-my $cpp_exclude = 0;
-my $error_codes = 0;
-my $comment_discard = 0;
-
-my @files = @ARGV;
-my $file = "";
-my $where = "";
-
-###############################################################################
-#
-# Handle defined types.
-#
-# Each type is specified by a hash of the following elements:
-#
-# class Complexity class (basic, string, struct, blob, array, bulk)
-# type Basic/struct type (char, {u,}int{8,16,32,64}_t, opaque, struct name)
-# elem Ref to element type def (if array/bulk)
-# multi 1 if array or bulk type, 0 otherwise
-# dim Number of elements in array or max elements in bulk array (if array/bulk)
-# members Members of struct
-# xdr_size Size of XDR encoded object
-# where Where defined in file
-# banner Banner comment
-#
-# Members/parameters take a copy of their parent type's hash and add:
-#
-# name Member or parameter name
-# ptr "*" if a pointer
-# dir Direction (IN, OUT or INOUT)
-#
-###############################################################################
-# Defined types
-our %types = (
- "char" => { class => "basic", type => "char", xdr_size => 4, multi => 0, },
- "int8_t" => { class => "basic", type => "int8_t", xdr_size => 4, multi => 0, },
- "int16_t" => { class => "basic", type => "int16_t", xdr_size => 4, multi => 0, },
- "int32_t" => { class => "basic", type => "int32_t", xdr_size => 4, multi => 0, },
- "int64_t" => { class => "basic", type => "int64_t", xdr_size => 8, multi => 0, },
- "uint8_t" => { class => "basic", type => "uint8_t", xdr_size => 4, multi => 0, },
- "uint16_t" => { class => "basic", type => "uint16_t", xdr_size => 4, multi => 0, },
- "uint32_t" => { class => "basic", type => "uint32_t", xdr_size => 4, multi => 0, },
- "uint64_t" => { class => "basic", type => "uint64_t", xdr_size => 8, multi => 0, },
- "string" => { class => "string", type => "char", xdr_size => 4, multi => 0, },
- "opaque" => { class => "opaque", type => "void", xdr_size => 4, multi => 0, },
- );
-
-sub look_up_type($)
-{
- my ($type) = @_;
-
- die $where, ": Undefined type '$type'\n" unless exists $types{$type};
- return $types{$type};
-}
-
-sub define_type($$)
-{
- my ($new_type, $as) = @_;
- die $where, ": Redefining type '$new_type'\n" if exists $types{$new_type};
- $as->{where} = $where;
- $types{$new_type} = $as;
-}
-
-sub define_typedef($$$)
-{
- my ($new_type, $as, $flags) = @_;
-
- my $type = look_up_type($as);
-
- my %combined = %{$type};
-
- if (exists $flags->{class} && $flags->{class} eq "bulk") {
- if ($type->{class} eq "string" ||
- $type->{class} eq "opaque") {
- $flags->{class} = "blob";
- }
- }
-
- if (exists $flags->{class} &&
- ($flags->{class} eq "blob" ||
- $flags->{class} eq "bulk" ||
- $flags->{class} eq "array")) {
- die $where, ": Typedef'ing array/bulk as array/bulk not supported\n"
- if ($type->{multi});
- $combined{multi} = 1;
- $combined{class} = $flags->{class};
- $combined{elem} = $type;
- $combined{dim} = $flags->{dim} if (exists $flags->{dim});
- $combined{xdr_size} *= $combined{dim} if ($flags->{class} eq "array");
- }
-
- die if (exists $combined{dim} && $combined{dim} eq -1);
-
- define_type($new_type, \%combined);
-}
-
-###############################################################################
-#
-# Parse an xg interface definition
-#
-###############################################################################
-sub parse_xg($) {
- my ($filename) = @_;
- $file = $filename;
- open my $APIHDR, "<$filename" || die $filename;
- while (my $line = <$APIHDR>) {
- my $pre_comment = "";
- $where = $file . ':' . $. ;
-
- # Detect #if 0/#endif pairs to exclude parts
- if ($line =~ m@^#\s*if\s+0@) {
- die $where, ": Embedded #if 0 clause\n" if $cpp_exclude;
- $cpp_exclude = 1;
- next;
- }
-
- if ($line =~ m@^#\s*endif@) {
- die $where, ": Unbalanced #endif\n" unless $cpp_exclude;
- $cpp_exclude = 0;
- next;
- }
-
- next if $cpp_exclude;
-
- chomp($line);
-
- # Extract error codes
- if ($line eq "/* Error codes */") {
- $error_codes = 1;
- next;
- }
-
- $error_codes = 0 if ($line eq "");
-
- # Discard comments
- my $line_comment = "";
-find_comment_terminator:
- if ($comment_discard) {
- # Find the terminator for a comment we're discarding
- if ($line =~ m@(.*)[*]/(.*)@) {
- $line_comment = $1;
- $line = $pre_comment . $2;
- $comment_discard = 0;
- } else {
- $line = $pre_comment;
- goto discarded_comments if ($line);
- next;
- }
- }
-
- if ($line =~ m@(.*)/[*](.*)@) {
- $pre_comment = $1;
- $line = $2;
- $comment_discard = 1;
- goto find_comment_terminator;
- }
-
-discarded_comments:
- # Remove leading/trailing whitespace and distil interior whitespace
- # down to a single space. Also remove whitespace next to symbols
- # (excluding underscores) and remove blank lines.
- $line =~ s/^\s+//;
- $line =~ s/\s+$//;
- $line =~ s/\s+/\t/g; # Convert all whitespace to single tabs as an intermediate step
- # Convert any tab surrounded by two numbers/symbols into a space
- $line =~ s!([a-zA-Z0-9_])\t([a-zA-Z0-9_])!$1 $2!g;
- # Discard any remaining tabs (have an adjacent symbol)
- $line =~ s!\t!!g;
- next if (!$line);
-
- $line_comment =~ s/^\s+//;
- $line_comment =~ s/\s+$//;
- $line_comment =~ s/\s+/ /g;
-
- #print "'$line'\n";
-
- # Complain about #defines
- die $where, ": Use const not #define" if ($line =~ /^#define/);
-
- # Extract package prefix
- if ($line =~ /^package\s+([A-Za-z_][A-Za-z0-9_]*)/) {
- my $prefix = $1;
- my $name = $prefix;
- $name =~ s/_$//;
- $pkg = {
- name => $name,
- prefix => $prefix,
- abort_codes => [],
- };
- $packages{$prefix} = $pkg;
- $abort_codes = $pkg->{abort_codes};
- next;
- }
-
- #######################################################################
- # Extract constants
- #
- if ($line =~ /^const ([A-Za-z0-9_]+)=(.*);/) {
- my $c = $1;
- my $v = $2;
- die $where, ": Duplicate constant $c (original at ", $constants{$c}->{where}, ": )"
- if (exists $constants{$c});
- $v =~ s/^ //;
- $v =~ s/ $//;
- $constants{$c} = { name => $c,
- val => $v,
- where => $where,
- };
- if ($error_codes) {
- if ($v < 0) {
- $v = 0xffffffff + $v + 1;
- }
-
- die $where, ": Duplicate abort ID"
- if (exists $abort_ids{$v});
-
- my %abort = (
- sym => $c,
- id => $v,
- msg => $line_comment,
- );
-
- push @{$abort_codes}, \%abort;
- $abort_syms{$c} = \%abort;
- $abort_ids{$v} = \%abort;
- $abort_count++;
- }
- next;
- }
-
- #######################################################################
- # Extract typedefs
- #
- if ($line =~ /^typedef ([a-zA-Z_][a-zA-Z0-9_]*) ([a-zA-Z_][a-zA-Z0-9_]*);/) {
- define_typedef($2, $1, { });
- next;
- }
-
- if ($line =~ /^typedef ([a-zA-Z_][a-zA-Z0-9_]*) ([a-zA-Z_][a-zA-Z0-9_]*)<>;/) {
- define_typedef($2, $1, { class => "bulk" });
- next;
- }
-
- if ($line =~ /^typedef ([a-zA-Z_][a-zA-Z0-9_]*) ([a-zA-Z_][a-zA-Z0-9_]*)<([a-zA-Z0-9_]+)>;/) {
- define_typedef($2, $1, { class => "bulk", dim => $3 });
- next;
- }
-
- #######################################################################
- # Extract structures
- #
- if ($line =~ /^struct ([a-zA-Z_][a-zA-Z0-9_]*){/) {
- my %type = (
- class => "struct",
- type => $1,
- members => [],
- xdr_size => 0,
- );
- define_type($1, \%type);
- push @structs, \%type;
- $struct = \%type;
- next;
- }
-
- if ($line =~ /};/ && $struct) {
- $struct = 0;
- next;
- }
-
- # Extract structure members
- if ($struct) {
- if ($line =~ /([a-zA-Z_][a-zA-Z0-9_]*) ([a-zA-Z_][a-zA-Z0-9_]*);/) {
- my %member = %{look_up_type($1)};
- die $where, ": Don't support bulk constructs in structs\n"
- if ($member{class} eq "bulk" || $member{class} eq "blob");
- $member{name} = $2;
- $member{where} = $where;
- push $struct->{members}, \%member;
- $struct->{xdr_size} += $member{xdr_size};
- #print "nonarray $2\n";
- } elsif ($line =~ /([a-zA-Z_][a-zA-Z0-9_]*) ([a-zA-Z_][a-zA-Z0-9_]*)\[([^]]+)\];/) {
- my $element = look_up_type($1);
- die $where, ": Don't support arrays of bulk constructs or arrays\n"
- if ($element->{multi});
-
- my %member = ();
- $member{class} = "array";
- $member{elem} = $element;
- $member{name} = $2;
- $member{dim} = $3;
- $member{where} = $where;
-
- if ($member{dim} =~ /^[0-9]+$/) {
- $constants{$member{dim}} = {
- val => $member{dim},
- };
- } elsif (exists $constants{$member{dim}}) {
- } else {
- die $where, ": No constant for [", $member{dim}, "]\n"
- }
- $member{xdr_size} = $constants{$member{dim}}->{val} * $element->{xdr_size};
- push $struct->{members}, \%member;
- $struct->{xdr_size} += $member{xdr_size};
- #print "array $2\n";
- } else {
- die $where, ": Unrecognised struct member '$line'";
- }
- }
-
- #######################################################################
- # Extract functions
- #
- if (!$func && $line =~ /^([a-zA-Z_][a-zA-Z0-9_]*)\((.*)$/) {
- #print "func $1\n";
- my $name = $1;
- die $where, ": No package set" unless $pkg;
- my $func_name = $pkg->{prefix} . $name;
- my %function = (
- pkg => $pkg,
- rawname => $name,
- name => $func_name,
- params => [],
- where => $where,
- split => 0,
- multi => 0,
- );
- die $where, ": Duplicate function name '$func_name'\n"
- if (exists($func_names{$func_name}));
- $func_names{$func_name} = \%function;
- push @funcs, \%function;
- $func = \%function;
- $line = $2;
- }
-
- # Extract function parameters
- if ($func) {
- parse_param:
- my $dir = "";
- my $term = 0;
- my $bulk_dim = 0;
-
- # Split parameters that are on the same line and divide the last
- # parameter from the function closure
- my $clause = $line;
- if ($line =~ /^([^,)]*),(.*)$/) {
- $clause = $1;
- $line = $2;
- } elsif ($line =~ /^([^)]*)([)].*)$/) {
- $clause = $1;
- $line = $2;
- }
-
- #print "CLAUSE: '", $clause, "'\n";
-
- $dir = $1 if ($clause =~ s@^(IN|OUT|INOUT) @@);
-
- if ($clause =~ s@<>@@) {
- $bulk_dim = -1;
- } elsif ($clause =~ s@<([0-9]+)>@@) {
- $bulk_dim = $1;
- $constants{$bulk_dim} = {
- val => $bulk_dim,
- };
- } elsif ($clause =~ s@<([a-zA-Z_][a-zA-Z0-9_]*)>@@) {
- die $where, ": No constant for $1\n" unless exists $constants{$1};
- $bulk_dim = $1;
- }
-
- if ($clause =~ /([a-zA-Z_][a-zA-Z0-9_]*)([*]*| )([a-zA-Z_][a-zA-Z0-9_]*)/) {
- die $where, ": No parameter direction specified\n" unless $dir;
-
- my $type = look_up_type($1);
- my %param = %{$type};
- $param{ptr} = $2;
- $param{name} = $3;
- $param{dir} = $dir;
- $param{where} = $where;
-
- die $where, ": 'string' only supported with IN\n"
- if ($param{type} eq "string" && $dir ne "IN");
- die $where, ": Array parameters not supported\n"
- if ($param{class} eq "array");
- if ($bulk_dim) {
- die $where, ": Bulk-of-bulk parameters not supported\n"
- if ($param{class} eq "bulk");
- if ($type->{class} eq "string" ||
- $type->{class} eq "opaque") {
- $param{class} = "blob";
- } else {
- $param{class} = "bulk";
- }
- $param{elem} = $type;
- $param{dim} = $bulk_dim unless $bulk_dim eq -1;
- }
-
- $param{ptr} = "*" if ($type->{class} eq "string");
-
- #print "- ", $1, " ", $param{name}, " ISA ", $param{class}, ".", $param{type}, " ", $param{dir}, "\n";
- push $func->{params}, \%param;
-
- } elsif ($clause eq "") {
- # No parameter here
- } else {
- die $where, ": Unhandled RPC call parameter '$clause'";
- }
-
- next unless ($line);
- goto parse_param unless ($line =~ /^[)]/);
-
- # Parse the function termination
- if ($line =~ s/[)]=([a-zA-Z0-9_]*);$//) {
- $term = 1;
- $func->{opcode} = $1;
- } elsif ($line =~ s/[)]split=([a-zA-Z0-9_]*);$//) {
- $func->{split} = 1;
- $term = 1;
- $func->{opcode} = $1;
- } elsif ($line =~ s/[)]multi=([a-zA-Z0-9_]*);$//) {
- $func->{multi} = 1;
- $term = 1;
- $func->{opcode} = $1;
- } else {
- die $where, ": Unexpected line termination '$line'";
- }
-
- if ($term) {
- $func = 0;
- next;
- }
- }
- }
-
- close($APIHDR);
- $pkg = 0;
-}
-
-foreach my $file (@files) {
- parse_xg($file);
-}
-
-print "Extracted ", scalar keys %constants, " constants\n";
-print "Extracted ", scalar @structs, " structs\n";
-print "Extracted ", scalar keys %types, " types\n";
-print "Extracted ", scalar @funcs, " functions\n";
-
-my @no_abort_codes = ();
-foreach $_ (sort(keys(%packages))) {
- my $pkg = $packages{$_};
- if (@{$pkg->{abort_codes}}) {
- print "Extracted ", scalar @{$pkg->{abort_codes}}, " ", $pkg->{name}, " abort codes\n";
- } else {
- push @no_abort_codes, $pkg->{name};
- }
-}
-print "No abort codes for ", join(" ", @no_abort_codes), "\n" if (@no_abort_codes);
-
-###############################################################################
-#
-# Create the output files and emit the file prologues.
-#
-###############################################################################
-open RXHDR, ">3_afs_xg.h" || die "3_afs_xg.h";
-print RXHDR "/* AUTOGENERATED */\n";
-#print RXHDR "#define _XOPEN_SOURCE\n";
-print RXHDR "#include <stdint.h>\n";
-print RXHDR "#include \"rxgen.h\"\n";
-
-open RXOUT, ">3_afs_xg.c" || die "3_afs_xg.c";
-print RXOUT "/* AUTOGENERATED */\n";
-print RXOUT "#include \"afs_xg.h\"\n";
-print RXOUT "#include <stdio.h>\n";
-print RXOUT "#include <stdlib.h>\n";
-print RXOUT "#include <string.h>\n";
-print RXOUT "#include <unistd.h>\n";
-print RXOUT "#include <errno.h>\n";
-print RXOUT "#include <sys/socket.h>\n";
-print RXOUT "#include <sys/param.h>\n";
-print RXOUT "#include <arpa/inet.h>\n";
-print RXOUT "\n";
-
-open PYHDR, ">3_afs_py.h" || die "3_afs_py.h";
-print PYHDR "/* AUTOGENERATED */\n";
-print PYHDR "#include <Python.h>\n";
-print PYHDR "#include \"afs_xg.h\"\n";
-print PYHDR "#include \"py_rxgen.h\"\n";
-
-open PYOUT, ">3_afs_py.c" || die "3_afs_py.c";
-print PYOUT "/* AUTOGENERATED */\n";
-print PYOUT "#include <Python.h>\n";
-print PYOUT "#include \"structmember.h\"\n";
-print PYOUT "#include \"afs_py.h\"\n";
-print PYOUT "#include <arpa/inet.h>\n";
-print PYOUT "\n";
-
-# Declare constants
-print RXHDR "\n";
-foreach my $c (sort keys %constants) {
- print RXHDR "#define $c ", $constants{$c}->{val}, "\n" unless ($c =~ /^[0-9]/)
-}
-
-# Declare types
-foreach my $s (@structs) {
- emit_struct_encdec_decls($s);
- emit_py_type_wrapper_decls($s);
-}
-
-foreach my $s (@structs) {
- emit_struct_encdec($s);
- emit_py_type_wrapper($s);
-}
-
-###############################################################################
-#
-# 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 (@funcs) {
- # Dump the banner comment block
- print RXOUT "/*\n";
- print RXOUT " * RPC Call ", $func->{name}, "\n";
- print RXOUT " */\n";
-
- # Find the Operation ID
- die "Operation ID unspecified for ", $func->{name}, "\n"
- unless exists $func->{opcode};
-
- # Filter the parameters into request and response
- my @request = ();
- my @response = ();
-
- foreach my $p (@{$func->{params}}) {
- #print RXOUT $dir, " ", $type, " ", $name, "\n";
-
- if ($p->{class} eq "basic") {
- ;
- } elsif ($p->{class} eq "struct") {
- die unless (exists $p->{xdr_size});
- } elsif ($p->{class} eq "blob") {
- die $p->{where}, ": No element type" unless (exists $p->{elem});
- if (exists $p->{dim}) {
- die $where, ": Missing constant ", $p->{dim} unless exists $constants{$p->{dim}};
- }
- } elsif ($p->{class} eq "bulk") {
- die $p->{where}, ": No element type" unless (exists $p->{elem});
- die $p->{where}, ": Element has no XDR size" unless (exists $p->{elem}->{xdr_size});
- if (exists $p->{dim} && $p->{elem}->{xdr_size} > 0) {
- die $where, ": Missing constant ", $p->{dim} unless exists $constants{$p->{dim}};
- }
- } else {
- die $p->{where}, ": Unsupported param class \"", $p->{class}, "\"";
- }
-
- if ($p->{dir} eq "IN") {
- push @request, $p;
- } elsif ($p->{dir} eq "OUT") {
- push @response, $p;
- } elsif ($p->{dir} eq "INOUT") {
- push @response, $p;
- push @request, $p;
- }
- }
-
- $func->{request} = \@request;
- $func->{response} = \@response;
-
- emit_func_prototype($func);
- emit_func_decode($func, "client", "response", \@response);
- emit_func_send($func, "request");
- #emit_func_decode($func, "server", "request", \@request);
- #emit_func_send($func, "response");
-
- emit_py_func_param_object($func, "request");
- emit_py_func_param_object($func, "response");
- emit_py_func_bulk_helper($func);
- emit_py_func_decode($func, "client", "response", \@response);
- emit_py_func_decode($func, "server", "request", \@request);
- emit_py_func_simple_sync_call($func);
-}
-
-emit_py_module();