/*
 *  idlgen.h: include file for default IDL generation
 *
 *  Copyright (c) 1994 MetaWare Incorporated
 *
 */

// Instructions for obtaining IDL generation from High C/C++ DTS compiler.

// 0. Example of how to compile:
//              hc myclass.h -Hidlgen
//    See below for more specifics.

// 1. This file, idlgen.h, must be in the High C inc/ or incc/ directory.

// 2. IDL is generated for those classes appearing only in the file
//    being compiled, not in any header files.  This allows you to
//    compile header files individually to generate the appropriate IDL.
//    -Hidlgen causes the driver to treat .h files as C++ files so
//    you can compile them.   For example:
//              hc myclass.h -Hidlgen
//    compiles myclass.h and produces IDL for any SOM classes defined
//    within myclass.h, but not for any SOM classes #include-d by
//    myclass.h.

//currently not supported:
//   nested classes
//typedefs outside a class (and native mode class/structs/unions)
//   declorder
//   friends
//predeclarations
//
//known problems:
//   nocall not recognized

#ifndef _IDLGEN_INCLUDED_
#define _IDLGEN_INCLUDED_

//debugging code
//#define _DBG_IDL_
#ifdef _DBG_IDL_
#define _DBG_(str) str
#else
#define _DBG_(str)
#endif

//sompredecls //generates IDL predeclaratios for SOMObjects
#ifndef _SOMPREDECLS_
#define _SOMPREDECLS_ \
   _DBG_("SOMPREDECLS==>") \
   "%nlinterface SOMObject;" \
   "%nlinterface SOMClass;" \
   "%nlinterface SOMClassMgr;" \
   "%nl#include <somobj.idl> //for somInitCtrl" \
   "%ic(" \
       "%nlinterface %cni;" \
       "%)" \
   "%nltypedef SOMFOREIGN SOMFOREIGN_LONG_DOUBLE;" \
       "%nl#pragma somemittypes on" \
       "%+t" \
       "%nl#pragma modifier SOMFOREIGN_LONG_DOUBLE:  impctx=%qC++%q, size=12, align=4;" \
       "%-t" \
       "%nl#pragma somemittypes off" \
   "%nl"
#endif /* _SOMPREDECLS_ */

//includes //generates IDL includes
#ifndef _INCLUDES_
#define _INCLUDES_  \
    _DBG_("INCLUDES==>") \
    "%ii(%nl#include <%fn.idl> //from %fp%)"
#endif /* _INCLUDES_ */

//passthrus
//global passthrus (default outside class is Begin)
#ifndef _BEGPASSTHRUS_
#define _BEGPASSTHRUS_  \
    _DBG_("BEGPASSTHRUS==>") \
    "%i(p,l(Begin)|l())(%nl%ps%)"
#endif
#ifndef _ENDPASSTHRUS_
#define _ENDPASSTHRUS_  \
    _DBG_("ENDPASSTHRUS==>") \
    "%i(p,l(End))(%nl%ps%)"
#endif
//class passthus (default within class is Implementation-Begin)
#ifndef _IMPBEGPASSTHRUS_
#define _IMPBEGPASSTHRUS_  \
   _DBG_("IMPBEGPASSTHRUS==>") \
   "%i(p,l(Implementation-Begin)|l())(%nl%ps%)"
#endif
#ifndef _IMPENDPASSTHRUS_
#define _IMPENDPASSTHRUS_  \
   _DBG_("IMPENDPASSTHRUS==>") \
   "%i(p,l(Implementation-End))(%nl%ps%)"
#endif
#ifndef _INTBEGPASSTHRUS_
#define _INTBEGPASSTHRUS_  \
   _DBG_("INTBEGPASSTHRUS==>") \
   "%i(p,l(Interface-Begin))(%nl%ps%)"
#endif
#ifndef _INTENDPASSTHRUS_
#define _INTENDPASSTHRUS_  \
   _DBG_("INTENDPASSTHRUS==>") \
   "%i(p,l(Interface-End))(%nl%ps%)"
#endif

//friends //generates friends modifier
#ifndef _FRIENDS_
#define _FRIENDS_ //not supported so we've removed it for now
#define _FRIENDS2_  \
   _DBG_("FRIENDS==>") \
    "%?if("      \
       "%nl"    \
       "friends = %q%if(%fr, %)%bs%bs%q;" \
       "%)"
#endif /* _FRIENDS_ */

//releaseorder //generates IDL releaseorder modifier
#ifndef _RELEASEORDER_
#define TMP \
    "%i(m,d&!pri&!st)(" \
    _DBG_("NODATA1==>") \
       "%?at(" \
	  "%!?i(q,q(nodata))(" \
	     "%nl%mni," \
	     "%)" \
	  "%)" \
       "%!?at(" \
	  "%nl%mni," \
	  "%)" \
       "%)"
