Previous Up Next

2  IDL syntax

This section describes the syntax of IDL files. IDL syntax is very close to that of C declarations, with extra attributes between brackets adding information to the C types. The following example should give the flavor of the syntax:
        int f([in,string] char * msg);
This reads: ``f is a function taking a character string as input and returning an int''.

2.1  Lexical conventions

Space, newline, horizontal tabulation, carriage return, line feed and form feed are considered as blanks. Blanks are ignored, but they separate adjacent tokens.

Both C-style comments /* ... */ and Java-style comments // ... are supported. C-style comments are introduced by /* and terminated by */. Java-style comments are introduced by // and extend to the end of the line. Comments are treated as blank characters. Comments do not occur inside string or character literals. Nested C-style comments are not supported.

Identifiers have the same syntax as in C.
ident ::= (A ... Z | a ... z | _) {A ... Z | a ... z | 0 ... 9 | _}

Integer literals, character literals and string literals have the same syntax as in C.
integer ::= [-] {0 ... 9} [-] 0x {0 ... 9 | a ... f | A ... F} [-] 0 {0 ... 7}
character ::= ' (regular-char | escape-char) '
string ::= " {regular-char | escape-char} "
escape-char ::= \ (b| n| r| t)
  | \ (0...7) [0...7] [0...7]

Unique identifiers are composed of 16 hexadecimal digits, in groups of 8, 4, 4, 4 and 12, separated by dashes.
uuid ::= hex8 -  hex4 -  hex4 -  hex4 -  hex4  hex4  hex4
hex ::= 0 ... 9 | a ... f | A ... F

2.2  Limited expressions

Limited expressions are similar to C expressions, with the omission of assignment operators (=, +=, etc), and the addition of the unsigned (logical) right shift operator >>>. Operators have the same precedences and associativities as in C. They are listed below in decreasing priority order.
lexpr ::= ident
  | integer
  | character
  | true
  | false
  | string
  | sizeof (  type-expr )
  | ( lexpr )
  | lexpr  (. | ->) ident
  | ( type-expr )  lexpr
  | (&| *| !| ~| -| +) lexpr
  | lexpr  (*| /| %) lexpr
  | lexpr  (+| -) lexpr
  | lexpr  (<<| >>
  | >>>) lexpr
  | lexpr  (==| !=| >=| <=| >| <)
  | lexpr  (&| ^| |) lexpr
  | lexpr  (&&| ||) lexpr
  | lexpr ?  lexpr :  lexpr
Constant limited expressions, written const-lexpr below, can only reference identifiers that are bound by the IDL const declaration.

2.3  Attributes

attributes ::= [ attribute  { , attribute } ]
attribute ::= ident
  | ident (  [lexpr]  { , [lexpr] } )
  | ident (  uuid )
  | attribute *
  | * attribute
Attribute lists are written in brackets [...], and are always optional. Each attribute is identified by a name, and may carry optional arguments. Starred attributes apply to the element type of a pointer or array type, rather than to the pointer or array type itself. The following table summarizes the recognized attributes and their arguments.
Attribute Context where it can appear
abstract typedef
bigarray array type
blocking function declaration
camlint int or long integer type
compare(fun-name) typedef
c2ml(fun-name) typedef
errorcheck(fun-name) typedef
errorcode typedef
finalize(fun-name) typedef
fortran array type with bigarray attribute
hash(fun-name) typedef
ignore any pointer type
in function parameter
int_default( camlint| nativeint| int32| int64) interface
int32 int or long integer type
int64 int or long integer type
length_is(le1, le2,...) array type
long_default( camlint| nativeint| int32| int64) interface
managed array type with bigarray attribute
ml2c(fun-name) typedef
mlname( fun-or-field-name ) function declaration, struct field
mltype(" caml-type-expr ") typedef
nativeint int or long integer type
null_terminated array of pointers
object interface
out function parameter
pointer_default( ref| unique| ptr) interface
propget function declaration
propput function declaration
propputref function declaration
ptr any pointer type
ref any pointer type
set enum type
size_is(le1, le2,...) array type
string character array or pointer
switch_is(le) union type or pointer to union
switch_type(ty) union or pointer to union
unique any pointer, array, or bigarray type
uuid( uuid ) interface

