From 81cc8820890e8dda1a1ec2a33052ce85a5e5684c Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 22 Sep 2015 17:38:42 +0100 Subject: [PATCH] Remove the Perl rxgen Remove the Perl rxgen program as it is now replaced with the Python version. Signed-off-by: David Howells --- rxgen/emit_c_struct.pm | 129 ------ rxgen/emit_c_sync_funcs.pm | 821 ------------------------------------ rxgen/emit_py_module.pm | 160 ------- rxgen/emit_py_sync_funcs.pm | 770 --------------------------------- rxgen/emit_py_types.pm | 398 ----------------- rxgen/rxgen.pl | 631 --------------------------- 6 files changed, 2909 deletions(-) delete mode 100644 rxgen/emit_c_struct.pm delete mode 100644 rxgen/emit_c_sync_funcs.pm delete mode 100644 rxgen/emit_py_module.pm delete mode 100644 rxgen/emit_py_sync_funcs.pm delete mode 100644 rxgen/emit_py_types.pm delete mode 100755 rxgen/rxgen.pl diff --git a/rxgen/emit_c_struct.pm b/rxgen/emit_c_struct.pm deleted file mode 100644 index f5dbb44..0000000 --- a/rxgen/emit_c_struct.pm +++ /dev/null @@ -1,129 +0,0 @@ -# -# 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; diff --git a/rxgen/emit_c_sync_funcs.pm b/rxgen/emit_c_sync_funcs.pm deleted file mode 100644 index 942bce5..0000000 --- a/rxgen/emit_c_sync_funcs.pm +++ /dev/null @@ -1,821 +0,0 @@ -# -# 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; diff --git a/rxgen/emit_py_module.pm b/rxgen/emit_py_module.pm deleted file mode 100644 index 6511a1e..0000000 --- a/rxgen/emit_py_module.pm +++ /dev/null @@ -1,160 +0,0 @@ -# -# 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; diff --git a/rxgen/emit_py_sync_funcs.pm b/rxgen/emit_py_sync_funcs.pm deleted file mode 100644 index 0588b44..0000000 --- a/rxgen/emit_py_sync_funcs.pm +++ /dev/null @@ -1,770 +0,0 @@ -# -# 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; diff --git a/rxgen/emit_py_types.pm b/rxgen/emit_py_types.pm deleted file mode 100644 index 09fa3f1..0000000 --- a/rxgen/emit_py_types.pm +++ /dev/null @@ -1,398 +0,0 @@ -# -# 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; diff --git a/rxgen/rxgen.pl b/rxgen/rxgen.pl deleted file mode 100755 index 54e3bac..0000000 --- a/rxgen/rxgen.pl +++ /dev/null @@ -1,631 +0,0 @@ -#!/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 \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 \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "#include \n"; -print RXOUT "\n"; - -open PYHDR, ">3_afs_py.h" || die "3_afs_py.h"; -print PYHDR "/* AUTOGENERATED */\n"; -print PYHDR "#include \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 \n"; -print PYOUT "#include \"structmember.h\"\n"; -print PYOUT "#include \"afs_py.h\"\n"; -print PYOUT "#include \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(); -- 2.50.1