/* @(#) 1.44 src/somk/somapi.h, somk.api, som3.0 5/31/96 17:54:14 [12/22/96 21:12:44] */

/*
 * 96F8647, 96F8648, 96F8850 (C) Copyright IBM Corp. 1992, 1994
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 */

/*
 *  SOMAPI.H
 *
 *  This file documents the public data structures and functions
 *  of the SOM API (Application Programming Interface). Primitive data
 *  types are defined in sombtype.h, and the public methods provided by
 *  the SOM kernel are declared in somobj.idl, somcls.idl and somcm.idl.
 *  An important header file for language bindings is somdefs.h, which
 *  defines the SOMLINK symbol used in various emitter outputs.
 *
 *  Note: typedefs & prototypes in this file explicitly show pointers
 *  to objects that support an interface described by IDL. These are
 *  C/C++ typedefs that reflect the implementation of object references
 *  in SOM as pointers to structures in memory.
 */

 /*
  * HISTORY [04/19/96] #21264 nsk Temproary ADD WIN32 Code
  */


#ifndef somapi_h
#define somapi_h

#if !defined(SOM_DLL_som)
#define SOMAPI_IMPORT SOMDLLIMPORT
#else
#define SOMAPI_IMPORT
#endif

/*  SOM Version Numbers  */
SOMEXTERN SOMAPI_IMPORT long SOMDLINK SOM_MajorVersion;
SOMEXTERN SOMAPI_IMPORT long SOMDLINK SOM_MinorVersion;

/*  SOM Thread Support  */
SOMEXTERN SOMAPI_IMPORT long SOMDLINK SOM_MaxThreads;

/*----------------------------------------
 * Typedefs for pointers to functions
 *----------------------------------------*/

typedef int SOMLINK somTD_SOMOutCharRoutine (IN char);
typedef int SOMLINK somTD_SOMLoadModule (
    IN string /* className */,
    IN string /* fileName */,
    IN string /* functionName */,
    IN long   /* majorVersion */,
    IN long   /* minorVersion */,
    OUT somToken * /* modHandle */);
typedef int SOMLINK somTD_SOMDeleteModule (IN somToken /* modHandle */);
typedef string SOMLINK somTD_SOMClassInitFuncName (void);
typedef somToken SOMLINK somTD_SOMMalloc (IN size_t /* nbytes */);
typedef somToken SOMLINK somTD_SOMCalloc (
    IN size_t /* element_count */,
    IN size_t /* element_size */);
typedef somToken SOMLINK somTD_SOMRealloc (
    IN somToken /* memory */,
    IN size_t   /* nbytes */);
typedef void SOMLINK somTD_SOMFree (IN somToken /* memory */);
typedef void SOMLINK somTD_SOMError (
    IN int     /* code */,
    IN string  /* fileName */,
    IN int     /* lineNum */);


typedef unsigned long SOMLINK somTD_SOMCreateMutexSem (OUT somToken *sem);
typedef unsigned long SOMLINK somTD_SOMRequestMutexSem (IN somToken sem);
typedef unsigned long SOMLINK somTD_SOMReleaseMutexSem (IN somToken sem);
typedef unsigned long SOMLINK somTD_SOMDestroyMutexSem (IN somToken sem);
typedef unsigned long SOMLINK somTD_SOMGetThreadId (void);


/*----------------------------------------------------------------------
 * SOM Environment Initialization Section
 *---------------------------------------------------------------------*/

/*
 *  Create and initialize the SOM environment.
 *
 *  This function is idempotent (may be invoked redundantly)
 *
 *  Will be called automatically when first object (including a class
 *  object) is created, if it has not already been done.
 *
 *  Returns the SOMClassMgrObject
 */
SOMEXTERN SOMClassMgr * SOMLINK somEnvironmentNew (void);

SOMEXTERN void          SOMLINK somEnvironmentEnd (void);
SOMEXTERN SOMClassMgr * SOMLINK somMainProgram (void);
SOMEXTERN boolean       SOMLINK somAbnormalEnd (void);

/*
 *  Replaceable SOM Memory Management Interfaces
 *
 *  External procedure variables SOMCalloc, SOMFree, SOMMalloc, SOMRealloc
 *  have the same interface as their standard C-library analogs.
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMCalloc  * SOMDLINK SOMCalloc;
SOMEXTERN SOMAPI_IMPORT somTD_SOMFree    * SOMDLINK SOMFree;
SOMEXTERN SOMAPI_IMPORT somTD_SOMMalloc  * SOMDLINK SOMMalloc;
SOMEXTERN SOMAPI_IMPORT somTD_SOMRealloc * SOMDLINK SOMRealloc;

/*
 *  Replaceable SOM Error handler
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMError * SOMDLINK SOMError;

/*
 *  Replaceable SOM Semaphore Operations
 *
 *  These operations are used by the SOM Kernel to make thread-safe
 *  state changes to internal resources and for synchronization between
 *  the SOM services process and client SOM processes.
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMCreateMutexSem  * SOMDLINK SOMCreateMutexSem;
SOMEXTERN SOMAPI_IMPORT somTD_SOMRequestMutexSem * SOMDLINK SOMRequestMutexSem;
SOMEXTERN SOMAPI_IMPORT somTD_SOMReleaseMutexSem * SOMDLINK SOMReleaseMutexSem;
SOMEXTERN SOMAPI_IMPORT somTD_SOMDestroyMutexSem * SOMDLINK SOMDestroyMutexSem;

/*
 * 18260 -- other thread-related routines used by the kernel were
 * moved to somkp.h, to keep them local to the kernel.
 */

