summaryrefslogtreecommitdiff
path: root/TAO/TAO_IDL/docs/WRITING_A_BE
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/TAO_IDL/docs/WRITING_A_BE')
-rw-r--r--TAO/TAO_IDL/docs/WRITING_A_BE1350
1 files changed, 1350 insertions, 0 deletions
diff --git a/TAO/TAO_IDL/docs/WRITING_A_BE b/TAO/TAO_IDL/docs/WRITING_A_BE
new file mode 100644
index 00000000000..5c3c069f7a1
--- /dev/null
+++ b/TAO/TAO_IDL/docs/WRITING_A_BE
@@ -0,0 +1,1350 @@
+OMG INTERFACE DEFINITION LANGUAGE COMPILER FRONT END PROTOCOLS
+==============================================================
+
+INTRODUCTION
+------------
+
+Welcome to the publicly available source release of SunSoft's
+implementation of the compiler front end (CFE) for OMG Interface Definition
+Language!
+
+This document explains how to use the release to create a fully functional
+OMG Interface Definition Language to target language compiler for your
+selected target system configuration. The section OVERVIEW explains this
+document's structure.
+
+CONTEXT
+-------
+
+The implementation has three parts:
+
+1. A main program driving the compilation process
+2. A parser and attendant utilities for converting the IDL input into
+ an internal form
+3. One or more back ends which take as input the internal form representing
+ the IDL input, and which produce output in a target language and target
+ format
+
+The release contains components 1 and 2, and a demonstration implementation
+of component 3. To use this release, you
+
+- write a back end which takes the internal representation of the parsed input
+ and translates it to the target language and format. You may replace or
+ modify the demonstration back end provided.
+- link the back end with the provided main program and parser sources
+ to produce a complete compiler.
+
+OVERVIEW
+--------
+
+This document does not explain IDL nor does it introduce IDL features.
+For this information, refer to the OMG CORBA specification, available by
+anonymous FTP from omg.org.
+
+This document does not explain C++, except to demonstrate how it is
+used to construct the CFE. The ARM by Stroustrup and Ellis provides a
+thorough explanation of C++.
+
+This document consists of two independent parts. The first part
+s all CFE supported protocols and the required
+application programmer's interface entry points that a conformant
+BE must provide. The second part steps through the process of
+constructing a working BE.
+
+The first part describes:
+
+- The compilation process
+- The Abstract Syntax Tree (AST) internal representation of parsed IDL
+ input
+- How access to member data fields is managed
+- How the AST is generated from the IDL input (Generator protocol)
+- How definition scopes are nested and how name lookup works
+- The narrowing mechanism
+- How definition scopes are managed and how nodes are added to scopes
+- How BEs get control during the AST construction process (Add protocol)
+- The inheritance scheme used by the AST and how it affects BEs
+- How errors are handled and reported
+- How the CFE is initialized
+- How the command line arguments are parsed
+- What global variables and functions are provided
+- What API is required to be supported by a BE in order to link
+ with the CFE
+- What files must be included in each BE file
+
+The second part describes
+
+- The API to be supplied by each BE
+- How to subclass from the AST to add BE specific functionality
+- How to subclass from the Generator protocol to create BE specific
+ extended AST nodes
+- How to write constructors for the derived BE classes
+- How to use the Add protocol to store BE specific information
+- How to maintain BE specific information which applies to the entire
+ AST generated from the IDL input
+- How to use data members in your BE
+- How to build a complete compiler
+
+PART I. FEATURES OF THE CFE
+-=========================-
+
+THE COMPILATION PROCESS
+-----------------------
+
+The OMG IDL compiler operates as follows:
+
+- Parses command line arguments. If an option is directed at a
+ BE, an appropriate operation provided by the BE is invoked to process
+ the option.
+- Performs global initialization.
+- Forks a copy of the compiler for each file specified as input.
+- An ANSI-compatible preprocessor preprocesses the IDL input.
+- Parses the file using the CFE parser, and constructs an AST describing the
+ IDL input.
+- Prints the AST for verification, if requested.
+- Invokes the BE to process the AST and produce the output
+ characteristic of that BE.
+
+ABSTRACT SYNTAX TREE
+--------------------
+
+The AST (Abstract Syntax Tree) is the primary mechanism for communication
+between a BE and the CFE. It consists of a tree of instances of classes
+defined in the CFE or refinements of those classes as defined in a BE.
+The class hierarchy of the AST closely resembles the structure of the IDL
+syntax. Most AST classes have direct equivalents in IDL constructs.
+
+The UTL_Scope class defines common functionality for definition scope
+management and name lookup. This is explained in a following section.
+UTL_Scope is defined in include/utl_scope.hh and implemented in
+util/utl_scope.cc.
+
+The AST provides the following classes:
+
+AST_Decl Base of the AST class hierarchy. Each class in the AST
+ inherits from AST_Decl. Defined in include/ast_decl.hh
+ and implemented in ast/ast_decl.cc
+
+AST_Type Common base class for all classes which represent IDL
+ type constructs. Defined in include/ast_type.hh and
+ implemented in ast/ast_type.cc. Inherits from AST_Decl.
+
+AST_ConcreteType Common base class for all classes which represent IDL
+ types other than interfaces. Defined in the file
+ include/ast_concrete_type.hh and implemented in
+ ast/ast_concrete_type.cc. Inherits from AST_Type.
+
+AST_PredefinedType Instances of this class represent all predefined types
+ such as long, char and so forth. Defined in the file
+ include/ast_predefined_type.hh and implemented in
+ ast/ast_predefined_type.cc. Inherits from
+ AST_ConcreteType.
+
+AST_Module Represents the IDL module construct. Defined in the
+ file include/ast_module.hh and implemented in
+ ast/ast_module.cc. Inherits from AST_Decl and
+ UTL_Scope.
+
+AST_Root Represents the root of the abstract syntax tree being
+ constructed. Is a subclass of AST_Module. Can be
+ subclassed in BEs to store information associated with
+ the entire AST. Defined in the file include/ast_root.hh
+ and implemented in ast/ast_root.cc. Inherits from
+ AST_Module.
+
+AST_Interface Represents the IDL interface construct. Defined in
+ include/ast_interface.hh and implemented in the file
+ ast/ast_interface.cc. Inherits from AST_Type and
+ UTL_Scope.
+
+AST_InterfaceFwd Represents a forward declaration of an IDL interface.
+ Defined in include/ast_interface_fwd.hh and implemented
+ in ast/ast_interface_fwd.cc. Inherits from AST_Decl.
+
+AST_Attribute Represents an IDL attribute construct. Defined in
+ include/ast_attribute.hh and implemented in the file
+ ast/ast_attribute.cc. Inherits from AST_Decl.
+
+AST_Exception Represents an IDL exception construct. Defined in
+ include/ast_exception.hh and implemented in the file
+ ast/ast_exception.cc. Inherits from AST_Decl.
+
+AST_Structure Represents an IDL struct construct. Defined in the file
+ include/ast_structure.hh and implemented in the file
+ ast/ast_structure.cc. Inherits from AST_ConcreteType
+ and UTL_Scope.
+
+AST_Field Represents a field in an IDL struct or exception
+ construct. Defined in include/ast_field.hh and
+ implemented in ast/ast_field.cc. Inherits from
+ AST_Decl.
+
+AST_Operation Represents an IDL operation construct. Defined in the
+ file include/ast_operation.hh and implemented in
+ ast/ast_operation.cc. Inherits from AST_Decl and
+ UTL_Scope.
+
+AST_Argument Represents an argument to an IDL operation construct.
+ Defined in include/ast_argument.hh and implemented in
+ ast/ast_argument.cc. Inherits from AST_Field.
+
+AST_Union Represents an IDL union construct. Defined in
+ include/ast_union.hh and implemented in
+ ast/ast_union.cc. Inherits from AST_ConcreteType and
+ from UTL_Scope.
+
+AST_UnionBranch Represents an individual branch in an IDL union
+ construct. Defined in include/ast_union_branch.hh and
+ implemented in ast/ast_union_branch.cc. Inherits from
+ AST_Field.
+
+AST_UnionLabel Represents the label of an individual branch in an IDL
+ union construct. Defined in include/ast_union_label.hh
+ and implemented in ast/ast_union_label.cc
+
+AST_Constant Represents an IDL constant construct. Defined in
+ include/ast_constant.hh and implemented in the file
+ ast/ast_constant.cc. Inherits from AST_Decl.
+
+AST_Enum Represents an IDL enum construct. Defined in the file
+ include/ast_enum.hh and implemented in ast/ast_enum.cc.
+ Inherits from AST_ConcreteType and UTL_Scope.
+
+AST_EnumVal Represents an enumerator in an IDL enum construct.
+ Defined in include/ast_enum_val.hh and implemented in
+ ast/ast_enum_val.cc. Inherits from AST_Constant.
+
+AST_Sequence Represents an IDL sequence construct. Defined in
+ include/ast_sequence.hh and implemented in
+ ast/ast_sequence.cc. Inherits from AST_Decl.
+
+AST_String Represents an IDL string construct. Defined in the file
+ include/ast_string.hh and implemented in
+ ast/ast_string.cc. Inherits from AST_Decl.
+
+AST_Array Represents an array modifier to the type of an IDL
+ field or typedef declaration. Defined in the file
+ include/ast_array.hh and implemented in
+ ast/ast_array.cc. Inherits from AST_Decl.
+
+AST_Typedef Represents an IDL typedef construct. Defined in the file
+ include/ast_typedef.hh and implemented in
+ ast/ast_typedef.cc. Inherits from AST_Decl.
+
+AST_Expression Represents an IDL expression. Defined in the file
+ include/ast_expression.hh and implemented in
+ ast/ast_expression.cc.
+
+AST_Root A subclass of AST_Module, an instance of this class
+ is used to represent the distinguished root node of
+ the AST. Defined in include/ast_root.hh and implemented
+ in ast/ast_root.cc. Inherits from AST_Module.
+
+
+USING INSTANCE DATA
+-------------------
+
+The AST classes define member data fields in addition to defining
+operations on instances. These member data fields are all private, to allow
+only the instance in which they are stored direct access. Other objects
+(including other instances of the same class) can obtain access to the
+member data fields of an instance through accessor functions. These
+accessor functions allow retrieval of the data, and in some cases update
+functions are also provided to store new values.
+
+There are several reasons why this approach is taken. First, it hides the
+actual implementation of the member data fields from outside the class. For
+example, a Thermometer class would not expose whether its temperature
+reading is stored in Farenheit or Celsius units, and it could allow access
+through either unit method.
+
+Second, protecting access to member data in this manner restricts the
+ability to update it to the instance itself, save where update functions
+are explicitly provided. This makes for more reliable implementations,
+since the manipulation of the data is isolated in the class implementation
+itself.
+
+Third, wrapping a function call around access to member data allows such
+access and update operations to be protected in a multithreaded
+environment. While the CFE itself is not multithreaded and the access
+operations as currently defined do no special work to protect against
+mutliple conflicting access operations, this may be changed in a future
+version. Moving the CFE to a multithreaded environment without protecting
+access to member data in this manner would be extremely difficult.
+
+The protocol defined in the CFE is that member data fields are all private
+and have names which start with the prefix "pd_" (denoting Private Data).
+The access functions have names which are the same as the name of the field
+sans the prefix. For example, AST_Decl has a field pd_defined_in and an
+access function defined_in().
+
+The update functions have names starting with "set_" followed by the name
+of the corresponding access function. Thus, AST_Decl defines a function
+set_in_main_file(boolean) which sets the pd_in_main_file data member's
+value to the boolean provided.
+
+GENERATION OF THE AST
+---------------------
+
+The CFE generates the abstract syntax tree after parsing IDL
+input. The nodes of the AST are defined by classes introduced in the
+previous section, or by subclasses thereof as defined by each BE. In
+writing the CFE, we were faced with the following problem: how to generate
+the AST containing nodes of the derived classes as defined in each BE
+without knowledge of the types and conventions of these BE classes.
+
+One alternative was to define a naming scheme which predetermines the names
+of each subclass a BE can define. The AST would then be generated by
+calling an appropriate constructor on the BE derived class. This scheme
+suffers from some shortcomings:
+
+- It breaks the modularity of the compiler and imports knowledge about
+ types defined in a BE into the CFE, where this information does not belong.
+- It restricts a compiler to having only one BE loaded at a time because the
+ names of these classes can be in use in only one BE at a time.
+- It requires a BE to provide derived classes for all AST classes, even for
+ those classes where the BE adds no functionality.
+
+The mechanism we chose is different. We define the AST_Generator class
+which has an operation for each constructor defined on each AST class. The
+operation takes arguments appropriate to the constructor, invokes it and
+returns the created AST node, using the type known to the CFE. All such
+operations on the generator are declared virtual. The names of all
+operations start with "create_" and contain the name of the construct.
+Thus, an operation which invokes a constructor of an AST_Module is named
+create_module. AST_Generator is defined in include/ast_generator.hh and
+implemented in ast/ast_generator.cc.
+
+If a BE derives from any AST class, it must also derive from the
+AST_Generator class and redefine the relevant operations to invoke
+constructors of the BE provided class instead of the AST provided class.
+For example, if BE_Module is a subclass of AST_Module in a BE, the BE would
+also define BE_Generator and redefine create_module to call the constructor
+of BE_Module instead of that provided by AST_Module.
+
+During initialization, the CFE causes an instance of the BE derived
+generator to be created and saved. This is explained in the section on
+REQUIRED ENTRY POINTS SUPPLIED BY A BE. During parsing, actions in the Yacc
+grammar invoke operations on the saved instance to create new nodes for the
+AST as it is being built. These operations invoke constructors for BE
+derived classes or for AST provided classes if they were not overridden.
+
+DEFINITION SCOPES
+-----------------
+
+IDL is a nested scoped language. The scoping rules are defined by the CORBA
+spec and closely follow those of C++.
+
+Scope management is implemented in two classes provided in the utilities
+library, UTL_Scope and UTL_Stack. UTL_Scope manages associations between
+names and AST nodes, and UTL_Stack manages scope nesting and entry and exit
+from definition scopes as the parse is proceeding. UTL_Scope is defined in
+include/utl_scope.hh and implemented in util/utl_scope.cc. UTL_Stack is
+defined in include/utl_stack.hh and implemented in util/utl_stack.cc.
+
+During initialization, the CFE creates an instance of UTL_Stack and saves
+it. During parsing, as definition scopes are entered and exited, AST nodes
+are pushed onto, or popped from, the stack represented by the saved
+instances. Nodes on the stack are stored as instances of UTL_Scope. Section
+THE NARROWING MECHANISM explains how to obtain the real type of a node
+retrieved from the stack.
+
+All definition scopes are linked in a tree rooted in the distinguished AST
+root node. This linkage is implemented by UTL_Scope and AST_Decl. The
+linkage is a permanent record of the scope nesting while the stack is a
+dynamic record which at each instant represents the current state of the
+parse.
+
+The nesting information is used to do name lookup. IDL uses scoped names
+which are concatenations of definition scope names ending with individual
+construct names. For example, in
+
+ interface a {
+ struct b {
+ long c;
+ };
+ const long k = 23;
+ struct s {
+ long ar[k];
+ };
+ };
+
+the name a::b::c represents the long field in the struct b inside the
+interface a.
+
+Lookup is performed by searching down the linkage chain for the first component
+of the name, then, when found, recursively resolving the remaining
+components in the scope defined by the first component. Lookup is relative
+to the scope of use; in the above example, k could also have been referred to
+as a::k within the struct s.
+
+Nodes are stored in a definition scope as instances of AST_Decl. Thus, name
+lookup returns instances of AST_Decl. The next section, THE NARROWING
+MECHANISM, explains how to obtain the real type of a node retrieved from a
+definition scope.
+
+THE NARROWING MECHANISM
+-----------------------
+
+Here we give only a cursory explanation of how narrowing works. We
+concentrate on defining the problem and showing how to use our narrowing
+mechanism. The narrowing mechanism is defined in include/idl_narrow.hh.
+
+As explained above, nodes are stored on the scope stack as instances of
+UTL_Scope, and inside definition scopes as instances of AST_Decl. Also,
+nodes are linked in a nesting tree as instances of AST_Decl. Given a node
+retrieved from the stack or a definition scope, one is faced with the task
+of obtaining its real class. C++ does not currently provide an implicit
+mechanism for narrowing to a derived class, so the CFE defines its own
+mechanism. This mechanism requires some work on your part as BE implementor
+and requires some explicit code to be written when it is to be used.
+
+The class AST_Decl defines an enum whose members encode specific AST node
+classes. AST_Decl provides an accessor function, node_type(), which
+retrieves a member of the enum representing the AST type of the node. Thus,
+if an instance of AST_Decl really is an instance of AST_Module, the
+node_type() accessor returns AST_Decl::NT_module.
+
+The class UTL_Scope also provides an accessor function, scope_node_type(),
+which returns a member of the enum encoding the actual type of the node.
+Thus, given an UTL_Scope instance which is really an instance of
+AST_Operation, scope_node_type() would return AST_Decl::NT_op.
+
+Perusing the header files for classes provided by the AST, you will note
+the use of some macros defined in include/idl_narrow.hh. These macros
+define the explicit narrowing mechanism:
+
+DEF_NARROW_METHODSx(<class name>,<parent_x>) for x equal to 0,1,2 or 3,
+defines a narrowing method for the specified class which has 0,1,2 or 3
+immediate base classes from which it inherits. For example, ast_module.hh
+which defines AST_Module contains the following line:
+
+ DEF_NARROW_METHODS2(AST_Module, AST_Decl, UTL_Scope)
+
+This is because AST_Module inherits directly from AST_Decl and UTL_Scope.
+
+DEF_NARROW_FROM_DECL(<class name>) appears in class definitions for classes
+which are derived from AST_Decl and which can be stored in a definition
+scope. This macro declares a static operation narrow_from_decl(AST_Decl *)
+on the class in which it appears. The operation returns the provided
+instance as an instance of <class name> if it can be narrowed, or NULL.
+
+DEF_NARROW_FROM_SCOPE(<class name>) appears in class definitions of classes
+which are derived from UTL_Scope and which can be stored on the scope
+stack. This macro declares a static operation narrow_from_scope(UTL_Scope *)
+on the class in which it appears. The operation returns the provided
+instance as an instance of <class name> if it can be narrowed, or NULL.
+
+Now look in the files implementing these classes. You will note occurrences
+of the following macros:
+
+IMPL_NARROW_METHODSx(<class name>,<parent_x>) for x equal to 0,1,2 or 3,
+implements a narrowing method for the specified class which has 0,1,2 or 3
+immediate base classes from which it inherits. For example, ast_module.cc
+which implements AST_Module contains the following line:
+
+ IMPL_NARROW_METHODS2(AST_Module, AST_Decl, UTL_Scope)
+
+IMPL_NARROW_FROM_DECL(<class name>) implements a method to narrow from an
+instance of AST_Decl to an instance of <class name> as defined above.
+
+IMPL_NARROW_FROM_SCOPE(<class name>) implements a method to narrow from an
+instance of UTL_Scope to an instance of <class name> as defined above.
+
+To put it all together: In the file ast_module.hh, you will find:
+
+ // Narrowing
+ DEF_NARROW_METHODS2(AST_Module, AST_Decl, UTL_Scope);
+ DEF_NARROW_FROM_DECL(AST_Module);
+ DEF_NARROW_FROM_SCOPE(AST_Module);
+
+In the file ast_module.cc, you will see:
+
+/*
+ * Narrowing methods
+ */
+IMPL_NARROW_METHODS2(AST_Module, AST_Decl, UTL_Scope)
+IMPL_NARROW_FROM_DECL(AST_Module)
+IMPL_NARROW_FROM_SCOPE(AST_Module)
+
+The CFE uses narrowing internally to obtain the correct type of nodes in
+the AST. The CFE contains many code fragments such as the following:
+
+ AST_Decl *d = get_an_AST_Decl_from_somewhere();
+ AST_Module *m;
+ ...
+ if (d->node_type() == AST_Decl::NT_module) {
+ m = AST_Module::narrow(d);
+ if (m == NULL) { // Narrow failed
+ ...
+ } else { // Success, do normal processing
+ ...
+ }
+ }
+ ...
+
+Similar code implements narrowing instances of UTL_Scope to their actual
+types.
+
+In your BE classes which derive from UTL_Scope you must include a line
+defining how to narrow from a scope, so:
+
+ DEF_NARROW_FROM_SCOPE(<your BE class>)
+
+and similarly for your BE classes which derive from AST_Decl.
+
+The narrowing mechanism is defined only for narrowing from AST_Decl and
+UTL_Scope. If your BE class inherits directly from one or more classes
+which themselves are derived from AST_Decl and/or UTL_Scope, you must
+include a line
+
+ DEF_NARROW_METHODSx(<your class name>,<parent 1>,<parent 2>)
+
+To make this concrete, here is what you'd write in a definition of BE_union
+which inherits from AST_Union:
+
+ DEF_NARROW_METHODS1(BE_Union, AST_Union);
+ DEF_NARROW_FROM_DECL(BE_Union);
+ DEF_NARROW_FROM_SCOPE(BE_Union);
+
+and in the implementation file of BE_Union:
+
+/*
+ * Narrowing methods:
+ */
+IMPL_NARROW_METHODS1(BE_Union, AST_Union)
+IMPL_NARROW_FROM_DECL(BE_Union)
+IMPL_NARROW_FROM_SCOPE(BE_Union)
+
+Then, in BE code which expects to see an instance of your derived BE_Union
+class, you will write:
+
+ AST_Decl *d = get_an_AST_Decl_from_somewhere();
+ BE_Union *u;
+ ...
+ if (d->node_type() == AST_Decl::NT_union) {
+ u = BE_Union::narrow_from_decl(d);
+ if (u == NULL) { // Narrow failed
+ ...
+ } else { // Success, do normal processing
+ ...
+ }
+ }
+ ...
+
+
+SCOPE MANAGEMENT
+----------------
+
+Instances of classes which are derived from UTL_Scope implement definition
+scopes. A definition scope can contain any kind of AST node as long as it
+is derived from AST_Decl. However, specific kinds of definition scopes such
+as interfaces and unions can contain only a restricted subset of all AST
+node types.
+
+UTL_Scope provides operations to add instances of each AST provided class
+to a definition scope. The names of these operations are constructed by
+prepending the string "add_" to the name of the IDL construct. So, to add
+an interface to a definition scope, invoke the operation add_interface.
+The operations are all defined virtual and are intended to be overridden in
+classes derived from UTL_Scope.
+
+If the node was successfully added to the definition scope, the node is
+returned as the result. Otherwise the node is not added to the definition
+scope and NULL is returned.
+
+All add operation implementations in UTL_Scope return NULL. Thus,
+only the operations which implement legal additions to a specific kind of
+definition scope must be overridden in the implementation of that
+definition scope. For example, in AST_Module the add_interface operation is
+overridden to add the provided instance of AST_Interface to the scope and
+to return the provided instance if the addition was successful. Operations
+which were not overridden return NULL to indicate that the addition is
+illegal in this context. For example, in AST_Operation the definition of
+add_interface is not overridden since it is illegal to store an interface
+inside an operation definition scope.
+
+The add operations are invoked in the actions in the Yacc grammar. The
+following fragment is a representative example of code using the add
+operations:
+
+ AST_Constant *d = construct_a_new_constant();
+ ...
+ if (current_scope->add_constant(d) == NULL) { // Failed
+ ...
+ } else { // Succeeded
+ ...
+ }
+
+BE INTERACTION DURING THE PARSING PROCESS
+-----------------------------------------
+
+The add operations can be overridden in BE derived classes to let the BE
+perform additional house-keeping work during the process of constructing
+the AST. For example, a BE could keep separate lists of interfaces as they
+are being added to a module.
+
+If you override an add operation in your BE, you must invoke the overridden
+operation in the superclass of your derived class to allow the CFE to
+perform its own house-keeping tasks. A good rule is to invoke the operation
+on the superclass before you do your own processing; then, if the
+superclass operation returns NULL, this indicates that the addition failed
+and your own code should immediately return NULL. An example explains this:
+
+AST_Interface *
+BE_Module::add_interface(AST_Interface *i)
+{
+ if (AST_Module::add_interface(i) == NULL) // Failed, bail out!
+ return NULL;
+ ... // Do your own work here
+ return i; // Return success indication
+}
+
+We strongly advise you to only define add operations that override add
+operations provided by the AST classes. Add operations which
+do not override equivalent operations in the AST in effect
+extend the semantics of the language accepted by the compiler. For
+example, the CFE does not have an add_interface operation on
+AST_Operation. If you were to define one in your BE_Operation class,
+the resulting compiler would allow an interface to be
+stored in an operation definition scope. The current CORBA specification
+does not allow this.
+
+AST INHERITANCE SCHEME
+----------------------
+
+The AST classes all use public virtual inheritance to construct the
+inheritance tree. This ensures that a class may appear several times in the
+inheritance tree through different paths and the derived class's instances
+will have only one copy of the inherited class's data.
+
+The use of public virtual inheritance has several important effects on how
+a BE is constructed. We explain those effects below.
+
+First, you must define a default constructor for your BE class, since
+your class may be used as a virtual base class of some other class. In this
+case the compiler may want to call a default constructor for your class. It
+is a good idea to have a default constructor anyway, even if you do not
+plan to subclass your BE class, since for most C++ compilers this causes
+the code to be smaller. Your default constructor should initialize all
+constant data members. Additionally, it may initialize any non-constant
+data member whose value must be set before the first time the instance is
+used.
+
+Second, the constructor of your BE derived class must explicitly call all
+constructors of virtual base classes which perform useful work. For
+example, if a class in the AST from which your BE class inherits has an
+initializer for a data member, you must call that constructor. This rule is
+discussed in detail in the C++ ARM. An example may help here.
+
+Suppose you define a class BE_attribute which inherits from AST_Attribute.
+Its constructor should be as follows:
+
+ BE_Attribute::BE_Attribute(boolean ro,
+ AST_Type *ft,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Attribute(ro, ft, n, p),
+ AST_Field(ft, n, p),
+ AST_Decl(AST_Decl::NT_attr, n, p)
+ {
+ }
+
+The calls to the constructors of AST_Attribute, AST_Field and AST_Decl are
+needed because these constructors do useful initializations on their
+classes.
+
+Note that there is some redundancy in the data passed to these
+constructors. We chose to preserve this redundancy since it should be
+possible to create BEs which subclass only some of the classes supplied by
+the AST. This means that the constructors on each class provided by the AST
+should take arguments which are sufficient to construct the instance if
+the AST class is the most derived one.
+
+The code supplied with this release contains a demonstration BE which
+subclasses all the AST provided classes. The constructors for each class
+provided by the BE are found in the file be/be_classes.cc.
+
+INITIALIZATION
+--------------
+
+The following steps take place at initialization:
+
+- The global data instance is created, stored in idl_global and filled with
+ default values (in driver/drv_init.cc).
+- The command line arguments are parsed (in driver/drv_args.cc).
+- For each IDL input file, a copy of the compiler process is forked (in
+ driver/drv_fork.cc).
+- The IDL input is preprocessed (in driver/drv_preproc.cc).
+- FE initialization stage 1 is done: the scopes stack is created and stored
+ in the global data variable idl_global->scopes() field (in fe/fe_init.cc).
+- BE_init is called to create the generator instance and the returned
+ instance is stored in the global data variable idl_global->gen() field.
+- FE initialization stage 2 is done: the global scope is created, pushed on
+ the scopes stack and populated with predefined types (in fe/fe_init.cc).
+
+GLOBAL STATE AND ENTRY POINTS
+-----------------------------
+
+The CFE has one global variable named idl_global, which stores an instance
+of a class IDL_GlobalData as explained below:
+
+The CFE defines a class IDL_GlobalData which defines the global
+information used in a specific run of the compiler. IDL_GlobalData is
+defined in include/idl_global.hh and implemented in the file
+util/utl_global.cc.
+
+Initialization creates an instance of this class and stores it in the value
+of the global variable idl_global. Thus, the individual pieces of
+information stored in the instance are accessible everywhere.
+
+ERROR HANDLING
+--------------
+
+All error handling is defined by a class provided by the CFE, UTL_Error.
+This class is defined in include/utl_error.hh and implemented in the file
+util/utl_error.cc. The class provides several methods for reporting
+specific errors as well as generic error reporting methods taking zero to
+three arguments.
+
+The CFE instantiates the class and stores the instance as part of the
+global state, accessible as idl_global->err(). Thus, to cause an error
+report, you would write code similar to the following:
+
+ if (error condition found)
+ idl_global->err()->specific_error_message(arg1, ..);
+
+or
+
+ if (error condition found)
+ idl_global->err()->generic_error_message(flag, arg1, ..);
+
+The flag argument is one of the predefined error conditions found in the
+enum at the head of the UTL_Error class definition. The arguments to the
+specific error message routine are defined by the signature of that
+routine. The arguments to a generic error message routine are always
+instances of AST_Decl.
+
+The running count of errors is accessible as idl_global->err_count(). If
+the value returned by this operation is non-zero after the IDL input has
+been parsed, the BE is not invoked.
+
+HANDLING OF COMMAND LINE ARGUMENTS
+----------------------------------
+
+Defined command line arguments are specified in the document CLI, in this
+directory. The CFE calls the required BE API entry point BE_prep_arg to
+process arguments passed within a -Wb flag.
+
+REQUIRED ENTRY POINTS SUPPLIED BY A BE
+--------------------------------------
+
+The following API entry points must be supplied by a BE in order to
+successfully link with the CFE:
+
+extern "C" AST_Generator *BE_init();
+
+ Creates an instance of the generator object and returns it. Note
+ that the global scope is not yet set up and the scopes stack is
+ empty when this routine is called.
+
+extern "C" void BE_produce();
+
+ Called by the compiler main program after the IDL input has been
+ successfully parsed and processed. The job of this routine is to
+ carry out the specific function of the BE. The AST is accessible as
+ the value of idl_global->root().
+
+extern "C" void BE_prep_arg(char *, idl_bool);
+
+ Called to process an argument passed in with a -Wb flag. The boolean
+ will always be FALSE.
+
+extern "C" void BE_abort();
+
+ Called when the CFE decides to abort the compilation. Can be used in
+ a BE to clean up after itself, e.g. remove temporary files or
+ directories it created while the parse was in progress.
+
+extern "C" void BE_version();
+
+ Called when a -V argument is processed. This should produce a
+ message for the user identifying the BE that is loaded and its
+ version information.
+
+PART II. WRITING A BACK END
+-=========================-
+
+REQUIRED API THAT EACH BE MUST SUPPORT
+--------------------------------------
+
+Below are the API entry points that each BE must supply in order to use the
+CFE framework. This is a repeat of the BE API section:
+
+extern "C" AST_Generator *BE_init();
+
+ Creates an instance of the generator object and returns it. Note
+ that the scopes stack is still not set up at the time this routine
+ is called.
+
+extern "C" void BE_produce();
+
+ Called by the compiler main program after the IDL input has been
+ successfully parsed and processed. The job of this routine is to
+ carry out the specific function of the BE. The AST is accessible as
+ the value of idl_global->root().
+
+extern "C" void BE_prep_arg(char *, boolean);
+
+ Called to process an argument passed in with a -Wb flag. The boolean
+ will always be FALSE.
+
+extern "C" void BE_abort();
+
+ Called when the CFE decides to abort the compilation. Can be used in
+ a BE to clean up after itself, e.g. remove temporary files or
+ directories it created while the parse was in progress.
+
+extern "C" void BE_version();
+
+ Called when a -V argument is processed. This should produce a
+ message for the user identifying the BE that is loaded and its
+ version information.
+
+WHAT FILES TO INCLUDE
+---------------------
+
+To use the CFE, each implementation file of your BE must include the
+following two header files:
+
+#include <idl.hh>
+#include <idl_extern.hh>
+
+Following this, you can include any header files needed by your BE.
+
+HOW TO SUBCLASS THE AST
+-----------------------
+
+Your BE may subclass from any of the classes provided by the AST. Your
+class should use public virtual inheritance to ensure that only one copy of
+the class's data members is present in each instance. Read the section on
+HOW TO WRITE CONSTRUCTORS to learn about additional considerations that you
+must take into account when writing constructors for your BE classes.
+
+HOW TO SUBCLASS THE GENERATOR TO CREATE BE ENHANCED AST NODES
+-------------------------------------------------------------
+
+Your BE subclasses from classes provided by the AST. To ensure that
+instances of these classes are constructed when the AST is built, you must
+also subclass AST_Generator and return an instance of your subclass from
+the call to BE_init.
+
+The AST_Generator class provides operations to create instances of all
+classes defined in the AST. For example, the operation to create an
+AST_Attribute node is as follows:
+
+ AST_Attribute *
+ AST_Generator::create_attribute(...)
+ {
+ return new AST_Attribute(...);
+ }
+
+In your BE_Generator subclass of AST_Generator, you will override methods
+for creation of nodes of all AST classes which you have subclassed. Thus,
+if your BE has a class BE_Attribute which is a subclass of AST_Attribute,
+your BE_Generator class definition has to override the create_attribute
+method to ensure that instances of BE_Attribute are created.
+
+The definition of the overriden operations should call the constructor of
+the derived class and return the new node as an instance of the inherited
+class. Thus, the implementation of create_attribute is as follows:
+
+ AST_Attribute *
+ BE_Generator::create_attribute(...)
+ {
+ return new BE_Attribute(...);
+ }
+
+The Yacc grammar actions call create_xxx operations on the generator
+instance stored in the global variable idl_global->gen() field. By storing
+an instance of your derived generator class BE_Generator you ensure that
+instances of the BE classes you defined will be created.
+
+HOW TO WRITE CONSTRUCTORS FOR BE CLASSES
+----------------------------------------
+
+As mentioned above, the AST uses public virtual inheritance to derive the
+AST class hierarchy. This has two important effects on how you write a BE,
+specifically how you write constructors for derived BE classes.
+
+First, you must define a default constructor for your BE class, since
+your class may be used as a virtual base class of some other class. In that
+case the compiler may want to call a default constructor for your class. It
+is a good idea to have a default constructor anyway, even if you do not
+plan to subclass your BE class, since for most C++ compilers this causes
+the code to be smaller. Your default constructor should initialize all
+constant data members. Additionally, it may initialize any non-constant
+data member whose value must be set before the first time the instance is
+used.
+
+Second, the constructor for your BE class must explicitly call all
+constructors of virtual base classes which do some useful work. For
+example, if a class in the AST from which your BE class inherits, directly
+or indirectly, has an initializer for a data member, your BE class's
+constructor must call the AST class's constructor. This is discussed
+extensively in the C++ ARM.
+
+Below is a list showing how to write constructors for subclasses of each
+class provided by the BE. For each AST class we show a definition of a
+constructor for a derived class which calls all neccessary constructors on
+AST classes:
+
+AST_Argument:
+
+ BE_Argument::BE_Argument(AST_Argument::Direction d,
+ AST_Type *ft,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Argument(d, ft, n, p),
+ AST_Field(AST_Decl::NT_argument, ft, n, p),
+ AST_Decl(AST_Decl::NT_argument, n, p)
+ {
+ }
+
+AST_Array:
+
+ BE_Array::BE_Array(UTL_ScopedName *n,
+ unsigned long nd,
+ UTL_ExprList *ds)
+ : AST_Array(n, nd, ds),
+ AST_Decl(AST_Decl::NT_array, n, NULL)
+
+ {
+ }
+
+AST_Attribute:
+
+ BE_Attribute::BE_Attribute(boolean ro,
+ AST_Type *ft,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Attribute(ro, ft, n, p),
+ AST_Field(AST_Decl::NT_attr, ft, n, p),
+ AST_Decl(AST_Decl::NT_attr, n, p)
+ {
+ }
+
+AST_ConcreteType:
+
+ BE_ConcreteType::BE_ConcreteType(AST_Decl::NodeType nt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(nt, n, p)
+ {
+ }
+
+AST_Constant:
+
+ BE_Constant::BE_Constant(AST_Expression::ExprType t,
+ AST_Expression *v,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Constant(t, v, n, p),
+ AST_Decl(AST_Decl::NT_const, n, p)
+ {
+ }
+
+AST_Decl:
+
+ BE_Decl::BE_Decl(AST_Decl::NodeType nt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(nt, n, p)
+ {
+ }
+
+AST_Enum:
+
+ BE_Enum::BE_Enum(UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Enum(n, p),
+ AST_Decl(AST_Decl::NT_enum, n, p),
+ UTL_Scope(AST_Decl::NT_enum)
+ {
+ }
+
+AST_EnumVal:
+
+ BE_EnumVal::BE_EnumVal(unsigned long v,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_EnumVal(v, n, p),
+ AST_Constant(AST_Expression::EV_ulong,
+ AST_Decl::NT_enum_val,
+ new AST_Expression(v),
+ n,
+ p),
+ AST_Decl(AST_Decl::NT_enum_val, n, p)
+ {
+ }
+
+AST_Exception:
+
+ BE_Exception::BE_Exception(UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(AST_Decl::NT_except, n, p),
+ AST_Structure(AST_Decl::NT_except, n, p),
+ UTL_Scope(AST_Decl::NT_except)
+ {
+ }
+
+AST_Field:
+
+ BE_Field::BE_Field(AST_Type *ft,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Field(ft, n, p),
+ AST_Decl(AST_Decl::NT_field, n, p)
+ {
+ }
+
+AST_Interface:
+
+ BE_Interface::BE_Interface(UTL_ScopedName *n,
+ AST_Interface **ih,
+ long nih,
+ UTL_StrList *p)
+ : AST_Interface(n, ih, nih, p),
+ AST_Decl(AST_Decl::NT_interface, n, p),
+ UTL_Scope(AST_Decl::NT_interface)
+ {
+ }
+
+AST_InterfaceFwd:
+
+ BE_InterfaceFwd::BE_InterfaceFwd(UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_InterfaceFwd(n, p),
+ AST_Decl(AST_Decl::NT_interface_fwd, n, p)
+ {
+ }
+
+AST_Module:
+
+ BE_Module::BE_Module(UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(AST_Decl::NT_module, n, p),
+ UTL_Scope(AST_Decl::NT_module)
+ {
+ }
+
+AST_Operation:
+
+ BE_Operation::BE_Operation(AST_Type *rt,
+ AST_Operation::Flags fl,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Operation(rt, fl, n, p),
+ AST_Decl(AST_Decl::NT_op, n, p),
+ UTL_Scope(AST_Decl::NT_op)
+ {
+ }
+
+AST_PredefinedType:
+
+ BE_PredefinedType::BE_PredefinedType(
+ AST_PredefinedType::PredefinedType *pt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_PredefinedType(pt, n, p),
+ AST_Decl(AST_Decl::NT_pre_defined, n, p)
+ {
+ }
+
+AST_Root:
+
+ BE_Root::BE_Root(UTL_ScopedName *n, UTL_StrList *p)
+ : AST_Module(n, p),
+ AST_Decl(AST_Decl::NT_module, n, p),
+ UTL_Scope(AST_Decl::NT_module)
+ {
+ }
+
+
+AST_Sequence:
+
+ BE_Sequence::BE_Sequence(AST_Expression *ms, AST_Type *bt)
+ : AST_Sequence(ms, bt),
+ AST_Decl(AST_Decl::NT_sequence,
+ new UTL_ScopedName(new String("sequence"), NULL),
+ NULL)
+ {
+ }
+
+AST_String:
+
+ BE_String::BE_String(AST_Expression *ms)
+ : AST_String(ms),
+ AST_Decl(AST_Decl::NT_string,
+ new UTL_ScopedName(new String("string"), NULL),
+ NULL)
+ {
+ }
+
+AST_Structure:
+
+ BE_Structure::BE_Structure(UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(AST_Decl::NT_struct, n, p),
+ UTL_Scope(AST_Decl::NT_struct)
+ {
+ }
+
+AST_Type:
+
+ BE_Type::BE_Type(AST_Decl::NodeType nt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Decl(nt, n, p)
+ {
+ }
+
+AST_Typedef:
+
+ BE_Typedef::BE_Typedef(AST_Type *bt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Typedef(bt, n, p),
+ AST_Decl(AST_Decl::NT_typedef, n, p)
+ {
+ }
+
+AST_Union:
+
+ BE_Union::BE_Union(AST_ConcreteType *dt,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_Union(dt, n, p),
+ AST_Structure(AST_Decl::NT_union, n, p),
+ AST_Decl(AST_Decl::NT_union, n, p),
+ UTL_Scope(AST_Decl::NT_union)
+ {
+ }
+
+AST_UnionBranch:
+
+ BE_UnionBranch::BE_UnionBranch(AST_UnionLabel *fl,
+ AST_Type *ft,
+ UTL_ScopedName *n,
+ UTL_StrList *p)
+ : AST_UnionBranch(fl, ft, n, p),
+ AST_Field(ft, n, p),
+ AST_Decl(AST_Decl::NT_union_branch, n, p)
+ {
+ }
+
+AST_UnionLabel:
+
+ BE_UnionLabel::BE_UnionLabel(AST_UnionLabel::UnionLabel lk,
+ AST_Expression *lv)
+ : AST_UnionLabel(lk, lv)
+ {
+ }
+
+HOW TO USE THE ADD PROTOCOL
+---------------------------
+
+As explained the section SCOPE MANAGEMENT, the CFE manages scopes by
+calling type-specific functions to add new nodes to the scope to be
+augmented. These functions can be overridden in your BE classes to do work
+specific to your BE class. For example, in a BE_module class, you might
+override add_interface to do additional work.
+
+The protocol defined by the "add_" functions is that they return NULL to
+indicate failure. They return the node that was added (and which was given
+as an argument) if the operation succeeded. Your functions in your BE class
+should follow the same protocol.
+
+The "add_" functions defined in the BE must call the overridden function in
+the base class defind in the CFE in order for the CFE scope management
+mechanism to work. Otherwise, the CFE does not get an opportunity to
+augment its scopes with the new node to be added. It is good practice to
+call the overridden "add_" function as the first action in your BE
+function, because the success or failure of the CFE operation indicates
+whether your function should complete its task or abort early.
+
+Here is an example. Suppose you have defined a class BE_module which
+inherits from AST_Module. You may wish to override the add_interface
+function as follows:
+
+ class BE_Module : public virtual AST_Module
+ {
+ ....
+ /*
+ * ADD protocol
+ */
+ virtual AST_Interface *add_interface(AST_Interface *);
+ ...
+ };
+
+The implementation of this function would look something like the following:
+
+ AST_Interface *
+ BE_Module::add_interface(AST_Interface *new_in)
+ {
+ /*
+ * Check that the CFE operation succeeds. If it returns
+ * NULL, stop any further work
+ */
+ if (AST_Module::add_interface(new_in) == NULL)
+ return NULL;
+ /*
+ * OK, non-NULL, this means the BE can do its own work here
+ */
+ ...
+ /*
+ * Finally, don't forget to return the argument to indicate
+ * success
+ */
+ return new_in;
+ }
+
+HOW TO MAINTAIN BE SPECIFIC INFORMATION
+---------------------------------------
+
+The CFE provides a special class AST_Root, a subclass of AST_Module. An
+instance of the AST_Root class is used as the distinguished root of the
+abstract syntax tree built during a parse.
+
+Your BE can subclass BE_Root from AST_Root and override the create_root
+operation in your BE_Generator class derived from AST_Generator. This will
+cause the CFE to create an instance of your BE_Root class as the root of
+the tree being constructed.
+
+You can use the instance of the BE_Root class as a convenient place to
+store information specific to an individual tree. For example, you could
+add operations on the BE_Root class to count how many nodes of each class
+are created.
+
+HOW TO USE MEMBER DATA
+----------------------
+
+As explained above, the AST classes provide access and update functions for
+manipulating data members. Your BE classes must use these functions when
+they require access to data members defined in the AST classes, since the
+data members themselves are private.
+
+It is good practice to follow the same scheme in your BE classes. Make all
+data members private. Prepend the names of all such fields with "pd_".
+Define access functions with names equal to the name of the field without the
+prefix. Define update functions according to need by prepending the name of
+the access function with the prefix "set_".
+
+Using these techniques will allow your BE to enjoy the same benefits that
+are imparted onto the CFE. Your BE will be easier to move to a
+multithreaded environment and its data members will be better protected and
+hidden.
+
+HOW TO BUILD A COMPLETE COMPILER
+--------------------------------
+
+We now have all information needed to write a BE and to link it in with the
+CFE, to produce a complete IDL compiler.
+
+The following assumes that your BE will be stored in the "be" directory
+under the "release" directory. See the document ROADMAP for an explanation
+of the directory structure of the source release. If you decide to use a
+different directory to store your BE, you may have to modify the CPP_FLAGS in
+"idl_make_vars" in the top-level directory to allow your BE to find the
+include files it needs. You will also need to modify several targets in
+the Makefile in the top-level directory to correctly compile your BE into a
+library and to correctly link it in with the CFE to produce a complete
+compiler.
+
+You can get started quickly on writing your BE by modifying the sources
+found in the "demo_be" directory. The Makefile supports all the the targets
+that are needed to build a complete system and the maintenance target
+"clean" which assists in keeping the files and directories tidy. The files
+provided in the "demo_be" directory also provide all the API entry points
+that are mandated by this document.
+
+To build a complete compiler, invoke "make" or "make all" in the top-level
+directory. This will compile your BE and all the CFE sources, if this is
+the first invocation. On subsequent invocations this will recompile only
+the modified files. You will rarely if at all modify the CFE sources, so
+the overhead of compiling the CFE is incurred only the first time. To build
+just your BE, you can invoke "make all" or "make" in the "demo_be"
+directory. You can also, from the top-level directory, invoke "make
+demo_be/libbe.a".
+
+HOW TO OBTAIN ASSISTANCE
+------------------------
+
+First, read all the documents provided. If you have unanswered questions,
+mail them to
+
+ idl-cfe@sun.com
+
+Sun does not promise to support the IDL CFE source release in any manner.
+However, we will attempt to answer questions and correct problems as time
+allows.
+
+NOTE:
+
+SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
+trademarks or registered trademarks of Sun Microsystems, Inc.
+
+COPYRIGHT NOTICE
+----------------
+
+Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United
+States of America. All Rights Reserved.
+
+This product is protected by copyright and distributed under the following
+license restricting its use.
+
+The Interface Definition Language Compiler Front End (CFE) is made
+available for your use provided that you include this license and copyright
+notice on all media and documentation and the software program in which
+this product is incorporated in whole or part. You may copy and extend
+functionality (but may not remove functionality) of the Interface
+Definition Language CFE without charge, but you are not authorized to
+license or distribute it to anyone else except as part of a product or
+program developed by you or with the express written consent of Sun
+Microsystems, Inc. ("Sun").
+
+The names of Sun Microsystems, Inc. and any of its subsidiaries or
+affiliates may not be used in advertising or publicity pertaining to
+distribution of Interface Definition Language CFE as permitted herein.
+
+This license is effective until terminated by Sun for failure to comply
+with this license. Upon termination, you shall destroy or return all code
+and documentation for the Interface Definition Language CFE.
+
+INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
+ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
+FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
+DEALING, USAGE OR TRADE PRACTICE.
+
+INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
+ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
+TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
+
+SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
+RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
+INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
+
+IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
+ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
+DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+Use, duplication, or disclosure by the government is subject to
+restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
+Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
+52.227-19.
+
+Sun, Sun Microsystems and the Sun logo are trademarks or registered
+trademarks of Sun Microsystems, Inc.
+
+SunSoft, Inc.
+2550 Garcia Avenue
+Mountain View, California 94043