#define _RELEASEORDER_ \
   _DBG_("RELEASEORDER==>") \
    "%nl"    \
    "releaseorder : " \
    "%+t" \
    /* emit all released members */ \
    "%ir(%nl%mni,%)" \
    /* emit all attributes which have data */ \
    "%i(m,d&at)("      \
       "%?!i(q,q(nodata))(" \
	  "%nl%mni,"   \
	  "%)" \
       "%)"    \
    /* emit all non-private non-attribue non-static members */ \
    "%i(m,d&!at&!pri&!st)(" \
       "%nl%mni," \
       "%)"    \
    "%bs;" \
    "%-t"
#endif /* _RELEASEORDER_ */

//declorder //generates IDL declorder modifier
//  a separate declaration order is needed since not only members
//  will be included here, and also some compiler introduced declarations
//  ignoring declaration order for now
#ifndef _DECLORDER_
#define _DECLORDER_ //not supported so we've removed it for now
#define _DECLORDER2_ \
   _DBG_("DECLORDER==>") \
   "%?id(%nldeclarationorder = %id(%mnn, %)%bs%bs%)"
#endif /* _DECLORDER_ */

//typedefs outside a class //generates types outside interfaces
#ifndef _TYPES_
#define _TYPES_ \
    _DBG_("TYPES==>") \
    "%?i(t,!sm)("      \
       "%nl"    \
       "#pragma somemittypes on" \
       "%i(t,!sm)("     \
	  "%nl" \
	  "%mdi;" \
	  "%nl" \
	  "#pragma modifier " _TYPEMODS_ \
	  "%)"    \
       "%nl"    \
       "#pragma somemittypes off" \
       "%nl"    \
       "#pragma modifier " _DECLORDER_ " /* keep order of C++ declared types */" \
       "%)"
#endif /* _TYPES_ */

//classtypes //generates IDL declarations for types inside a class
#ifndef _CLASSTYPES_
#define _CLASSTYPES_ \
    _DBG_("FIXME!CLASSTYPES==>") \
    "%i(m,t&!sm)("     \
       "%nl" \
       "%mdi;" \
       "%)"
//to distinguish between pub/pro/pri:
#define _CLASSTYPES2_ \
    _DBG_("CLASSTYPES==>") \
    "%i(m,t&!sm&(pub|pro))("     \
       "%nl" \
       "%mdi;" \
       "%)"    \
    "%?i(m,t&!sm&pri)(" \
       "%nl"   \
       "#ifdef __PRIVATE__" \
       "%+t"     \
       "%i(m,t&!sm&pri)(" \
	  "%nl" \
	  "%mdi;" \
	  "%)"   \
       "%-t"     \
       "%nl"   \
       "#endif"  \
       "%)"
#endif /* _CLASSTYPES_ */

//typemods //generates modifiers for each class type
#ifndef _TYPEMODS_
//removed from ?!sf: %?%msz(size=%msz, %) %?%mal(align=%mal, %)
#define _TYPEMODS_ \
      _DBG_("TYPEMODS==>") \
      "%?sf("        \
	"%?e("       \
	   "%nl"   \
	   "%mni:  impctx=%qSOM, instance(%cni)%q;"  \
	   "%)"      \
	"%?(!e&!cg)(" \
	   "%nl"   \
	   "%mni:  impctx=%qC++%q, size=%msz, align=%mal," \
	   "%nl" \
	   "cxxdecl=%q%mdn;%q;" \
	   "%)"      \
	"%)"         \
      "%?!sf("       \
	"%nl"      \
	"%mni:  "    \
	   "%?!cg(%nlcxxdecl=%q%mdn;%q, %)" \
	   "%bs%bs;" \
	"%)"
#endif /* _TYPEMODS_ */

//classes //generates interfaces
//may want to change %ic to %i(t,sm) at some point since classes are types..?
#ifndef _CLASSES_
#define _CLASSES_  \
    _DBG_("CLASSES==>") \
    "%ic("          \
       _CLASS_      \
       "%nl"      \
       "%)"

//nested classes aren't modules anymore
//but namespaces probably should be!
#define _OLDCLASSES_ \
    _DBG_("OLDCLASSES==>") \
    "%ic("           \
       "%?in(%nlmodule %cmn {"  \
	  "%+t"      \
	  "%in("     \
	     "%nl" \
	     "interface %cni;" \
	     "%)"    \
	  "%)"       \
       _CLASS_      \
       "%?in("       \
	  "%in(" _CLASS_ "%)" \
	  "%nl"    \
	  "}"        \
	  "%-t"      \
	  "%)"       \
       "%nl"       \
       "%)"
#endif /* _CLASSES_ */