/*
 *  Replaceable SOM Thread Identifier Operation
 *
 *  This operation is used by the SOM Kernel to index data unique to the
 *  currently executing thread.  It must return a small integer that
 *  uniquely represents the current thread within the current process.
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMGetThreadId * SOMDLINK SOMGetThreadId;


/*----------------------------------------------------------------------
 * SOM Class Manager Section
 *---------------------------------------------------------------------*/

/*
 * Global class manager object
 */
SOMEXTERN SOMAPI_IMPORT SOMClassMgr * SOMDLINK SOMClassMgrObject;

/*
 * The somRegisterClassLibrary function is provided for use in SOM class
 * libraries on platforms that have loader-invoked entry points
 * associated with shared libraries (DLLs).
 *
 * This function registers a SOM Class Library with the SOM Kernel.
 * The library is identified by its file name and a pointer to its
 * initialization routine.  Since this call may occur prior to the
 * invocation of somEnvironmentNew, its actions are deferred until the
 * SOM environment has been initialized.  At that time, the
 * SOMClassMgrObject is informed of all pending library initializations
 * via the _somRegisterClassLibrary method.  The actual invocation of
 * the library's initialization routine will occur during the execution
 * of the SOM_MainProgram macro (for statically linked libraries), or
 * during the _somFindClass method (for libraries that are dynamically
 * loaded).
 */
SOMEXTERN void SOMLINK somRegisterClassLibrary (
    string libraryName,
    somMethodProc *libraryInitRtn);
SOMEXTERN void SOMLINK somUnregisterClassLibrary (string libraryName);

/*
 * Pointers to routines used to do dynamic code loading and deleting
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMLoadModule        * SOMDLINK SOMLoadModule;
SOMEXTERN SOMAPI_IMPORT somTD_SOMDeleteModule      * SOMDLINK SOMDeleteModule;
SOMEXTERN SOMAPI_IMPORT somTD_SOMClassInitFuncName * SOMDLINK SOMClassInitFuncName;


/*----------------------------------------------------------------------
 * SOM Stream Output Section
 *---------------------------------------------------------------------*/

/*
 * Uses <SOMOutCharRoutine> to output its arguments under control of the
 * ANSI C style format.  Returns the number of characters output.
 */
SOMEXTERN int SOMLINK somPrintf (string fmt, ...);

/*
 * vprint form of somPrintf
 */
SOMEXTERN int SOMLINK somVprintf (string fmt, va_list ap);

/*
 * Outputs (via somPrintf) blanks to prefix a line at the indicated level
 */
SOMEXTERN void SOMLINK somPrefixLevel (long level);

/*
 * Combines somPrefixLevel and somPrintf
 */
SOMEXTERN int SOMLINK somLPrintf (int level, string fmt, ...);

/*
 * Specify a thread-specific user-defined SOMOutCharRoutine
 */
SOMEXTERN void SOMLINK somSetOutChar (somTD_SOMOutCharRoutine *outch);

/*
 *  Replaceable character output handler.
 *  Points to the character output routine to be used in development
 *  support.  Initialized to <somOutChar>, but may be reset at anytime.
 *  Should return 0 (false) if an error occurs and 1 (true) otherwise.
 */
SOMEXTERN SOMAPI_IMPORT somTD_SOMOutCharRoutine * SOMDLINK SOMOutCharRoutine;


/*--------------
 * Initializers
 *--------------*/

#ifndef SOM_CTI_DEFINED
/*
 * C++-style constructors are called initializers in SOM. Initializers
 * are methods that receive a pointer to a somCtrlStruct as an argument.
 * Language bindings hide details associated with manipulating the following
 * data structures.
 */
typedef  struct  {
    SOMClass      *cls; /* class whose introduced data is to be initialized */
    somMethodProc *defaultInit;
    somMethodProc *defaultCopyInit;
    somMethodProc *defaultConstCopyInit;
    somMethodProc *defaultNCArgCopyInit;
    long          dataOffset;
    somMethodProc *legacyInit;
} somInitInfo;

typedef struct {
    SOMClass      *cls; /* class whose introduced data is to be destroyed */
    somMethodProc *defaultDestruct;
    long          dataOffset;
    somMethodProc *legacyUninit;
} somDestructInfo;

typedef struct {
    SOMClass      *cls; /* class whose introduced data is to be assigned */
    somMethodProc *defaultAssign;
    somMethodProc *defaultConstAssign;
    somMethodProc *defaultNCArgAssign;
    somMethodProc *udaAssign;
    somMethodProc *udaConstAssign;
    long          dataOffset;
} somAssignInfo;

typedef octet *somBooleanVector;
typedef somToken somCtrlInfo;

typedef struct somInitCtrlStruct {
    somBooleanVector mask; /* an array of booleans to control ancestor calls */
    somInitInfo     *info; /* an array of structs */
    int              infoSize; /* increment for info access */
    somCtrlInfo      ctrlInfo;
} somInitCtrl,som3InitCtrl;

typedef struct somDestructCtrlStruct {
    somBooleanVector  mask; /* an array of booleans to control ancestor calls */
    somDestructInfo  *info; /* an array of structs */
    int               infoSize; /* increment for info access */
    somCtrlInfo       ctrlInfo;
} somDestructCtrl,som3DestructCtrl;

typedef struct somAssignCtrlStruct {
    somBooleanVector  mask; /* an array of booleans to control ancestor calls */
    somAssignInfo    *info; /* an array of structs */
    int               infoSize; /* increment for info access */
    somCtrlInfo       ctrlInfo;
} somAssignCtrl,som3AssignCtrl;
#endif

/*-----------------------------------------------
 * Common Typedefs & Data Structures for SOM
 *----------------------------------------------*/

