@setfilename ilu-m3.info
@settitle Using ILU with Modula-3
@ifclear largerdoc
@titlepage
@title Using ILU with Modula-3
@author Mike Spreitzer @code{<spreitzer@@parc.xerox.com>}
@sp
@today{}
@sp
Copyright @copyright{} 1993 Xerox Corporation@*
All Rights Reserved.
@end titlepage
@end ifclear

This document is for the @language{Modula-3} programmer who wishes to use 
@system{ILU}.  @system{ILU} currently supports only DEC SRC @language{Modula-3} version 2.08.

@section Mapping ILU ISL to Modula-3
@cindex Mapping to Modula-3

@subsection Names
@cindex Mapping ISL names to Modula-3 names

An item named @code{Bar} in @language{ISL} interface @interface{Foo} becomes an item named @code{Bar} in the @language{Modula-3} interface @interface{Foo}.  A hyphen in an @language{ISL} name becomes an underscore in the corresponding @language{Modula-3} name.

@subsection Types
@cindex Mapping ISL types to Modula-3 types

@language{ISL} types appear in @language{Modula-3} as follows:

@enumerate
@item
@kwd{SHORT INTEGER} becomes @code{[-32768 .. 32767]}.
@item
@kwd{INTEGER} becomes @code{INTEGER}.
@item
@kwd{LONG INTEGER} becomes
@codeexample
TYPE LongInt = RECORD
                 high: [-16_80000000 .. 2147483647];
                 low : Word.T (*[0 ..  4294967295]*)
               END;
@end codeexample
This represents the number @code{high*2^32 + low}.  We always have the invariants @code{-2^31 <= high < 2^31} and @code{0 <= low < 2^32}, even on systems whose natural word size is greater than 32 bits.
@item
@kwd{BYTE} becomes @code{[0 .. 255]}.
@item
@kwd{SHORT CARDINAL} becomes @code{[0 .. 65535]}.
@item
@kwd{CARDINAL} becomes @code{Word.T}.
@item
@kwd{LONG CARDINAL} becomes @code{RECORD high, low: Word.T END}.  This representation works analogously to that for @kwd{LONG CARDINAL}.
@item
@kwd{SHORT REAL} becomes @code{REAL}.
@item
@kwd{REAL} becomes @code{LONGREAL}.
@item
@kwd{LONG REAL} becomes an opaque type.  Values of this type can only be handed around; no other operations are provided, not even equality testing.  @kwd{LONG REAL} is not really supported yet.
@item
@kwd{SHORT CHARACTER} becomes @code{['\000' .. '\377']}.
@item
@kwd{CHARACTER} becomes @code{[0 .. 65535]}.
@item
Variable-length @kwd{ARRAY}s of @kwd{SHORT CHARACTER} become @code{TEXT}.
@item
Other variable-length arrays become @code{REF ARRAY OF}.
@item
Fixed-length arrays of @kwd{SHORT CHARACTER} become arrays of @code{BITS 8 FOR ['\000' .. '\377']}.
@item
Fixed or variable-length @kwd{ARRAY}s of @kwd{BYTE} become arrays of @code{BITS 8 FOR [0 .. 255]}.
@item
No other arrays specify packing in the @language{Modula-3}.
@item
A fixed length array, @code{ARRAY OF @metavar{L1}, ... @metavar{Ln}}, becomes @code{ARRAY [0 .. @metavar{L1}-1] OF ... ARRAY [0 .. @metavar{Ln}-1] OF}.
@item
An @language{ISL} record becomes a @language{M3} record.
@item
An @language{ISL} union becomes a @language{M3} object type and some subtypes.  The @language{ISL}
@codeexample
TYPE @metavar{Foo} = @metavar{DiscT} UNION
    @metavar{case1}: @metavar{T1} = @metavar{val1-1}, ... @metavar{val1-j} END,
    ...
    @metavar{casen}: @metavar{Tn} = @metavar{valn-1}, ... @metavar{valn-k} END
    END OTHERS;
