#
# Interface Definition Language (OMG IDL CORBA v3.0)
#
package CORBA::Perl::CdrVisitor;
use strict;
use warnings;
our $VERSION = '0.43';
use File::Basename;
use POSIX qw(ctime);
# needs $node->{pl_name} $node->{pl_package} (PerlNameVisitor)
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless $self, $class;
my ($parser, $pkg_prefix) = @_;
$self->{srcname} = $parser->YYData->{srcname};
$self->{srcname_size} = $parser->YYData->{srcname_size};
$self->{srcname_mtime} = $parser->YYData->{srcname_mtime};
$self->{symbtab} = $parser->YYData->{symbtab};
$self->{client} = 1;
$self->{miop} = 0;
$self->{use} = {};
if ($pkg_prefix) {
$self->{pkg_prefix} = $pkg_prefix;
$self->{pkg_prefix} =~ s/\//::/g;
$self->{pkg_prefix} .= '::';
}
else {
$self->{pkg_prefix} = q{};
}
my $filename = basename($self->{srcname}, '.idl') . '.pm';
$self->open_stream($filename);
$self->{done_hash} = {};
$self->{num_key} = 'num_pl_cdr';
$self->{pkg_modif} = 0;
$self->{stringify} = 1;
$self->{id} = 1;
return $self;
}
sub open_stream {
my $self = shift;
my ($filename) = @_;
open $self->{out}, '>', $filename
or die "can't open $filename ($!).\n";
$self->{filename} = $filename;
}
sub _insert_use {
my $self = shift;
my ($module) = @_;
my $FH = $self->{out};
$module = basename($module, '.idl');
unless (exists $self->{use}->{$module}) {
$self->{use}->{$module} = 1;
print $FH "use ",$self->{pkg_prefix},$module,";\n";
print $FH "\n";
}
}
sub _get_defn {
my $self = shift;
my ($defn) = @_;
if (ref $defn) {
return $defn;
}
else {
return $self->{symbtab}->Lookup($defn);
}
}
#
# 3.5 OMG IDL Specification (could be specialized)
#
sub visitSpecification {
my $self = shift;
my ($node) = @_;
my $FH = $self->{out};
$self->{pkg_modif} = 0;
print $FH "# ex: set ro:\n";
print $FH "# This file was generated (by ",$0,"). DO NOT modify it.\n";
print $FH "# From file : ",$self->{srcname},", ",$self->{srcname_size}," octets, ",POSIX::ctime($self->{srcname_mtime});
print $FH "\n";
print $FH "use strict;\n";
print $FH "use warnings;\n";
print $FH "\n";
print $FH "package main;\n";
print $FH "\n";
print $FH "use CORBA::Perl::CORBA;\n";
print $FH "use Carp;\n";
print $FH "\n";
if (exists $node->{list_import}) {
foreach (@{$node->{list_import}}) {
$_->visit($self);
}
}
foreach (@{$node->{list_decl}}) {
$self->_get_defn($_)->visit($self);
if ($self->{pkg_modif}) {
$self->{pkg_modif} = 0;
print $FH "package main;\n";
print $FH "\n";
}
}
print $FH "1;\n";
print $FH "\n";
print $FH "# end of file : ",$self->{filename},"\n";
print $FH "\n";
print $FH "# Local variables:\n";
print $FH "# buffer-read-only: t\n";
print $FH "# End:\n";
close $FH;
}
#
# 3.6 Import Declaration
#
sub visitImport {
my $self = shift;
my ($node) = @_;
foreach (@{$node->{list_decl}}) {
$self->{symbtab}->Lookup($_)->visit($self);
}
}
#
# 3.7 Module Declaration
#
sub visitModules {
my $self = shift;
my ($node) = @_;
unless (exists $node->{$self->{num_key}}) {
$node->{$self->{num_key}} = 0;
}
my $module = ${$node->{list_decl}}[$node->{$self->{num_key}}];
$module->visit($self);
$node->{$self->{num_key}} ++;
}
sub visitModule {
my $self = shift;
my ($node) = @_;
my $FH = $self->{out};
if ($self->{srcname} eq $node->{filename}) {
my $defn = $self->{symbtab}->Lookup($node->{full});
$self->{pkg_modif} = 0;
print $FH "#\n";
print $FH "# begin of module ",$defn->{pl_package},"\n";
print $FH "#\n";
print $FH "\n";
print $FH "package ",$defn->{pl_package},";\n";
print $FH "\n";
print $FH "use Carp;\n";
print $FH "use CORBA::Perl::CORBA;\n";
print $FH "\n";
foreach (@{$node->{list_decl}}) {
$self->_get_defn($_)->visit($self);
if ($self->{pkg_modif}) {
$self->{pkg_modif} = 0;
print $FH "package ",$defn->{pl_package},";\n";
print $FH "\n";
}
}
print $FH "\n";
print $FH "#\n";
print $FH "# end of module ",$defn->{pl_package},"\n";
print $FH "#\n";
print $FH "\n";
$self->{pkg_modif} = 1;
}
else {
$self->_insert_use($node->{filename});
}
}
#
# 3.8 Interface Declaration (could be specialized)
#
sub visitBaseInterface {
my $self = shift;
my($node) = @_;
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
$self->{pkg_modif} = 0;
print $FH "#\n";
print $FH "# begin of '",ref $node,"' ",$node->{pl_package},"\n";
print $FH "#\n";
print $FH "\n";
print $FH "package ",$node->{pl_package},";\n";
print $FH "\n";
print $FH "use CORBA::Perl::CORBA;\n";
print $FH "use Carp;\n";
print $FH "\n";
foreach (@{$node->{list_decl}}) {
my $defn = $self->_get_defn($_);
if ( $defn->isa('Operation')
or $defn->isa('Attributes')
or $defn->isa('Initializer')
or $defn->isa('StateMembers') ) {
next;
}
$defn->visit($self);
if ($self->{pkg_modif}) {
$self->{pkg_modif} = 0;
print $FH "package ",$node->{pl_package},";\n";
print $FH "\n";
}
}
print $FH "\n";
print $FH "#\n";
print $FH "# end of '",ref $node,"' ",$node->{pl_package},"\n";
print $FH "#\n";
print $FH "\n";
$self->{pkg_modif} = 1;
}
else {
$self->_insert_use($node->{filename});
}
}
sub visitForwardBaseInterface {
# empty
}
#
# 3.9 Value Declaration
#
#
# 3.10 Constant Declaration
#
sub visitConstant {
my $self = shift;
my ($node) = @_;
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
print $FH "# ",$node->{pl_package},"::",$node->{pl_name},"\n";
print $FH "sub ",$node->{pl_name}," () {\n";
print $FH "\treturn ",$node->{value}->{pl_literal},";\n";
print $FH "}\n";
print $FH "\n";
}
}
#
# 3.11 Type Declaration
#
sub visitTypeDeclarators {
my $self = shift;
my ($node) = @_;
foreach (@{$node->{list_decl}}) {
$self->_get_defn($_)->visit($self);
}
}
sub visitTypeDeclarator {
my $self = shift;
my ($node) = @_;
my $type = $self->_get_defn($node->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('EnumType')
or $type->isa('SequenceType')
or $type->isa('FixedPtType') ) {
$type->visit($self);
}
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
print $FH "# ",$node->{pl_package},"::",$node->{pl_name}," (typedef)\n";
if (exists $node->{array_size}) {
warn __PACKAGE__,"::visitTypeDecalarator $node->{idf} : empty array_size.\n"
unless (@{$node->{array_size}});
my $n;
print $FH "sub ",$node->{idf},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$value) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
$n = 0;
print $FH "\tlocal \$_ = \$value;\n";
foreach (@{$node->{array_size}}) {
$n ++;
print $FH "\tcroak \"bad size of array '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (scalar(\@{\$_}) == ",$_->{pl_literal},");\n";
print $FH "\tforeach (\@{\$_}) {\n";
}
if (exists $type->{max}) {
print $FH "\t\t",$type->{pl_package},'::',$type->{pl_name},"__marshal(\$r_buffer, \$_, ",$type->{max}->{value},");\n";
}
else {
print $FH "\t\t",$type->{pl_package},'::',$type->{pl_name},"__marshal(\$r_buffer, \$_);\n";
}
while ($n--) {
print $FH "\t}\n";
}
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{idf},"__demarshal {\n";
print $FH "\tmy (\$r_buffer, \$r_offset, \$endian) = \@_;\n";
$n = 0;
foreach (@{$node->{array_size}}) {
$n ++;
print $FH "\tmy \@array",$n," = ();\n";
print $FH "\tfor (my \$idx",$n," = 0; ";
print $FH "\$idx",$n," < ",$_->{pl_literal},"; ";
print $FH "\$idx",$n,"++) {\n";
}
print $FH "\t\tpush \@array",$n,", ";
print $FH $type->{pl_package},'::',$type->{pl_name},"__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
print $FH "\t}\n";
while ($n > 1) {
print $FH "\t\tpush \@array",($n - 1),", ";
print $FH "\\\@array",$n,";\n";
print $FH "\t}\n";
$n --;
}
print $FH "\treturn \\\@array1;\n";
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
my $type2 = $type;
while ( $type2->isa('TypeDeclarator')
and ! exists $type2->{array_size} ) {
$type2 = $self->_get_defn($type2->{type});
}
print $FH "sub ",$node->{idf},"__stringify {\n";
print $FH "\tmy (\$value, \$tab) = \@_;\n";
print $FH "\t\$tab = q{} unless (defined \$tab);\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
$n = 0;
print $FH "\tmy \$str = '{';\n";
print $FH "\tlocal \$_ = \$value;\n";
foreach (@{$node->{array_size}}) {
$n ++;
print $FH "\tcroak \"bad size of array '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (scalar(\@{\$_}) == ",$_->{pl_literal},");\n";
print $FH "\tmy \$first",$n," = 1;\n";
print $FH "\tforeach (\@{\$_}) {\n";
print $FH "\t\tif (\$first",$n,") {\n";
print $FH "\t\t\t\$first",$n," = 0;\n";
print $FH "\t\t}\n";
print $FH "\t\telse {\n";
print $FH "\t\t\t\$str .= ',';\n";
print $FH "\t\t}\n";
unless ($type2->isa('BasicType')) {
print $FH "\t\t\$str .= \"\\n\$tab \";\n";
}
}
if (exists $type->{max}) {
print $FH "\t\t\$str .= ",$type->{pl_package},'::',$type->{pl_name},"__stringify(\$_, \$tab . q{ } x 2, ",$type->{max}->{value},");\n";
}
else {
print $FH "\t\t\$str .= ",$type->{pl_package},'::',$type->{pl_name},"__stringify(\$_, \$tab . q{ } x 2);\n";
}
while ($n--) {
print $FH "\t}\n";
unless ($type2->isa('BasicType')) {
print $FH "\t\$str .= \"\\n\$tab\";\n";
}
print $FH "\t\$str .= '}';\n";
}
print $FH "\treturn \$str;\n";
print $FH "}\n";
print $FH "\n";
}
}
else {
print $FH "sub ",$node->{idf},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$value) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
if (exists $type->{max}) {
print $FH "\t",$type->{pl_package},"::",$type->{pl_name},"__marshal(\$r_buffer, \$value, ",$type->{max}->{value},");\n";
}
else {
print $FH "\t",$type->{pl_package},"::",$type->{pl_name},"__marshal(\$r_buffer, \$value);\n";
}
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{idf},"__demarshal {\n";
print $FH "\tmy (\$r_buffer, \$r_offset, \$endian) = \@_;\n";
print $FH "\treturn ",$type->{pl_package},"::",$type->{pl_name},"__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
print $FH "sub ",$node->{idf},"__stringify {\n";
print $FH "\tmy (\$value, \$tab) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
if (exists $type->{max}) {
print $FH "\treturn ",$type->{pl_package},"::",$type->{pl_name},"__stringify(\$value, \$tab, ",$type->{max}->{value},");\n";
}
else {
print $FH "\treturn ",$type->{pl_package},"::",$type->{pl_name},"__stringify(\$value, \$tab);\n";
}
print $FH "}\n";
print $FH "\n";
}
}
if ($self->{id}) {
print $FH "sub ",$node->{pl_name},"__id () {\n";
print $FH "\treturn \"",$node->{repos_id},"\";\n";
print $FH "}\n";
print $FH "\n";
}
}
}
sub visitNativeType {
# empty
}
#
# 3.11.2 Constructed Types
#
# 3.11.2.1 Structures
#
sub visitStructType {
my $self = shift;
my ($node) = @_;
my $name = $node->{pl_package} . '::' . $node->{pl_name};
return if (exists $self->{done_hash}->{$name});
$self->{done_hash}->{$name} = 1;
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('SequenceType')
or $type->isa('FixedPtType') ) {
$type->visit($self);
}
}
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
print $FH "# ",$name," (struct)\n";
print $FH "sub ",$node->{pl_name},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$value) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
print $FH "\tcroak \"invalid struct for '",$node->{idf},"' (not a HASH reference).\\n\"\n";
print $FH "\t\t\tunless (ref \$value eq 'HASH');\n";
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
print $FH "\tcroak \"no member '",$member->{idf},"' in structure '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (exists \$value->{",$member->{idf},"});\n";
}
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
$self->_member_marshal($member, $node, "\$value->{" . $member->{idf} . "}");
}
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{pl_name},"__demarshal {\n";
print $FH "\tmy (\$r_buffer, \$r_offset, \$endian) = \@_;\n";
print $FH "\tmy \$value = {};\n";
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
$self->_member_demarshal($member, $node, "\$value->{" . $member->{idf} . "}");
}
print $FH "\treturn \$value;\n";
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
print $FH "sub ",$node->{pl_name},"__stringify {\n";
print $FH "\tmy (\$value, \$tab) = \@_;\n";
print $FH "\t\$tab = q{} unless defined (\$tab);\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
print $FH "\tcroak \"invalid struct for '",$node->{idf},"' (not a HASH reference).\\n\"\n";
print $FH "\t\t\tunless (ref \$value eq 'HASH');\n";
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
print $FH "\tcroak \"no member '",$member->{idf},"' in structure '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (exists \$value->{",$member->{idf},"});\n";
}
print $FH "\tmy \$str = \"struct ",$node->{pl_name}," {\";\n";
my $idx = 0;
my $first = 1;
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
if ($first) {
$first = 0;
}
else {
print $FH "\t\$str .= ',';\n";
}
$self->_member_stringify($member, $node, "\$value->{" . $member->{idf} . "}", \$idx);
}
print $FH "\t\$str .= \"\\n\$tab}\";\n";
print $FH "\treturn \$str;\n";
print $FH "}\n";
print $FH "\n";
}
if ($self->{id}) {
print $FH "sub ",$node->{pl_name},"__id () {\n";
print $FH "\treturn \"",$node->{repos_id},"\";\n";
print $FH "}\n";
print $FH "\n";
}
}
}
sub _member_marshal {
my $self = shift;
my ($node, $parent, $val) = @_;
my $tab = $parent->isa('UnionType') ? "\t\t" : "\t";
my $n = 0;
my $type = $self->_get_defn($node->{type});
my $FH = $self->{out};
if (exists $node->{array_size}) {
print $FH $tab,"local \$_ = ",$val,";\n";
foreach (@{$node->{array_size}}) {
$n ++;
print $FH $tab,"croak \"bad size of array '",$node->{idf},"'.\\n\"\n";
print $FH $tab,"\t\tunless (scalar(\@{\$_}) == ",$_->{pl_literal},");\n";
print $FH $tab,"foreach (\@{\$_}) {\n";
}
if (exists $type->{max}) {
print $FH $tab,"\t",$type->{pl_package},'::',$type->{pl_name};
print $FH "__marshal(\$r_buffer, \$_, ",$type->{max}->{value},");\n";
}
else {
print $FH $tab,"\t",$type->{pl_package},'::',$type->{pl_name};
print $FH "__marshal(\$r_buffer, \$_);\n";
}
while ($n--) {
print $FH $tab,"}\n";
}
}
else {
if (exists $type->{max}) {
print $FH $tab,$type->{pl_package},'::',$type->{pl_name};
print $FH "__marshal(\$r_buffer, ",$val,", ",$type->{max}->{value},");\n";
}
else {
print $FH $tab,$type->{pl_package},'::',$type->{pl_name};
print $FH "__marshal(\$r_buffer, ",$val,");\n";
}
}
}
sub _member_demarshal {
my $self = shift;
my ($node, $parent, $val) = @_;
my $tab = $parent->isa('UnionType') ? "\t\t" : "\t";
my $n = 0;
my $FH = $self->{out};
my $type = $self->_get_defn($node->{type});
if (exists $node->{array_size}) {
foreach (@{$node->{array_size}}) {
$n ++;
print $FH $tab,"my \@",$node->{idf},"_array",$n," = ();\n";
print $FH $tab,"for (my \$idx",$n," = 0; ";
print $FH "\$idx",$n," < ",$_->{pl_literal},"; ";
print $FH "\$idx",$n,"++) {\n";
}
print $FH $tab,"\tpush \@",$node->{idf},"_array",$n,", ";
print $FH $type->{pl_package},'::',$type->{pl_name},"__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
print $FH $tab,"}\n";
while ($n > 1) {
print $FH $tab,"\tpush \@",$node->{idf},"_array",($n - 1),", ";
print $FH "\\\@",$node->{idf},"_array",$n,";\n";
print $FH $tab,"}\n";
$n --;
}
print $FH $tab,$val," = \\\@",$node->{idf},"_array1;\n";
}
else {
print $FH $tab,$val," = ";
print $FH $type->{pl_package},'::',$type->{pl_name},"__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
}
}
sub _member_stringify {
my $self = shift;
my ($node, $parent, $val, $r_idx) = @_;
my $tab = $parent->isa('UnionType') ? "\t\t" : "\t";
my $n = 0;
my $type = $self->_get_defn($node->{type});
my $array = q{};
if (exists $node->{array_size}) {
foreach (@{$node->{array_size}}) {
$array .= '[]';
}
}
my $FH = $self->{out};
print $FH $tab,"\$str .= \"\\n\$tab ",$type->{pl_name},$array," ",$node->{pl_name}," = \";\n";
if (exists $node->{array_size}) {
my $type2 = $type;
while ( $type2->isa('TypeDeclarator')
and ! exists $type2->{array_size} ) {
$type2 = $self->_get_defn($type2->{type});
}
print $FH $tab,"local \$_ = ",$val,";\n";
foreach (@{$node->{array_size}}) {
$n ++;
$$r_idx ++;
print $FH $tab,"croak \"bad size of array '",$node->{idf},"'.\\n\"\n";
print $FH $tab,"\t\tunless (scalar(\@{\$_}) == ",$_->{pl_literal},");\n";
print $FH $tab,"\$str .= \"{\";\n";
print $FH $tab,"my \$first",$$r_idx," = 1;\n";
print $FH $tab,"foreach (\@{\$_}) {\n";
print $FH $tab,"\tif (\$first",$$r_idx,") {\n";
print $FH $tab,"\t\t\$first",$$r_idx," = 0;\n";
print $FH $tab,"\t}\n";
print $FH $tab,"\telse {\n";
print $FH $tab,"\t\t\$str .= \",\";\n";
print $FH $tab,"\t}\n";
unless ($type2->isa('BasicType')) {
print $FH $tab,"\$str .= \"\\n\";\n";
}
}
if (exists $type->{max}) {
print $FH $tab,"\t\$str .= ",$type->{pl_package},'::',$type->{pl_name};
print $FH "__stringify(\$_, \$tab . \" \", ",$type->{max}->{value},");\n";
}
else {
print $FH $tab,"\t\$str .= ",$type->{pl_package},'::',$type->{pl_name};
print $FH "__stringify(\$_, \$tab . \" \");\n";
}
while ($n--) {
print $FH $tab,"}\n";
unless ($type2->isa('BasicType')) {
print $FH "\t\t\$str .= \"\\n\";\n";
}
print $FH $tab,"\$str .= \"}\";\n";
}
}
else {
if (exists $type->{max}) {
print $FH $tab,"\$str .= ",$type->{pl_package},'::',$type->{pl_name};
print $FH "__stringify(",$val,", \$tab . \" \", ",$type->{max}->{value},");\n";
}
else {
print $FH $tab,"\$str .= ",$type->{pl_package},'::',$type->{pl_name};
print $FH "__stringify(",$val,", \$tab . \" \");\n";
}
}
}
# 3.11.2.2 Discriminated Unions
#
sub visitUnionType {
my $self = shift;
my ($node) = @_;
my $name = $node->{pl_package} . '::' . $node->{pl_name};
return if (exists $self->{done_hash}->{$name});
$self->{done_hash}->{$name} = 1;
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{element}->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('EnumType')
or $type->isa('SequenceType')
or $type->isa('FixedPtType') ) {
$type->visit($self);
}
}
if ($self->{srcname} eq $node->{filename}) {
my $type = $self->_get_defn($node->{type});
while ($type->isa('TypeDeclarator')) {
$type = $self->_get_defn($type->{type});
}
my $equal;
if ($type->isa('IntegerType')) {
$equal = '==';
}
else {
$equal = 'eq';
}
$type = $self->_get_defn($node->{type});
my $default = undef;
foreach my $case (@{$node->{list_expr}}) { # case
foreach (@{$case->{list_label}}) { # default or expression
$default = $case if ($_->isa('Default'));
}
}
my $FH = $self->{out};
print $FH "# ",$name," (union)\n";
print $FH "sub ",$node->{pl_name},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$union) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$union);\n";
print $FH "\tcroak \"invalid union for '",$node->{idf},"' (not a ARRAY reference).\\n\"\n";
print $FH "\t\t\tunless (ref \$union eq 'ARRAY');\n";
print $FH "\tcroak \"invalid union '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (scalar(\@{\$union}) == 2);\n";
print $FH "\tmy \$d = \${\$union}[0];\n";
print $FH "\tmy \$value = \${\$union}[1];\n";
print $FH "\t",$type->{pl_package},"::",$type->{pl_name},"__marshal(\$r_buffer,\$d);\n";
print $FH "\tif (0) {\n";
print $FH "\t\t# empty\n";
foreach my $case (@{$node->{list_expr}}) { # case
foreach (@{$case->{list_label}}) { # default or expression
unless ($_->isa('Default')) {
print $FH "\t}\n";
print $FH "\telsif (\$d ",$equal," ",$_->{pl_literal},") {\n";
my $member = $self->_get_defn($case->{element}->{value});
$self->_member_marshal($member, $node, "\$value");
}
}
}
if (defined $default) {
print $FH "\t}\n";
print $FH "\telse {\t# default\n";
my $member = $self->_get_defn($default->{element}->{value});
$self->_member_marshal($member, $node, "\$value");
}
else {
print $FH "\t}\n";
print $FH "\telse {\n";
print $FH "\t\tcroak \"invalid discriminator (\$d) for '",$node->{idf},"'.\\n\";\n";
}
print $FH "\t}\n";
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{pl_name},"__demarshal {\n";
print $FH "\tmy (\$r_buffer, \$r_offset, \$endian) = \@_;\n";
print $FH "\tmy \$value = undef;\n";
print $FH "\tmy \$d = ",$type->{pl_package},"::",$type->{pl_name},"__demarshal(\$r_buffer,\$r_offset,\$endian);\n";
print $FH "\tif (0) {\n";
print $FH "\t\t# empty\n";
foreach my $case (@{$node->{list_expr}}) { # case
foreach (@{$case->{list_label}}) { # default or expression
unless ($_->isa('Default')) {
print $FH "\t}\n";
print $FH "\telsif (\$d ",$equal," ",$_->{pl_literal},") {\n";
my $member = $self->_get_defn($case->{element}->{value});
$self->_member_demarshal($member, $node, "\$value");
}
}
}
if (defined $default) {
print $FH "\t}\n";
print $FH "\telse {\t# default\n";
my $member = $self->_get_defn($default->{element}->{value});
$self->_member_demarshal($member, $node, "\$value");
}
else {
print $FH "\t}\n";
print $FH "\telse {\n";
print $FH "\t\tcroak \"invalid discriminator (\$d) for '",$node->{idf},"'.\\n\";\n";
}
print $FH "\t}\n";
print $FH "\treturn [\$d, \$value];\n";
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
print $FH "sub ",$node->{pl_name},"__stringify {\n";
print $FH "\tmy (\$union, \$tab) = \@_;\n";
print $FH "\t\$tab = q{} unless defined (\$tab);\n";
print $FH "\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$union);\n";
print $FH "\tcroak \"invalid union for '",$node->{idf},"' (not a ARRAY reference).\\n\"\n";
print $FH "\t\t\tunless (ref \$union eq 'ARRAY');\n";
print $FH "\tcroak \"invalid union '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\tunless (scalar(\@{\$union}) == 2);\n";
print $FH "\tmy \$d = \${\$union}[0];\n";
print $FH "\tmy \$value = \${\$union}[1];\n";
print $FH "\tmy \$str = \"union ",$node->{pl_name}," {\";\n";
print $FH "\tif (0) {\n";
print $FH "\t\t# empty\n";
my $idx = 0;
foreach my $case (@{$node->{list_expr}}) { # case
foreach (@{$case->{list_label}}) { # default or expression
unless ($_->isa('Default')) {
print $FH "\t}\n";
print $FH "\telsif (\$d ",$equal," ",$_->{pl_literal},") {\n";
my $member = $self->_get_defn($case->{element}->{value});
$self->_member_stringify($member, $node, "\$value", \$idx);
}
}
}
if (defined $default) {
print $FH "\t}\n";
print $FH "\telse {\t# default\n";
my $member = $self->_get_defn($default->{element}->{value});
$self->_member_stringify($member, $node, "\$value", \$idx);
}
else {
print $FH "\t}\n";
print $FH "\telse {\n";
print $FH "\t\tcroak \"invalid discriminator (\$d) for '",$node->{idf},"'.\\n\";\n";
}
print $FH "\t}\n";
print $FH "\t\$str .= \"\\n\$tab}\";\n";
print $FH "\treturn \$str;\n";
print $FH "}\n";
print $FH "\n";
}
if ($self->{id}) {
print $FH "sub ",$node->{pl_name},"__id () {\n";
print $FH "\treturn \"",$node->{repos_id},"\";\n";
print $FH "}\n";
print $FH "\n";
}
}
}
# 3.11.2.3 Constructed Recursive Types and Forward Declarations
#
sub visitForwardStructType {
# empty
}
sub visitForwardUnionType {
# empty
}
# 3.11.2.4 Enumerations
#
sub visitEnumType {
my $self = shift;
my ($node) = @_;
my $name = $node->{pl_package} . '::' . $node->{pl_name};
return if (exists $self->{done_hash}->{$name});
$self->{done_hash}->{$name} = 1;
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
print $FH "# ",$name," (enum)\n";
print $FH "sub ",$node->{pl_name},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$value) = \@_;\n";
print $FH "\tif (0) {\n";
my $idx = 0;
foreach (@{$node->{list_expr}}) {
print $FH "\t}\n";
print $FH "\telsif (\$value eq '",$_->{pl_name},"') {\n";
print $FH "\t\tCORBA::Perl::CORBA::unsigned_long__marshal(\$r_buffer, ",$idx++,");\n";
}
print $FH "\t}\n";
print $FH "\telse {\n";
print $FH "\t\tcroak \"bad value for '",$name,"'.\\n\";\n";
print $FH "\t}\n";
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{pl_name},"__demarshal {\n";
print $FH "\tmy \$value = CORBA::Perl::CORBA::unsigned_long__demarshal(\@_);\n";
print $FH "\tif (0) {\n";
$idx = 0;
foreach (@{$node->{list_expr}}) {
print $FH "\t}\n";
print $FH "\telsif (\$value == ",$idx++,") {\n";
print $FH "\t\treturn '",$_->{pl_name},"';\n";
}
print $FH "\t}\n";
print $FH "\telse {\n";
print $FH "\t\tcroak \"bad value for '",$name,"'.\\n\";\n";
print $FH "\t}\n";
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
print $FH "sub ",$node->{pl_name},"__stringify {\n";
print $FH "\tmy (\$value) = \@_;\n";
print $FH "\treturn \$value;\n";
print $FH "}\n";
print $FH "\n";
}
if ($self->{id}) {
print $FH "sub ",$node->{pl_name},"__id () {\n";
print $FH "\treturn \"",$node->{repos_id},"\";\n";
print $FH "}\n";
print $FH "\n";
}
foreach (@{$node->{list_expr}}) { # enum
print $FH "sub ",$_->{pl_name}," () {\n";
print $FH "\treturn '",$_->{pl_name},"';\n";
print $FH "}\n";
}
print $FH "\n";
}
}
#
# 3.11.3 Template Types
#
sub visitSequenceType {
my $self = shift;
my ($node) = @_;
my $name = $node->{pl_package} . '::' . $node->{pl_name};
return if (exists $self->{done_hash}->{$name});
$self->{done_hash}->{$name} = 1;
if ($self->{srcname} eq $node->{filename}) {
my $type = $self->_get_defn($node->{type});
if ( $type->isa('SequenceType')
or $type->isa('FixedPtType') ) {
$type->visit($self);
}
my $FH = $self->{out};
print $FH "# ",$name," (sequence)\n";
print $FH "sub ",$node->{pl_name},"__marshal {\n";
print $FH "\tmy (\$r_buffer, \$value, \$max) = \@_;\n";
print $FH "\tcroak \"undefined value for '",$node->{pl_name},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
if ( $type->{pl_name} eq 'char'
or $type->{pl_name} eq 'octet' ) {
print $FH "\tcroak \"value '\$value' is not a string.\\n\"\n";
print $FH "\t\t\tif (ref \$value);\n";
print $FH "\tmy \$len = length(\$value);\n";
print $FH "\tcroak \"too long sequence for '",$node->{pl_name},"' (max:\$max).\\n\"\n";
print $FH "\t\t\tif (defined \$max and \$len > \$max);\n";
print $FH "\tCORBA::Perl::CORBA::unsigned_long__marshal(\$r_buffer, \$len);\n";
print $FH "\t\$\$r_buffer .= \$value;\n";
}
else {
print $FH "\tmy \$len = scalar(\@{\$value});\n";
print $FH "\tcroak \"too long sequence for '",$node->{pl_name},"' (max:\$max).\\n\"\n";
print $FH "\t\t\tif (defined \$max and \$len > \$max);\n";
print $FH "\tCORBA::Perl::CORBA::unsigned_long__marshal(\$r_buffer, \$len);\n";
print $FH "\tforeach (\@{\$value}) {\n";
print $FH "\t\t",$type->{pl_package},"::",$type->{pl_name},"__marshal(\$r_buffer, \$_);\n";
print $FH "\t}\n";
}
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{pl_name},"__demarshal {\n";
print $FH "\tmy (\$r_buffer, \$r_offset, \$endian) = \@_;\n";
print $FH "\tmy \$len = CORBA::Perl::CORBA::unsigned_long__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
print $FH "\tmy \@seq = ();\n";
if ( $type->{pl_name} eq 'char'
or $type->{pl_name} eq 'octet' ) {
print $FH "\tmy \$str = substr \$\$r_buffer, \$\$r_offset, \$len;\n";
print $FH "\t\$\$r_offset += \$len;\n";
print $FH "\treturn \$str;\n";
}
else {
print $FH "\twhile (\$len--) {\n";
print $FH "\t\tpush \@seq,",$type->{pl_package},"::",$type->{pl_name},"__demarshal(\$r_buffer, \$r_offset, \$endian);\n";
print $FH "\t}\n";
print $FH "\treturn \\\@seq;\n";
}
print $FH "}\n";
print $FH "\n";
if ($self->{stringify}) {
my $type2 = $type;
while ( $type2->isa('TypeDeclarator')
and ! exists $type2->{array_size} ) {
$type2 = $self->_get_defn($type2->{type});
}
print $FH "sub ",$node->{pl_name},"__stringify {\n";
print $FH "\tmy (\$value, \$tab, \$max) = \@_;\n";
print $FH "\t\$tab = q{} unless (defined \$tab);\n";
print $FH "\tcroak \"undefined value for '",$node->{pl_name},"'.\\n\"\n";
print $FH "\t\t\tunless (defined \$value);\n";
if ($type->{pl_name} eq 'char') {
print $FH "\tcroak \"value '\$value' is not a string.\\n\"\n";
print $FH "\t\t\tif (ref \$value);\n";
print $FH "\tmy \$len = length(\$value);\n";
print $FH "\tcroak \"too long sequence for '",$node->{pl_name},"' (max:\$max).\\n\"\n";
print $FH "\t\t\tif (defined \$max and \$len > \$max);\n";
print $FH "\treturn \"\$value\";\n";
}
else {
if ($type->{pl_name} eq 'octet') {
print $FH "\t\$value = [map ord, split //, \$value];\n";
}
print $FH "\tmy \$len = scalar(\@{\$value});\n";
print $FH "\tcroak \"too long sequence for '",$node->{pl_name},"' (max:\$max).\\n\"\n";
print $FH "\t\t\tif (defined \$max and \$len > \$max);\n";
print $FH "\tmy \$str = '{';\n";
print $FH "\tmy \$first = 1;\n";
print $FH "\tforeach (\@{\$value}) {\n";
print $FH "\t\tif (\$first) {\n";
print $FH "\t\t\t\$first = 0;\n";
print $FH "\t\t}\n";
print $FH "\t\telse {\n";
print $FH "\t\t\t\$str .= ',';\n";
print $FH "\t\t}\n";
unless ($type2->isa('BasicType')) {
print $FH "\t\t\$str .= \"\\n\$tab \";\n";
}
print $FH "\t\t\$str .= ",$type->{pl_package},"::",$type->{pl_name},"__stringify(\$_, \$tab . q{ } x 2);\n";
print $FH "\t}\n";
unless ($type2->isa('BasicType')) {
print $FH "\t\$str .= \"\\n\$tab\";\n";
}
print $FH "\t\$str .= '}';\n";
print $FH "\treturn \$str;\n";
}
print $FH "}\n";
print $FH "\n";
}
}
}
sub visitFixedPtType {
# empty
}
sub visitFixedPtConstType {
# empty
}
#
# 3.12 Exception Declaration
#
sub visitException {
my $self = shift;
my ($node) = @_;
my $name = $node->{pl_package} . '::' . $node->{pl_name};
return if (exists $self->{done_hash}->{$name});
$self->{done_hash}->{$name} = 1;
if (exists $node->{list_expr}) {
warn __PACKAGE__,"::visitException $node->{idf} : empty list_expr.\n"
unless (@{$node->{list_expr}});
foreach (@{$node->{list_expr}}) {
my $type = $self->_get_defn($_->{type});
if ( $type->isa('StructType')
or $type->isa('UnionType')
or $type->isa('SequenceType')
or $type->isa('FixedPtType') ) {
$type->visit($self);
}
}
}
if ($self->{srcname} eq $node->{filename}) {
my $FH = $self->{out};
print $FH "# ",$name," (exception)\n";
print $FH "sub ",$node->{pl_name},"__marshal {\n";
print $FH "\t\tmy (\$r_buffer,\$value) = \@_;\n";
print $FH "\t\tcroak \"undefined value for '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\t\tunless (defined \$value);\n";
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
print $FH "\t\tcroak \"no member '",$member->{idf},"' in structure '",$node->{idf},"'.\\n\"\n";
print $FH "\t\t\t\tunless (exists \$value->{",$member->{idf},"});\n";
}
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
$self->_member_marshal($member, $node, "\$value->{" . $member->{idf} . "}");
}
print $FH "}\n";
print $FH "\n";
print $FH "sub ",$node->{pl_name},"__demarshal {\n";
print $FH "\t\tmy (\$r_buffer,\$r_offset,\$endian) = \@_;\n";
print $FH "\t\tmy \$value = {};\n";
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
$self->_member_demarshal($member, $node, "\$value->{" . $member->{idf} . "}");
}
print $FH "\t\treturn \$value;\n";
print $FH "}\n";
print $FH "\n";
if ($self->{id}) {
print $FH "sub ",$node->{pl_name},"__id () {\n";
print $FH "\treturn \"",$node->{repos_id},"\";\n";
print $FH "}\n";
print $FH "\n";
}
print $FH "package ",$node->{pl_package},"::",$node->{pl_name},";\n";
print $FH "\n";
print $FH "use base qw(CORBA::Perl::CORBA::UserException);\n";
print $FH "\n";
print $FH "sub new {\n";
print $FH "\tmy \$self = shift;\n";
print $FH "\tlocal \$Error::Depth = \$Error::Depth + 1;\n";
print $FH "\t\$self->SUPER::new(\@_);\n";
print $FH "}\n";
print $FH "\n";
print $FH "sub stringify {\n";
print $FH "\tmy \$self = shift;\n";
print $FH "\tmy \$str = \$self->SUPER::stringify() . \"\\n\";\n";
if (scalar(@{$node->{list_member}})) {
foreach (@{$node->{list_member}}) {
my $member = $self->_get_defn($_); # member
print $FH "\t\$str .= \"\\t",$member->{idf}," => \$self->{",$member->{idf},"}\\n\";\n";
}
}
else {
print $FH "\t\$str .= \"\\t(no data)\";\n";
}
print $FH "\t\$str .= sprintf(\" at \%s line \%d.\\n\", \$self->file, \$self->line);\n";
print $FH "\treturn \$str;\n";
print $FH "}\n";
print $FH "\n";
$self->{pkg_modif} = 1;
}
}
#
# 3.13 Operation Declaration (specialized)
#
#
# 3.14 Attribute Declaration
#
sub visitAttribute {
my $self = shift;
my ($node) = @_;
$node->{_get}->visit($self);
$node->{_set}->visit($self) if (exists $node->{_set});
}
#
# 3.15 Repository Identity Related Declarations
#
sub visitTypeId {
# empty
}
sub visitTypePrefix {
# empty
}
#
# XPIDL
#
sub visitCodeFragment {
# empty
}
1;