/*
 *  The Method Table Structure
 */
#ifndef SOM_MTAB_DEFINED
/* -- to specify an embedded object (or array of objects). */
typedef struct {
    SOMClass     **copp; /* address of class object ptr */
    long         cnt;    /* object count */
    long         offset; /* Offset to pointer (to embedded objs) */
} somEmbeddedObjStruct, *somEmbeddedObjStructPtr;

#ifndef SOM_CLASSINFO_DEFINED
typedef somToken somClassInfo;
#endif

#ifndef SOM_MDT_DEFINED
/* -- Method/Data Tokens -- For locating methods and data members. */
typedef somToken somMToken;
typedef somToken somDToken;
#endif

typedef struct somMethodTabStruct {
    SOMClass        *classObject;
    somClassInfo    *classInfo;
    char            *className;
    long            instanceSize; /* free */
    long            dataAlignment;
    long            mtabSize; /* free */
    long            protectedDataOffset; /* from class's introduced data */
    somDToken       protectedDataToken;
    somEmbeddedObjStruct *embeddedObjs;
    /* remaining structure is opaque */
    somMethodProc* entries[1];
} somMethodTab, *somMethodTabPtr;
#endif

/* -- For building lists of class objects */
typedef struct somClassList {
    SOMClass   *cls;
    struct somClassList *next;
} somClassList, *somClasses;


/* -- For building lists of objects */
typedef struct somObjectList {
    SOMObject   *obj;
    struct somObjectList *next;
} somObjectList, *somObjects;

#ifndef SOM_CLASSDATA_DEFINED
/*
 * The Class Data Structures -- these are used to implement static
 * method and data interfaces to SOM objects.
 */
/* -- (Generic) Class data Structure */
typedef struct somClassDataStruct {
    SOMClass *classObject; /* changed by shadowing */
    somToken tokens[1];    /* method tokens, etc. */
} somClassDataStructure, *somClassDataStructurePtr;


/*
 * A special info access structure pointed to by
 * the parentMtab entry of somCClassDataStructure.
 */
typedef void SOMLINK somTP_somRenewNoInitNoZeroThunk(void*);
typedef somTP_somRenewNoInitNoZeroThunk *somTD_somRenewNoInitNoZeroThunk;
struct SOM_CIB;
typedef struct som3ClassDetailsStruct {
    somMethodTab    *mtab; /* this class' mtab -- changed by shadowing */
    somMethodTabPtr *next; /* parentMtabs array */
    struct SOM_CIB  *cib;
    somTD_somRenewNoInitNoZeroThunk somRenewNoInitNoZeroThunk; /* changed by shadowing */
    long            instanceSize;   /* changed by shadowing */
    somMethodProc   **resolvedInits;/* resolved initializers in releaseorder */
    somClassDataStructurePtr resolvedMTokens;   /* resolved methods for ABI2 */
    somInitCtrl     initCtrl;
    somDestructCtrl destructCtrl;
    somAssignCtrl   assignCtrl;
    long            layoutVersion;
    void*           extension;
    somDToken       publicDataToken;
    somDToken       protectedDataToken;
    long            instanceAlignment;
} som3ClassDetails, *som3ClassDetailsPtr, *somMethodTabs,
    *somParentMtabStructPtr; /* 22552 */

typedef struct som3ClassInfoStruct {
    SOMClass             *classObject;
    som3ClassDetailsPtr  classDetails;
} som3ClassInfoStruct, *som3ClassInfoStructPtr;


/*
 * (Generic) Auxiliary Class Data Structure
 */
typedef struct somCClassDataStruct {
    som3ClassDetailsPtr parentMtab; /* so named for historical reasons */
    somDToken              instanceDataToken;
    somMethodProc          *wrappers[1]; /* for valist methods */
} somCClassDataStructure, *somCClassDataStructurePtr;
#endif


/*---------------------------------
 * Method & Data Resolution
 *--------------------------------*/

/*
 * Offset-based method resolution functions
 */
SOMEXTERN somMethodProc * SOMLINK somResolve (SOMObject *obj,
                                              somMToken mdata);
SOMEXTERN somMethodProc * SOMLINK somPCallResolve(SOMObject *obj,
                                                  SOMClass *callingCls,
                                                  somMToken method);
SOMEXTERN somMethodProc * SOMLINK somParentResolve (somMethodTabs parentMtabs,
                                                    somMToken mToken);
SOMEXTERN somMethodProc * SOMLINK somParentNumResolve (somMethodTabs parentMtabs,
                                                       int parentNum,
                                                       somMToken mToken);
SOMEXTERN somMethodProc * SOMLINK somClassResolve (SOMClass *,
                                                   somMToken mdata);
SOMEXTERN somMethodProc * SOMLINK somResolveTerminal (SOMClass *,
                                                      somMToken mdata);
SOMEXTERN somMethodProc * SOMLINK somAncestorResolve (SOMObject *obj,/* the object */
                                                      somCClassDataStructure *ccds, /* id the ancestor */
                                                      somMToken mToken);
SOMEXTERN somMethodProc * SOMLINK somResolveByName (SOMObject *obj,
                                                    char *methodName);

/*
 * Offset-based data resolution functions
 */
SOMEXTERN somToken SOMLINK somDataResolve (
    SOMObject *obj,
    somDToken dataId);
SOMEXTERN somToken SOMLINK somDataResolveChk (
    SOMObject *obj,
    somDToken dataId);


/*-----------------------------------
 * Method Stubs -- Signature Support
 *-----------------------------------*/