@end codeexample
maps to the @language{Modula-3}
@codeexample
TYPE @metavar{Foo} = BRANDED OBJECT d: @metavar{DiscT} END;
TYPE  @metavar{Foo}_@metavar{case1} = @metavar{Foo} BRANDED OBJECT v: @metavar{T1} END;
CONST @metavar{Foo}_@metavar{case1}__Code : @metavar{DiscT} = @metavar{val1-1};
...
TYPE  @metavar{Foo}_@metavar{casen} = @metavar{Foo} BRANDED OBJECT v: @metavar{Tn} END;
CONST @metavar{Foo}_@metavar{casen}__Code : @metavar{DiscT} = @metavar{valn-1};
TYPE  @metavar{Foo}_OTHERS = @metavar{Foo} BRANDED OBJECT END;
(* Where every @metavar{Foo} is of one of the subtypes enumerated here,
   and the tag field (d) is consistent with the subtype. *)
@end codeexample
The @code{@metavar{Foo}_OTHERS} subtype appears only for union constructions including the @kwd{OTHERS} keyword.
If the @language{ISL} union has a @kwd{DEFAULT} arm
@codeexample
    @metavar{cased}: @metavar{Td} = DEFAULT
@end codeexample
it maps to another subtype in @language{Modula-3}:
@codeexample
TYPE  @metavar{Foo}_@metavar{cased} = @metavar{Foo} BRANDED OBJECT v: @metavar{Td} END;
@end codeexample
The @code{@metavar{Foo}_@metavar{casen}__Code} constants are conveniences for filling in and decoding the @code{d} field.
Note that code that creates a @metavar{Foo} is responsible for filling in the @code{d} field.
@item
An @language{ISL} enumeration becomes a @language{M3} enumeration.  Due to the fact that @language{Modula-3} offers no way to specify the codes used to represent enumerated values, the codes specified in @language{ISL}, if any, have no effect on the translation.
@item
When a @metavar{Foo} becomes a @metavar{Bar}, an @code{OPTIONAL @metavar{Foo}} becomes a @code{REF @metavar{Bar}}, unless @metavar{Bar} is a subtype of @kwd{REFANY}, in which case @code{OPTIONAL @metavar{Foo}} becomes @metavar{Bar}; @kwd{NIL} encodes the @kwd{NULL} case.
@item
An @language{ISL} object type becomes a @language{Modula-3} object type.  The @language{ISL} adjectives @kwd{SINGLETON}, @kwd{DOCUMENTATION}, @kwd{COLLECTIBLE}, @kwd{OPTIONAL}, @kwd{AUTHENTICATION}, and @kwd{BRAND} have no effect on the mapping into the @language{Modula-3} type system.

@kwd{OUT} and @kwd{INOUT} method parameters in @language{ISL} become @kwd{VAR} parameters in @language{Modula-3}; @kwd{IN} parameters become @kwd{VALUE} (by default) parameters.  The @kwd{SIBLING} constraint in @language{ISL} has no manifestation in the @language{Modula-3} type system.

The methods are declared to raise the exceptions @code{IluBasics.Failed} and @code{Thread.Alerted} in addition to the exceptions declared in the @language{ISL}.  Exception @code{IluBasics.Failed} is used to convey all the errors that can arise from the RPC mechanism, except @code{Thread.Alerted}.  Is the surrogate (and the other surrogates from the same server?) broken after either of these exceptions is raised?

Because @system{ILU} has multiple inheritance (i.e., an object type can have more than one direct supertype), the @language{Modula-3} subtype relation is a sub-relation of the @system{ILU} subtype relation.    In general, an @system{ILU} object type is mapped to a suite of @language{Modula-3} object types, and a cohort of @language{Modula-3} objects (one of each of the suite of @language{Modula-3} types) correspond to one @system{ILU} object.  There will be only one @language{Modula-3} object (type) when only single-inheritance is used in constructing the @system{ILU} object type: when every ancestor type has at most one direct ancestor.  Except where the programmer knows this is the case, and plans for it to remain so, she must abandon the native @language{Modula-3} @kwd{TYPECASE}/@kwd{NARROW}/automatic-widen facilities for explicit calls that invoke the @system{ILU} subtype relation.

