#!/usr/bin/perl

use strict;
use warnings;

use CORBA::IDL;
use CORBA::IDL::parser30;
use CORBA::IDL::symbtab;
use CORBA::Python;
# visitors
use CORBA::IDL::repos_id;
use CORBA::Python::name;
use CORBA::Python::import;
use CORBA::Python::literal;
use CORBA::Python::class;
use CORBA::Python::server;

my $parser = new Parser;
$parser->YYData->{verbose_error} = 1;		# 0, 1
$parser->YYData->{verbose_warning} = 1;		# 0, 1
$parser->YYData->{verbose_info} = 1;		# 0, 1
$parser->YYData->{verbose_deprecated} = 0;	# 0, 1 (concerns only version '2.4' and upper)
$parser->YYData->{symbtab} = new CORBA::IDL::Symbtab($parser);
my $cflags = '-D__idl2pysrv';
if ($Parser::IDL_version lt '3.0') {
	$cflags .= ' -D_PRE_3_0_COMPILER_';
}
if ($^O eq 'MSWin32') {
	$parser->YYData->{preprocessor} = 'cpp -C ' . $cflags;
#	$parser->YYData->{preprocessor} = 'CL /E /C /nologo ' . $cflags;	# Microsoft VC
}
else {
	$parser->YYData->{preprocessor} = 'cpp -C ' . $cflags;
}
$parser->getopts('hi:J:Ovx');
if ($parser->YYData->{opt_v}) {
	print "CORBA::Python $CORBA::Python::VERSION\n";
	print "CORBA::IDL $CORBA::IDL::VERSION\n";
	print "IDL $Parser::IDL_version\n";
	print "$0\n";
	print "Perl $] on $^O\n";
	exit;
}
if ($parser->YYData->{opt_h}) {
	use Pod::Usage;
	pod2usage(-verbose => 1);
}
$parser->YYData->{collision_allowed} = 1;
$parser->Run(@ARGV);
$parser->YYData->{symbtab}->CheckForward();
$parser->YYData->{symbtab}->CheckRepositoryID();

if (exists $parser->YYData->{nb_error}) {
	my $nb = $parser->YYData->{nb_error};
	print "$nb error(s).\n"
}
if (        $parser->YYData->{verbose_warning}
		and exists $parser->YYData->{nb_warning} ) {
	my $nb = $parser->YYData->{nb_warning};
	print "$nb warning(s).\n"
}
if (        $parser->YYData->{verbose_info}
		and exists $parser->YYData->{nb_info} ) {
	my $nb = $parser->YYData->{nb_info};
	print "$nb info(s).\n"
}
if (        $parser->YYData->{verbose_deprecated}
		and exists $parser->YYData->{nb_deprecated} ) {
	my $nb = $parser->YYData->{nb_deprecated};
	print "$nb deprecated(s).\n"
}

if (        exists $parser->YYData->{root}
		and ! exists $parser->YYData->{nb_error} ) {
	$parser->YYData->{root}->visit(new CORBA::IDL::repositoryIdVisitor($parser));
	if (        $Parser::IDL_version ge '3.0'
			and $parser->YYData->{opt_x} ) {
		$parser->YYData->{symbtab}->Export();
	}
	$parser->YYData->{root}->visit(new CORBA::Python::nameVisitor($parser));
	$parser->YYData->{root}->visit(new CORBA::Python::importVisitor($parser));
	$parser->YYData->{root}->visit(new CORBA::Python::literalVisitor($parser, 'server'));
	$parser->YYData->{root}->visit(new CORBA::Python::serverVisitor($parser));
}

__END__

=head1 NAME

idl2pysrv - IDL compiler to Python RPC-GIOP skeleton server

=head1 SYNOPSIS

idl2pysrv [options] I<spec>.idl

=head1 OPTIONS

All options are forwarded to C preprocessor, except -h -i -J -v -x.

With the GNU C Compatible Compiler Processor, useful options are :

=over 8

=item B<-D> I<name>

=item B<-D> I<name>=I<definition>

=item B<-I> I<directory>

=item B<-I->

=item B<-nostdinc>

=back

Specific options :

=over 8

=item B<-h>

Display help.

=item B<-i> I<directory>

Specify a path for import (only for version IDL 3.0).

=item B<-J> I<directory>

Specify a path for Python package.

=item B<-v>

Display version.

=item B<-x>

Enable export (only for version IDL 3.0).

=back

=head1 DESCRIPTION

B<idl2pysrv> parses the given input file (IDL) and generates :

=over 4

=item *
a set of Python sources : an optional _I<spec>_skel.py
and I<pkg>_skel/__init__.py for each package

=item *
setup_skel.py

=back

B<idl2pysrv> is a Perl OO application what uses the visitor design pattern.
The parser is generated by Parse::Yapp.

B<idl2pysrv> needs a B<cpp> executable.

CORBA Specifications, including IDL (Interface Language Definition) and
Python Language Mapping are available on E<lt>http://www.omg.org/E<gt>.

=head1 INSTALLATION

After standard Perl installation, you must install the Python package PyIDL :

    setup.py install

=head1 TUTORIAL

=head2 RPC-GIOP

RPC-GIOP is an another RPC (Remote Procedure Call) mecanism.

RPC-GIOP reuses a subset of CORBA GIOP messages, but don't deal with
any CORBA ORB (Object Request Broker). RPC-GIOP reuses the CORBA CDR
(Common Data Representation) transfer syntax.

An interface (a set of operations) is defined with CORBA IDL
(Interface Definition Language).
And this package supplies an client stub generator F<idl2pycli.pl> and
an server skeleton generator F<idl2pysrv.pl>.

RPC-GIOP has a lot of common properties with CORBA GIOP :

=over 8

=item *
needs a reliable transport layer (typically TCP/IP)

=item *
uses a binary format (CDR)

=item *
is interoperable (byte-order)

=back

=head2 EXAMPLE 1

Use F<rpc1> as current directory.

The file F<Calc.idl> describes the interface of a simple calculator.

Nota : the IDL interface Calc is in the global scope.

First, run :

    idl2pysrv.pl Calc.idl

Second, install :

    python setup_skel.py install

Third, create your implementation F<MyCalc.py> which inherits of F<_Calc_skel.py>

    from _Calc_skel import *

    class MyCalc(Calc_skel):
        def Add(self, val1, val2):
            ...

Fourth, create a server F<server.py> that registers your implementation
(a server could register several interfaces).

    servant = RPC_GIOP.Servant()
    myCalc = MyCalc()
    servant.Register('IDL:Calc:1.0', myCalc)

Fifth, run the server and the client (see idl2pycli.pl).

=head1 SEE ALSO

cpp, idl2html, idl2pycli, idl2py

=head1 COPYRIGHT

(c) 2005-2007 Francois PERRAD, France. All rights reserved.

This program and all CORBA::Python modules are distributed
under the terms of the Artistic Licence.

=head1 AUTHOR

Francois PERRAD, francois.perrad@gadz.org

=cut