//nested classes //generates nests and nested modifiers
#ifndef _NESTS_
#define _NESTS_ \
       _DBG_("NESTS==>") \
       "%?in("       \
	  "%nlnests = "  \
	  "%in("     \
	     "%mni;" \
	     "%)"    \
	  "%)"       \
       "%?iN("       \
	  "%iN("       \
	     "%nlnested = "  \
	      "%cni;"   \
	     "%)" \
	  "%)"
#endif /* _NESTS_ */

//modifiers //generates member modifiers
#ifndef _MODIFIERS_
#define _MODIFIERS_ \
    _DBG_("MODIFIERS==>") \
    "%nlcallstyle=%ccs;" \
    "%?dts(%nldtsclass;%)"       \
    "%?%cmc(%nlmetaclass=%cmc;%)" \
    "%?%cv1(%nlmajorversion = %cv1;%)" \
    "%?%cv2(%nlminorversion = %cv2;%)" \
    "%?%cal(%nlalign = %cal;%)" \
    "%?ab(%nlabstract;%)" \
    _MEMBERMODS_ \
    _NESTS_ \
    _FRIENDS_ \
    _RELEASEORDER_ \
    _DECLORDER_
#endif /* _MODIFIERS_ */

//bases //generates bases on interface statement
#ifndef _BASES_
#define _BASES_ \
    _DBG_("BASES==>") \
    "%?!i(b,!pri)(: SOMObject%)" \
    "%?i(b,!pri)(: %i(b,!pri)(%bni, %)%bs%bs%)"
#endif /* _BASES_ */

//classdatamods //generates modifiers for each class data
#ifndef _CLASSDATAMODS_
#define _CLASSDATAMODS_ \
    _DBG_("CLASSDATAMODS==>") \
    "%nl"             \
    "%mni:  "           \
    "%+t"               \
      "%?!pri(%?%mac(%mac, %)%)" \
      "%?sf("             \
	 "%?%msz(size=%msz, %)"  \
	 "%)"                    \
      "%?(sf|pro1)("             \
	 "%?%mal(align=%mal, %)" \
	 "%)"                    \
      "%?st(staticdata, %)"      \
      "%?e(embedded=%mne, %)"    \
      "%?!cg(%nlcxxdecl=%q%?st(static %)%mdn;%q, %)" \
      "%bs%bs;"                 \
    "%-t"
#endif /* _CLASSDATAMODS_ */

//global data modifiers //generates data modifiers for globals and types outside an interface
#ifndef _DATAMODS_
#define _DATAMODS_ \
    _DBG_("DATAMODS==>") \
    "#pragma modifier " _CLASSDATAMODS_
#endif /* _DATAMODS_ */

//funcmods //generates modifiers for each class function
#ifndef _FUNCMODS_
#define _FUNCMODS_ \
    _DBG_("FUNCMODS==>") \
    "%nl"        \
    "%mni:  "      \
    "%+t"          \
      "%?!pri(%?%mac(%mac, %)%)" \
      "%?o(override, %)"         \
      "%?r(reintroduce, %)"      \
      "%?mi(init, %)"            \
      "%?mnc(nocall, %)"         \
      "%?mc(const, %)"           \
      "%?st(procedure, noself, noenv, %)" \
      "%?ns(nonstatic, %)"                \
      "%?!cg("                            \
	 "%nlcxxdecl=%q%?st(static %)%mdn;%q, " \
	 "%nlcxxmap=%q%mnn%mrg;%q, "  \
	 "%)"   \
      "%bs%bs;"                          \
    "%-t"
#endif /* _FUNCMODS_ */

//funcs //generates IDL declarations for functions
#ifndef _FUNCS_
//don't want attributes generated
#define _FUNCS_ \
    _DBG_("FUNC==>") \
    "%i(m,f&(pub|pro)&!(o|r)&!at)(" \
       "%nl"   \
       "%mdi;"    \
       "%)"      \
    "%?i(m,f&pri&!(o|r)&!at)(" \
       "%nl"   \
       "#ifdef __PRIVATE__" \
       "%+t"     \
       "%i(m,f&pri&!(o|r)&!at)(" \
	  "%nl" \
	  "%mdi;" \
	  "%)"   \
       "%-t"     \
       "%nl"   \
       "#endif"  \
       "%)"
#endif /* _FUNCS_ */

//attributes //generates IDL declarations for attributes
#ifndef _ATTRIBUTES_
#define _ATTRIBUTES_ \
    _DBG_("ATTRIBUTES==>") \
    "%i(m,d&at)("      \
       "%nl" \
       "%?i(q,q(readonly))(readonly %)" \
       "attribute " \
       "%mdi;"   \
       "%)"
#endif /* _ATTRIBUTES_ */