To generalize the @language{Modula-3} @kwd{TYPECASE}/@kwd{NARROW}/automatic-widen facilities, the @language{Modula-3} object type @code{Ilu.Object} includes the following method:
@codeexample
PROCEDURE ILU_Qua_Type(ot: ObjectType): Object;
@end codeexample
If the object has, in @system{ILU}, the given object type, the @language{Modula-3} object of the appropriate @language{Modula-3} type is returned; otherwise, NIL is returned.  As an added convenience, the @language{Modula-3} mapping of interface @metavar{Foo} will contain, for each of its object types @metavar{Bar}:
@codeexample
PROCEDURE ILU_Qua_@metavar{Bar}(x: Ilu.Object): @metavar{Bar};
@end codeexample
This procedure takes a non-@kwd{NIL} argument.  If the argument is, in @system{ILU}, an instance of @metavar{Bar} or one of its subtypes, the corresponding language-specific object is returned; otherwise, @code{NIL} is returned.
@end enumerate

@subsection Exceptions
@cindex Mapping ISL exceptions to Modula-3 exceptions

@language{ISL} exceptions are exactly like @language{Modula-3} exceptions, and are mapped directly.

@subsection Example
@cindex Modula-3 mapping example

Here's a sample @language{ISL} spec, and the resulting @language{Modula-3} mappings:

@codeexample
INTERFACE Foo;

TYPE String = ilu.CString;
TYPE UInt = CARDINAL;

TYPE E1 = ENUMERATION val1, val2, val3 = 40 END;
TYPE R1 = RECORD field1 : CARDINAL, field2 : E1 END;
TYPE FAB = ARRAY OF 200 BYTE;
TYPE VAB = SEQUENCE OF BYTE;
TYPE FASC = ARRAY OF 10 SHORT CHARACTER;
TYPE VASC = SEQUENCE OF SHORT CHARACTER;
TYPE FAC = ARRAY OF 5 CHARACTER;
TYPE VAC = SEQUENCE OF CHARACTER;
TYPE A2 = ARRAY OF 41, 3 R1;
TYPE S1 = SEQUENCE OF E1;
TYPE U1 = UNION R1, A2 END;

EXCEPTION Except1 : String;

CONSTANT Zero : CARDINAL = 0;

TYPE O1 = OBJECT
    METHODS
        M1(r1: R1, INOUT v: VASC, OUT s1: S1): UInt RAISES Except1 END,
        FUNCTIONAL Hash(v: VASC): FASC,
        ASYNCHRONOUS Note(x: LONG REAL)
    END;
@end codeexample

The @language{Modula-3} mapping:

@codeexample
INTERFACE Foo;

IMPORT Ilu, IluBasics, Thread;
IMPORT ilu; <*NOWARN*>

TYPE UInt = CARDINAL;
TYPE E1 = @{
  val1,
  val2,
  val3@};
TYPE R1 = RECORD
   field1 : CARDINAL;
   field2 : E1;
END;
TYPE VASC = TEXT;  (* NIL not allowed *)
TYPE S1 = REF ARRAY OF E1;  (* NIL not allowed *)
TYPE FASC = ARRAY [0..9] OF Ilu.PackedShortChar;


(* declaration of M3 type "Foo.O1" from ILU class "Foo:O1"  *)

TYPE O1 = Ilu.Object OBJECT
  METHODS
    M1 (r1: R1; VAR v: VASC; VAR s1: S1): UInt
       RAISES @{IluBasics.Failed, Thread.Alerted, Except1@};
    Hash (v: VASC): FASC RAISES @{IluBasics.Failed, Thread.Alerted@};
    Note (x: Ilu.LongReal) RAISES @{IluBasics.Failed, Thread.Alerted@};
  OVERRIDES
    ILU_Get_Type := ILU_Get_Type_O1
  END;

