home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / CMDbgOps.c < prev    next >
C/C++ Source or Header  |  1997-03-21  |  32KB  |  871 lines

  1. /* @(#)Z 1.4 com/src/cm/CMDbgOps.c, odstorage, od96os2, odos29712d 97/03/21 17:19:31 (96/10/29 09:16:30) */
  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:         CMDbgOps.c 
  31.  
  32.     Contains:    Container Manager Debugging Operations
  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.          <3>     12/9/94    EL        #1182275 Optionally do not maintain
  43.                                     continue flag.
  44.          <2>     8/26/94    EL        #1181622 Ownership update
  45.          <1>      2/3/94    EL        first checked in
  46.          <2>    11/23/93    EL        When updating save TOC data so that TOC
  47.                                     don't need to be read twice.
  48.  
  49.     To Do:
  50. */
  51.  
  52. /*---------------------------------------------------------------------------*
  53.  |                                                                           |
  54.  |                           <<<  CMDbgOps.c  >>>                            |
  55.  |                                                                           |
  56.  |                  Container Manager Debugging Operations                   |
  57.  |                                                                           |
  58.  |                               Ira L. Ruben                                |
  59.  |                                 4/23/92                                   |
  60.  |                                                                           |
  61.  |                    Copyright Apple Computer, Inc. 1992-1994               |
  62.  |                           All rights reserved.                            |
  63.  |                                                                           |
  64.  *---------------------------------------------------------------------------*
  65.  
  66.  This file defines a set of special debugging API routines.  They are kept separate from
  67.  the API (and undocumented) since they may or may not be supported in a particular
  68.  installation.
  69.  
  70.  There are three routines:
  71.  
  72.      1. CMDebugging()                    - to set some internal debugging "options"
  73.     2. CMDumpTOCStructures()    - to dump in-memory TOC as a tree-like format
  74.     3. CMDumpContainerTOC()        - to read in container TOC and display it in a table format
  75.  
  76.  The CMDebugging() routine is under control of the CMDEBUGGING switch macro.  The 
  77.  installer may suppress this functionality by setting this macro to 0 (its default).
  78.  
  79.  Similarly, the other routines are under control of the CMDUMPTOC switch.
  80.  
  81.  The switches are defined in CMTypes.h.
  82. */
  83.  
  84.  
  85. #include <stddef.h>
  86. #include <stdio.h>
  87. #include <string.h>
  88. #include <stdarg.h>
  89. #include <limits.h>
  90.  
  91. #ifndef __CMTYPES__
  92. #include "CMTypes.h"
  93. #endif
  94. #ifndef __CM_API_DEBUG__
  95. #include "CMAPIDbg.h"
  96. #endif
  97. #ifndef __CM_API__
  98. #include "CMAPI.h"
  99. #endif
  100. #ifndef __LISTMGR__
  101. #include "ListMgr.h"
  102. #endif
  103. #ifndef __TOCENTRIES__
  104. #include "TOCEnts.h"   
  105. #endif
  106. #ifndef __TOCOBJECTS__
  107. #include "TOCObjs.h"   
  108. #endif
  109. #ifndef __TOCIO__
  110. #include "TOCIO.h"
  111. #endif
  112. #ifndef __CONTAINEROPS__
  113. #include "Containr.h"  
  114. #endif
  115. #ifndef __HANDLERS__
  116. #include "Handlers.h"
  117. #endif
  118. #ifndef __UPDATING__
  119. #include "Update.h"  
  120. #endif
  121. #ifndef __REFERENCES__
  122. #include "Refs.h"      
  123. #endif
  124. #ifndef __ERRORRPT__
  125. #include "ErrorRpt.h"      
  126. #endif
  127. #ifndef __SESSIONDATA__
  128. #include "Session.h"          
  129. #endif
  130. #ifndef __UTILITYROUTINES__
  131. #include "Utility.h"        
  132. #endif
  133.  
  134.                                                                     CM_CFUNCTIONS
  135.  
  136. /* The following generates a segment directive for Mac only due to 32K Jump Table             */
  137. /* Limitations.  If you don't know what I'm talking about don't worry about it.  The        */
  138. /* default is not to generate the pragma.  Theoritically unknown pragmas in ANSI won't    */
  139. /* choke compilers that don't recognize them.  Besides why would they be looked at if        */
  140. /* it's being conditionally skipped over anyway?  I know, famous last words!                        */
  141.  
  142. #if CM_MPW
  143. #pragma segment Debugging
  144. #endif
  145.  
  146.  
  147. #if CMDEBUGGING || CMDUMPTOC
  148. /*------------------------------*
  149.  | display - isolate all output |
  150.  *------------------------------*
  151.  
  152.  In some environments it may be more desirable (or necessary) to handle I/O specially. To
  153.  that end this routine is provided.  All the debug printing goes through  here.  It's
  154.  parameters are identical to fprintf(), with the same meaning.  So, as delivered, in its
  155.  simplest form, this routine maps into a fprintf().  Feel free to "warp" this routine into
  156.  somthing appropriate to your system.
  157. */
  158.  
  159. static void CM_NEAR CM_C display(FILE *stream, const CM_CHAR *format, ...)
  160. {
  161.     va_list ap;
  162.     
  163.     va_start(ap, format);
  164.     vfprintf(stream, format, ap);
  165.     va_end(ap);
  166. }
  167. #endif
  168.  
  169.  
  170. #if CMDEBUGGING
  171. /*------------------------------------------------*
  172.  | CMDebugging - set internal debugging "options" |
  173.  *------------------------------------------------*
  174.  
  175.  This is an undocumented (except for what you're reading now) routine to allow me (the
  176.  idiot who got stuck coding this stuff) to do some debugging.  It is called AFTER 
  177.  CMStartSession() but BEFORE any containers are opened.  It takes the session global data
  178.  pointer returned by CMStartSession() and adds (actually modifies) some of the data there
  179.  to enable debugging.
  180.  
  181.  The current data that can be set is:
  182.  
  183.          1. The size of the TOC index tables.  If 0 is passed, the default is used.  The
  184.              current implementation of the TOC uses an index table mechanism with the tables
  185.              each being tocTableSize entries long.  See  TOCObjs.c   and .h for further details.
  186.         
  187.         2. A FILE* debugging output variable.  It is usually stdout, stderr, or NULL.  For NULL
  188.              no debugging output is produced.  Currently this thing is used to display the TOC as
  189.              a table when it is open for input.
  190.              
  191.         3. The dynamic switch controlling the refNum validations (e.g., checking for NULL) and
  192.              various other protections.  If set to 0 the protection checks are suppressed.  If
  193.              nonzero they are performed, but only if the protection code is present.  On a per-
  194.              installation basis it may be suppressed.  In that case the switch has no effect.
  195.  
  196.  The entire routine may be suppressed, which it is by default, by setting the macro
  197.  variable CMDEBUGGING to 0.
  198. */
  199.  
  200. void CM_FIXEDARGS CMDebugging(CMSession sessionData, CM_USHORT tocTableSize, 
  201.                                                             FILE CM_PTR *debuggingFile, CMBoolean doValidations)
  202. {
  203.     CM_CHAR s1[10], s2[10];
  204.     #if !CMVALIDATE
  205.     CMBoolean unused = doValidations;
  206.     #endif
  207.     
  208.     if (sessionData != NULL) {
  209.         ((SessionGlobalDataPtr)sessionData)->cmDbgFile        = debuggingFile;                            
  210.         ((SessionGlobalDataPtr)sessionData)->cmTocTblSize = (CM_ULONG)tocTableSize;
  211.         
  212.         if (tocTableSize == 0)
  213.             ((SessionGlobalDataPtr)sessionData)->cmTocTblSize = DefaultIndexTableSize;
  214.         else if (tocTableSize < MinIndexTableSize || tocTableSize > MaxIndexTableSize) {
  215.             SessionERROR2(CM_err_BadTocSize, cmltostr(MinIndexTableSize, 1, false, s1),
  216.                                                                               cmltostr(MaxIndexTableSize, 1, false, s2));
  217.             ((SessionGlobalDataPtr)sessionData)->cmTocTblSize = DefaultIndexTableSize;
  218.         }
  219.         
  220.         #if CMVALIDATE
  221.         ((SessionGlobalDataPtr)sessionData)->validate = doValidations;
  222.         #endif
  223.     }
  224. }
  225. #endif
  226.  
  227.  
  228. #if CMDUMPTOC
  229. /*----------------------------------------------------*
  230.  | showTouchedList - display an object's touched list |
  231.  *----------------------------------------------------*
  232.  
  233.  This is called by showObject() if there is a updating touch list for that object.  The
  234.  entire touch list is displayed.
  235. */
  236.  
  237. static void showTouchedList(TouchedListEntryPtr touch, CMRefCon refCon)
  238. {
  239.     FILE                      *f = (FILE *)refCon;
  240.     CM_USHORT             i, mask, touchFlags;
  241.     CM_CHAR               flagsMeaning[256];
  242.     
  243.     display(f, "\n                           --- Touched List ---\n");
  244.     
  245.     while (touch) {
  246.         touchFlags = touch->touchFlags;
  247.         
  248.         if (touchFlags == 0x0000U) 
  249.             *flagsMeaning = '\0';
  250.         else {
  251.             strcpy(flagsMeaning, " (");
  252.             
  253.             for (i = 0, mask = 1; i < 16; ++i, mask <<= 1) {
  254.                 if ((touchFlags & mask) == TouchedRemoved) {
  255.                     strcat(flagsMeaning, "TouchedRemoved/");
  256.                     continue;
  257.                 }
  258.                 if ((touchFlags & mask) == TouchedInserted) {
  259.                     strcat(flagsMeaning, "TouchedInserted/");
  260.                     continue;
  261.                 }
  262.                 if ((touchFlags & mask) == TouchedDeletedValue) {
  263.                     strcat(flagsMeaning, "TouchedDeletedValue/");
  264.                     continue;
  265.                 }
  266.                 if ((touchFlags & mask) == TouchedDeletedProperty) {
  267.                     strcat(flagsMeaning, "TouchedDeletedProperty/");
  268.                     continue;
  269.                 }
  270.                 if ((touchFlags & mask) == TouchedEdited) {
  271.                     strcat(flagsMeaning, "TouchedEdited/");
  272.                     continue;
  273.                 }
  274.                 if ((touchFlags & mask) == TouchedImmediate) {
  275.                     strcat(flagsMeaning, "TouchedImmediate/");
  276.                     continue;
  277.                 }
  278.                 if ((touchFlags & mask) == TouchedBaseType) {
  279.                     strcat(flagsMeaning, "TouchedBaseType/");
  280.                     continue;
  281.                 }
  282.                 if ((touchFlags & mask) == TouchedSetinfoed) {
  283.                     strcat(flagsMeaning, "TouchedSetinfoed/");
  284.                     continue;
  285.                 }
  286.             } /* for */
  287.             
  288.             strcpy(flagsMeaning + strlen(flagsMeaning) - 1, ")");
  289.         }
  290.         
  291.         display(f, "\n            0x%.8lX: theValueHdr  = 0x%.8lX\n"
  292.                              "                        touchFlags     = 0x%.4lX%s\n"
  293.                              "                        OPT          = 0x%.8lX/0x%.8lX/0x%.8lX = %ld/%ld/%ld\n"
  294.                              "                        removedEntry = 0x%.8lX\n",
  295.                              touch,
  296.                              touch->theValueHdr,
  297.                              touch->touchFlags, flagsMeaning,
  298.                              touch->objectID, touch->propertyID, touch->typeID, touch->objectID, touch->propertyID, touch->typeID,
  299.                              touch->removedEntry);
  300.         
  301.         touch = (TouchedListEntryPtr)cmGetNextListCell(touch);
  302.     } /* while */
  303.     
  304.     display(f, "\n                        --- end of touched list ---\n");
  305. }
  306.  
  307.  
  308. /*-----------------------------------------------------------------*
  309.  | showObject - action routine for displaying an object in the TOC |
  310.  *-----------------------------------------------------------------*
  311.  
  312.  This is a debugging routine used as the "action" parameter to cmWalkThroughEntireTOC()
  313.  calls to display selected info for an object in the TOC. The "refCon" here is expected to
  314.  be a file variable.
  315.  
  316.  Note, this "static" is intentionally left to default memory model under DOS since it is
  317.  passed as a function pointer to cmWalkThroughEntireTOC().
  318. */
  319.  
  320. static TOCWalkReturns showObject(ContainerPtr container, TOCObjectPtr theObject, CMRefCon refCon)
  321. {
  322.     ContainerPtr      unused = container;
  323.     FILE                      *f = (FILE *)refCon;
  324.     CM_USHORT             i, mask, objectFlags;
  325.     CM_CHAR               flagsMeaning[256];
  326.     
  327.     objectFlags  = theObject->objectFlags;
  328.     
  329.     if (objectFlags == 0x0000U) 
  330.         *flagsMeaning = '\0';
  331.     else {
  332.         strcpy(flagsMeaning, " (");
  333.         
  334.         for (i = 0, mask = 1; i < 16; ++i, mask <<= 1) {
  335.             if ((objectFlags & mask) == UndefinedObject) {
  336.                 strcat(flagsMeaning, "UndefinedObject/");
  337.                 continue;
  338.             }
  339.             if ((objectFlags & mask) == ObjectObject) {
  340.                 strcat(flagsMeaning, "ObjectObject/");
  341.                 continue;
  342.             }
  343.             if ((objectFlags & mask) == PropertyObject) {
  344.                 strcat(flagsMeaning, "PropertyObject/");
  345.                 continue;
  346.             }
  347.             if ((objectFlags & mask) == TypeObject) {
  348.                 strcat(flagsMeaning, "TypeObject/");
  349.                 continue;
  350.             }
  351.             if ((objectFlags & mask) == DeletedObject) {
  352.                 strcat(flagsMeaning, "DeletedObject/");
  353.                 continue;
  354.             }
  355.             if ((objectFlags & mask) == ProtectedObject) {
  356.                 strcat(flagsMeaning, "ProtectedObject/");
  357.                 continue;
  358.             }
  359.             if ((objectFlags & mask) == LinkedObject) {
  360.                 strcat(flagsMeaning, "LinkedObject/");
  361.                 continue;
  362.             }
  363.             if ((objectFlags & mask) == UndefObjectCounted) {
  364.                 strcat(flagsMeaning, "UndefObjectCounted/");
  365.                 continue;
  366.             }
  367.             if ((objectFlags & mask) == DynamicValuesObject) {
  368.                 strcat(flagsMeaning, "DynamicValuesObject/");
  369.                 continue;
  370.             }
  371.         } /* for */
  372.         
  373.         strcpy(flagsMeaning + strlen(flagsMeaning) - 1, ")");
  374.     }
  375.     
  376.     display(f, "---------------------------------------------\nTOCObject\n");
  377.     display(f, "0x%.8lX: objectID          = 0x%.8lX = %ld\n"
  378.                             "            container         = 0x%.8lX (%s) [%d]\n"
  379.                             "            nextObject        = 0x%.8lX\n"
  380.                             "            prevObject        = 0x%.8lX\n"
  381.                             "            nextTypeProperty  = 0x%.8lX\n"
  382.                             "            prevTypeProperty  = 0x%.8lX\n"
  383.                             "            nextTouchedObject = 0x%.8lX\n"
  384.                             "            objectFlags       = 0x%.4X%s\n",
  385.                             theObject,
  386.                             theObject->objectID, theObject->objectID,
  387.                             theObject->container, CONTAINERNAMEx(theObject->container), theObject->container->depth,
  388.                             theObject->nextObject,
  389.                             theObject->prevObject,
  390.                             theObject->nextTypeProperty,
  391.                             theObject->prevTypeProperty,
  392.                             theObject->nextTouchedObject,
  393.                             theObject->objectFlags, flagsMeaning);
  394.                             
  395.     if (!cmIsEmptyList(&theObject->touchedList))
  396.         showTouchedList((TouchedListEntryPtr)cmGetListHead(&theObject->touchedList), refCon);
  397.     
  398.     return (WalkNextTOCProperty);
  399. }
  400.  
  401.  
  402. /*---------------------------------------------------------------------*
  403.  | showProperty - action routine for displaying an property in the TOC |
  404.  *---------------------------------------------------------------------*
  405.  
  406.  This is a debugging routine used as the "action" parameter to cmWalkThroughEntireTOC() 
  407.  calls to display selected info for a property in the TOC. The "refCon" here is expected
  408.  to be a file variable.
  409.  
  410.  Note, this "static" is intentionally left to default memory model under DOS since it is
  411.  passed as a function pointer to cmWalkThroughEntireTOC().
  412. */
  413.  
  414. static TOCWalkReturns showProperty(ContainerPtr container, TOCPropertyPtr theProperty, CMRefCon refCon)
  415. {
  416.     ContainerPtr unused = container;    
  417.     FILE                 *f = (FILE *)refCon;
  418.     
  419.     display(f, "\n            TOCProperty\n"
  420.                          "            0x%.8lX: propertyID = 0x%.8lX = %ld\n"
  421.                          "                        theObject  = 0x%.8lX\n",
  422.                          theProperty,
  423.                          theProperty->propertyID, theProperty->propertyID,
  424.                          theProperty->theObject);
  425.  
  426.     return (WalkNextTOCValueHdr);
  427. }
  428.  
  429.  
  430. /*------------------------------------------------------------------------*
  431.  | showValueHdr - action routine for displaying a value header in the TOC |
  432.  *------------------------------------------------------------------------*
  433.  
  434.  This is a debugging routine used as the "action" parameter to cmWalkThroughEntireTOC()
  435.  calls to display selected info for a value header in the TOC. The "refCon" here is
  436.  expected to be a file variable.
  437.  
  438.  Note, this "static" is intentionally left to default memory model under DOS since it is
  439.  passed as a function pointer to cmWalkThroughEntireTOC().
  440. */
  441.  
  442. static TOCWalkReturns showValueHdr(ContainerPtr container, TOCValueHdrPtr theValueHdr, CMRefCon refCon)
  443. {
  444.     FILE                      *f = (FILE *)refCon;
  445.     CM_USHORT             i, mask, valueFlags;
  446.     CM_CHAR                 *extensions, *refs, *shadowListStatus = "", flagsMeaning[256];
  447.     ContainerPtr      unused = container;
  448.     #if CMSHADOW_LIST
  449.     RefDataShadowEntryPtr r = NULL;
  450.     #endif
  451.     
  452.     valueFlags = theValueHdr->valueFlags;
  453.     
  454.     if (valueFlags & ValueDynamic)
  455.         extensions = "extensions   ";
  456.     else
  457.         extensions = "dynValue     ";
  458.     
  459.     #if CMSHADOW_LIST
  460.     if (HasRefDataObject(theValueHdr))
  461.         refs = "refDataObject";
  462.     else if (theValueHdr->typeID == CM_StdObjID_ObjRefData) {
  463.         refs = "refShadowList";
  464.         if (RefShadowList(theValueHdr) != NULL) {
  465.             r = (RefDataShadowEntryPtr)cmGetListHead(RefShadowList(theValueHdr));
  466.             shadowListStatus = (r == NULL) ? " (<empty>)" : "";
  467.         }
  468.     } else
  469.         refs = "refDataObject";
  470.     #else
  471.     refs = "refDataObject";
  472.     #endif
  473.     
  474. #if !CMKEEP_CONTINUE_FLAG
  475.     if (cmCountListCells(&theValueHdr->valueList) > 1)
  476.         valueFlags |= ValueContinued;
  477.     else
  478.         valueFlags &= ~ValueContinued;
  479. #endif
  480.  
  481.     if (valueFlags == 0x0000U)
  482.         *flagsMeaning = '\0';
  483.     else {
  484.         strcpy(flagsMeaning, " (");
  485.         
  486.         for (i = 0, mask = 1; i < 16; ++i, mask <<= 1) {
  487.             if ((theValueHdr->valueFlags & mask) == ValueDeleted) {
  488.                 strcat(flagsMeaning, "ValueDeleted/");
  489.                 continue;
  490.             }
  491.             if ((theValueHdr->valueFlags & mask) == ValueContinued) {
  492.                 strcat(flagsMeaning, "ValueContinued/");
  493.                 continue;
  494.             }
  495.             if ((theValueHdr->valueFlags & mask) == ValueGlobal) {
  496.                 strcat(flagsMeaning, "ValueGlobal/");
  497.                 continue;
  498.             }
  499.             if ((theValueHdr->valueFlags & mask) == ValueImmediate) {
  500.                 strcat(flagsMeaning, "ValueImmediate/");
  501.                 continue;
  502.             }
  503.             if ((theValueHdr->valueFlags & mask) == ValueOffPropChain) {
  504.                 strcat(flagsMeaning, "ValueOffPropChain/");
  505.                 continue;
  506.             }
  507.             if ((theValueHdr->valueFlags & mask) == ValueDynamic) {
  508.                 strcat(flagsMeaning, "ValueDynamic/");
  509.                 continue;
  510.             }
  511.             if ((theValueHdr->valueFlags & mask) == ValueUndeletable) {
  512.                 strcat(flagsMeaning, "ValueUndeletable/");
  513.                 continue;
  514.             }
  515.             if ((theValueHdr->valueFlags & mask) == ValueProtected) {
  516.                 strcat(flagsMeaning, "ValueProtected/");
  517.                 continue;
  518.             }
  519.             if ((theValueHdr->valueFlags & mask) == ValueDefined) {
  520.                 strcat(flagsMeaning, "ValueDefined/");
  521.                 continue;
  522.             }
  523.         } /* for */
  524.         
  525.         strcpy(flagsMeaning + strlen(flagsMeaning) - 1, ")");
  526.     }
  527.     
  528.     display(f, "\n                        TOCValueHdr\n"
  529.                          "                        0x%.8lX: typeID        = 0x%.8lX = %ld\n"
  530.                          "                                    theProperty   = 0x%.8lX\n"
  531.                          "                                    container     = 0x%.8lX (%s) [%d]\n"
  532.                          "                                    size          = 0x%.8lX = %ld\n"
  533.                          "                                    logicalSize   = 0x%.8lX = %ld\n"
  534.                          "                                    generation    = 0x%.8lX\n",
  535.                          theValueHdr,
  536.                          theValueHdr->typeID, theValueHdr->typeID,
  537.                          theValueHdr->theProperty,
  538.                          theValueHdr->container, CONTAINERNAMEx(theValueHdr->container), theValueHdr->container->depth,
  539.                          theValueHdr->size, theValueHdr->size,
  540.                          theValueHdr->logicalSize, theValueHdr->logicalSize,
  541.                          theValueHdr->generation);
  542.     display(f, "                                    useCount      = 0x%.8lX\n"
  543.                          "                                    valueRefCon   = 0x%.8lX\n"
  544.                          "                                    touch         = 0x%.8lX\n"
  545.                          "                                    %s = 0x%.8lX\n"
  546.                          "                                    %s = 0x%.8lX%s\n"
  547.                          "                                    valueFlags    = 0x%.4X%s\n",
  548.                          theValueHdr->useCount,
  549.                          theValueHdr->valueRefCon,
  550.                          theValueHdr->touch,
  551.                          extensions, DYNEXTENSIONS(theValueHdr),
  552.                          refs, RefDataObject(theValueHdr), shadowListStatus,
  553.                          theValueHdr->valueFlags, flagsMeaning);
  554.     
  555.     if (theValueHdr->valueFlags & ValueDynamic)
  556.         display(f, "                        Extensions: baseValue     = 0x%.8lX\n",
  557.                              DYNEXTENSIONS(theValueHdr)->baseValue);
  558.     
  559.     #if CMSHADOW_LIST
  560.     if (r != NULL) {
  561.         display(f, "\n                                                    Key      Object ID\n"
  562.                              "                        Shadow List: 0x%.8lX: 0x%.8lX  0x%.8lX = %ld\n",
  563.                              r, r->key, r->objectID, r->objectID);
  564.         r = (RefDataShadowEntryPtr)cmGetNextListCell(r);
  565.         if (r == NULL)
  566.             display(f, "                        0x%.8lX\n", RefShadowList(theValueHdr));
  567.         else {
  568.             display(f, "                        0x%.8lX   0x%.8lX: 0x%.8lX  0x%.8lX = %ld\n",
  569.                                  RefShadowList(theValueHdr), r, r->key, r->objectID, r->objectID);
  570.             r = (RefDataShadowEntryPtr)cmGetNextListCell(r);
  571.         }
  572.         while (r) {
  573.             display(f, "                                     0x%.8lX: 0x%.8lX  0x%.8lX = %ld\n",
  574.                                  r, r->key, r->objectID, r->objectID);
  575.             r = (RefDataShadowEntryPtr)cmGetNextListCell(r);
  576.         }
  577.     } /* r */
  578.     #endif
  579.     
  580.     if (!cmIsEmptyList(&theValueHdr->valueList))
  581.         display(f, "\n");
  582.  
  583.     return (WalkNextTOCValue);
  584. }
  585.  
  586.  
  587. /*--------------------------------------------------------------*
  588.  | showValue - action routine for displaying a value in the TOC |
  589.  *--------------------------------------------------------------*
  590.  
  591.  This is a debugging routine used as the "action" parameter to cmWalkThroughEntireTOC()
  592.  calls to display selected info for a value in the TOC.  The "refCon" here is expected to
  593.  be a file variable.
  594.  
  595.  Note, this "static" is intentionally left to default memory model under DOS since it is
  596.  passed as a function pointer to cmWalkThroughEntireTOC().
  597. */
  598.  
  599. static TOCWalkReturns showValue(ContainerPtr container, TOCValuePtr theValue, CMRefCon refCon)
  600. {
  601.     ContainerPtr      unused = container;    
  602.     FILE                      *f = (FILE *)refCon;
  603.     CM_ULONG             i, value4, valueLen;
  604.     CM_USHORT             mask, flags;
  605.     CM_CHAR               *s, valueChars[5], flagsMeaning[256];
  606.     CM_UCHAR             *b;
  607.     
  608.     flags = theValue->flags;
  609. #if !CMKEEP_CONTINUE_FLAG
  610.     if (cmGetNextListCell(theValue))
  611.         flags |= kCMContinued;
  612.     else
  613.         flags &= ~kCMContinued;
  614. #endif
  615.     
  616.     if (flags == 0x0000U)
  617.         *flagsMeaning = '\0';
  618.     else {    
  619.         strcpy(flagsMeaning, " (");
  620.         
  621.         for (i = 0, mask = 1; i < 16; ++i, mask <<= 1) {
  622.             if ((flags & mask) == kCMImmediate) {
  623.                 strcat(flagsMeaning, "kCMImmediate/");
  624.                 continue;
  625.             }
  626.             if ((flags & mask) == kCMContinued) {
  627.                 strcat(flagsMeaning, "kCMContinued/");
  628.                 continue;
  629.             }
  630.             if ((flags & mask) == kCMDynValue) {
  631.                 strcat(flagsMeaning, "kCMDynValue/");
  632.                 continue;
  633.             }
  634.             if ((flags & mask) == kCMGlobalName) {
  635.                 strcat(flagsMeaning, "kCMGlobalName/");
  636.                 continue;
  637.             }
  638.         } /* for */
  639.         
  640.         strcpy(flagsMeaning + strlen(flagsMeaning) - 1, ")");
  641.     }
  642.     
  643.     display(f, "                                    TOCValue\n"
  644.                          "                                    0x%.8lX: theValueHdr     = 0x%.8lX\n"
  645.                          "                                                flags           = 0x%.4X%s\n"
  646.                          "                                                container       = 0x%.8lX (%s) [%d]\n"
  647.                          "                                                logicalOffset   = 0x%.8lX = %ld\n",
  648.                          theValue,
  649.                          theValue->theValueHdr,
  650.                          theValue->flags, flagsMeaning,
  651.                          theValue->container, CONTAINERNAMEx(theValue->container), theValue->container->depth,
  652.                          theValue->logicalOffset, theValue->logicalOffset);
  653.                             
  654.     if (theValue->flags & kCMGlobalName)
  655.         display(f, "                                                offset          = 0x%.8lX\n"
  656.                              "                                                globalNameSymbol= 0x%.8lX\n"
  657.                              "                                                \"%s\"\n",
  658.                              theValue->value.globalName.offset, theValue->value.globalName.globalNameSymbol,
  659.                              theValue->value.globalName.globalNameSymbol ? GetGlobalName(theValue->value.globalName.globalNameSymbol)
  660.                                                                                                                       : "????");
  661.     else {
  662.         valueLen = theValue->value.notImm.valueLen;
  663.         value4   = theValue->value.notImm.value;
  664.         
  665.         if (flags & kCMImmediate) {
  666.             for (i = 0, b = (CM_UCHAR *)&value4, s = valueChars; i < valueLen; ++i, ++b)
  667.                 *s++ = (CM_CHAR)((*b < (CM_UCHAR)' ' ||  *b > (CM_UCHAR)126) ? '.' : (*b));
  668.             *s = '\0';
  669.             
  670.             if (valueLen == 1)
  671.                 value4 >>= 3 * CHAR_BIT;
  672.             else if (valueLen == 2)
  673.                 value4 >>= 2 * CHAR_BIT;
  674.             else  if (valueLen == 3)
  675.                 value4 >>= 1 * CHAR_BIT;
  676.             
  677.             display(f, "                                                value           = 0x%.*lX = '%s' = %ld\n"
  678.                                  "                                                length          = 0x%.8lX = %ld\n",
  679.                                  (int)(valueLen * 2), value4, valueChars, value4,
  680.                                  valueLen, valueLen);
  681.         } else
  682.             display(f, "                                                value           = 0x%.8lX = %ld\n"
  683.                                  "                                                length          = 0x%.8lX = %ld\n",
  684.                                  value4, value4,
  685.                                  valueLen, valueLen);
  686.     }
  687.     
  688.     return (WalkNextTOCValue);
  689. }
  690.  
  691.  
  692. /*-------------------------------------------------------------------------*
  693.  | CMDumpTOCStructures - dump all the TOC structures to the specified file |
  694.  *-------------------------------------------------------------------------*
  695.  
  696.  This routine is used for internal debugging of the TOC data structures for the specified
  697.  container.  It displays their current state to the (open) file associated with the
  698.  specified file variable, f.
  699. */
  700.  
  701. void CM_FIXEDARGS CMDumpTOCStructures(CMContainer container, FILE CM_PTR *f)
  702. {
  703.     display(f, "\nTOC for type \"%s\" (%s) [%d]...\n\n", TYPENAME, CONTAINERNAME, ((ContainerPtr)container)->depth);
  704.     cmWalkThroughEntireTOC((ContainerPtr)container, ((ContainerPtr)container)->toc,
  705.                                                     ALLOBJECTS, MAXUSERID, f,
  706.                                                     showObject, showProperty, showValueHdr, showValue);
  707.     
  708.     if (((ContainerPtr)container)->usingTargetTOC) {
  709.         display(f, "\n\nPrivate TOC for type \"%s\" (%s)...\n\n", TYPENAME, CONTAINERNAME);
  710.         cmWalkThroughEntireTOC((ContainerPtr)container, ((ContainerPtr)container)->privateTOC,
  711.                                                         ALLOBJECTS, MAXUSERID, f,
  712.                                                         showObject, showProperty, showValueHdr, showValue);
  713.     }
  714.     
  715.     display(f, "\n");
  716. }
  717.  
  718.  
  719. #if TOC1_SUPPORT
  720. /*-----------------------------------------------------------------------------*
  721.  | dumpContainerTOCfmt1 - dump the format 1 TOC as it appears in the container |
  722.  *-----------------------------------------------------------------------------*
  723.  
  724.  This routine is used for internal debugging of the format 1 TOC data as it appears in its
  725.  final form in the container itself.  The entire TOC in the container, starting at 
  726.  container offset tocOffset for tocSize bytes, is displayed to the (open) file associated
  727.  with the file variable f.  It is formatted, but otherwise unchanged.  You can use this
  728.  routine to see if the TOC was correctly written to its container.
  729.  
  730.  Note, the container's handler routines are used to do the positioning and reading.
  731. */
  732.  
  733. static void CM_NEAR dumpContainerTOCfmt1(CMconst_CMContainer container, FILE CM_PTR *f,
  734.                                                                                    const CM_ULONG tocOffset, const CM_ULONG tocSize)
  735. {    
  736.     CM_ULONG           objectID, propertyID, typeID;
  737.     TOCValueBytes  value;
  738.     CM_USHORT             generation, flags;
  739.     CM_UCHAR             tocBuffer[TOCentrySize];
  740.     CM_ULONG           size      = (CM_ULONG)tocSize,
  741.                                  offset    = (CM_ULONG)tocOffset,
  742.                                  relOffset = 0;
  743.     
  744.     display(f, "\nTOC for type \"%s\" (%s)...\n\n", TYPENAME, CONTAINERNAME);
  745.     
  746.     display(f, "              | objectID |propertyID|  typeID  |  value   |  length  | gen  |flags |\n"
  747.                          "              +----------+----------+----------+----------+----------+------+------+\n");
  748.     
  749.     /* Position to the start of the TOC...                                                                                                */
  750.     
  751.     CMfseek(container, tocOffset, kCMSeekSet);
  752.     
  753.     while (size > 0) {                                            /* for each entry in the container's TOC...        */
  754.         if (CMfread(container, tocBuffer, sizeof(CM_UCHAR), TOCentrySize) != TOCentrySize) {
  755.             display(f, "### Read error in cmDumpContainerTOC()\n");
  756.             return;
  757.         }
  758.         
  759.         ExtractTOC(tocBuffer, objectID, propertyID, typeID, value.notImm.value,
  760.                                                     value.notImm.valueLen, generation, flags);
  761.                 
  762.         display(f, "%.8lX:%.4lX | %.8lX | %.8lX | %.8lX | %.8lX | %.8lX | %.4X | %.4X |\n",
  763.                                          offset, relOffset, objectID, propertyID, typeID, value.notImm.value,
  764.                                          value.notImm.valueLen, generation, flags);
  765.         
  766.         offset    += TOCentrySize;
  767.         relOffset += TOCentrySize;
  768.  
  769.         size      -= TOCentrySize;                        /* count down the size                                                */
  770.     } /* while */
  771.  
  772.     display(f, "%.8lX:%.4lX +----------+----------+----------+----------+----------+------+------+\n\n",
  773.                           offset, relOffset);
  774. }
  775. #endif
  776.  
  777.  
  778. /*------------------------------------------------------------------*
  779.  | CMDumpContainerTOC - dump the TOC as it appears in the container |
  780.  *------------------------------------------------------------------*
  781.  
  782.  This routine is used for internal debugging of the TOC data as it appears in its final
  783.  form in the container itself.  The entire TOC in the container, starting at container
  784.  offset tocOffset for tocSize bytes, is displayed to the (open) file associated with the
  785.  file variable f.  It is formatted, but otherwise  unchanged.  You can use this routine to
  786.  see if the TOC was correctly written to its container.
  787.  
  788.  Note, the container's handler routines are used to do the positioning and reading.
  789. */
  790.  
  791. void CM_FIXEDARGS CMDumpContainerTOC(CMconst_CMContainer container, FILE CM_PTR *f,
  792.                                                                         const CM_ULONG tocOffset, const CM_ULONG tocSize)
  793. {    
  794.     TOCentry             tocEntry;
  795.     CM_ULONG           refsDataObjectID;
  796.     CM_ULONG             prevObjectID, prevPropertyID, prevTypeID;
  797.     CM_ULONG           offset, relOffset;
  798.     void                      *tocIOCtl;
  799.     jmp_buf                 dumpEnv;
  800.     
  801.     USE_TOC_FORMAT_1_ALTERNATIVE1(dumpContainerTOCfmt1,(container, f, tocOffset, tocSize));
  802.     
  803.     /* Display the format 2 TOC.  Information is not repeated if it it wasn't repeated in */
  804.     /* the actual TOC.                                                                                                                                        */
  805.     
  806.     if (setjmp(dumpEnv))                                         /* set setjmp/longjmp environment vector            */
  807.         return;                                                                /* ...just quit if there's a TOC input error    */
  808.  
  809.     /* Position to the start of the TOC...                                                                                                */
  810.     
  811.     CMfseek(container, tocOffset, kCMSeekSet);
  812.     
  813.     /* Create the TOC I/O control block and its buffer...                                                                    */
  814.     
  815.     tocIOCtl = cmStartTOCIO((ContainerPtr)container, ((ContainerPtr)container)->tocBufSize,
  816.                                                     (jmp_buf *)&dumpEnv, tocOffset, tocSize);
  817.     if (tocIOCtl == NULL) return;
  818.     
  819.     prevObjectID = prevPropertyID = prevTypeID = 0x00000000UL;
  820.     
  821.     display(f, "\nTOC for type \"%s\" (%s)...\n\n", TYPENAME, CONTAINERNAME);
  822.     
  823.     display(f, "              | objectID |propertyID|  typeID  |generation|  value   |  length  |flags |  Ref ID  |\n"
  824.                          "              +----------+----------+----------+----------+----------+----------+------+----------+\n");
  825.     
  826.     /* Read the entire TOC and display it in the following loop...                                                */
  827.     
  828.     while (cmRead1TOCSegment(tocIOCtl, &tocEntry, &refsDataObjectID)) {
  829.         offset = SESSION->currTOCoffset;
  830.         relOffset = offset - tocOffset;
  831.         display(f, "%.8lX:%.4lX ", offset, relOffset);
  832.         
  833.         if (tocEntry.objectID != prevObjectID) {
  834.             prevObjectID      = tocEntry.objectID;
  835.             prevPropertyID = tocEntry.propertyID;
  836.             prevTypeID        = tocEntry.typeID;
  837.             display(f, "| %.8lX | %.8lX | %.8lX | ", tocEntry.objectID, tocEntry.propertyID, tocEntry.typeID);
  838.         } else if (tocEntry.propertyID != prevPropertyID) {
  839.             prevPropertyID = tocEntry.propertyID;
  840.             prevTypeID     = tocEntry.typeID;
  841.             display(f, "|          | %.8lX | %.8lX | ", tocEntry.propertyID, tocEntry.typeID);
  842.         } else if (tocEntry.typeID != prevTypeID) {
  843.             prevTypeID = tocEntry.typeID;
  844.             display(f, "|          |          | %.8lX | ", tocEntry.typeID);
  845.         } else {
  846.             display(f, "|          |          |          | ");
  847.         }
  848.         
  849.         if (SESSION->gotExplicitGen) {
  850.             display(f, "%.8lX | ", tocEntry.generation);
  851.         } else
  852.             display(f, "         | ");
  853.         
  854.         display(f, "%.8lX | %.8lX | %.4X | ", tocEntry.value.notImm.value, tocEntry.value.notImm.valueLen, tocEntry.flags);
  855.         
  856.         if (refsDataObjectID == 0x00000000UL)
  857.             display(f, "         |\n");
  858.         else
  859.             display(f, "%.8lX |\n", refsDataObjectID);
  860.     } /* while */
  861.     
  862.     offset = SESSION->currTOCoffset;
  863.     relOffset = offset - tocOffset;
  864.     display(f, "%.8lX:%.4lX +----------+----------+----------+----------+----------+----------+------+----------+\n\n",
  865.                             offset, relOffset);
  866.     
  867.     (void)cmEndTOCIO(tocIOCtl);
  868. }
  869. #endif 
  870.                                                           CM_END_CFUNCTIONS
  871.