/*
 * Moved from somplatf.h - was here originally
 *
 * This section defines the structures used to pass method signature
 * info to the runtime. This supports selection of generic apply stubs
 * and runtime generation of redispatchstubs when these are needed. The
 * information is registered with the runtime when methods are defined.
 *
 * When calling somAddStaticMethod, if the redispatchStub is -1, then a
 * pointer to a struct of type somApRdInfo is passed as the applyStub.
 * Otherwise, the passed redispatchstub and applystub are taken as given.
 * When calling somAddDynamicMethod, an actual apply stub must be passed.
 * Redispatch stubs for dynamic methods are not available, nor is
 * automated support for dynamic method apply stubs. The following
 * atructures only appropriate in relation to static methods.
 *
 * In SOMr2, somAddStaticMethod can be called with an actual redispatchstub
 * and applystub *ONLY* if the method doesn't return a structure. Recall
 * that no SOMr1 methods returned structures, so SOMr1 binaries obey this
 * restriction. The reason for this rule is that SOMr2 *may* use thunks,
 * and thunks need to know if a structure is returned. We therefore assume
 * that if no signature information is provided for a method through the
 * somAddStaticMethod interface, then the method returns a scalar.
 *
 * If a structure is returned, then a -1 *must* be passed to
 * somAddStaticMethod as a redispatchstub. In any case, if a -1 is passed,
 * then this means that the applystub actually points to a structure of type
 * somApRdInfo. This structure is used to hold and access signature
 * information encoded as follows.
 *
 * If the somApRdInfo pointer is NULL, then, if the runtime was built with
 * SOM_METHOD_STUBS defined, a default signature is assumed (no more than
 * a specified number of arguments, and no structure returned -- see below);
 * otherwise, the stubs are taken as somDefaultMethod (which produces a
 * runtime error when used) if dynamic stubs are not available.
 *
 * If the somApRdInfo pointer is not NULL, then the structure it points to can
 * either include (non-null) redispatch and applystubs (the method is then
 * assumed to return a structure), or null stubs followed by information needed
 * to generate necessary stubs dynamically.
 */

typedef unsigned long somRdAppType; /* method signature code -- see def below */
typedef unsigned long somFloatMap[13]; /* float map -- see def below */
typedef struct somMethodInfoStruct {
    somRdAppType       callType;
    long               va_listSize;
    somFloatMap        *float_map;
} somMethodInfo, *somMethodInfoPtr;

typedef struct somApRdInfoStruct {
    somMethodProc *rdStub;
    somMethodProc *apStub;
    somMethodInfo *stubInfo;
} somApRdInfo;

/*
 * Values for somRdAppType are generated by summing one from column A
 * and one from column B of the following constants:
 */

/* Column A: return type */
#define SOMRdRetsimple     0 /* Return type is a non-float fullword */
#define SOMRdRetfloat      2 /* Return type is (single) float */
#define SOMRdRetdouble     4 /* Return type is double */
#define SOMRdRetlongdouble 6 /* Return type is long double */
#define SOMRdRetaggregate  8 /* Return type is struct or union */
#define SOMRdRetbyte      10 /* Return type is a byte */
#define SOMRdRethalf      12 /* Return type is a (2 byte) halfword */
#define SOMRdRetsmallaggregate      14 /* Return type is a small struct or union */

/* Column B: are there any floating point scalar arguments? */
#define SOMRdNoFloatArgs   0
#define SOMRdFloatArgs     1

/*
 * The float map is an array of offsets for up to the first 13 floating point
 * arguments.  If there are fewer than 13 floating point arguments, then there
 * will be zero entries following the non-zero entries which represent the
 * float args.  A non-zero entry signals either a single- or a double-precision
 * floating point argument.  For a double-precision argument, the entry is the
 * stack frame offset.  For a single-precision argument the entry is the stack
 * frame offset + 1.  For the final floating point argument, add 2 to the
 * code that would otherwise be used.
 */
#define SOMFMSingle 1        /* add to indicate single-precision */
#define SOMFMLast   2        /* add to indicate last floating point arg */



/*----------
 * somApply
 *----------*/

/*
 * somApply replaces direct use of applyStubs in SOM 1.0. The reason
 * for the replacement is that the SOM 1.0 style of applyStub is not
 * generally available in SOM 2.0, which uses a fixed set of applyStubs
 * according to method information in the somMethodData. In particular,
 * neither the redispatch stub nor the apply stub found in the method
 * data structure are necessarily useful as such. The method somGetRdStub
 * is now the way to get a redispatch stub, and somApply is now the
 * way to call an apply stub. If an appropriate apply stub for the
 * method indicated by md is available, then this is invoked and TRUE is
 * returned; otherwise FALSE is returned.
 *
 * The va_list passed to somApply *must* include the target object (often
 * named somSelf) as its first entry, and any single precision floating point
 * arguments being passed to the the method procedure must be represented on
 * the va_list using double precision values (i.e. ANSI standard widening
 * must have been done). retVal cannot be NULL even for methods that return void.
 */

#ifndef SOM_MD_DEFINED
typedef somToken somSharedMethodData;

typedef struct somMethodDataStruct {
    somId id;
    unsigned long type;            /* see method types below */
    somId descriptor;              /* for use with IR interfaces */
    somMToken mToken;              /* NULL for dynamic methods */
    somMethodPtr method;           /* depends on resolution context */
    somSharedMethodData *shared;   /* opaque pointer */
} somMethodData, *somMethodDataPtr;
#endif

SOMEXTERN boolean SOMLINK somApply (
    SOMObject *somSelf,
    somToken *retVal,
    somMethodDataPtr mdPtr,
    va_list ap);