PROCEDURE ILU_SBH_To_O1 (sbh: TEXT; mostSpecificTypeID: TEXT := NIL): O1
  RAISES @{IluBasics.Failed, Thread.Alerted@};

PROCEDURE ILU_Get_Type_O1 (self : Ilu.Object): Ilu.ObjectType;

PROCEDURE ILU_Qua_O1 (x: Ilu.Object): O1;

TYPE A2 = ARRAY [0..40] OF ARRAY [0..2] OF R1;
TYPE  U1 = BRANDED OBJECT d: Ilu.ShortInt END;  (* NIL not allowed *)
TYPE  U1_R1       = U1 BRANDED OBJECT v: R1 END;
CONST U1_R1__Code : [-32768..32767] = 0;
TYPE  U1_A2       = U1 BRANDED OBJECT v: A2 END;
CONST U1_A2__Code : [-32768..32767] = 1;
TYPE VAC = REF ARRAY OF Ilu.Character;  (* NIL not allowed *)
TYPE FAC = ARRAY [0..4] OF Ilu.Character;
TYPE VAB = REF ARRAY OF BITS 8 FOR Ilu.Byte;  (* NIL not allowed *)
TYPE FAB = ARRAY [0..199] OF Ilu.PackedByte;
TYPE String = TEXT;  (* NIL not allowed *)

CONST Zero : CARDINAL = 0;

(* Exceptions *)

EXCEPTION Except1 (String);

END Foo.
@end codeexample

@section Importing an ILU interface in Modula-3
@cindex Modula-3 client programming
@cindex Client programming

A client can acquire a @language{Modula-3} language-specific object by calling the @code{ILU_SBH_To_...} stub procedure, passing the string binding handle and most specific type ID; these are typically obtained through some name service.  The Simple Binding facility is available in an integrated way, as exhibited later.

The client can then proceed to make calls on the object.

@section Exporting an ILU interface in Modula-3
@cindex Modula-3 server programming
@cindex Server programming

A server uses the following interface to expose itself to the @system{ILU}/@language{M3} runtime.

@codeexample
INTERFACE Ilu;
IMPORT IluKernel, Word;
FROM IluBasics IMPORT Failed, Failure;

<*PRAGMA lL, Ll, Main*>


(* Concurrency and locking:

   As in iluExports.h.  The ILU/Modula-3 runtime adds the folloing
   mutexes:
| ssMu		global mutex for server registry;
| srmu		global mutex for StrongRef implementation;
| ocMu		global mutex for ObjectCreator registry;
| Ilu.Server	each one is a mutex;

   and the following ordering constraints:
|  IluKernel.Server < ssMu < Ilu.Server
|  IluKernel.Server < srmu
|  IluKernel.Server < ocMu

   *)

(* RPC protocol failures *)

TYPE
  ProtocolFailure =
    Failure BRANDED OBJECT case: ProtocolFailureCase; END;


  ProtocolResultCode =
    @{Success, NoSuchTypeAtServer, TypeVersionMismatch,
     NoSuchMethodOnType, GarbageArguments, Unknown, LostConnection,
     RequestRejected, RequestTimeout@};

  ProtocolFailureCase = [ProtocolResultCode.NoSuchTypeAtServer ..
                          ProtocolResultCode.RequestTimeout];


(* Datatypes defined in ISL. *)

TYPE Byte = [0 .. 255];
TYPE PackedByte = BITS 8 FOR Byte;
TYPE ShortInt = [-32768 .. 32767];
TYPE Integer = INTEGER;
TYPE
  LongInt = RECORD
              high: [-16_80000000 .. 2147483647];
              low : Word.T (*[0 ..  4294967295]*)
            END;
