home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warphead.zip / H / DYNVALUS.H < prev    next >
C/C++ Source or Header  |  1997-02-28  |  28KB  |  477 lines

  1. /* @(#)Z 1.5 com/src/cm/DynValus.h, odstorage, od96os2, odos29646d 96/11/15 15:27:04 (96/10/29 09:18:00) */
  2. /*====START_GENERATED_PROLOG======================================
  3.  */
  4. /*
  5.  *   COMPONENT_NAME: odstorage
  6.  *
  7.  *   CLASSES: none
  8.  *
  9.  *   ORIGINS: 82,27
  10.  *
  11.  *
  12.  *   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13.  *   All Rights Reserved
  14.  *   Licensed Materials - Property of IBM
  15.  *   US Government Users Restricted Rights - Use, duplication or
  16.  *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17.  *       
  18.  *   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19.  *   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20.  *   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21.  *   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22.  *   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23.  *   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24.  *   OR PERFORMANCE OF THIS SOFTWARE.
  25.  */
  26. /*====END_GENERATED_PROLOG========================================
  27.  */
  28.  
  29. /*
  30.     File:        DynValus.h
  31.  
  32.     Contains:    Container Manager Dynamic Value Interfaces
  33.  
  34.     Written by:    Ira L. Ruben
  35.  
  36.     Owned by:    Ed Lai
  37.  
  38.     Copyright:    ⌐ 1992-1994 by Apple Computer, Inc., all rights reserved.
  39.  
  40.     Change History (most recent first):
  41.  
  42.          <2>     8/26/94    EL        #1181622 Ownership update.
  43.          <2>      5/9/94    MB        #1162181: Changes necessary to install MMM.
  44.          <1>      2/3/94    EL        first checked in
  45.  
  46.     To Do:
  47. */
  48.  
  49. /*---------------------------------------------------------------------------*
  50.  |                                                                           |
  51.  |                          <<<   DynValus.h    >>>                          |
  52.  |                                                                           |
  53.  |                Container Manager Dynamic Value Interfaces                 |
  54.  |                                                                           |
  55.  |                               Ira L. Ruben                                |
  56.  |                                  5/5/92                                   |
  57.  |                                                                           |
  58.  |                     Copyright Apple Computer, Inc. 1992-1994              |
  59.  |                           All rights reserved.                            |
  60.  |                                                                           |
  61.  *---------------------------------------------------------------------------*
  62.  
  63.  Dynamic values are special values which "know" how to manipulate on their own value data.
  64.  They do this through a set of value operation handlers which are expected to be
  65.  semantically the same as the standard API value operations.
  66.  
  67.  The following value operations are expected to be supported by these handlers:
  68.  
  69.  CMSize CMGetValueSize(CMValue value);
  70.  CMSize CMReadValueData(CMValue value, CMPtr buffer, CMCount offset, CMSize maxSize,
  71.                                                  CMType *type);
  72.  void CMWriteValueData(CMValue value, CMPtr buffer, CMCount offset, CMSize size);
  73.  void CMInsertValueData(CMValue value, CMPtr buffer, CMCount offset, CMSize size);
  74.  void CMDeleteValueData(CMValue value, CMCount offset, CMSize size);
  75.  void CMGetValueInfo(CMValue value, CMContainer *container, CMObject *object,
  76.                                          CMProperty *property, CMType *type, CMGeneration *generation);
  77.  void CMSetValueType(CMValue value, CMType type);
  78.  void CMSetValueGeneration(CMValue value, CMGeneration generation);
  79.  void CMReleaseValue(CMValue);
  80.  
  81.  Whenever a dynamic value is passed to a standard API value routine corresponding to the
  82.  above handlers, the handler is called instead.  That is why the handler must be
  83.  semantically identical.
  84.  
  85.  Basically, dynamic values are similar to C++ objects where the handlers are the object's
  86.  methods.  They are dynamic in the sense that they only exist from creation (discussed
  87.  below) and last until until they are released (CMReleaseValue()).
  88.  
  89.  A dynamic value can have its own data (similar to C++ class fields).  The data is
  90.  generally used to create the handler's refCon during dynamic value creation.
  91.   
  92.  A dynamic value results when a value is created by to CMNewValue() or attempted to be
  93.  used by CMUseValue(), and the following two conditions occur:
  94.  
  95.      1. The type or any of its base types (if any, created by CMAddBaseType()), are for
  96.           global names that have associated metahandlers registered by CMRegisterType().
  97.          
  98.     2. The metahandlers support the operation type to return a "use value" handler, and
  99.          in addition for CMNewValue(), a "new value" handler.
  100.  
  101.  The "new value" handlers are used to define initialization data for the "use value"
  102.  handlers.  The "use value" handlers are called to set up and return a refCons.  Another
  103.  metahandler address is also returned. This is used to get the address of the value
  104.  operation handlers corresponding to the standard API CM... value routines mentioned above.
  105.  
  106.  Just like C++, dynamic values may be "subclassed" via their (base) types.  If a handler
  107.  for a particular operation is not defined for a value, its "base value" is used to get the
  108.  "inherited" handler.  This continues up a dynamic value's chain of base values, up to the
  109.  original "real" value that spawned the base values from the CMNewValue() or CMUseValue().
  110.  
  111.  Thus for each dynamic value, there is a vector of handler addresses.    DynValus.h   
  112.  defines the layout of that vector.  Also defined there are the other interfaces needed to
  113.  process a dynamic value by the API routines themselves.  The routines themselves are in
  114.  this file.
  115.  
  116.  The vector becomes part of a set of "extensions" to the dynamic value header.  The
  117.  extensions struct is defined in  TOCEnts.h   along with the other value header
  118.  definitions.  The dynamic value stuff is kept separate because it is sufficiently
  119.  distinct.
  120.  
  121.  For a full description of the dynamic value data structures and how dynamic values work
  122.  see DynamicValues.c.  It's "everything you wanted to know about dynamic values and
  123.  afraid to ask" kind of description.
  124.   
  125.  Implementation note: This header is slightly different from the other headers in its
  126.                                              organization.  This is due to the complexity involved with dynamic
  127.                                             values.  The various declarations are ordered such that this reads
  128.                                             as a description from top to bottom.  They are not just as set of
  129.                                             isolated (but related) definitions which is generally the case in
  130.                                             the other headers.  So this file is best understood by reading it 
  131.                                             in the order presented.
  132. */
  133.  
  134. #ifndef __DYNAMICVALUES__
  135. #define __DYNAMICVALUES__
  136.  
  137. #include <stdarg.h>
  138.  
  139. #ifndef __CMTYPES__
  140. #include "CMTypes.h"
  141. #endif
  142. #ifndef __CM_API_TYPES__
  143. #include "CMAPITyp.h"
  144. #endif
  145.  
  146. struct Container;
  147. struct TOCObject;
  148. struct TOCValueHdr;
  149.  
  150.                                                                     CM_CFUNCTIONS
  151.  
  152. /* The following defines what each entry in the dynamic value vector looks like...            */
  153.  
  154. struct DynamicValueVectorEntries {        /* Layout of a dynamic value vector entry:                */
  155.     CMHandlerAddr handler;                            /*        the handler address                                                    */
  156.     CMValue                thisValue;                        /*        the handler's value (C++ "this")                        */
  157.     CMBoolean         active;                                /*        true ==> handler is in calling chain                */
  158. };
  159. typedef struct DynamicValueVectorEntries DynamicValueVectorEntries, *DynamicValueVectorEntriesPtr;
  160.  
  161. /* When a handler is called, it is expected to do its operations on the "base value" of    */
  162. /* the value passed to it.  It gets its base value using CMGetBaseValue().  However,        */
  163. /* we don't want to allow recursive use of the API for the same value.  That would            */
  164. /* call the handler again and we would be in an infinit loop!  Thus the active switch        */
  165. /* is provided to check for this so we can report an error.                                                            */
  166.  
  167. /* The vector is initialized with each handler address thisValue set to NULL.  On first */
  168. /* use we use the methandler returned from the "use value" handler (saved in the value     */
  169. /* header extensions) to get the proper handler address.  It is saved in the handler         */
  170. /* field of the vector entry. Remember we may have to search up through a dynamic value */
  171. /* chain to find an "inherited" method ('er, excuse me, value handler operation).  Thus */
  172. /* the handler used may correspond to a different dynamic value. We must therefore save */
  173. /* the dynamic value refNum along with the handler address (in the thisValue).  It is     */
  174. /* basically the C++ "this" pointer for the method (oops, sorry again, value handler         */
  175. /* operation).                                                                                                                                                    */
  176.  
  177. /* Of course, in the simplest case, where the handler is provided for the original             */
  178. /* value, the thisValue will point to its own dynamic value header.  At the other                */
  179. /* extreme no handlers are supplied for the operation and we end up using the "real"        */
  180. /* value that spawned the dynamic value(s).  In that case the handler pointer in the        */
  181. /* vector entry remains NULL and the thisValue will be the "real" value refNum.  With        */
  182. /* no handler we use the actual API routine to process the real value.                                    */
  183.  
  184. /* Now that you understand what each vector entry contains, we can define the vector        */
  185. /* itself...                                                                                                                                                        */
  186.  
  187. struct DynamicValueVector {
  188.     DynamicValueVectorEntries cmGetValueSize;
  189.     DynamicValueVectorEntries cmReadValueData;
  190.     DynamicValueVectorEntries cmWriteValueData;
  191.     DynamicValueVectorEntries cmInsertValueData;
  192.     DynamicValueVectorEntries cmDeleteValueData;
  193.     DynamicValueVectorEntries cmGetValueInfo;
  194.     DynamicValueVectorEntries cmSetValueType;
  195.     DynamicValueVectorEntries cmSetValueGen;
  196.     DynamicValueVectorEntries cmReleaseValue;
  197. };
  198. typedef struct DynamicValueVector DynamicValueVector;
  199.  
  200. /* Remember this becomes part of the extensions belonging only to a dynamic value header*/
  201. /* as defined in TOCEntries.h.                                                                                                                    */
  202.  
  203. /* Just as with standard handlers, to make it easier and more readable for the Container*/
  204. /* Manager to call the dynamic value handlers, we will use macros.  These macros will        */
  205. /* require the following typedefs as casts to convert the generic handler typedef,             */
  206. /* HandlerAddr (the type used to store the addresses in the vector), to the actual            */
  207. /* function type:                                                                                                                                                */
  208.  
  209. typedef CMSize (*TcmGetValueSize)(CMValue value);
  210. typedef CMSize (*TcmReadValueData)(CMValue value, CMPtr buffer, CMCount offset, CMSize maxSize);
  211. typedef void (*TcmWriteValueData)(CMValue value, CMPtr buffer, CMCount offset, CMSize size);
  212. typedef void (*TcmInsertValueData)(CMValue value, CMPtr buffer, CMCount offset, CMSize size);
  213. typedef void (*TcmDeleteValueData)(CMValue value, CMCount offset, CMSize size);
  214. typedef void (*TcmGetValueInfo)(CMValue value, CMContainer *container, CMObject *object,
  215.                                                                 CMProperty *property, CMType *type, 
  216.                                                                 CMGeneration *generation);
  217. typedef void (*TcmSetValueType)(CMValue value, CMType type);
  218. typedef void (*TcmSetValueGen)(CMValue value, CMGeneration generation);
  219. typedef void (*TcmReleaseValue)(CMValue);
  220.  
  221. /* Note, these casts are not just placed here for the fun of it!  They are delibertly    */
  222. /* placed in front of the macros which will use them!  Why?  It seems some compilers        */
  223. /* don't support ANSI correctly (as I understand it) and require this. The c89 compiler    */
  224. /* on the RS/6000 is one such compiler.  It reported errors if the casts followed the        */
  225. /* macros (sounds like a bug to me)!                                                                                                        */
  226.  
  227. /* Here now are the macros used to do the calls using the vector...                                            */
  228.  
  229. #define CMDynGetValueSize(v)                            (*(TcmGetValueSize)DYNEXTENSIONS(v)->dynValueVector.cmGetValueSize.handler)((CMValue)(v))
  230. #define CMDynReadValueData(v, b, x, m)        (*(TcmReadValueData)DYNEXTENSIONS(v)->dynValueVector.cmReadValueData.handler)((CMValue)(v), (CMPtr)(b), (CMCount)(x), (CMSize)(m))
  231. #define CMDynWriteValueData(v, b, x, n)        (*(TcmWriteValueData)DYNEXTENSIONS(v)->dynValueVector.cmWriteValueData.handler)((CMValue)(v),    (CMPtr)(b), (CMCount)(x), (CMSize)(n))
  232. #define CMDynInsertValueData(v, b, x, n)    (*(TcmInsertValueData)DYNEXTENSIONS(v)->dynValueVector.cmInsertValueData.handler)((CMValue)(v), (CMPtr)(b), (CMCount)(x), (CMSize)(n))
  233. #define CMDynDeleteValueData(v, x, n)            (*(TcmDeleteValueData)DYNEXTENSIONS(v)->dynValueVector.cmDeleteValueData.handler)((CMValue)(v), (CMCount)(x), (CMSize)(n))
  234. #define CMDynGetValueInfo(v,c,obj,p,t, g) (*(TcmGetValueInfo)DYNEXTENSIONS(v)->dynValueVector.cmGetValueInfo.handler)((CMValue)(v), (CMContainer*)(c), (CMObject*)(obj),\
  235.                                                                                                                                                                                                                                         (CMProperty*)(p), (CMType*)(t), (CMGeneration*)(g))
  236. #define CMDynSetValueType(v, t)                          (*(TcmSetValueType)DYNEXTENSIONS(v)->dynValueVector.cmSetValueType.handler)((CMValue)(v), (CMType)(t))
  237. #define CMDynSetValueGen(v, g)                         (*(TcmSetValueGen)DYNEXTENSIONS(v)->dynValueVector.cmSetValueGen.handler)((CMValue)(v), (CMGeneration)(g))
  238. #define CMDynReleaseValue(v)                            (*(TcmReleaseValue)DYNEXTENSIONS(v)->dynValueVector.cmReleaseValue.handler)((CMValue)(v))
  239.  
  240. /* If nothing else, the above shows that, with enough casts, you can get away with             */
  241. /* anything in C!  Aren't casts wonderful?  Repeat after me -- casts are your friend.        */
  242.  
  243. /* As mentioned earlier, each corresponding API value operation must check to see if it    */
  244. /* has a dynamic value and call the corresponding handler which does the operation. It    */
  245. /* must get the proper address on first use.  It must set switches to mark the handler    */
  246. /* as active.  It must also set a switch to allow CMGetBaseValue() calls which are only    */
  247. /* allowed from dynamic value handlers.  Thus the algorithm looks something like this     */
  248. /* (ignoring all errors for the moment):                                                                                                */
  249.  
  250. /*    if (IsDynamicValue(v)) {                                                                                                                        */
  251. /*        v = GetDynHandlerAddress(v, h, g);                                                                                                */
  252. /*        if (IsDynamicValue(v)) {                                                                                                                    */
  253. /*            SignalDynHandlerInUse(v, h);                                                                                                        */
  254. /*            AllowCMGetBaseValue(container);                                                                                                    */
  255. /*                                                                                                                                                                            */
  256. /*            Call the proper dynamic value handler with one of the above macros definitions.    */
  257. /*             The macro will pass the appropriate value corresponding to a possibly inherited    */
  258. /*             handler.  If the handler returns a value save it to be returned as the result.    */
  259. /*                                                                                                                                                                            */
  260. /*            DisAllowCMGetBaseValue(container);                                                                                            */
  261. /*            SignalDynHandlerAvailable(v, h);                                                                                                */
  262. /*            return [result];                                                                                                                                */
  263. /*        }                                                                                                                                                                    */
  264. /*    }                                                                                                                                                                        */
  265.  
  266. /* In the above algorithm,                                                                                                                             */
  267. /*        v is a dynamic CMValue (note that GetDynHandlerAddress may CHANGE it),                         */
  268. /*        h is a pointer to a vector entry in the extensions,                                                             */
  269. /*        g is the metahandlers operation type string,                                                                            */
  270.  
  271. /* The GetDynHandlerAddress() takes a vector entry and sets the handler address as a        */
  272. /* function of the "g" metahandler operation code.  On first call it will search for the*/
  273. /* inherited method if necessary.     The vector is updated with the found handler address    */
  274. /* and the associated "this" value saved.  This is the value returned and whose switches*/
  275. /* we set.  We do the call and reset the switches, all using the same "this" value.            */
  276.  
  277. /* Note, in the limit, the search for the inherited handler may end up finding the             */
  278. /* original "real" value that spawned the dynamic values!  Thus what is returned from        */
  279. /* GetDynHandlerAddress() in this case is a "real" value to be operated upon using the    */
  280. /* standard API routine itself.  That is why a second IsDynamicValue() must be done to    */
  281. /* bypass the handler call and switch setting/resetting.                                                                */
  282.  
  283. /* Be careful here!  Since there is no guarantee the value coming back from the                    */
  284. /* GetDynHandlerAddress() call is the one that went in, the code must reload any copies    */
  285. /* of the value sometime following the GetDynHandlerAddress() calls. This is highlighted*/
  286. /* as something to look out for because it has already caused one bug!                                    */
  287.  
  288. /* All of the above is what each corresponding API value operation must do.  Given all     */
  289. /* this, it is impossible to write a generalized macro to minimize the coding. We could */
  290. /* write a unique macro for each handler just as the vector calls are done above, but         */
  291. /* that would probably be confusing.                                                                                                         */
  292.  
  293. /* So as a comprimise, the following macros are defined.  They basically mimic the            */
  294. /* above algorithm, but here take errors into account.                                                                    */
  295.  
  296. #define GetDynHandlerAddress(v, h, g, s, x) if ((v = cmGetDynHandlerAddress((CMValue)(v), &DYNEXTENSIONS(v)->dynValueVector.h, (CMGlobalName)(g), s)) == NULL) \
  297.                                                                                             return x
  298. #define SignalDynHandlerInUse(v, h)                     DYNEXTENSIONS(v)->dynValueVector.h.active = true
  299. #define SignalDynHandlerAvailable(v, h)             DYNEXTENSIONS(v)->dynValueVector.h.active = false
  300. #define AllowCMGetBaseValue(container)            ++((ContainerPtr)(container))->getBaseValueOk
  301. #define DisAllowCMGetBaseValue(container)        if (--((ContainerPtr)(container))->getBaseValueOk < 0) \
  302.                                                                                             ((ContainerPtr)(container))->getBaseValueOk = 0;
  303.  
  304. /* The IsDynamicValue() call is defined in TOCEntries.h.                                                                */
  305.  
  306. /* The "h" in all these macros is the vector entry name.                                                                */
  307.  
  308. /* The "x" parameter in GetDynHandlerAddress has the same purpose as in    ErrorRpt.h   */
  309. /* where we return CM_NOVALUE, NULL, or whatever is appropriate to indicate failure of    */
  310. /* the API routine.                                                                                                                                            */
  311.  
  312. /* Also for GetDynHandlerAddress, the "s" is the name of the API routine doing the call.*/
  313. /* This is used by cmGetDynHandlerAddress() simply to use as an insert if it should         */
  314. /* report an error prior to returning NULL.                                                                                            */
  315.  
  316. /* Note the AllowCMGetBaseValue and DisAllowCMGetBaseValue macros. As mentioned earlier,*/
  317. /* a CMGetBaseValue() is only allowed from value operation handlers.  The two macros        */
  318. /* control a single switch, getBaseValueOk, the CMGetBaseValue() checks.  The switch is    */
  319. /* actualy a counter which, just to be safe, is never allowed to stay negative.  0 means*/
  320. /* CMGetBaseValue() is illegal.  Greater than 0, it's legal.  The reason the switch is a*/
  321. /* counter is because dynamic values use CMGetBaseValue() to do their operations in         */
  322. /* terms of their base values. If a dynamic value's base is also dynamic (i.e., we have */
  323. /* layered dynamic values), then we have a nesting condition.  Hence the counter.                */
  324.  
  325. /* The rest of this header is more "normal", i.e., a collection of related definitions    */
  326. /* and function headers.                                                                                                                                */
  327.  
  328.     
  329. struct TOCValueHdr *cmFollowTypes(struct TOCValueHdr *theBaseValueHdr,
  330.                                                                     struct TOCObject *type,
  331.                                                                     CMBoolean isNewValue, va_list *constructorData);
  332.     /*
  333.     This routine creates a dynamic value layers for the passed type and all of its base types,
  334.     if any of these types have a "use value" handler.  This routine is only called by
  335.     CMNewValue() or CMUseValue().  For CMNewValue(), "metadata" handler and "new value"
  336.     handlers are also required.  The top-most dynamic value header pointer is returned.  This
  337.     should be returned from CMUseValue() or CMNewValue().  NULL is returned if an error is
  338.     reported.  The original "real" value is returned if no dynamic values are created.
  339.      
  340.     For CMUseValue(), isNewValue should be set to false.  It should only be set to true for
  341.     CMNewValue().  Also for CMNewValue(), the constructorData must point at the CMNewValue()
  342.     "..." parameters.  These are consumed as the base type metadata (returned from the 
  343.     "metadata" handler) describes how to create data packets from the "..." parameters.  The
  344.     packets, in turn, are passed to the "new value" handlers.  A "new value" handler uses its
  345.     data packet to write (possibly different) data to its base value.  This written data will
  346.     then be read and used by the "use value" handler.
  347.     
  348.     The "use value" handler is called for both the CMUseValue() and CMNewValue() cases.  If
  349.     it's companion "new value" handler wrote data to its base value, the "use value" handler
  350.     will probably read the data to create its refCon.  The refCon will be passed to all
  351.     value handlers.  The "use value" handler returns its refCon along with another
  352.     metahandler address that is used to get the value handler addresses.  These are then
  353.     used to create the dynamic value.
  354.     
  355.     See dynamic value documentation in   DynValus.c    for a full a description of the
  356.     prototypes for the "metadata", "new value", and "use value" handlers, as well as the
  357.     description of the metadata itself.
  358.     
  359.     To produce all the required dynamic values, cmFollowTypes() recursively follows the
  360.     types, looking for base types as defined by CMAddBaseType().  Each type can have any
  361.     number of base types.  The recursion effectively produces a depth-first search of all
  362.     the base types.
  363.     
  364.     As each type is completed (i.e., no more base types for it), a dynamic value is created
  365.     as described above.  That is, for CMNewValue(), a type's "metadata" handler instructs us
  366.     on how many CMNewValue() "..." parameters to consume and how to construct their packet.
  367.     That is passed to the "new value" handler so it can write some appropriate data to the
  368.     base value.  The "use value" is called in all cases which reads the data written by "new
  369.     value" to construct its refCon.  The refCon is returned here along with the metahandler
  370.     address that will yield the value handler routine addresses.
  371.     
  372.     The refCon and metahandler address are passed to newDynamicValue() to construct one
  373.     dynamic value (layer).  The resulting dynamic value is used as the base value for the
  374.     next layer.  This produces the desired data structures.
  375.     
  376.     Note, because this routine searches through the types down to their leaves, and then
  377.     generates the dynamic values on the way back "up", the CMNewValue() "..." parameters
  378.     must be ordered for the "deepest" type first.  For example, given the following type
  379.     inheritance heirarchy (read these as T1 inherits from T2 and T3, and so on):
  380.     
  381.                                       T4      T5
  382.                                         *    *
  383.                                          *  *
  384.                                   T2      T3
  385.                                     *    *
  386.                                      *  *
  387.                                       T1
  388.                              
  389.     The depth-first search, starting at T1, yields the sequence: T2 T4 T5 T3 T1.  Then this
  390.     is the order the CMNewValue() "..." parameters must be in.
  391.     */
  392.     
  393.     
  394. CMValue cmGetDynHandlerAddress(CMValue value, DynamicValueVectorEntriesPtr vectorEntry,
  395.                                                              CMconst_CMGlobalName operationType, char *routineName);
  396.     /*
  397.     A dynamic value handler is callable if it exists (of course!) and it is not being used
  398.     recursively.  The vectorEntry points to the dynamic value entry in its vector belonging
  399.     to the extensions of the passed dynamic value.  If this is not the first use of the
  400.     handler, the vector entry contains the handler address and its associated ("this") value
  401.     (discussed below).  If it is first use, cmGetDynHandlerAddress() must find the
  402.     ("inherited") handler address and its associated "this" value.
  403.     
  404.     No matter which case it is, the "this" value is returned as the function result.  NULL
  405.     is returned if an error is reported (discussed later).
  406.      
  407.     The returned value, and the one saved in the vector entry may not be the same.  They are
  408.     if the passed value has a handler.  If it doesn't, an "inherited" handler, from one of
  409.     the dynamic value's base values is used. The value associated for whoever has the handler 
  410.     is the "owning" value.  In C++ terms, it is the "this" pointer.
  411.     
  412.     In the limit, we could end up using the original "real" value that spawned the dynamic
  413.     value(s).  In that is indeed the case, we end up using the calling routine which will
  414.     always be an API value operation (as shown in the algorithm above).
  415.  
  416.     The found handler address and "this" pointer are saved in the passed dynamic value's
  417.     vector entry so we don't have to do the search on successive uses.  The "this" pointer
  418.     and handler address are also saved in the vector entry corresponding to "this" (unless,
  419.     of course, it is the "real" value).
  420.      
  421.     In the vector entry there is also a boolean flag that tells us whether the handler is
  422.     currently active, i.e., in the call chain.  If it is we have a recursion attempt.  This
  423.     causes an error report and NULL to be returned.  Since we will always find the handler
  424.     or use the "real" value, we can never get an error from that.  The recursion is the only
  425.     error condition.
  426.     */
  427.  
  428. CM_ULONG cmVScanDataPacketGuts(struct TOCObject *type, CM_CHAR *metaData,
  429.                                                              CM_UCHAR *dataPacket, va_list dataInitParams);
  430.     /*
  431.     This routine is the "guts" of the routine CMScanDataPacket().  It is used to extract the
  432.     fields of a data packet created from CMNewValue() "..." parameters according to the
  433.     specified metadata and place it in the "dataInitParams" parameters.  Each dataInitParams
  434.     parameter must be a pointer; extracted data read from the data packet are stored into the
  435.     locations pointed to by the pointers.
  436.     
  437.     The Container Manager accesses the metadata through a "metadata" handler for the type to
  438.     build the data packet.  cmVScanDataPacket() inverts the operation and allows a "new
  439.     value" handler to extract the data back into distinct variables. The "new value" handler
  440.     can use its own "metadata" handler to pass to the CMScanDataPacket() routine to extract
  441.     the data.
  442.     
  443.     The function returns the number of data items extracted and assigned to the parameters.
  444.     This could be 0 if the type does not have any metadata (or if an error is reported).
  445.     
  446.     NULL may be passed as the dataPacket or metaData pointer to indicate there is no
  447.     metadata.  
  448.     
  449.     The metadata format is discussed in DynamicValues.c.  The only special case is for the
  450.     "%*s" format specification.  This generates a fixed length string (not null terminated)
  451.     of n characters, where n is determined from a parameter in the CMNewValue() "..."
  452.     paramters.  The value of n is explicitly written to the packet data in front of the
  453.     string.  For symmetry (and so we can determine the number of characters to extract from
  454.     the packet data), we return the value of n to an explict parameter pointer passed here.
  455.     Thus the parameter pointer list passed to this routine should be identical to the "..."
  456.     parameters passed to a CMNewValue() "..." parameter list (at least the portion
  457.     corresponding to this type).
  458.     */
  459.  
  460.  
  461. void cmDeleteAllDynamicValueLayers(struct TOCValueHdr *theValueHdr, CMBoolean freeValueHdr);
  462.     /*
  463.     This routine is used in two contexts; first, for error recovery to free all the memory
  464.     for a newly allocated dynamic value layer set, and second, when freeing the entire TOC
  465.     to make usre all memory for any "dangling" dynamic values are freed.
  466.     
  467.     The current top-most dynamic value layer is passed in theValueHdr.  The layers are
  468.     back-linked up to the base "real" value.  All the dynamic value memory on this chain are
  469.     freed.  If freeValueHdr is true, then we were creating dynamic values for CMNewValue().
  470.     In that case, the real value itself is freed.  Really freed!  Not marked free as is the
  471.     usual case.
  472.     */
  473.  
  474.  
  475.                                                          CM_END_CFUNCTIONS
  476. #endif
  477.