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

  1. /* @(#)Z 1.4 com/src/cm/CMErrOps.c, odstorage, od96os2, odos29712d 97/03/21 17:19:31 (96/10/29 09:16:36) */
  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:        CMErrOps.c
  31.  
  32.     Contains:    Container Manager Error Handler Support Operations
  33.  
  34.     Written by:    Ira L. Ruben
  35.  
  36.     Owned by:    Ed Lai
  37.  
  38.     Copyright:    ⌐ 1991-1994 by Apple Computer, Inc., all rights reserved.
  39.  
  40.     Change History (most recent first):
  41.  
  42.          <3>     8/24/95    EL        1274602, 1277989: bad container name when
  43.                                     deleting object with use count > 1.
  44.          <2>     8/26/94    EL        #1181622 Ownership update.
  45.          <1>      2/3/94    EL        first checked in
  46.  
  47.     To Do:
  48. */
  49.  
  50. /*---------------------------------------------------------------------------*
  51.  |                                                                           |
  52.  |                        <<<     CMErrOps.c      >>>                        |
  53.  |                                                                           |
  54.  |            Container Manager Error Handler Support Operations             |
  55.  |                                                                           |
  56.  |                               Ira L. Ruben                                |
  57.  |                                 12/06/91                                  |
  58.  |                                                                           |
  59.  |                  Copyright Apple Computer, Inc. 1991-1994                 |
  60.  |                           All rights reserved.                            |
  61.  |                                                                           |
  62.  *---------------------------------------------------------------------------*
  63.  
  64.  All the routines in this file deal with error reporting.  They are provided as a
  65.  convenience to allow the user (usually a handler writer) to convert error codes (defined
  66.  in CMAPIErr.h) to their corresponding message strings.
  67. */
  68.  
  69.  
  70. #include <stddef.h>
  71. #include <stdarg.h>
  72. #include <ctype.h>
  73. #include <string.h>
  74. #include <stdio.h>
  75.  
  76. #ifndef __CMTYPES__
  77. #include "CMTypes.h"
  78. #endif
  79. #ifndef __CM_API_TYPES__
  80. #include "CMAPITyp.h"
  81. #endif
  82. #ifndef __CM_API__
  83. #include "CMAPI.h"
  84. #endif
  85. #ifndef __TOCENTRIES__
  86. #include "TOCEnts.h"   
  87. #endif
  88. #ifndef __TOCOBJECTS__
  89. #include "TOCObjs.h"   
  90. #endif
  91. #ifndef __CONTAINEROPS__
  92. #include "Containr.h"  
  93. #endif
  94. #ifndef __SESSIONDATA__
  95. #include "Session.h"          
  96. #endif
  97. #ifndef __ERRORRPT__
  98. #include "ErrorRpt.h"      
  99. #endif
  100. #ifndef __UTILITYROUTINES__
  101. #include "Utility.h"        
  102. #endif
  103.                                                                     
  104.                                                                     CM_CFUNCTIONS
  105.  
  106. /* The following generates a segment directive for Mac only due to 32K Jump Table             */
  107. /* Limitations.  If you don't know what I'm talking about don't worry about it.  The        */
  108. /* default is not to generate the pragma.  Theoritically unknown pragmas in ANSI won't    */
  109. /* choke compilers that don't recognize them.  Besides why would they be looked at if        */
  110. /* it's being conditionally skipped over anyway?  I know, famous last words!                        */
  111.  
  112. #if CM_MPW
  113. #pragma segment CMErrorHandlerOps
  114. #endif
  115.  
  116.  
  117. #define MaxMsgLen 1024                                        /* no msg should be bigger than this                    */
  118.  
  119.  
  120. /*------------------------------------------*
  121.  | my_strtoul - parse a integer in a string |
  122.  *------------------------------------------*
  123.  
  124.  This routine is my private implementation of the standard ANSII library routine strtoul().
  125.  It taks a pointer to a string which is assumed to be pointing at some digits and returns
  126.  the resulting integer.  The pointer to the character that stopped the scan is returned
  127.  in endptr.
  128.  
  129.  This routine is coded here for the following reasons:
  130.  
  131.          (1).  strtoul() is a ANSI standard routine which another installation might not have
  132.                     if they don't have a full ANSI runtime library.
  133.                     
  134.         (2).  I don't need all the generality of strtoul().  The base is always assumed as 10
  135.                     here and endptr is never NULL.
  136.                     
  137.         (3).    There is a bug in the Mac MPW strtoul() routine!  Ah-ha, the REAL reason!  It 
  138.                     seems that MPW's strtoul() treats characters as signed.  We could have characters
  139.                     with values larger than 127 in our strings.  This causes MPW's strtoul() to
  140.                     fail in wierd ways (like when it passes such charas to isalnum()).
  141. */
  142.  
  143. static CM_ULONG CM_NEAR my_strtoul(CM_CHAR *s, CM_CHAR **endptr)
  144. {
  145.     CM_ULONG    digit, value = 0;
  146.     
  147.     for (;;) {                                                        /* scan until we don't hit a digit...                        */
  148.         switch (*s) {                                                /* done this way to be *completely* portable!        */
  149.             case '0':    digit = 0; break;                /* yuk!     (there MUST be another way to do this)    */
  150.             case '1':    digit = 1; break;                /*        But it must be done WITHOUT assuming  */
  151.             case '2':    digit = 2; break;                /*                a character set ordering dependence!    */
  152.             case '3':    digit = 3; break;
  153.             case '4':    digit = 4; break;
  154.             case '5':    digit = 5; break;
  155.             case '6':    digit = 6; break;
  156.             case '7':    digit = 7; break;
  157.             case '8':    digit = 8; break;
  158.             case '9':    digit = 9; break;
  159.             default:    *endptr = s;                        /* return ptr to delimiting non-digit                        */
  160.                                 return (value);                    /* return collected value                                                */
  161.         } /* switch */
  162.         
  163.         value = value * 10 + digit;                    /* build up the (decimal) number                                */
  164.         ++s;                                                                /* ready to look at next character                            */
  165.     } /* for */
  166. }
  167.  
  168.  
  169. /*-------------------------------------------------------*
  170.  | CMAddMsgInserts - add all inserts to an error message |
  171.  *-------------------------------------------------------*
  172.  
  173.  This routine takes the (error) message string in msgString and replaces all substrings
  174.  of the form "^n" with the inserts from the variable arg list of insert strings.  The
  175.  function returns the edited msgString as its result.
  176.  
  177.  The string buffer must be passed in msgString.  Its max length is also specified but this
  178.  must be a value less than or equal 1024 (not including delimiting null). The message will
  179.  be truncated to fit in the buffer.  The string pointer is returned as the function
  180.  result.
  181.  
  182.  The substring "^0" is replaced with the first insert. "^1" is replaced with the second
  183.  insert, and so on.  It is assumed that there are enough insert strings to cover all the
  184.  "^n"s called for (not unlike printf()).
  185.  
  186.  Note, the "^n"s in the message string do not have to be in ascending order.  Thus "^1"
  187.  could occur before "^0" in the msgString.
  188. */
  189.  
  190. CM_CHAR CM_PTR * CM_VARARGS CMAddMsgInserts(CM_CHAR CM_PTR *msgString, CMSize maxLength, ...)
  191. {
  192.     va_list inserts;
  193.  
  194.     va_start(inserts, maxLength);
  195.     CMVAddMsgInserts(msgString, maxLength, inserts);
  196.     va_end(inserts);
  197.     
  198.     return (msgString);
  199. }
  200.  
  201.  
  202. /*--------------------------------------------------------*
  203.  | CMVAddMsgInserts - add all inserts to an error message |
  204.  *--------------------------------------------------------*
  205.  
  206.  This routine is the same as CMAddMsgInserts() above, except that the extra (insert) 
  207.  arguments are given as a variable argument list as defined by the "stdarg" facility.
  208.  
  209.  This routine assumes the caller sets up and terminates the variable arg list using the
  210.  "stdarg.h" calls as follows:
  211.  
  212.              #include <stdarg.h>
  213.             
  214.              callersRoutine(args, ...)
  215.             {
  216.                 va_list inserts;
  217.                 
  218.                 - - -
  219.                 
  220.                 va_start(inserts, args);
  221.                 CMVAddMsgInserts(msgString, maxLength, inserts);
  222.                 va_end(inserts);
  223.                 
  224.                 - - -
  225.             }
  226.             
  227.  See CMAddMsgInserts() for further details.
  228. */
  229.  
  230. CM_CHAR CM_PTR * CM_FIXEDARGS CMVAddMsgInserts(CM_CHAR CM_PTR *msgString, CMSize maxLength,
  231.                                                                                            va_list inserts)
  232. {
  233.     CM_CHAR              c, *src, *dst, *p, *insert, msgString0[MaxMsgLen];
  234.     CM_ULONG            cnt = (unsigned long)maxLength;
  235.     CM_LONG                n;
  236.     va_list             inserts0 = inserts;
  237.     
  238.     src = strcpy(msgString0, (dst = msgString));
  239.     
  240.     while (((CMBoolean)(c = *src++)) && cnt > 0) {/* scan src buffer for "^n"s...                        */
  241.         if (c != '^') {                                                        /* if we don't hace an "^n"...                        */
  242.             *dst++ = c;                                                            /* ...just copy src to dst (output) buffer*/
  243.             --cnt;                                                                    /* ...make sure we don't exceed maxLen        */
  244.             continue;
  245.         }
  246.     
  247.         n = my_strtoul(src, &p);                                /* extract the insert number (n) from "^n"*/
  248.         if (p == src) {                                                        /* leave a lone "^" alone                                            */
  249.             *dst++ = c;                                                            /* ...they are treated like normal chars    */
  250.             --cnt;
  251.             continue;
  252.         }
  253.         
  254.         inserts = inserts0;                                                /* get n'th insert (there better be one!)    */
  255.         while (n-- >= 0)                                                    /* there's no way to chk that there isn't    */
  256.             insert = va_arg(inserts, CM_CHAR *);
  257.     
  258.         while (*insert && cnt > 0) {                            /* copy the insert to the dst buffer...     */
  259.             *dst++ = *insert++;
  260.             --cnt;                                                                    /* ..careful here too about going to far    */
  261.         }
  262.         
  263.         src = p;                                                                    /* point past "^n" in the input string        */
  264.     } /* while */                                                                /* keep scanning the src, copying to dst    */
  265.     
  266.     *dst = '\0';                                                                /* that's all there is to it!                            */
  267.     return (msgString);
  268. }
  269.  
  270.  
  271. #if 0 /* orignal code not used -- it's overkill (it's an insert-in-place algorithm) */
  272. /*--------------------------------------------------------*
  273.  | CMVAddMsgInserts - add all inserts to an error message |
  274.  *--------------------------------------------------------*
  275.  
  276.  This routine takes the (error) message string in msgString and replaces all substrings
  277.  of the form "^n" with the inserts from the variable arg list of insert strings.  The
  278.  function returns the edited msgString as its result.
  279.  
  280.  The string buffer must be passed in msgString.  Its max length is also specified but this
  281.  must be a value less than or equal 1024 (not including delimiting null). The message will
  282.  be truncated to fit in the buffer.  The string pointer is returned as the function
  283.  result.
  284.  
  285.  The substring "^0" is replaced with the first insert. "^1" is replaced with the second
  286.  insert, and so on.  It is assumed that there are enough insert strings to cover all the
  287.  "^n"s called for (not unlike printf()).
  288.  
  289.  Note, the "^n"s in the message string do not have to be in ascending order.  Thus "^1"
  290.  could occur before "^0" in the msgString.
  291. */
  292.  
  293. CM_CHAR CM_PTR * CM_FIXEDARGS CMVAddMsgInserts(CM_CHAR CM_PTR *msgString, CMSize maxLength,
  294.                                                                                            va_list inserts)
  295. {
  296.     CM_CHAR     *s, *p, *q, *x, *last, *insert, c;
  297.     CM_LONG        n;
  298.     CM_SHORT    msglen, inslen, signalLen, cnt;
  299.     va_list     inserts0 = inserts;
  300.     
  301.     s = msgString;                                                    /* get initial length and ptr to last char+1    */
  302.     while (*s++);
  303.     msglen = --s - msgString;
  304.     
  305.     while (--s > msgString) {                                /* scan msgString right-to-left for inserts...*/
  306.         if (*s != '^') continue;                            /* leave everything else along                                */
  307.         
  308.         n = my_strtoul(s+1, &x);                            /* extract the insert number                                    */
  309.         if (x == s + 1) continue;                            /* leave a lone "^" alone                                            */
  310.         signalLen = x - s;                                        /* this many chars must be replaced                        */
  311.         
  312.         inserts = inserts0;
  313.         while (n-- >= 0)                                            /* get the n'th insert (there better be one!)    */
  314.             insert = va_arg(inserts, CM_CHAR *);
  315.         inslen = strlen(insert);                            /* we need its length too                                            */
  316.         
  317.         cnt  = maxLen - msglen + signalLen;        /* accounts for deletion of the "^n" chars        */
  318.         
  319.         if (inslen > signalLen) {                            /* if expanding string with insert...                    */
  320.             p    = msgString + msglen;                    /* 1st position beyond end of current string    */
  321.             q      = p + inslen - signalLen;            /* q points to 1 beyond where to put last char*/
  322.             last = msgString + maxLen;                    /* 1 beyond the last char allowed in string        */
  323.             while (--p > s)                                         /* make room for insertion...                                    */ 
  324.                 if (--q < last) {                                    /* i.e., move chars right in insertion string    */
  325.                     *q = *p;
  326.                 } else                                                        /* we may have to truncate here!                            */
  327.                     cnt++;
  328.         } else if (inslen < signalLen) {            /* if contracting string for short insert...    */
  329.             q = s + signalLen;                                    /* ptr to the char immediately following "^n"    */
  330.             p = s + inslen;                                            /* ptr to end of inset (p < q)                                */ 
  331.             while (*p) *p++ = *q++;                            /* move chars left in msg string                            */
  332.         }
  333.         
  334.         p = s;
  335.         while (cnt && *insert) {                            /* insert the insert...                                             */
  336.             cnt--;
  337.             *p++ = *insert++;
  338.         }
  339.         
  340.         msglen = maxLen - cnt;                                /* update total length including insert                */
  341.         *(msgString + msglen) = '\0';                    /* add required null at end of msg string            */
  342.     } /* while */
  343.         
  344.     return (msgString);                                            /* return fully inserted msg string to caller    */
  345. }
  346. #endif
  347.  
  348.  
  349. /*---------------------------------------------------------------------------------------*
  350.  | CMGetErrorString - return CM (error) message string corresponding to a message number |
  351.  *---------------------------------------------------------------------------------------*
  352.  
  353.  This routine takes a defined Container Manager (error) message number and its
  354.  corresponding insert strings and returns a (english) string corresponding to the message
  355.  number with the inserts filled into their proper positions. It is assumed the error
  356.  number and inserts were the ones reported to the error handler. 
  357.  
  358.  The string buffer must be passed in errorString.  Its max length is also specified but
  359.  this must be a value less than or equal 1024 (not including delimiting null).  The
  360.  message will be truncated to fit in the buffer.  The string pointer is returned as the
  361.  function result.
  362.  
  363.  This routine is provided as a convenience to easily convert the error codes and their
  364.  corresponding inserts to a printable string.
  365. */
  366.  
  367. CMErrorString CM_VARARGS CMGetErrorString(CMErrorString errorString, CMSize maxLength, 
  368.                                                                                       CMErrorNbr errorNumber, ...)
  369. {
  370.     va_list inserts;
  371.  
  372.     va_start(inserts, errorNumber);
  373.     CMVGetErrorString(errorString, maxLength, errorNumber, inserts);
  374.     va_end(inserts);
  375.     
  376.     return (errorString);
  377. }
  378.  
  379.  
  380. /*----------------------------------------------------------------------------------------*
  381.  | CMVGetErrorString - return CM (error) message string corresponding to a message number |
  382.  *----------------------------------------------------------------------------------------*
  383.  
  384.  This routine is the same as CMGetErrorString() above, except that the extra (inserts) 
  385.  arguments are given as a variable argument list as defined by the "stdarg" facility.
  386.  
  387.  This routine assumes the caller sets up and terminates the variable arg list using the
  388.  "stdarg.h" calls as follows:
  389.  
  390.              #include <stdarg.h>
  391.             
  392.              callersRoutine(args, ...)
  393.             {
  394.                 va_list inserts;
  395.                 
  396.                 - - -
  397.                 
  398.                 va_start(inserts, args);
  399.                 CMVGetErrorString(errorString, maxLength, errorNumber, inserts);
  400.                 va_end(inserts);
  401.                 
  402.                 - - -
  403.             }
  404.             
  405.  See CMGetErrorString() for further details.
  406. */
  407.  
  408. CMErrorString CM_FIXEDARGS CMVGetErrorString(CMErrorString errorString, CMSize maxLength, 
  409.                                                                                         CMErrorNbr errorNumber, va_list inserts)
  410. {
  411.     CM_CHAR     *msgStr, msg[MaxMsgLen];
  412.     CM_CHAR        tmpStr[15];
  413.     CMBoolean    gotInserts = true;
  414.     
  415.     #define TheErrorList    switch (errorNumber) {
  416.     #define e0(n, s)                 case n:  msgStr = (CM_CHAR *)s; gotInserts = false; break
  417.     #define e1(n, s)                 case n:  msgStr = (CM_CHAR *)s; break
  418.     #define EndOfList(s)        default: msgStr = (CM_CHAR *)s; gotInserts = false; break;\
  419.                                                 }                                                                                                                 \
  420.                                                 strcpy((char *)msg, (char *)msgStr);
  421.     
  422.     /* To define a new error number and message, use the macro e1(n, s) if the string s     */
  423.     /* contains inserts.  Use e0(n, s) if there are no inserts.  DON'T FORGET TO UPDATE        */
  424.     /* CMErrno.h.                                                                                                                                                    */
  425.     
  426.     TheErrorList
  427.         /*----------------------------------------------------------------------------------*/
  428.         e1(CM_err_GenericMessage,     "^0");
  429.         e1(CM_err_BadTocSize,             "TOC index table size out of range (^0 <= range <= ^1)");
  430.         e1(CM_err_NoSession,                 "Unable to allocate session (task) global data");
  431.         e1(CM_err_NoHandler,                 "Cannot allocate space for handler for type \"^0\"");
  432.         e1(CM_err_BadWriteUse,            "Cannot do a CMOpenNewContainer(...^0...) with useFlags set for update-in-place");
  433.         e1(CM_err_NoContainer,            "Cannot allocate CCB space for type \"^0\"");
  434.         e1(CM_err_UndefMetaHandler, "Metahandler was not defined for type \"^0\"");
  435.         e1(CM_err_HandlerError,            "Allocation problem while looking up handler for type \"^0\"");
  436.         e1(CM_err_NullMetaPtr,            "Null metahandler pointer for type \"^0\"");
  437.         e1(CM_err_UndefRoutine,         "Handler routine(s) missing for operation type(s): ^0");
  438.         e1(CM_err_NoTOC,                        "Cannot allocate TOC for container \"^0\"");
  439.         e1(CM_err_BadReadUse,                "Cannot do a CMOpenContainer(...\"^0\"...) with useFlags set for ^1");
  440.         e1(CM_err_BadMagicBytes,        "Invalid magic byte sequence in label for container \"^0\" - expected \"^1\", got \"^2\"");
  441.         e1(CM_err_BadVersion,                "Invalid version fields in label for container \"^0\" - expected ^1.^2, got ^3.^4");
  442.         e1(CM_err_BadTOCRead,                "Incorrect byte length read while reading TOC for container \"^0\"");
  443.         e1(CM_err_NoObjEntry,                "Cannot allocate space for TOC object entry for container \"^0\"");
  444.         e1(CM_err_MultDef,                    "Multiple definition for TOC object ^0 for container \"^1\"");
  445.         e1(CM_err_NoPropEntry,            "Cannot allocate space for TOC property entry for container \"^0\"");
  446.         e1(CM_err_BadContinue,            "Invalid continued value (inconsistent types) in container \"^0\"");
  447.         e1(CM_err_NoValueEntry,            "Cannot allocate space for TOC value entry for container \"^0\"");
  448.         e1(CM_err_BadOffset,                "Invalid offset or value (^0, ^1) for TOC value entry for container \"^2\"");
  449.         e1(CM_err_UndefObjects,            "There is (are) ^0 undefined object(s) in container \"^1\"");
  450.         e1(CM_err_NoStrValue,                "Cannot allocate space for constant value in container \"^0\"");
  451.         e1(CM_err_DupBaseType,            "Cannot add dup base type \"^0\" to type \"^1\" in container \"^2\"");
  452.         e1(CM_err_BadTOCWrite,            "Incorrect byte length written while writing TOC for \"^0\"");
  453.         e1(CM_err_NotGlobalName,        "Have global name tied to value of wrong type in containter \"^0\"");
  454.         e1(CM_err_BadGNameWrite,        "Incorrect byte length written while writing global name \"^0\" in container \"^1\"");
  455.         e1(CM_err_DupGlobalName,        "Duplicate global name definition for \"^0\" in container \"^1\"");
  456.         e1(CM_err_MultGlblNames,        "Object ^0 alread defined -- trying to redefine it for \"^1\" (container \"^2\")");
  457.         e1(CM_err_NoGlobalName,            "Cannot allocate space for global name \"^0\" in container \"^1\"");
  458.         e1(CM_err_NoGNameLoad,            "Cannot allocate space for global name during load in container \"^0\"");
  459.         e1(CM_err_BadGNameRead,            "Incorrect byte length read while reading global name in container \"^0\"");
  460.         e1(CM_err_NotGName,                    "Invalid global name string read in container \"^0\"");
  461.         e1(CM_err_BadType,                    "Invalid ^0 type passed to ^1 for container \"^2\"");
  462.         e1(CM_err_2Containers,            "Objects not in same containers (containers \"^0\" and \"^1\")");
  463.         e1(CM_err_3Containers,            "Objects not in same containers (containers \"^0\", \"^1\", and \"^2\")");
  464.         e1(CM_err_MissingMinIDSeed,    "Min ID seed value missing in TOC object 1 in container \"^0\"");
  465.         e1(CM_err_MissingTOCObj,        "TOC object ID 1 missing in TOC in container \"^0\"");
  466.         e1(CM_err_NotConverting,        "Cannot use CMDefineValueData except for converting container \"^0\"");
  467.         e1(CM_err_BadDefineData,        "Attempt to define offset (^0) out of range in container \"^1\"");
  468.         e1(CM_err_BadValue,                    "Attempt to use a deleted value in container \"^0\"");
  469.         e1(CM_err_BadObject,                "Attempt to use a deleted object in container \"^0\"");
  470.         e1(CM_err_BadContainer,            "Container for ^0 (\"^1\") does not belong to the container being used (\"^2\")");
  471.         e1(CM_err_NoValue,                    "No value defined for object ID ^0, property \"^1\" in container \"^2\"");
  472.         e1(CM_err_HasValue,                    "Cannot set a (sub)value to an already defined value (container \"^0\")");
  473.         e1(CM_err_AlreadyReleased1,    "Attempting to release a value already completely released in container \"^0\"");
  474.         e1(CM_err_NotReleased,            "A dynamic value has not been fully released in container \"^0\"");
  475.         e1(CM_err_MissingFreeTotal,    "Total free space value missing in TOC object 1 in container \"^0\"");
  476.         e1(CM_err_DupType,                    "Attempt to insert two values with the same type (^0) in container \"^1\"");
  477.         e1(CM_err_HasNoValue,                "No value defined for CMReadValueData in container \"^0\"");
  478.         e1(CM_err_BadWrite,                    "Write error writing to container \"^0\"");
  479.         e1(CM_err_CantWriteGlbl,        "Cannot write to a global name in container \"^0\"");
  480.         e1(CM_err_Offset2Big,                "Write/insert offset (^0) beyond end of a value in container \"^1\"");
  481.         e1(CM_err_Internal1,                "Internal error! Unknown flags setting (0x^0)");
  482.         e1(CM_err_MissingIDSeed,        "ID seed value missing in TOC object 1 in container \"^0\"");
  483.         e1(CM_err_AmbiguousType,        "^0 object is ambiguous in container \"^1\"");
  484.         e1(CM_err_TypeNotGlobal,        "^0 object is not for a global name in container \"^1\"");
  485.         e1(CM_err_MissingFreeList,    "Internal error - empty free list for property in container \"^0\"");
  486.         e1(CM_err_NoNewValueHandler,"A \"new value\" handler is not defined for type \"^0\"");
  487.         e1(CM_err_UndefReference,        "Object ID ^0 from a reference is undefined in container \"^1\"");
  488.         e1(CM_err_BadObjectKind,        "Invalid kind of object -- expected ^0 in container \"^1\"");
  489.         e1(CM_err_WriteIllegal1,        "Cannot write to a container (\"^0\") opened for reading");
  490.         e1(CM_err_WriteIllegal2,        "Attempt to write to a protected object in container \"^0\"");
  491.         e1(CM_err_ReadIllegal,            "Cannot read from a container (\"^0\") opened for writing");
  492.         e1(CM_err_MissingSize,            "Size value missing in TOC object 1 in container \"^0\"");
  493.         e1(CM_err_BadSize,                    "Inconsistent size values between container label and TOC (container \"^0\")");
  494.         e1(CM_err_Internal2,                "Internal error! TOC offset to offset/size value not found in container \"^0\"");
  495.         e1(CM_err_CantDelete1,            "Attempt to delete to a protected object in container \"^0\"");
  496.         e1(CM_err_CantDelete2,            "Attempt to delete to a property with a protected value in container \"^0\"");
  497.         e1(CM_err_CantDelete3,            "Attempt to delete to a protected value in container \"^0\"");
  498.         e1(CM_err_StillOpen,                "Container \"^0\" is still open at session close time");
  499.         e1(CM_err_EmptyRead,                "Cannot read from an empty embedded container value (container \"^0\")");
  500.         e1(CM_err_NoEmbedding,            "Cannot allocate space to save embedding status while opening container \"^0\"");
  501.         e1(CM_err_BadGenNbr,                "Invalid generation number (^0) passed to ^1 (container \"^2\")");
  502.         e1(CM_err_NoRef,                        "Connot allocate space for an object reference in container \"^0\")");
  503.         e1(CM_err_CantGetBase,            "CMGetBaseValue() may only be called from a dynamic value handler in container \"^0\"");
  504.         e1(CM_err_MultTypeProp,            "Attempt to register a ^0 name (^1) in container \"^2\" -- already defined as a ^3");
  505.         e1(CM_err_NotSameMode,            "Embedded container (\"^0\") must be opened in same mode as its parent (\"^1\")");
  506.         e1(CM_err_CantDelete4,            "Cannot delete a value currently in use in container \"^0\"");
  507.         e1(CM_err_MissingHandler,        "Memory allocator and dealocator handlers must be supplied");
  508.         e1(CM_err_NoMissingBuffer,    "Unable to allocate private temporary buffer while opening type \"^0\"");
  509.         e1(CM_err_MoveIllegal,            "Cannot move a value in a container (\"^0\") not opened for writing");
  510.         e1(CM_err_DeleteIllegal,        "Attempt to delete ^0 in a container (\"^1\") not opened for writing");
  511.         e1(CM_err_BadDefineType,        "Attempt to define additional data for a immediate value in container \"^0\"");
  512.         e1(CM_err_NoDynExtensions,    "Cannot allocate space for TOC dynamic value entry for type \"^0\" in container \"^1\"");
  513.         e1(CM_err_HandlerRecursed,    "Attempt to use dynamic value handler for ^0() recursively in container \"^1\"");
  514.         e1(CM_err_BadRealValue,            "Invalid base (\"real\") value passed to ^0() in container \"^1\"");
  515.         e1(CM_err_NoMetahandler,        "A value operations metahandler is not defined for type \"^0\" in container \"^1\"");
  516.         e1(CM_err_NotDynValue,            "A \"use value\" metahandler did not create a dynamic value in container \"^0\"");
  517.         e1(CM_err_NoGlobalTable,        "Cannot allocate globally unique name table for container \"^0\"");
  518.         e1(CM_err_BadMetaSpec,            "Invalid metadata format specification (%^0) for type \"^1\" in container \"^2\"");
  519.         e1(CM_err_NoDeletesList,        "Internal error - empty \"deletes\" list for property in container \"^0\"");
  520.         e1(CM_err_NoDataPacket,            "Cannot allocate space for data packet for type \"^0\" in container \"^1\"");
  521.         e1(CM_err_BaseRelAttempted,    "A dynamic value release handler attempted to release its base in container \"^0\"");
  522.         e1(CM_err_NoDynMetahandler,    "\"Use value\" handler for type \"^0\" in container \"^1\" MUST return a metahandler");
  523.         e1(CM_err_MissingTotalSize,    "Total container size value missing in TOC object 1 in container \"^0\"");
  524.         e1(CM_err_Internal3,                "Internal error! TOC offset to container value not found in container \"^0\"");
  525.         e1(CM_err_AmbiguousUseFlags,"Ambiguous updating useFlags passed to CMOpenNewContainer(...\"^0\"...) - ^1");
  526.         e1(CM_err_NoTypeHandler,        "Dynamic value type handler not defined for updating in container \"^0\"");
  527.         e1(CM_err_NotDynamicValue,    "Dynamic value in container \"^0\" not created to access target for updating");
  528.         e1(CM_err_NoMetaDataHandler,"A \"metadata\" handler is not defined for type \"^0\"");
  529.         e1(CM_err_NoDataBuffer,            "Cannot allocate space for data I/O buffer in container \"^0\"");
  530.         e1(CM_err_BadUpdateRead,        "Incorrect byte length read while reading updates in container \"^0\"");
  531.         e1(CM_err_BadUpdateWrite,        "Write error while writing updates in container \"^0\"");
  532.         e1(CM_err_Internal4,                "Internal error! End-of-updates signal not detected in container \"^0\"");
  533.         e1(CM_err_Internal5,                "Internal error! TOC offset to updates TOC subsection not found in container \"^0\"");
  534.         e1(CM_err_NoNewValuesTOC,        "\"New values\" TOC offset/size missing in TOC object 1 in container \"^0\"");
  535.         e1(CM_err_wrappedIDs,                "Too many objects in container \"^0\" or next user object ID > 0xFFFFFFFF");
  536.         e1(CM_err_NoTouchedEntry,        "Cannot allocate space for recording updating operation in container \"^0\"");
  537.         e1(CM_err_NoUpdateObject,        "Container \"^0\" updating -- cannot find object ID ^1 to be ^2");
  538.         e1(CM_err_NoUpdateProperty,    "Container \"^0\" updating -- cannot find a property ID ^1 in object ID ^2 to be ^3");
  539.         e1(CM_err_BadUpdateControl,    "Container \"^0\" updating -- unknown control byte read (0x^1, during ^2)");
  540.         e1(CM_err_NoUpdateType,            "Container \"^0\" updating -- cannot find value (type ID ^1) in object ^2, property ^3");
  541.         e1(CM_err_UndefUpdateObject,"Container \"^0\" updating -- cannot find ^1 (ID ^2) to use in ^3");
  542.         e1(CM_err_UpdateBadGenNbr,    "Container \"^0\" updating -- invalid generation number (^1)");
  543.         e1(CM_err_BadInsertData,        "Container \"^0\" updating -- bad updating info (0 segment insert encountered)");
  544.         e1(CM_err_BadInsertOffset,    "Container \"^0\" updating -- insert offset (^1) beyond end of a value");
  545.         e1(CM_err_CantRepImmediate,    "Container \"^0\" updating -- attempt to replace non-immediate with immediate");
  546.         e1(CM_err_CantRepBaseType,    "Container \"^0\" updating -- attempt to replace non-base type value with a base type");
  547.         e1(CM_err_CantReference,        "Value and referenced object not in the same containers (containers \"^0\" and \"^1\")");
  548.         e1(CM_err_GloblaNameError,    "Allocation problem while looking up global name \"^0\" in container \"^1\"");
  549.         e1(CM_err_FlushErr,                    "Error detected in flushing output while closing container \"^0\"");
  550.         e1(CM_err_CantDelete5,            "Cannot delete an object with unreleased dynamic values in use in container \"^0\"");
  551.         e1(CM_err_NoTOCBuffer,            "Cannot allocate space for TOC I/O buffer in container \"^0\"");
  552.         e1(CM_err_BadTOCCode,                "Invalid TOC code read (0x^0) from TOC in container \"^1\"");
  553.         e1(CM_err_TOCoutOfSync,            "TOC reading out-of-sync (trying to read across buffer boundary) in container \"^0\"");
  554.         e1(CM_err_TOCParseErr1,            "TOC \"parse\" error - expected object ID, got 0x^0 in container \"^1\"");
  555.         e1(CM_err_TOCParseErr2,            "TOC \"parse\" error - got 0x^0 at an unexpected time in container \"^1\"");
  556.         e1(CM_err_Unsupported1,            "8-byte offset in container \"^0\" are not supported in this implementation");
  557.         e1(CM_err_CantDelete6,            "Cannot delete an object currently in use in container \"^0\"");
  558.         e1(CM_err_AlreadyReleased2,    "Attempting to release an object already completely released in container \"^0\"");
  559.         e1(CM_err_BadRefRead,                "Read error while reading references in container \"^0\"");
  560.         e1(CM_err_Internal6,                "Internal error! Missing reference property or value in container \"^0\"");
  561.         e1(CM_err_ZeroRefKey,                "Attempt to use a CMReference key of 0 in container \"^0\"");
  562.         e1(CM_err_NoRefShadowList,    "Cannot allocate space to record reference in container \"^0\"");
  563.     /*----------------------------------------------------------------------------------*/
  564.     EndOfList(strcat("Undefined error message for error #", cmltostr(errorNumber, 1, false, tmpStr)));
  565.  
  566.     if (gotInserts)
  567.         CMVAddMsgInserts(msg, maxLength, inserts);
  568.     
  569.     if ((CMSize)strlen(msg) <= maxLength)
  570.         strcpy((CM_CHAR *)errorString, (CM_CHAR *)msg);
  571.     else {
  572.         strncpy((CM_CHAR *)errorString, (CM_CHAR *)msg, (int)maxLength);
  573.         *(errorString + maxLength) = '\0';
  574.     }
  575.         
  576.     return (errorString);
  577. }
  578.  
  579.  
  580. /*------------------------------------------------------*
  581.  | CMReturnContainerName - get container identification |
  582.  *------------------------------------------------------*
  583.  
  584.  Generally the errors reported are provided with at least one insert that identifies which
  585.  container we're talking about.  The wording of the messages defined for the Container 
  586.  Manager assume this identification insert.  The identification takes the form of the
  587.  container "name" which is obtained from a handler routine provided for that purpose.
  588.  
  589.  For convenience, the name providing handler routine is allowed to be optional, i.e., the
  590.  user need not provide one.  This means every time we want to get the identification we
  591.  must test to see if the handler was provided.  This could be a waste of code space, 
  592.  particularly since we mostly use this for error reporting ("mostly" -- actually this is
  593.  the only context it is presenting used in).
  594.  
  595.  To avoid the space waste, this routine is provided to do the test and call the handler if
  596.  it exists.  If it doesn't exist the container type name (using the TYPENAMEx macro) is
  597.  used.  If it does, we use the handler.
  598.  
  599.  Note, this routine is available to users (usually handler writers) so that they too can
  600.  generalize their error reporting/message routines and word their messages with the
  601.  container identification. 
  602. */
  603.  
  604. CM_CHAR CM_PTR * CM_FIXEDARGS CMReturnContainerName(CMContainer container)
  605. {
  606.     return (((ContainerPtr)container)->handler.cmreturnContainerName == NULL ? 
  607.                         TYPENAMEx(container) :
  608.                         CMreturnContainerName(container));
  609. }
  610.                                                           
  611.                                                             CM_END_CFUNCTIONS
  612.