TYPE ShortCard = [0 .. 65535];
TYPE Cardinal = Word.T;
TYPE LongCard = RECORD high, low: Word.T (*[0 ..  4294967295]*) END;
TYPE ShortReal = REAL;
TYPE Real = LONGREAL;
TYPE LongReal <: REFANY;
TYPE ShortChar = ['\000' .. '\377'];
TYPE PackedShortChar = BITS 8 FOR ShortChar;
TYPE Character = ShortCard; (* In Unicode. *)
TYPE String = TEXT; (* With no embedded '\000'. *)
TYPE WString = REF ARRAY OF Character; (* With no embedded 0. *)
TYPE Bytes = REF ARRAY OF PackedByte;


(* The String Binding Handle. *)

TYPE
  SBH = TEXT;
  (* A string that includes an instance ID and a contact-info *)

TYPE
  InstanceId = TEXT;
  (* A unique identifier for an object; it is factored into a ServerId
     and an ObjectHandle. *)

TYPE
  ServerId = TEXT;
  (* A unique identifier for a server *)

TYPE
  ObjectHandle = TEXT;
  (* A server-relative identifier for an object *)

TYPE
  ContactInfo = TEXT;
  (* An encoding of how to reach a server *)


(* ================ Server stuff ================ *)

TYPE
  ServerPrivate <: ROOT;
  Server = ServerPrivate OBJECT
             <*lL, Ll, Main unconstrained*>
             id: ServerId; (*READONLY*)
           METHODS
           END;
  (* A data structure that represents a server, either local to this
     program or remote.  Each server is actually one of the following
     two types. *)

TYPE SurrogateServer <: Server;

TYPE
  TrueServer <:
    Server OBJECT
    METHODS
      <*Main Invariant holds; Ll otherwise unconstrained*>

      HandleListenerFailure (f: Failure): FailureAction;
      (* When there's a failure in a listener for this server, this
         procedure is notified, and the result indicates whether the
         listener is abandoned or continues listening. *)
      HandleWorkerFailure (f: Failure): FailureAction;
      (* When there's a failure in a worker for this server, this
         procedure is notified, and the result indicates whether the
         connection is abandoned or continues listening. *)
    END;
  (* A server local to this program. *)

TYPE FailureAction = @{Quit, Continue@};

<*lL, Ll = @{@}*>
PROCEDURE DefaultHandleListenerFailure (self: TrueServer; f: Failure):
  FailureAction;

<*lL, Ll = @{@}*>
PROCEDURE DefaultHandleWorkerFailure (self: TrueServer; f: Failure):
  FailureAction;

<*Main Invariant holds; Ll otherwise unconstrained*>

PROCEDURE InitTrueServer (self  : TrueServer;
                          id    : ServerId := NIL;
                          objtab: ObjectTable := NIL ): TrueServer
  RAISES @{Failed@};

TYPE
  ObjectTable =
    OBJECT
    METHODS
      <*lL >= @{the kernel server@}*>
      <*lL >= @{gcmu@} if the object is collectible*>
      <*Ll, Main unconstrained*>

      ObjectToHandle (o: Object): ObjectHandle;
      (* Returns the handle associated with the given object, inventing
         and recording a new handle if necessary. *)
      HandleToObject (h: ObjectHandle): Object;
      (* Returns the Object associated with the given handle, or NIL if
         no such Object. *)
    END;
  (* An one-to-one association between Objects and ObjectHandles, such
     as a server might maintain. *)

PROCEDURE Export_Server (server: TrueServer;
                         p     : ProtocolInfo;
                         t     : TransportInfo ) RAISES @{Failed@};

TYPE ProtocolInfo = BRANDED OBJECT END;
TYPE SunRpc2 = ProtocolInfo BRANDED OBJECT prognum, version := 0 END;
TYPE Courier = ProtocolInfo BRANDED OBJECT prognum, version := 0 END;