/*
 * The somMethodData structure is used to specify a method to somApply, or
 * simply to provide information to a user about a method. The class methods
 * somGetMethodData and somGetNthMethodData load a somMethodData structure
 * pointed to by an "out" paramter.
 *
 * Here is a discussion of the different types of method in SOM. To aid
 * understanding, we compare with C++.
 *
 *       SOM                      C++                       Comments
 *       ~~~                      ~~~                       ~~~~~~~~
 *  dynamic method          < not available >           Dynamically Resolved (1)
 *  static method           virtual member function     Dynamically Resolved (2)
 *  nonstatic method        nonstatic member function   Statically Resolved  (3)
 *  direct call procedure   static member function      Statically Resolved  (4)
 *
 * (1) Dynamic methods are resolved using name lookup -- by searching all
 *     ancestors of a class in postorder -- to locate an implementation.
 * (2) Static methods are resolved through the instance method table of a class
 *     using a method token. The token for a static method may be located statically
 *     based on the introducing class, or by using name lookup. A static method can
 *     have only one entry in a method table, and only its introducing class can
 *     provide a method token to select this entry.
 * (3) Nonstatic methods are resolved through the instance method table of a
 *     class using a method token. The method token can be located statically based
 *     on the "closest" class that provides a token for the method, or name lookup
 *     can be used. In general, a nonstatic method will have multiple entries in a
 *     method table. Different method tokens select different entries (with
 *     different implementations). In IDL, "reintroduce" is used to provide a new
 *     token for the method. In DTS C++, the class implementor reintroduces a
 *     nonstatic member function.
 * (4) Direct call procedures are resolved statically by using a static symbol
 *     provided by the "closest" class that provides the procedure. In IDL,
 *     "reintroduce" is used to provide a new implementation for the procedure; in
 *     DTS C++, the class implementation reintroduces a static member function.
 *
 * Direct call procedures are not registered with SOM classes, so only the
 * first three categories are provided in somMethodData. Bit 0 of the type
 * field is set if and only if the method is dynamic. For non-dynamic methods,
 * bit 1 is set if and only if the method is nonstatic.
 *
 */
#define SOM_IsDynamicMethod(md_type) ((md_type) & 1)
#define SOM_IsNonstaticMethod(md_type) ((md_type) & 2)
#define SOM_IsStaticMethod(md_type) \
    (!(SOM_IsDynamicMethod(md_type) || SOM_IsNonstaticMethod(md_type)))

/*-----------------------
 * Utility Functions
 *----------------------*/

/*
 * Test whether <obj> is a valid SOM object.  This test is based solely
 * on the fact that (on this architecture) the first word of a SOM
 * object is a pointer to its method table.  The test is therefore most
 * correctly understood as returning true if and only if <obj> is a
 * pointer to a pointer to a valid SOM method table.  If so, then
 * methods can be invoked on <obj>.
 */
SOMEXTERN boolean SOMLINK somIsObj (somToken obj);

/*
 * Verifies that the passed object is a valid instance of the passed
 * class.  A detected failure generates an error message and causes
 * program termination.  This call is automatically employed as part
 * of the C method resolution macros if the preprocessor variable
 * SOM_TestOn is defined.
 */
SOMEXTERN SOMObject * SOMLINK somTestCls (
    SOMObject *obj,
    SOMClass *classObj,
    string fileName,
    int lineNumber);

/*
 * Return the class that introduced the method represented by a given
 * method token.
 */
SOMEXTERN SOMClass* SOMLINK somGetClassFromMToken (somMToken mToken);


/*----------------------------------------------------------------------
 *  SOM Id Manager Section
 *---------------------------------------------------------------------*/

/*
 * typedef char* somId; // the "public" somId type (in sombtype.h)
 *
 * This above definition prevents users from building assumptions about
 * how somIds are implemented into their programs. However, a little more
 * information is useful to understand the different alternatives for
 * creating somIds.
 *
 * All somIds point to something called an idKey. The content of the
 * idKey for a somId depends on whether the somId has been registered.
 *
 * The idKey for an unregistered somId is a char* that points to a
 * null-terminated array of chars that is called the id name.
 *
 * When a somId is registered, the idKey it points to is changed to
 * point to a special structure whose representation is not made public.
 * Among other things, of course, this structure contains the address of
 * the id name. Normally the id name for a registered somId will be a copy
 * of the originally indicated name, but copying strings is expensive
 * because it requires dynamic memory allocation. As an alternative, to
 * speed up creation of somIds and minimize memory use, you can use
 * somBeginPersistentIds and somEndPersistentIds to bracket registration
 * of somIds. If you do this, you must use somRelocateIds before the
 * names for any of the "persistent" somIds that you create are changed
 * (or perhaps destroyed as a result of program termination).
 *
 * There are basically two different ways to create registered somIds:
 * from unregistered somIds, or from id names. To create registered
 * somIds from unregistered somIds, you pass the address of an idKey
 * to either somRegisterId or somCheckId; or, to register multiple
 * somIds in one step, you can pass the address of an array of idKeys
 * to somRegisterIds. To create registered somIds from id names, you
 * pass the address of the id name to either somIdFromString or
 * somIdFromStringNoFree. These routines are declared below.
 */

/*
 * Register a somId. Returns 1 (true) if the id is a new one, and
 * 0 (false) otherwise. An id is new if no previously-registered id
 * has the same name (where name comparison is case-insensitive).
 */
SOMEXTERN int SOMLINK somRegisterId (somId id);

/*
 * Like somRegisterId, but it returns the somId as its result.
 */
SOMEXTERN somId SOMLINK somCheckId (somId id);