2.4  Types and declarators

The declaration of an identifier along with its type is as in C: a type specification comes first, followed by the identifier possibly decorated with * and [...] to denote pointers and array types. For instance, int x declares an identifier x of type int, while int (*x)[] declares an identifier x that is a pointer to an array of integers.
type-spec ::= [unsigned| signed] (int| short| long| char| hyper| long long| __int64)
  | byte
  | float
  | double
  | boolean
  | void
  | ident
  | wchar_t
  | handle_t
  | struct ident
  | union ident
  | enum ident
  | struct-decl
  | union-decl
  | enum-decl
declarator ::= {*} direct-declarator
direct-declarator ::= ident
  | ( declarator )
  | direct-declarator [  [const-lexpr] ]

2.5  Structures, unions and enumerations

struct-decl ::= struct [ident] {  {field-decl} }
field-decl ::= attributes  type-spec  declarator  { , declarator } ;
union-decl ::= union [ident] {  {union-case} }
  | union [ident] switch (  type-spec  ident ) {  {union-case} }
union-case ::= {case ident :}+  [field-decl] ; default :  [field-decl] ;
enum-decl ::= enum [ident] {  enum-case  {, enum-case}  [,] }
enum-case ::= ident  [= const-lexpr]

IDL struct declarations are like those of C, with the addition of optional attributes on each field. union declarations are also as in C, except that each case of an union must be labeled by one or several case ident :. The first form of union declaration assumes that the discriminant of the union is provided separately via a switch_is annotation on the union type, while the second form encapsulates the discriminant along with the union itself (like in Pascal's record case of construct).

2.6  Function declarations

function-decl ::= attributes  type-spec  {*} ident (  params )  {quote(ident, string)}
params ::= e
  | void
  | param  { , param }
param ::= attributes  type-spec  declarator
Function declarations are like in ANSI C, with the addition of attributes on each parameter and on the function itself. Parameters must be named. The optional quote statements following the declaration are user-provided calling sequences and deallocation sequences that replaces the default sequences in the camlidl-generated stub code for the function.

2.7  Constant definitions

constant-decl ::= const attributes  type-spec  {*} ident =  const-lexpr ;
A constant declaration associates a name to a limited expression. The limited expression can refer to constant names declared earlier, but cannot refer to other kinds of identifiers. The optional attributes influence the interpretation of the type specification, e.g. const int x = 3 defines x with Caml type int, but const [int64] long x = 5 defines x with Caml type int64.

2.8  IDL files

file ::= {decl}
decl ::= function-decl ;
  | constant-decl ;
  | struct-decl ;
  | union-decl ;
  | enum-decl ;
  | typedef attributes  type-spec  declarator  { , declarator } ;
  | attributes interface  ident  [ : ident ] {  {decl} }
  | struct ident ;
  | union ident ;
  | union switch ( type-spec  ident ) ;
  | attributes interface  ident ;
  | import string ;
  | quote ( [ident ,]  string )
  | cpp_quote ( string )
An IDL file is a sequence of IDL declarations. Declarations include function declarations, constant declarations, type declarations (structs, unions, enums, as well as a C-style typedef declaration to name a type expression), and interfaces.

An interface declaration gives a name and attributes to a collection of declarations. For interfaces with the object attribute, an optional super-interface can be provided, as in interface intf :  super-intf. The name of the interface can be used as a type name in the remainder of the file.

Forward declarations of structs, unions and interfaces are supported in the usual C manner, by just giving the name of the struct, union or interface, but not its actual contents.

The import statement reads another IDL file and makes available its type and constant declarations in the remainder of the file. No code is generated for the functions and interfaces declared in the imported file. The same file can be imported several times, but is read in only the first time.

The quote ( ident ,  str ) diversion copies the string str verbatim to one of the files generated by the camlidl compiler. The ident determines the file where str is copied: it can be ml for the Caml implementation file (.ml), mli for the Caml interface file (.mli), mlmli for both Caml files, h for the C header file (.h), and c for the C source file containing the generated stub code (.c file). For backward compatibility, cpp_quote ( str ) is recognized as synonymous for quote ( h , str ).

Previous Up Next