TYPE TransportInfo = BRANDED OBJECT END;
TYPE
  TCP = TransportInfo BRANDED OBJECT host, port := 0 END;
  UDP = TransportInfo BRANDED OBJECT host, port := 0 END;
  (* host and port are in host, not network, byte order. *)
TYPE SPP = TransportInfo BRANDED OBJECT addr := AnyXnsAddr END;

TYPE
  XnsAddr = RECORD
              net   : XnsNet;
              host  : XnsHost;
              socket: XnsSocket
            END;
  XnsNet = Cardinal;
  XnsHost = ARRAY [0 .. 5] OF PackedByte;
  XnsSocket = ShortCard;
CONST AnyXnsAddr = XnsAddr@{0, XnsHost@{0, ..@}, 0@};

TYPE Root <: ROOT;

TYPE
  Object <: ObjectPublic;
  ObjectPublic =
    Root OBJECT
      <*lL, Ll, Main unconstrained*>
      ilu_is_surrogate: BOOLEAN := FALSE;
    METHODS
      <*lL, Ll, Main unconstrained*>

      ILU_Get_Server (): Server;
      ILU_Get_Type (): ObjectType;
      (* Returns the most specific ILU type known to this program for
         the ILU object represented by this Modula-3 object. *)
      ILU_Qua_Type (ot: ObjectType): Object;

      <*Main Invariant holds; Ll otherwise unconstrained*>

      ILU_Close           () RAISES @{@};
      ILU_Close_Surrogate () RAISES @{@};
    END;

TYPE ObjectType = IluKernel.ObjectType;

