last modified: November 25 2002
The IDL compiler
Introduction
The Jonathan idl2java Compiler generates the java classes and interfaces necessary to run distributed objects on
the David personality of the Jonathan ORB platform. In its present version, it handles a subset of the IDL Grammar
as described in the CORBA 2.3 specification document of october 1999 (mainly the grammar minus all object
by value related constructions.
The compiler automatically launches jpp a simple preprocessor which implements a subset of
the ansi C preprocessor facilities.
Compiler utilization
The syntax of the compilation command is : idl2java (option_list | idl_File_List)*. The
command idl2java stands here for java org.omg.objectweb.david.tools.idlcompiler.Idl2Java. It could
be implemented through a simple shell script (unix, Linux) or .bat file (dos, windows).
Options and file names can appear several times and be intertwinned in the command line. Option values are then
used from their declaration point until they are redefined. Following options are available in the present version :
- -D jpp_variable, where jpp_variable is a variable to be added as a "defined"
preprocessor variable by the jpp preprocessor.
- -I directory, where directory is a directory to be added to the "include"
list used by the jpp preprocessor. When the jpp preprocessor encounters a #include directive, it first
looks in the . directory and then continues the search in the "include" list. Search is stopped as soon
as a matching file has been found.
- -d directory : Following the standard, java files are generated
in directories organized to mirror the package structure. directory indicates the root for all these
directories. This option is very similar to -d option of the javac compiler. The default value for this option
is -d .
- -p base_package : the compiler builds package names which mirrors the scope hierarchy.
For example java classes for an interface defined in the submodule planet of the submodule star of the module
galaxy belongs to the package : galaxy.stars.planet. When the -p options is used,
base_package is prefixed to the generated package name.
The default value for base_package is the null string.
- -idl2pkg directory : This option implements a feature similar to the -idl2package
option of Visibroker's idl2java. It maps individual IDL module scopes to JAVA packages
and overrides the global -p option.
E.g. ...Idl2Java -p idl -idl2pkg ::CORBA org.omg.CORBA would place the code generated from the CORBA
module in the package org.omg.CORBA but all other code in the idl
package.
- -std : This option generates standard stubs and skeletons (conforming with the standard
jonathan model). This is the default value.
- -poa : This option generates POA files.
- -rmi : This option generates stubs and skeletons conforming with the rmi programming
model.
- -rmiIName name_mapping : On one side RMI naming convention for the tie class and file
rely on the name of the implementation class. IDL naming convention on the other side rely on the interface name.
By default the compiler assumes the implementation class belongs to the same package as the interface
and has a name equal to the interface name appended with Impl.
For example exemple.AlphaCetiImpl is the implementation class of the interface
::exemple::AlphaCeti. This option allows the definition of another
mapping. The name_mapping syntax is interface_name=impl_name where interface_name is an
ABSOLUTE IDL name (i.e. it must start with a ::) and impl_name a complete
java type.
E.g. ... Idl2Java -rmi -rmiIName ::exemple::AlphaCeti=myPackage.BetaAurigae ... fic.idl
- -noTie itfName : This option inhibits the generation of the Tie class for an interface.
It is useful when only the client side code has to be generated and compiled. itfname is an
ABSOLUTE IDL interface name (i.e. it must start with a ::).
This option only works when the rmi option is on.
- -g_include=BOOLOPTION, where BOOLOPTION is either false or true : If BOOLOPTION is false,
no code is generated for interfaces, types, constants, ... defined in an included file.
If BOOLOPTION is true code is generated for all interfaces, types, ... encountered by the compiler.
The default value for this option is false.
- -verbose : the compiler displays the name of the idl file before and after compilation
- -case=BOOLOPTION, where BOOLOPTION is either false or true : indicates whether the
compiler is case sensitive or not. If BOOLOPTION is true, two names differing only by cases are considered
different and do not result in name clashes. This is a non standard behaviour. If BOOLOPTION is false the
compiler reacts to case in full conformance with the CORBA standard. Two names differing only by cases result
in name clashes.The default value for this option is false.
- -silent=BOOLOPTION where BOOLOPTION is either false or true : If BOOLOPTION is true,
the compiler does not display the name of the the file before and after compilation. IF BOOLOPTION is false
this option is equivalent to the -verbose option.
- -fSRule=BOOLOPTION where BOOLOPTION is either false or true : If BOOLOPTION is true, the
compiler handles file scopes in conformance with the standard rule (i.e. the root scope of names starting
with :: is the file scope). If BOOLOPTION is false, the root scope of names starting with :: is the global
scope.
For example :
- java A.idl B.idl, which compiles the A.idl and B.idl files using the default option values. Generated java
files are placed in directories whose root is the current directory.
- java -d ../myapp A.idl -case=TRUE B.Idl -d . -case=FALSE -verbose C.idl which :
- compiles A.idl with the default options. Generated java files are placed in directories whose
root is ../myapp.
- compiles B.idl with the sensitiveoptions enabled. Generated java files are placed in directories whose
root is ../myapp.
- compiles C.idl with the verbose option enabled. Generated java files are placed whose root is the
current directory.
IDL Grammar
The compiler handles the IDL Grammar as described in the CORBA 2.3 specification document of october 1999 with one
main exception : it does not recognize any object by value related constructions.
Main characteristics of the compiler are :
- Constants and litterals : the compiler accepts all IDL types (including wide chars and strings, fixed points, long long, unsigned ...). It accepts corresponding literals for all types and computes arithmetic expressions for most of them (such expressions can be used in constant definition). It performs the concatenation of two contiguous strings. Known limitations and features are :
- fixed type litterals are accepted but no arithmetic is performed
- integer and floating point arithmetic is performed. Overflow and underflow are not formally
tested but are detected through effective evaluation. They correspond then to the Java overflow and underflow
specifications and not the CORBA ones.
- obsolete u,U,l,L in integer constant definitions are accepted and ignored (a warning is displayed)
- no test is performed to detect concatenation of different string types
(for example const string str="hello" L"World";). Concatenation is silently performed.
- Identifiers and scopes : the compiler handles scopes and scoped identifiers in full conformance with the standard.
- name conflict with the target programming language (here java) is tested. The escape mechanism is implemented to avoid
clash name of an identifier with an IDL key word. The leading underscore is ignored during java code generation, when
this suppression does not lead to a conflict with the target language keywords (here java key words).
- There is a single name space per scope (module, interface, struct, union, exception). In particular it is not possible to
reuse the name of a scope inside the scope itself (although there is usually no ambiguity). Following the standard, the
test for checking name clashes against already defined identifiers is not case sensitive, but name look up is case
sensitive.
- scope handling follows the standard. No unicity check is performed (in fact risk only exists in case of interface
multiple inheritance).
- Types : the compiler accepts all basic types, native types. It also accepts all array, sequence,
typedef, struct, union, enum constructions, ... It complies to the standard (I hope). It accepts inner types
(for example, struct defined inside another struct or union) and recursive definitions of struct and exceptions.
- Types Object, interfaces and any are fully treated.
- some consistency tests related to unions are not performed : (i) no type consistency is done between
discriminators and case values. The compiler will not generate an error if one declares a discriminator of
one type and uses constants of other types.. No test on the absence/presence of default label to ensure
that all possible values of the discriminator are accounted for (once and only once).
- TypeCode and Principal are no more considered as basic types. Their names are ::CORBA::TypeCode and
::CORBA::Principal.
- Interfaces : multiple inheritance is treated in accordance with the standard. Known features are :
- Multiple occurrence of an interface in a inheritance specification generates a warning but no error.
The first occurrence is accounted for, the following are ignored. (for example interface gamma :
beta,alpha,beta,delta { .... is equivalent to interface gamma : beta,alpha,delta { .... ).
- No unicity check is performed for operation and attribute names in case of (multiple) inheritance. The existence
of operations having the same name in inherited interfaces may not result in java compilation errors
(if their signature are different), but will result in ambiguous IIOP messages.
- An attribute cannot be redefined in derived classes. The compiler is more strict than the OMG standard,
which accepts redefinition as long as they have the same type.
- The compiler accepts a pseudo modifier for interfaces. This is equivalent to a forward declaration
for a interface provided by the environment.
- The abstract modifier is accepted by the compiler but is not used during java code generation.
- The local modifier is accepted by the compiler and used during java code generation.
- #pragma : they are all treated in accordance with the standard.
An additional pragma has been added : inhibit-code-generation making it
possible to inhibit the code generation of constants, types, interfaces
etc. defined in included files. It is today obsolete since it is the
default behavior of the presen tcompiler (see -g_include option).
std Language mapping
The IDL mapping onto the java language modules complies to the IDL/Java Language Mapping as described in the CORBA specification of June 1999. There are generated classes for each struct, union, exception, enumeration type, for each constant (excepted enum constants), for each interface declared in the IDL file. Classes are stored in separate files. Scopes define packages.
- A type TYP will generate the following classes :
- TYP.java which contains the java class mapping the TYP type.
- TYPHolder.java which contains the holder class.
- TYPHelper.java which contains the helper class.
- A constant CONST (excepted enum constants) will generate the following class :
- CNT.java which contains a java class mapping the IDL constant
- An interface ITF will generate the following classes :
- TYPOperations.java which is a java interface declaring all methods supported by the interface.
- _TYPImplBase.java which is a java class corresponding to the server skeleton
- _TYPstub.java which is a java class corresponding to the client stub
- TYPHolder.java which contains the holder class.
- TYPHelper.java which contains the helper class.
No POA and POAtie classes are generated.
Specific features are :
- Classes related to IDL constants, types, exceptions and interfaces defined in the unnamed IDL module are generated in a special < global > package. This is motivated by a Java language feature that does not allow to designate a class of the unnamed package from a named package.
- Java classes and class fields are generated for IDL constants (in conformance with the orbos document). However the compiler uses the internally computed value whenever the constant is referred to (for example for dimensioning arrays, for checking size limits of strings or sequences, ...).
rmi Language mapping
The IDL mapping onto the java language modules complies to the IDL/Java Language Mapping as described in the CORBA specification of June 1999. There are generated classes for each struct, union, exception, enumeration type, for each constant (excepted enum constants), for each interface declared in the IDL file. Classes are stored in separate files. Scopes define packages.
- A type TYP will generate the following classes :
- TYP.java which contains the java class mapping the TYP type.
- TYPHolder.java which contains the holder class.
- TYPHelper.java which contains the helper class.
- A constant CONST (excepted enum constants) will generate the following class :
- CNT.java which contains a java class mapping the IDL constant
- An interface ITF will generate the following classes :
- _IMPLCLASS_Tie.java which is a java class corresponding to the server skeleton,
where IMPLCLASS is the name of the implementation class (by default TYPImpl or the name given though
the -rmiINaming option).
- _TYPstub.java which is a java class corresponding to the client stub
- TYPHolder.java which contains the holder class.
- TYPHelper.java which contains the helper class.
No POA and POAtie classes are generated.
Specific features are :
- Classes related to IDL constants, types, exceptions and interfaces defined in the unnamed IDL module are generated in a special < global > package. This is motivated by a Java language feature that does not allow to designate a class of the unnamed package from a named package.
- Java classes and class fields are generated for IDL constants (in conformance with the orbos document). However the compiler uses the internally computed value whenever the constant is referred to (for example for dimensioning arrays, for checking size limits of strings or sequences, ...).
Known
bugs and limitations
- The present compiler complains when the file is empty and does not contain at least one
module, or const, or type or interface or java comment to compile.
/etc...
This compiler is made of two separate parts :
- A front end building a tree representation of the idl declarations
- a back end generating the corresponding java code.
The
javacc grammar
The grammar implemented in the compiler is described by the following rules. Note that this grammar is, for historical
reasons not precisely the same as the one specified in the OMG standard. However they seem to be equivalent.
The corresponding front end has been generated with the help of the javacc compiler from metadata.
rule 1) specification :: definition+
rule 2) definition :: (type_dcl | const_dcl | except_dcl | interfacex | module) ";"
rule 3) module :: "module" identifier "{" definition* "}"
rule 4) interfacex :: "pseudo" interfacex1 | "abstract" interfacex1 | "local" interfacex1 | interfacex1
rule 4') interfacex1 :: interface_dcl | forward_dcl
rule 5) interface_dcl :: interface_header "{" interface_body "}"
rule 6) forward_dcl :: "interface" identifier
rule 7) interface_header :: "interface" identifier [ inheritance_spec ]
rule 8) interface_body :: export*
rule 9) export :: (type_dcl | const_dcl | except_dcl | attr_dcl| op_dcl) ";"
rule 10) inheritance_spec :: ":" scoped_name inheritance_spec1*
rule 10') inheritance_spec1 :: "," scoped_name
rule 11) scoped_name :: scoped_name1
rule 11') scoped_name1 :: "::" identifier scoped_name2* identifier scoped_name2*
rule 11") scoped_name2 :: "::" identifier
rule 12) const_dcl :: "const" const_type identifier "=" const_exp
rule 13) const_type :: floating_type | integer_type | char_type | boolean_type |
string_type | fixed_type | scoped_name
rule 14) const_exp :: or_expr
rule 15) or_expr :: xor_expr or_expr1*
rule 15') or_expr1 ;: "|" xor_expr
rule 16) xor_expr :: and_expr xor_expr1*
rule 16') xor_expr1 :: "^" and_expr
rule 17) and_expr :: shift_expr and_expr1*
rule 17') and_expr1 :: "&" shift_expr
rule 18) shift_expr :: add_expr shift_expr1*
rule 18') shift_expr1 :: ">>" add_expr | "<<" add_expr
rule 19) add_expr :: mult_expr add_expr1*
rule 19') add_expr1 :: "+" mult_expr | "-" mult_expr
rule 20) mult_expr :: unary_expr mult_expr1*
rule 20') mult_expr1 :: "*" unary_expr | "/" unary_expr | "%" unary_expr
rule 21) unary_expr :: "-" primary_expr | "+" primary_expr | "~" primary_expr | primary_expr
rule 23) primary_expr :: scoped_name | literal | "(" const_exp ")"
rule 24) literal :: integer_literal | string_literal | character_literal
| floating_literal | boolean_literal
rule 25) boolean_literal :: "TRUE" | "FALSE"
rule 26) positive_int_const :: const_exp *
rule 27) type_dcl :: "typedef" type_spec type_declarators | "native" native_type | constr_type_spec
rule 28) type_declarator :: type_spec type_declarators
rule 29) type_spec :: simple_type_spec | constr_type_spec
rule 30) simple_type_spec :: base_type_spec | template_type_spec | scoped_name
rule 31) base_type_spec :: floating_type | integer_type | char_type | boolean_type
| octet_type | object_type | any_type
rule 32) template_type_spec :: sequence_type | fixed_type | string_type
rule 33) constr_type_spec :: struct_type | union_type | enum_type
rule 34) type_declarators :: t_declarator ( "," t_declarator )*
rule 35) t_declarator :: complex_declarator | simple_declarator
rule 36) simple_declarator :: identifier
rule 37) complex_declarator :: array_declarator
rule 63) array_declarator :: identifier fixed_array_size+
rule 64) fixed_array_size :: "[" positive_int_const "]"
rule 38) floating_type :: "float" | "double" | "long" "double"
rule 39) integer_type :: "unsigned" int_type | int_type
rule 40) int_type :: "long" "long" | "long" | "short"
rule 46) char_type :: "char" | "wchar"
rule 47) boolean_type :: "boolean"
rule 48) octet_type :: "octet"
rule 48') object_type :: "Object"
rule 49) any_type :: "any"
rule 49') typeCode_type :: "TypeCode"
rule 49'') principal_type :: "Principal"
rule native_type :: simple_declarator
rule s_declarator :: complex_declarator | simple_declarator
rule e_declarator :: complex_declarator | simple_declarator
rule u_declarator :: complex_declarator | simple_declarator
rule 50) struct_type :: "struct" identifier "{" struct_member_dcl+ "}"
rule 51) struct_member_dcl :: type_spec struct_declarators
rule 52) struct_declarators :: s_declarator ( "," s_declarator )* ";"
rule 53) union_type :: "union" identifier "switch" "(" switch_type_spec ")" {" switch_body "}"
rule 54) switch_type_spec :: integer_type | char_type | boolean_type | enum_type | scoped_name
rule 55) switch_body :: (casex)+
rule 56) casex :: case_label (case_label1)* union_member_dcl ";"
rule 57) case_label :: "case" const_exp ":" | "default" ":"
rule 57') case_label1 :: "case" const_exp ":"
rule 58) union_member_dcl :: type_spec union_declarators
rule 58') union_declarators :: u_declarator
rule 59) enum_type :: "enum" identifier "{" enumerator ( "," enumerator )* "}"
rule 60) enumerator :: identifier
rule 61) sequence_type :: "sequence" "<" simple_type_spec sequence_type1
rule 61') sequence_type1 :: "," positive_int_const ">" | ">"
rule ) fixed_type :: "fixed" "<" positive_int_const "," integer_literal ">"
rule 62) string_type :: "string" | "string" "<" positive_int_const ">"
| "wstring" | "wstring" "<" positive_int_const ">"
rule 65) attr_dcl :: "readonly" "attribute" param_type_spec attr_declarator ( "," attr_declarator )*
| "attribute" param_type_spec attr_declarator(false) ( "," attr_declarator(false) )*
rule 65') attr_declarator :: simple_declarator
rule 66) except_dcl :: "exception" identifier "{" exception_member_dcl* "}"
rule 66') exception_member_dcl :: type_spec exception_declarators
rule 66") exception_declarators :: e_declarator ( "," e_declarator )* ";"
rule 67 ) op_dcl :: "oneway" "void" identifier parameter_dcls[ context_expr ]
| op_type_spec identifier(true) parameter_dcls [ raises_expr ] [ context_expr ]
rule 68) op_type_spec :: param_type_spec | "void"
rule 70) parameter_dcls :: "(" [ param_dcl ( "," param_dcl )* ] ")"
rule 71) param_dcl :: param_attribute param_type_spec simple_declarator
rule 72) param_attribute :: "in" | "out" | "inout"
rule 73) raises_expr :: "raises" "(" raises_expr1 ( "," raises_expr1 )* ")"
rule 73') raises_expr1 :: scoped_name
rule 74) context_expr :: "context" "(" context_expr1 ( "," context_expr1 )* ")"
rule 74') context_expr1 :: string_literal
rule 75) param_type_spec :: base_type_spec | string_type | scoped_name
Tokens used are :
identifier :: ID
integer_literal :: OCTALINT | DECIMALINT | HEXADECIMALINT
string_literal :: STRING
character_literal :: CHARACTER
floating_literal :: FLOATONE | FLOATTWO
ID :: ["a"-"z","A"-"Z", "_"] (["a"-"z","A"-"Z","0"-"9","_"])*
OCTALINT :: ["0"] (["0"-"7"])* (["u","U","l","L"])?
DECIMALINT :: ["1"-"9"] (["0"-"9"])* (["u","U","l","L"])?
HEXADECIMALINT :: ("0x"|"0X") (["0"-"9","a"-"f","A"-"F"])+ (["u","U","l","L"])?
FLOATONE :: ((["0"-"9"])+ "." (["0"-"9"])* | (["0"-"9"])* "." (["0"-"9"])+)
(["e","E"] (["-","+"])? (["0"-"9"])+)? (["f","F","l","L"])?
FLOATTWO :: (["0"-"9"])+ ["e","E"] (["-","+"])? (["0"-"9"])+ (["f","F","l","L"])?
CHARACTER :: (["L"])? "'" (
( ~["'","\\","\n","\r"])
| ("\\" ( ["n","t","v","b","r","f","a","\\","?","'","\""]
| "0" (["0"-"7"])* | ["1"-"9"] (["0"-"9"])*
| ("x" | "X") (["0"-"9","a"-"f","A"-"F"])+
| ("u" | "U") (["0"-"9","a"-"f","A"-"F"])+
) "'"
STRING :: (["L"])? "\""
( ( ~["\"","\\","\n","\r"])
| ("\\" ( ["n","t","v","b","r","f","a","\\","?","'","\""]
| "0" (["0"-"7"])*
| ["1"-"9"] (["0"-"9"])*
| ("x" | "X") (["0"-"9","a"-"f","A"-"F"])+
| ("u" | "U") (["0"-"9","a"-"f","A"-"F"])+
)
)
)* "\""
Characters and sequences to be skipped are :
" " | "\t" "\r" | "\n" | "//" (~["\n"])* "\n"
| "/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"
| "#" ([" ","\t"])* (["0"-"9"])+ (([" ","\t"])*
"\"" (~["\""])+ "\"" ([" ","\t"])* (["0"-"9"])* ([" ","\t"])* (["0"-"9"])*)? "\n"