/*
 * Tell the id manager to register ids for an array of idKeys.
 * The id argument points to an idKey array of length idCount.
 * If idCount is zero, then the array is assumed to be terminated
 * by a null pointer.
 */
SOMEXTERN void SOMLINK somRegisterIds(somId idKeys, long idCount);

/*
 * Return a somId that must be freed (using SOMFree) when the user
 * has finished with it.
 */
SOMEXTERN somId SOMLINK somIdFromString (string aString);

/*
 * Return a somId that must *not* be freed when the user
 * has finished with it. This function is more efficient
 * than the previous one.
 */
SOMEXTERN somId SOMLINK somIdFromStringNoFree(string aString);

/*
 * Return a string that must never be freed or modified.
 */
SOMEXTERN string SOMLINK somStringFromId (somId id);

/*
 * Returns true (1) if the two ids are equal, else false (0).
 */
SOMEXTERN int SOMLINK somCompareIds (somId id1, somId id2);

/*
 * Return the total number of ids that have been registered so far, you
 * can use this to advise the SOM runtime concerning expected number of
 * ids in later executions of your program, via a call to
 * somSetExpectedIds defined below
 */
SOMEXTERN unsigned long SOMLINK somTotalRegIds (void);

/*
 * Tell the SOM runtime how many unique ids you expect to use during
 * the execution of your program, this can improve space and time
 * utilization slightly, this routine must be called before the SOM
 * environment is created to have any effect
 */
SOMEXTERN void SOMLINK somSetExpectedIds (unsigned long numIds);

/*
 * Return the unique key for this id. This is the key used for
 * comparing somIds.
 */
SOMEXTERN unsigned long SOMLINK somUniqueKey (somId id);

/*
 * Signal the beginning of an interval during which the id manager
 * need not copy strings when registering new ids (because the caller
 * knows that these strings will not be destroyed or modified without
 * first calling somRelocateIds for each "persistent" id registered
 * during the interval).
 */
SOMEXTERN void SOMLINK somBeginPersistentIds (void);

/*
 * End the interval started with somBeginPersistentIds. Tells the
 * id manager that strings for any new ids subsequently registered
 * may be freed or otherwise modified without first calling somRelocateIds.
 * Therefore the id manager must copy the strings remember the name of an
 * id.
 */
SOMEXTERN void SOMLINK somEndPersistentIds (void);

/*
 * Tell the id manager to replace the names for the specified registered
 * ids with dynamically allocated copies. The id argument points to an
 * array of char* variables of length idCount. If idCount is zero,
 * then the array is assumed to be terminated by a null pointer.
 */
SOMEXTERN void SOMLINK somRelocateIds(somId id, long idCount);


/*----------------------------------------------------------------------
 * SOM Class Construction Section

 -- somBuildClass  introduced by SOM 2.0, SCI augmented for SOM 2.1
 -- somBuildClass2 introduced by SOM 3.0

 *---------------------------------------------------------------------*/

/* -- somBuildClass
 *
 * somBuildClass automates construction of a new class object. A variety of
 * special structures are used to allow language bindings to statically define
 * the information necessary to specify a class. Pointers to these static
 * structures are accumulated into an overall "static class information"
 * structure or SCI, passed to somBuildClass. The SCI has evolved over time.
 * The current version is defined here.
 *
 * The arguments to somBuildClass are as follows:
 *
 *   inherit_vars: a bit mask used to control inheritance of
 *                 implementation. Implementation is inherited from
 *                 parent i iff the bit 1<<i is on, or i>=32.
 *
 *   sci:          the somStaticClassInfo defined below.
 *
 *   majorVersion, minorVersion: the version of the class implementation.
 */

/* to specify a new static method */
typedef struct somStaticMethodStruct {
    somMToken *classData;
    somId *methodId; /* this must be a simple name (no colons) */
    somId *methodDescriptor;
    somMethodProc *method;
    somMethodProc *redispatchStub;
    somMethodProc *applyStub;
} somStaticMethod_t;

/* to specify an overridden method */
typedef struct somOverideMethodStruct {
    somId *methodId; /* this can be a method descriptor */
    somMethodProc *method;
} somOverrideMethod_t;

/* to inherit a specific parent's method implementation */
typedef struct somInheritedMethodStruct {
    somId     *methodId;  /* identify the method */
    long parentNum;       /* identify the parent */
    somMToken *mToken;    /* for parentNumresolve */
} somInheritedMethod_t;

/* to register a method that has been moved from this */
/* class <cls> upwards in the class hierachy to class <dest> */
typedef struct somMigratedMethodStruct {
    somMToken *clsMToken; /* points into the <cls> classdata structure */
                          /* the method token in <dest> will copied here */
    somMToken *destMToken;/* points into the <dest> classdata structure */
                          /* the method token here will be copied to <cls> */
} somMigratedMethod_t;

/* to specify non-internal data */
typedef struct somNonInternalDataStruct {
    somDToken *classData;
    char *basisForDataOffset;
} somNonInternalData_t;

/* to specify a "procedure" or "staticdata" */
typedef struct somProcMethodsStruct {
    somMethodProc **classData, *pEntry;
} somProcMethods_t;