PROCEDURE SbhFromObject (o: Object): SBH RAISES @{Failed@};
  (* May be applied to any Object; returns a reference that can be
     passed to other programs.  Export_Server must have been called on
     the object's server. *)

<*lL, Ll, Main unconstrained*>
PROCEDURE IdOfObjectType (ot: ObjectType): TEXT;
  (* Returns a shortish string that identifies this object type. *)


END Ilu.
@end codeexample

A server module begins by creating an @type{Ilu.TrueServer} and calling @code{Ilu.InitTrueServer} on it.  The server module may either specify the server's ID in this call, or let the @system{ILU} runtime choose one.  The server module may specify how to handle errors arising in the server stubs, or let the ILU runtime handle them in the default way: print an error message to stdout and quit the listener or connection worker.  The server module may assert control over the association between @metavar{object-handle}s and objects in the server by supplying an @kwd{ObjectTable}, or let the @system{ILU} runtime manage the association in its default way.

The server module continues by calling @code{Ilu.Export_Server}, specifying the protocol and transport combinations through which the server should be contactable.  Due to internal restrictions in the current runtime, this procedure should be called exactly once.

Each true object should be a subtype of @code{Ilu.Object}; the implementor of the true object is responsible for ensuring that the @kwd{ilu_is_surrogate} is filled in with @code{FALSE} and that the @kwd{Ilu_Get_Server}, @kwd{Ilu_Get_Type}, and @kwd{ILU_Qua_Type} methods have reasonable behavior.  The @kwd{ilu_is_surrogate} field defaults to @code{FALSE}, and the object type declared in a @language{Modula-3} interface generated by the @program{m3-stubber} from an @language{ISL} interface takes care of implementing @kwd{Ilu_Get_Type}, so a programmer using the stubs needs to worry only about @kwd{Ilu_Get_Server} and @kwd{ILU_Qua_Type}.

Once a true object has been created, and @code{Ilu.Export_Server} has been called, the server can export individual objects.  This can be done through a name service or by passing the object to another module among the arguments, results, or exception parameter contents of a call on a different language-specific object.  The Simple Binding facility described later is integrated with @system{ILU}.  To use a non-integrated name service, the object's string binding handle and most specific type ID are needed; they can be determined by calling @code{Ilu.SbhFromObject(@metavar{obj})} and @code{Ilu.IdOfObjectType(@metavar{obj}.ILU_Get_Type())}.

@section ILU API for Modula-3
@cindex Modula-3 client programming
@cindex Client programming
@cindex Modula-3 server programming
@cindex Server programming

The full API is presented in the previous section.

@system{ILU} currently supports DEC SRC Modula-3 version 2.08 --- which lacks finalization.  When an application program --- any combination of client and server modules --- knows it is done with a particular object, it can explicitly free the resources associated with that object.  This is done by invoking the @kwd{ILU_Close} method on that object.

It is always safe --- but may be expensive --- to invoke @kwd{ILU_Close} on a surrogate object or on a true object that will be found by the @kwd{HandleToObject} method of its server's @kwd{ObjectTable}.  The @kwd{HandleToObject} method of the default @kwd{ObjectTable} implementation will not find a true object after @kwd{ILU_Close} has been called on that object.

@subsection Simple Binding

The Simple Binding functionality is available through the following interface.

@codeexample
INTERFACE IluSimpleBind;
FROM IluBasics IMPORT Failed;
IMPORT Ilu;

<*PRAGMA lL, Ll, Main*>

<*Main invariant holds*>

TYPE Cookie <: REFANY;

PROCEDURE Publish (obj: Ilu.Object): Cookie RAISES @{Failed@};

PROCEDURE Withdraw (obj: Ilu.Object; c: Cookie) RAISES @{Failed@};

PROCEDURE Lookup (iid: Ilu.InstanceId; ot: Ilu.ObjectType): Ilu.Object
  RAISES @{Failed@};

END IluSimpleBind.
@end codeexample

The instance ID used in the @code{Lookup} call is what's called an @metavar{object ID} in chapter 1.  It is the concatenation of: (1) the object handle, as determined by the server's @code{Ilu.ObjectTable}; (2) an at-sign (@@); and (3) the server ID, determined in the call on @code{Ilu.InitTrueServer}.

@section Generating ILU stubs for Modula-3
@cindex Modula-3 stub generation
@cindex Stub generation

To generate @language{Modula-3} stubs from an @language{ISL} file, you use the
program @language{m3-stubber}.
@pindex m3-stubber
Five files are generated from the
@file{.isl} file:
@itemize @bullet
@item
@file{@metavar{interface-name}.i3} contains the Modula-3 renderings of the types, exceptions, and constants declared in the interface, plus some items needed to import or export objects of types declared in the interface;
@item
@file{@metavar{interface-name}_x.i3} is a private interface between the following three implementation modules;
@item
@file{@metavar{interface-name}_y.m3} contains code useful to both server and client stubs;
@item
@file{@metavar{interface-name}_c.m3} contains the client stubs; and
@item
@file{@metavar{interface-name}_s.m3} contains the server
stubs for the interface.
@end itemize
Typically, client and server programmers directly reference only the first of these five files.

@transcript
% @userinput{m3-stubber foo.isl}
translating interface foo to ./foo.i3...
private interface for foo to ./foo_x.i3...
common code for interface foo to ./foo_y.m3...
client stubs for interface foo to ./foo_c.m3...
server stubs of interface foo to ./foo_s.m3...
%
@end transcript


@section Libraries and Linking
@cindex Modula-3 Libraries and linking
@cindex Libraries and linking

Clients of an @system{ILU} interface need to link with all but the server stubs; servers need to link with all five modules.  It's convenient to make a library containing all five modules and let the linker worry about the details of which are needed; the @program{imake} macro @macro{IluM3Files} (see later) conveniently generates the names of all five modules.

Both clients and servers also need to link with the libraries @file{@metavar{ILUHOME}/lib/libilu-m3.a} and @file{@metavar{ILUHOME}/lib/libilu.a} (in this
order, as the former uses functions in the latter).  Because the former library contains only @language{Modula-3} code, and the latter only @language{C} code, invocations of the @command{m3} command need to mention the latter library only when a complete program is being built.

@ifclear largerdoc
@page
@section Index
@printindex cp
@end ifclear