//attributemods //generates modifiers for each attribute
#ifndef _ATTRIBUTEMODS_
#define _ATTRIBUTEMODS_ \
    _DBG_("ATTRIBUTEMODS==>") \
    "%nl"      \
    "%mni:  "    \
    "%+t"        \
      "%iq("     \
	  "%?!q(readonly)(%maq, %)" \
	  "%)"   \
      "%?%mac(%mac, %)"  \
      "%?%msz(size=%msz, %)"  \
      "%?%mal(align=%mal, %)" \
      "%?e(embedded=%mne, %)" \
      "%?!cg(%nlcxxdecl=%q%mdn;%q, %)" \
      "%bs%bs;"  \
    "%-t"
#endif /* _ATTRIBUTEMODS_ */

//classdata //generates IDL declarations for class data
#ifndef _CLASSDATA_
//should literals get modifiers?
//spec says embedded objects (see d&e below) should be private,
//but this doesn't seem right - waiting for answer from Austin
#define _CLASSDATA_ \
    _DBG_("CLASSDATA==>") \
    "%i(m,li)("  \
       "%nl"   \
       "%mdi;"   \
       "%)"      \
    "%i(m,d&(pub|pro)&!at&(!st|rl))(" \
       "%nl"   \
       "%mdi;"   \
       "%)"      \
    "%?i(m,d&pri&(!st|rl))(" \
       "%nl"   \
       "#ifdef __PRIVATE__" \
       "%+t"     \
       "%i(m,d&pri&!at&(!st|rl))(" \
	  "%nl" \
	  "%mdi;" \
	  "%)"   \
       "%-t"     \
       "%nl"   \
       "#endif"  \
       "%)"      \
    "%?i(m,d&e)(" \
       "%nl"   \
       "#ifdef __PRIVATE__" \
       "%+t"     \
       "%i(m,d&e)(%nl%mde;%)" \
       "%-t"     \
       "%nl"   \
       "#endif"  \
       "%)"
#endif /* _CLASSDATA_ */

//globals //generates types and modifiers outside an interface
#ifndef _GLOBS_
//was: _CLASSDATAMODS_; replaced with __TYPEMODS__
//won't be supporting global data, so can treat types exclusively
#define _GLOBS_  \
    _DBG_("GLOBS==>") \
    /* som globs */ \
    "%i(g,sm)("    \
       "%nl" \
       "interface %mni;" \
       "%)"   \
    /* non-som globs */ \
    "%?i(g,!sm)("      \
       "%nl"   \
       "#pragma somemittypes on" \
       "%+t"     \
       "%i(g,!sm)("    \
	  "%nl" \
	  "%mdi;" \
	  "%nl" \
	  "#pragma modifier " \
	  "%+t"  \
	  _TYPEMODS_ \
	  "%-t"  \
	  "%)"   \
       "%-t"     \
       "%nl"   \
       "#pragma somemittypes off" \
       "%)"
#endif /* _GLOBS_ */

//membmods //generates modifiers for each member
#ifndef _MEMBMODS_
#define _MEMBMODS_ \
    _DBG_("MEMBMODS==>") \
       "%?(t&!sm)(" _TYPEMODS_ "%)" \
       "%?(d&at)(" _ATTRIBUTEMODS_ "%)" \
       "%?(d&!at&(!st|rl))(" _CLASSDATAMODS_ "%)" \
       "%?(f&!at)(" _FUNCMODS_ "%)"
#endif /* _MEMBMODS_ */

//membermods //generates all member modifiers
#ifndef _MEMBERMODS_
#define _MEMBERMODS_ \
    _DBG_("MEMBERMODS==>") \
    "%i(m,(pub|pro))(" \
       _MEMBMODS_ \
       "%)"      \
    "%?i(m,pri)(" \
       "%nl"   \
       "#ifdef __PRIVATE__" \
       "%+t"     \
       "%i(m,pri)(" \
	  _MEMBMODS_ \
	  "%)"   \
       "%-t"     \
       "%nl"   \
       "#endif"  \
       "%)"
#endif /* _MEMBERMODS_ */

//classes //generates a single interface
#ifndef _CLASS_
//should use %bdn instead of "%i(b,!cg)(%?!pri(%bac %)%bnn, %)"
//but compiler doesn't seem to support bdn
#define _CLASS_ \
    _DBG_("CLASS==>") \
    "%nl"      \
    "interface %cni " _BASES_ " {" \
    "%+t"        \
    _INTBEGPASSTHRUS_ \
    _CLASSTYPES_ \
    _ATTRIBUTES_ \
    _FUNCS_      \
    _INTENDPASSTHRUS_ \
    "%nl"      \
    "#ifdef __SOMIDL__" \
    "%nl"      \
    "implementation {" \
    "%+t"        \
    "%nl"      \
    "cxxdecl = %q%cdn" \
       "%?i(b,!cg)(" \
	  " : "  \
	  "%i(b,!cg)(%bdn, %)" \
	  "%bs%bs" \
	  "%)"   \
       "%q;"     \
    _IMPBEGPASSTHRUS_ \
    _CLASSDATA_ \
    _MODIFIERS_ \
    _IMPENDPASSTHRUS_ \
    "%nl"      \
    "};"         \
    "%-t"        \
    "%nl"      \
    "#endif"     \
    "%nl"      \
    "};"         \
    "%-t"