/*
 * to specify a general method "action" using somMethodStruct. The
 * type of action is specified in the type field of somMethodStruct.
 *
 * action (in type & 0xFF)
 *  0: static -- (i.e., virtual) uses somAddStaticMethod
 *  1: dynamic -- uses somAddDynamicMethod (classData==0)
 *  2: nonstatic -- (i.e., nonvirtual) uses somAddMethod
 *  3: udaAssign -- registers a method as the udaAssign
 *                  (but doesn't add the method)
 *  4: udaConstAssign -- like 3, this doesn't add the method
 *  5: somClassResolve Override (using the class pointed to by *classData)
 *  6: somMToken Override (using the method token pointed to by methodId)
 *                        (note: classData==0 for this)
 *  7: classAllocate -- indicates the default heap allocator for this class.
 *                 If classData == 0, then method is the code address (or NULL)
 *                 If classData != 0, then *classData is the code address.
 *                 No other info required (or used)
 *  8: classDeallocate -- like 7, but indicates the default heap deallocator.
 *  9: classAllocator -- indicates a non default heap allocator for this class.
 *                       like 7, but a methodDescriptor can be given.
 *
 */

typedef struct somMethodStruct {
    unsigned long type;
    somMToken *classData;
    somId *methodId;
    somId *methodDescriptor;
    somMethodProc *method;
    somMethodProc *redispatchStub;
    somMethodProc *applyStub;
} somMethods_t;

/* to specify a varargs function */
typedef struct somVarargsFuncsStruct {
    somMethodProc **classData, *vEntry;
} somVarargsFuncs_t;

/* to specify dynamically computed information (incl. embbeded objs) */
typedef struct {
    int   version;                      /* 1 for now */
    long  instanceDataSize;             /* true size (incl. embedded objs) */
    long  dataAlignment;                /* true alignment */
    somEmbeddedObjStruct *embeddedObjs; /* array end == null copp */
} somDynamicSCI;

/*
 * to specify a DTS class, use the somDTSClass entry in the following
 * data structure. This entry is a bit vector interpreted as follows:
 *
 * (somDTSClass & 0x0001) == the class is a DTS C++ class
 */

/*
 *  The Static Class Info Structure passed to somBuildClass
 */
typedef struct somStaticClassInfoStruct {
    unsigned long layoutVersion;  /* 3 */
    unsigned long numStaticMethods;   /* count of smt entries */
    unsigned long numStaticOverrides; /* count of omt entries */
    unsigned long numNonInternalData; /* count of nit entries */
    unsigned long numProcMethods;     /* count of pmt entries */
    unsigned long numVarargsFuncs;    /* count of vft entries */
    unsigned long majorVersion;
    unsigned long minorVersion;
    unsigned long instanceDataSize;   /* instance data introduced by this class */
    unsigned long maxMethods;         /* count numStaticMethods and numMethods */
    unsigned long numParents;
    somId    classId;
    somId    explicitMetaId;
    long implicitParentMeta;
    somId                  *parents;
    somClassDataStructure  *cds;
    somCClassDataStructure *ccds;
    somStaticMethod_t      *smt; /* basic "static" methods for mtab */
    somOverrideMethod_t    *omt; /* overrides for mtab */
    char                   *nitReferenceBase;
    somNonInternalData_t   *nit; /* datatokens for instance data */
    somProcMethods_t       *pmt; /* Arbitrary ClassData members */
    somVarargsFuncs_t      *vft; /* varargs stubs */
    somTP_somClassInitFunc *cif; /* class init function */
    /* end of layout version 1 */

    /* begin layout version 2 extensions */
    long dataAlignment; /* the desired byte alignment for instance data */
    /* end of layout version 2 */

#define SOMSCIVERSION 1

    /* begin layout version 3 extensions */
    long numDirectInitClasses;
    somId *directInitClasses;
    unsigned long numMethods; /* general (including nonstatic) methods for mtab */
    somMethods_t       *mt;
    unsigned long protectedDataOffset; /* access = resolve(instanceDataToken) + offset */
    unsigned long somSCIVersion;  /* used during development. currently = 1 */
    unsigned long numInheritedMethods;
    somInheritedMethod_t *imt; /* inherited method implementations */
    unsigned long numClassDataEntries; /* should always be filled in */
    somId *classDataEntryNames; /* either NULL or ptr to an array of somIds */
    unsigned long numMigratedMethods;
    somMigratedMethod_t *mmt; /* migrated method implementations */
    unsigned long numInitializers; /* the initializers for this class */
    somId *initializers;     /* in order of release */
    unsigned long somDTSClass; /* used to identify a DirectToSOM class */
    somDynamicSCI *dsci;  /* used to register dynamically computed info */
    /* end of layout version 3 */

} somStaticClassInfo, *somStaticClassInfoPtr;

SOMEXTERN SOMClass * SOMLINK somBuildClass(IN long inherit_vars,
                                           IN somStaticClassInfo *sci,
                                           IN long majorVersion,
                                           IN long minorVersion);


/*
 * -- somBuildClass2
 *
 * somBuildClass2 was added in SOM 3.0 to allow reuse of static class
 * information to hold a class's instance variables. This speeds class
 * creation, and reduces the need for dynamically allocated memory. The
 * static class information structures are accumulated into a CIB (class
 * initialization block) instead of the SCI structure used with
 * somBuildClass.
 */

/*
 * to register a method that has been moved from this
 * class <orig> upwards in the class hierachy to class <dest>
 */
typedef struct somMigratedMethodStruct_t2 {
    somId  methodId;           /* id of the method being migrated */
    somMToken *abi2TokenAddr;   /* if abi2, this class's classData field addr */
    somToken  *abi3SymbolAddr;   /* if abi3, this class's method symbol addr */
} somMigratedMethod_t2;

/*
 * to select a specific ancestor's implementation for an inherited method
 */
typedef struct somInheritedMethodStruct_t2 {
    somId methodId;
    long  parentNum;
    SOMClass ** ancestorClass;
} somInheritedMethod_t2;

/*
 * to register a normal method override
 */
typedef struct somOverideMethodStruct_t2 {
    somId methodId;
    somMethodPtr *pcall;
    somMethodPtr pcallResolve;
    somMethodPtr methodProc;
} somOverrideMethod_t2;