#endif /* _CLASS_ */

//idl //generates IDL for DTS C++
#ifndef _IDL_
//main function to generate everything
#define _IDL_  \
    _DBG_("IDL==>") \
      _SOMPREDECLS_ \
      _BEGPASSTHRUS_ \
      _INCLUDES_ \
      _GLOBS_  \
      _TYPES_  \
      _CLASSES_\
      _ENDPASSTHRUS_ "%nl"
#endif /* _IDL_ */

pragma on(print_som);
pragma som_idl_format( _IDL_ );
#endif /* _IDLGEN_INCLUDED_ */

/*******************************************************************                  

The compiler generates IDL for SOM classes by interpreting an
IDL-generating program written in an IDL generation language.  This
language provides access to the compiler's internal data structures for
classes and other types, and provides testing and iteration facilities
powerful enough to express IDL generation.

The SOM_IDL_format pragma takes as an argument a single string; that
string is the IDL-generating program (for short, call it the "IDLGP").
The compiler front-end interprets the IDLGP when it's finished
processing a C++ program.

Intrepid individuals may wish to make minor changes to the IDL
generation by modifying the IDLGP.  The purpose of this write-up is to
provide enough information to do so.  Please note, however, that the IDL
generation language is not end-user supported, and so our technical
support staff can't be expected to answer questions about IDL generation
when you've modified the IDLGP.  

More information about the IDLGP is presented later.  First, here are
some examples of the language syntax.

Each character of an IDL-generating program is merely reproduced as
output, except that % indicates iteration, testing, or other language
semantics.  So, for example, the program

	this is a test
	
causes "this is is a test" to be produced as output.  All interesting
work, however, is done with the % designations.

To iterate, write:

	%ix(expr%) 

"x" indicates what item to iterate over (e.g., c = classes, i = include
files).  For each such item, "expr" is processed (reproduced as output,
except where % designations occur, of course).  Access to the iteration
value during iteration is via another % designation.

When you want to iterate over only certain kinds of x, you can provide a
filter with the following syntax, where f is a condition:

	%i(x,f)(expr%) 

In this case, expr is applied only to those x that satisfy f.  f is an
expression that typically tests properties about the iteration value.

A general test anywhere is written as

	%?t(expr%) 

Usually, the test is made on the iteration value.

Other % designations generate text for various aspects of iteration
values, such as IDL method declarations, alignment of data members, etc.

Here's a simple example of an IDL generating program that generates
simple IDL for a class S:

pragma On(Print_SOM);
pragma SOM_IDL_format(
   "%ic("		   // Iterate over classes.  For each:
      "interface %cni {"   // Print interface name.
	 "%+t%nl"	   // Indent and new-line.
	 "%i(m,f)("        // Iterate over class members that are functions.
	    "%mdi;%nl"     // For each function, print IDL definition.
	    "%)"	   // End iteration over functions.
	 "implementation {"// Start implementation section and indent.
	    "%+t%nl" 
	    "%i(m,d)("     // Iterate over members with data filter.
	       "%mdi;%nl"  // For each data item, print IDL definition.
	       "%)"        // End iteration over data.   
	    "%-t};%nl"     // Close implementation section.
	 "%-t};%nl"        // Close interface section.   
      "%)"                 // End iteration over classes
   ); 

For the C++ program

pragma on(som_bindings);
struct a_class {
   int x;                  // Data item
   virtual void fnc();     // Virtual method
   };

The IDL program iterates over classes, finding a_class. While iterating
over the members of a_class, it finds data item x and virtual method
fnc().  Since functions go into the interface section of an IDL module,
while data items go into the implementation section, the IDL generator
must be able to distinguish between functions and data.  It does this
with filters on the iterator for members. 

The IDL output is for the example C++ program is:

interface a_class {
    void fnc__fv();
    void somDestruct(inout somDestructCtrl ctrl, octet iamabase);
    void somDefaultConstCopyInit(inout somInitCtrl ctrl,in a_class dts__dummy1);
    void somDefaultInit(inout somInitCtrl ctrl);
    a_class * dts____as__frx7a_class(in a_class dts__dummy2);
    a_class * somDefaultConstAssign(inout somAssignCtrl ctrl,in a_class dts__dummy3);
    implementation {
	long x;
	void * dts____zclasszdata[6];
	void * dts____zczclasszdata[2];
	};
    };

Here is a more complex example of an IDL generating program, a sample
C++ program, and the IDL output:

pragma On(Print_sOM);
pragma SOM_IDL_format(
   "%ii(%nl#include <%fn.idl> %)" 	// Iterate over includes.     
   // Types
   "%i(t,!sm)("      			// Iterate over non-SOM types.
      "%nl"        			// Print a new line.
      "#pragma somemittypes on"  	// Print pragma for IDL.
      "%nl%mdi;"               	// Print type definition.
      "%nl#pragma somemittypes off" 	// Print pragma for IDL.
   "%)"                                 // End iteration over types
   // Classes
   "%ic("  				// Iterate over classes.  For each class:
      "%nl"   
      "interface %cni {"                // Print interface name.   
      "%+t"                             // Increase tab.
   // Passthroughs  
   "%i(p,l(Interface-Begin))(%nl%ps%)" // Iterate over passthroughs.
   // Attributes  
   "%i(m,d&at)("      			// Iterate over members with attributes filter.
      "%nl"     
      "%?i(q,q(readonly))("             // For any attribute qualifier that is readonly:  
	 "readonly "                    //  Print readonly  
	 "%)"                           // End iteration.
      "attribute %mdi;"                 // Print attribute and declaration.
      "%)"
   // Functions   
   "%i(m,f&!at)(" 			// Iterate over members with function filter.
      "%nl"
      "%mdi;"                           // For each, print IDL definition.
      "%)"                              // End iteration over functions.
   "%nl"
   "implementation {"                   // Start implementation section.
   "%+t"                                // Increase tab.
   // Data
   "%i(m,d&!at&(!st|rl))("		// iterate over data members that are not attributes,
					// but either data items or released.
     "%nl"
      "%mdi;"				// For each, print idl definition.
      "%)"                              // End iteration over data.of 
   // Data modifiers
   "%i(m,d&!at)("			// Iterate over members with data filter.
      "%nl"
      "%mni:  "                         // Print IDL member name.
      "%+t"                             // increase tab count.
      "%?!pri(%mac, %)"                 // Print member access type if not private
      "%?st(staticdata, %)"             // If static, print static modifier.
      "%bs%bs;"                         // Backspace over.
      "%-t"                             // Decrease tab count.
      "%)"                              // End iteration over data.
   // Attribute modifiers
   "%i(m,d&at)("			// Iterate over data members which are attributes.
      "%nl"
      "%mni:  "                         // Print IDL member name.
      "%+t"                             // Increase tab count.
      "%iq("                            // Iterate over attribute's qualifiers.
	 "%?!q(readonly)(%maq, %)"      // Print all qualifiers but readonly.
	 "%)"                           
	 "%?%mac(%mac, %)"		// Print member access.
	 "%bs%bs;"			// Backspace over.
      "%-t"				// Decrease tab count.            
      "%)"                              // End iteration over attributes.
   // Function modifiers
   "%i(m,f&!at)(" 			// Iterate over members with function filter,
					//  ignoring attribute's methods.
      "%nl"
      "%mni:  "                         // Print idl member name.
      "%+t"                             // Increase tab count.
      "%?!pri(%mac, %)"                 // Print member access type if not private.
      "%?st(procedure, noself, noenv, %)" // Print modifiers for static functions.
      "%?ns(nonstatic, %)"              // Print nonstatic modifier. 
      "%bs%bs;"                         // Backspace over.
      "%-t"                             // Decrease tab count.
      "%)"                              // End iteration over data.
   // Release order
   "%nl"
   "releaseorder : "			// Release order
      "%ir(%mni, %)"                    // Iterate over released items, printing 
					//  name of each.
      "%i(m,d&!pri&!st)(%mni, %)"       // Iterate over non-private non-static data items,
					//  printing name of each.
      "%bs%bs;"                         // Backspace twice to delete ending.
      "%nl"   "};"                    // Close implementation section.
      "%-t"                             // Decrease tab.
   "%nl"
   "};"                                 // Close interface section.
   "%-t"                                // Decrease tab.
   "%)"                                 // End iteration over classes.
);

The DTS C++ program:

#include <som.hh>
typedef int t_int;    
class a_class: SOMObject {
   static int z;                    // Static class data
   int x;                           // Data item
public:
   int y;                           // Readonly attrubute
   pragma SOM_attribute(y; readonly);
   void fnc1();                     // Method 
   virtual void fnc2();             // Method 
   static void fnc3();              // Method 
   };
pragma SOM_IDL_passthrough(a_class;"Interface-Begin",
			   "#define ME3 300");

Here is the resultant IDL:

#include <som.idl> 
interface a_class {
    #define ME3 300
    readonly attribute long y;
    void fnc1__fv();
    void fnc2__fv();
    void fnc3__fv();
    void somDestruct(inout somDestructCtrl ctrl, octet iamabase);
    void somDefaultConstCopyInit(inout somInitCtrl ctrl,in a_class dts__dummy1);
    void somDefaultInit(inout somInitCtrl ctrl);
    a_class * dts____as__frx7a_class(in a_class dts__dummy2);
    a_class * somDefaultConstAssign(inout somAssignCtrl ctrl,in a_class dts__dummy3);
    implementation {
	long z;
	long x;
	z:  staticdata;
	x:;
	dts____zclasszdata:  public, staticdata;
	dts____zczclasszdata:  public, staticdata;
	y:  public;
	fnc1__fv:  public, nonstatic;
	fnc2__fv:  public;
	fnc3__fv:  public, procedure, noself, noenv;
	somDestruct:  public;
	somDefaultConstCopyInit:  public;
	somDefaultInit:  public;
	dts____as__frx7a_class:  public, nonstatic;
	somDefaultConstAssign:  public;
	releaseorder : z, fnc1__fv, fnc2__fv, fnc3__fv, _get_y, dts____as__frx7a_class, y;
	};
    };

The IDLPG given in idlgen.h breaks up the translation problem by
defining a series of macros, each handling a section of IDL translation.
These macros are:

   Macro	      Purpose
   ----------	      -----------------------------
   _INCLUDES_         Generates IDL includes 
   _BEGPASSTHRUS_     Generates strings from passthroughs with no literal
			or with Begin 
   _ENDPASSTHRUS_     Generates strings from passthroughs with End 
   _IMPBEGPASSTHRUS_  Generates strings from passthroughs with no literal
			or Implementation-Begin 
   _IMPENDPASSTHRUS_  Generates strings from passthroughs with
			Implementation-End 
   _INTBEGPASSTHRUS_  Generates strings from passthroughs with Interface-Begin 
   _INTENDPASSTHRUS_  Generates strings from passthroughs with Interface-End 
   _TYPES_            Generates types outside interfaces 
   _GLOBS_            Generates types and modifiers outside an interface 
   _DATAMODS_         Generates data modifiers for globals and types outside an
			interface 
   _CLASSES_          Generates interfaces 
   _CLASS_            Generates a single interface
   _BASES_            Generates bases on interface statement 
   _MODIFIERS_        Generates member modifiers 
   _RELEASEORDER_     Generates IDL releaseorder modifier  
   _ATTRIBUTES_       Generates IDL declarations for attributes 
   _CLASSTYPES_       Generates IDL declarations for types 
   _CLASSDATA_        Generates IDL declarations for class data 
   _FUNCS_            Generates IDL declarations for functions 
   _ATTRIBUTEMODS_    Generates modifiers for each attribute 
   _CLASSDATAMODS_    Generates modifiers for each class data 
   _FUNCMODS_         Generates modifiers for each class function 
   _TYPEMODS_         Generates modifiers for each class type 
   _MEMBMODS_         Generates modifiers for each member 
   _MEMBERMODS_       Generates all member modifiers 
   _IDL_              Generates IDL from DTS C++  


Below is a grammar for the IDL generation language.

Program -> TEXT;
TEXT -> (Iterate | Test | Gen | anything_else)*;
Iterate -> Iteration_specification(TEXT%)
	// Anything after % must be legal; otherwise it is
	// diagnosed.
Iteration_specification
   -> %iI  	// Do TEXT for each iterated element, where I specifies the iteration.
   -> %i(I,E)   // Iterate as specified by I when E holds true.
Test -> %?Condition(TEXT%)
	// Test evaluates to TEXT if Condition evaluates to true    
Condition -> Single_test | (E)
I 
   -> b   // Iterate over bases.
   -> m   // Iterate over members.
   -> r   // Iterate over released items.
   -> t   // Iterate over non-SOM types.
   -> c   // Iterate over SOM types (classes/structs)
	  //  that are NOT nested. 
   -> n   // Iterate over nested classes. 
   -> N   // Iterate over the class in which I am nested. This applies
	  // to %ic and essentially does an %ic for the parent of the
	  // current %ic.  It has nothing to do with %in.
   -> d   // Iterate over everything declared in
	  //  declaration order (non-compiler-
	  //  generated).
   -> q   // Iterate over qualifiers of the iterated data
	  //  item  (which is an attribute).
   -> p   // Iterate over passthroughs (at global level 
	  //  or within a class)
   -> i   // Iterate over includes (%ni gets IDL name,
	  //  but may be same as %nn) 
   -> g   // Iterate over declarations outside a class or 
	  //  struct (for example, global).

 
E  -> E | T   // True if E and T
   -> T    
T  -> F & P   
   -> P    
P
   -> !P  // True if T evaluates to False
   -> (E) 
   -> Gen // True if Gen is not NUL
   -> Single_test

Single_test 
   -> Iteration_specification
	   // True if iteration would iterate over anything
   -> f    // True if y is a function
   -> d    // True if y is data 
   -> dts  // True if class is a dts class 
   -> pri  // True if y is private
   -> pro  // True if y is protected
   -> pro1 // True if y is the first protected data member
   -> pub  // True if y is public
   -> ns   // True if y is nonstatic (function or data)
   -> v    // True if y is virtual (function) or, if not a
	   //  function, the base is virtual.
   -> st   // True if y is static
   -> sf   // True if SOMFOREIGN type
   -> sm   // True if this entity is a definition of a SOM class (body)
   -> e    // True if y is an embbedded object or array
	   //  thereof, or is a type created to support embedded members
   -> en   // True if y is an enum definition
   -> o    // True if y overrides a method in a base class
   -> ri   // True if y is a reintroduced method; that is, 
	   //  if it overrides a non-virtual method in a base
   -> r    // Same as ri, for working with old idlgen.h
   -> rr   // True if y is a re-leased method (re-release;
	   //  only applies to iteration 'r')
   -> rl   // True if y is released data item; this is for
	   //  screening out __ClassData etc. 
   -> ab   // True if y is an abstract class (the current base)
   -> at   // True if the item is an attribute data item or 
	   //  a _set or _get function generated to handle such
   -> aq   // True if the attribute has any qualifiers 
   -> mi   // True if y has init modifier (constructors) 
   -> mnc  // True if y has nocall modifier 
   -> mne  // True if y has noenv modifier (env) 
   -> mc   // True if y has const modifier (const member function) 
   -> cg   // True if y has been compiler-generated; for 
	   //  example:  default ctor/dtor/asn op;  
	   //  types/members for embedded objects. 
   -> 1    // True
   -> 0    // Not true 
   -> d    // True if the iterated-over item is data
   -> li   // True if the iterated-over item is a literal (enum lit for now) 
   -> t    // True if the iterated-over item is a type
   -> f    // True if the iterated-over item is a function
   -> s    // True if the iterated-over item is static (function or data)
   -> a    // True if the iterated-over item has attribute
	   //  qualifiers (data)
   -> v    // True if the iterated-over base class is virtual
   -> l(xxx)   // True if the iterated-over passthrough has label
	       //  xxx (which may be NULL; case is insensitive)
   -> q(xxx)   // True if the qualifier is xxx.
      
generators:
   //  organized by first letter:
   //   %Xxx where X is...means applicable to...
   //                   m                    member
   //                   c                     class
   //                   b                      base
Gen
   // Members (and typedefs), if iterating over class
   //  members/release order:
   -> %mac     // Access (eg. public)
   -> %maq     // Attribute qualifier if iterating
	       //  over qualifiers
   -> %mnn     // Normal name
   -> %mnm     // Mangled name
   -> %mns     // SOM mangled name
   -> %mni     // IDL translated name (same as %ns)
   -> %mne     // Name of associated IDL embedded
	       //  object (if any)
   -> %mnu     // Produce nothing (for testing;
	       //  possibly generally useful)
   -> %mdn     // Normal declaration
   -> %mdm     // Declaration including mangled
	       //  names
   -> %mds     // Declaration including SOM mangled
	       //  names
   -> %mdi     // Declaration including IDL translated
	       //  names (same as %mds)
   -> %mde     // Declaration of associated IDL
	       //  embedded object (if any)
   -> %msz     // Size of member
   -> %mal     // Alignment of member d
   -> %mrg     // Arguments (e.g., (int)) for a
	       //  function. 
   Bases, if iterating over bases:
   -> %bnn     // Base normal name
   -> %bnm     // Base mangled name
   -> %bns     // Base SOM mangled name
   -> %bni     // Base IDL translated name (same as
	       //  %bns)
   -> %bac     // Access in derivation (public,
	       //  private, etc.)
   -> %bdn     // Declaration of base from C++:
		  //  "virtual public X" for example
   // Classes, if iterating over classes classes:
   -> %cnn     // Normal class name being iterated
	       //  over
   -> %cnm     // Mangled class name
   -> %cns     // SOM mangled class name
   -> %cni     // IDL translated class name
   -> %cdn     // Class normal declaration from C++ 
   -> %cal     // Alignment of class
   -> %csz     // Size of instance data introduced in
	       //  the class
   -> %ccs     // Callstyle
   -> %cmc     // Metaclass
   -> %cv1     // Major version
   -> %cv2     // Minor version
   // Includes, if iterating over includes:
   -> %fn      // Filename alone (directory stuff
	       //  removed, no extension)
   -> %fe      // Filename alone (directory stuff
	       //  removed, including extension)
   -> %fp      // Full path name of file
   // Passthroughs, if iterating over passthroughs:
   -> %ps      // Passthrough string if iterating over
	       //  passthroughs
   // Formatting controls:
   -> %nl      // Newline, followed by optional tabs
	       //  (see %+)
   -> %t       // Tab
   -> %q       // Double-quote
   -> %s       // Space
   -> %+t      // Increase tab count.  When %n occurs,
	       //  \n is printed followed by as many
	       //  tabs as the tab count
   -> %-t      // Decrease tab count
   -> %Z       // For Z anything else produces a Z
********************************************************************/