typedef struct {
    somMethodData  md;
    somMethodProc* dispatchFcn;
    /* ... arbitrary remaining structure known to dispatchFcn */
} somRedispatchInfo, *somRedispatchInfoPtr;

/*
 * to register information for a new method
 */
#ifndef SOM_MD_DEFINED
typedef struct {
    unsigned long  type;
    somId descriptor;
    somMToken mToken; /* address of method symbol if one exists */
    somMethodPtr method; /* address of method proc */
    somMethodPtr redispatchStub;    /* either these 2 */
    somMethodPtr applyStub;
    somMethodInfoPtr methodInfo;    /* or this 1 */
    somMToken *tokenLoc;          /* address of ClassData field */
    somRedispatchInfoPtr redispatchInfo; /* rdstub desired (we'll fill in md) */
    long layoutVersion;
} somMethodDefn, *somMethodDefnPtr;
#endif


/*
 * class variables that don't change after class intialization
 */
typedef struct somClassVars1Struct {
    long layoutVersion; /* 1 */
    void* extension;
    long dataSize;
    long dataAlignment;
    somMethodProc       *classAllocate;
    somMethodProc       *classDeallocate;
} somClassVars1, *somClassVars1Ptr;


/*
 * storage addressed by a method symbol
 */
typedef struct somMethodSymbolBindingStruct {
    char content[4];
} somMethodSymbol, *somMethodSymbolBinding;

/*
 * Overrides for SOMObject Specials
 */
typedef struct somSpecialOverridesStruct {
    somMethodSymbolBinding ctorThunk;
    somMethodSymbolBinding resolvedThunk; /* #13082 */
    somMethodPtr      methodProc;
} somSpecialOverrides, *somSpecialOverridesPtr;

/*
 * (non-SOMObject) initializer symbols (#13082)
 */
typedef struct somInitSymbolsStruct {
    somId methodId;
    somMethodSymbolBinding ctorThunk;
    somMethodSymbolBinding resolvedThunk;
} somInitSymbols, *somInitSymbolsPtr;


/*
 * CIB
 */

typedef struct SOM_CIB {
    long                    layoutVersion;
    somClassVars1Ptr        classVars1;
    void**                  unsharedVars;
    long                    majorVersion;
    long                    minorVersion;
    unsigned long           constFlags;
    unsigned long           inheritVars;
    SOMClass**              classMeta;
    somMethodPtr            classInit;
    somMethodPtr            classUninit;
    somMethodPtr            legacyInit;
    somMethodPtr            legacyUninit;
    somMethodPtr            udaAssign;
    somMethodPtr            udaConstAssign;
    long                    protectedDataOffset;
    long                    numEmbeddedObjs;
    somEmbeddedObjStructPtr embeddedObjs;
    long                    numRegIds;
    char**                  regIds;
    long                    numClassDataEntries;
    somClassDataStructurePtr  somClassData;
    somCClassDataStructurePtr somCClassData;
    som3ClassInfoStructPtr    som3ClassInfo;
    long                    numParents;
    SOMClass***             parents;
    long                    numDirectInitClasses;
    SOMClass***             directInitClasses;
    long                    numNewInitializers;
    somInitSymbolsPtr       newInitializerSymbols;
    long                    numOvInitializers;
    somInitSymbolsPtr       ovInitializerSymbols;
    somSpecialOverridesPtr  specialOverrides;
    long                    maxNDMethods;
    somMethodDefn*          newNDMethods;
    long                    numOverrides;
    somOverrideMethod_t2*   overrides;
    long                    numInheritedSelections;
    somInheritedMethod_t2*  inheritedSelections;
    long                    numMigratedMethods;
    somMigratedMethod_t2*   migratedMethods;
} SOM_CIB, *SOM_CIBPtr;


SOMEXTERN SOMClass * SOMLINK somBuildClass2(SOM_CIBPtr cib,
                                            long requestedMajorVersion,
                                            long requestedMinorVersion);

/*
 *  Used by old single-inheritance emitters to make class creation
 *  an atomic operation. Kept for backwards compatability only.
 */
typedef void     SOMLINK somTD_classInitRoutine  (
    IN SOMClass * /* parent class */,
    IN SOMClass * /* metaclass */);
SOMEXTERN void SOMLINK somConstructClass (
    IN somTD_classInitRoutine *classInitRoutine,
    IN SOMClass *parentClass,
    IN SOMClass *metaClass,
    IN somClassDataStructure *cds);

/*
 * somRegisterLibraryClasses - the parameters are defined as follows:
 * 1. libHandle is the operating system-dependent library handle that
 *    is returned by the operating system's "load library" function.
 *    See somplatf.h for the definition of the somLibraryHandle type.
 * 2. numClasses is the number of SOM classes in the library.
 * 3. classInfoStructs is a pointer to an array of pointers to
 *    som3ClassInfoStruct (one for each class in the library).
 *    The array must be a static variable, so the pointer to this
 *    array will be valid after the call has completed.
 * 4. userInitRoutine may either be NULL or the address of an
 *    initialization function to be called.
 */
typedef void SOMLINK userInitTermProc (somLibraryHandle, unsigned long);

SOMEXTERN long SOMLINK
somRegisterLibraryClasses(
                          somLibraryHandle       libHandle,
                          long                   numClasses,
                          som3ClassInfoStructPtr classInfoStructs[],
                          userInitTermProc*      userInitTermRoutine );
SOMEXTERN long SOMLINK somUnregisterLibraryClasses (somLibraryHandle libHandle);

#endif /* somapi_h */

