home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ODDebug.cpp
-
- Contains: xxx put contents here xxx
-
- Owned by: David McCusker
-
- Copyright: © 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 3/29/96 DM 1335889: add TRY block to _Warn() so
- exceptions cannot propagate
-
- To Do:
- */
-
- /*
- File: ODDebug.cpp
-
- Contains: Useful debugging macros and functions.
-
- Owned by: Jens Alfke
-
- Copyright: © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #ifndef _ODDEBUG_
- #include "ODDebug.h"
- #endif
-
- #ifndef _EXCEPT_
- #include "Except.h"
- #endif
-
- #ifndef _PLFMDEF_
- #include "PlfmDef.h"
- #endif
-
- #ifndef _PASCLSTR_
- #include "PasclStr.h"
- #endif
-
- #ifndef _PLFMDEF_
- #include "PlfmDef.h"
- #endif
-
- #ifndef _EXCEPT_
- #include "Except.h"
- #endif
-
- #ifndef _TEXTUTILS_
- #include "TextUtils.h"
- #endif
-
- #ifndef _CRAWL_
- #include "Crawl.h"
- #endif
-
- #ifndef _USERSRCM_
- #include "UseRsrcM.h"
- #endif
-
- #ifndef _DLOGUTIL_
- #include "DlogUtil.h"
- #endif
-
- #ifndef _UTILDEFS_
- #include "UtilDefs.h"
- #endif
-
- #include <somobj.xh>
- #include <somcls.xh>
-
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
-
-
- const ODSShort kOutputBufferSize = 400;
-
- static somTD_SOMOutCharRoutine *gOld_SOMOutCharRoutine;
- static somTD_SOMError *gOld_SOMError;
-
- // The output buffer is circular. We keep two indices, one for the start
- // of the most recent string and one for the end (the current input position.)
- static char gOutputBuffer[kOutputBufferSize];
- static ODSShort gOutputStart = 0;
- static ODSShort gOutputEnd = 0;
-
- static DebugOutputMode gOutputMode = kNoOutput;
-
-
- void BREAK( const char[] );
-
- static short gOutputFile = kODNULL;
-
- //=====================================================================================
- // ODInitExceptions
- //=====================================================================================
-
-
- extern "C" {
- static int OD_SOMOutCharRoutine( char c );
- static void OD_SOMError( int error, corbastring filename, int linenum );
- }
-
-
- void
- ODInitExceptions( )
- {
- gOld_SOMOutCharRoutine = SOMOutCharRoutine;
- gOld_SOMError = SOMError;
- SOMOutCharRoutine = OD_SOMOutCharRoutine;
- SOMError = OD_SOMError;
- // SOM_WarnLevel = 1; // all, from somcdev.h
- }
-
-
- //=====================================================================================
- // Output routines
- //=====================================================================================
-
-
- #ifdef _PLATFORM_MACINTOSH_
-
- #ifndef __STRINGS__
- #include <Strings.h>
- #endif
-
-
- static OSErr
- SendToDebugWindow( const char buffer[], short length )
- {
- // Code adapted from API to "DebugWindow" app by Keith Ledbetter
- AEAddressDesc address;
- AppleEvent appleEvent, reply;
- OSType targetSig;
- OSErr err;
-
- targetSig = 'LdbW';
- err= AECreateDesc( typeApplSignature, (Ptr)&targetSig,
- sizeof(targetSig), &address );
- if( !err ) {
- err= AECreateAppleEvent( 'misc', 'dmsg', &address, kAutoGenerateReturnID,
- kAnyTransactionID, &appleEvent );
- AEDisposeDesc( &address );
- if( !err ) {
- err= AEPutParamPtr( &appleEvent, keyDirectObject, typeChar,
- buffer, length );
- if( !err ) {
- err= AESend( &appleEvent, &reply,
- kAEWaitReply + kAENeverInteract,
- kAENormalPriority,
- 300, // up to 5 second wait..
- kODNULL, kODNULL );
- AEDisposeDesc( &reply );
- }
- AEDisposeDesc( &appleEvent );
- }
- }
- return err;
- }
-
-
- static short CreateNewOutputFile()
- {
- static long nextFilePrefixNum = 1;
-
- Str255 fileNameRootString = "\pstdout";
- Size fileNameRootLength = fileNameRootString[0];
- Str255 numString;
- Str255 fileNameString;
- short file = 0;
-
- CopyPascalString(fileNameString, fileNameRootString);
-
- OSErr err = Create(fileNameRootString, 0, 'MPS ', 'TEXT');
- if (err)
- {
- while(err)
- {
- CopyPascalString(fileNameString, fileNameRootString);
- NumToString(nextFilePrefixNum, numString);
- // check for filename too long.
- if (numString[0] + fileNameRootLength > 255)
- {
- err = 1;
- break;
- }
- ConcatPascalStrings(fileNameString, numString);
- err = Create(fileNameString, 0, 'MPS ', 'TEXT');
- ++nextFilePrefixNum;
- if (nextFilePrefixNum > 10000) // arbitrary infinite loop stopper.
- break;
- }
- }
-
- if (!err)
- {
- err = FSOpen(fileNameString, 0, &file);
- if (err)
- file = 0;
- }
-
- return file;
- }
-
-
- static ODSShort
- ExtractBufferString( ODSShort start, ODSShort end, char output[] )
- {
- ODSShort len = end-start;
- if( len >= 0 )
- ODBlockMove(gOutputBuffer+start, output, len);
- else {
- ODSShort len1 = kOutputBufferSize-start;
- ODBlockMove(gOutputBuffer+start, output,len1);
- ODBlockMove(gOutputBuffer, output+len1, end);
- len += kOutputBufferSize;
- }
- output[len] = '\0';
- return len;
- }
-
-
- static int
- OD_SOMOutCharRoutine( char c )
- {
- if( c ==0x0A ) // Convert Unix-style newline to Return
- c = 0x0D;
-
- // Add to buffer, wrapping around:
- gOutputBuffer[gOutputEnd++] = c;
- if( gOutputEnd >= kOutputBufferSize )
- gOutputEnd = 0;
-
- if( c == 0x0D ) { // Dump buffer at end of line
- if( gOutputMode == kWriteToDebugWindow
- || gOutputMode == kGenerateDebugStrs
- || gOutputMode == kWriteToFile)
- {
- // Convert latest output to string:
- char output[kOutputBufferSize+1];
- ODSShort len = ExtractBufferString(gOutputStart,gOutputEnd, output);
-
- OSErr err = noErr;
-
- if (gOutputMode == kWriteToDebugWindow)
- err = SendToDebugWindow(output,len);
- else if (gOutputMode == kGenerateDebugStrs)
- {
- // Convert buffer to pascal string
- memmove(output + 1, output, len);
- output[0] = len<=255 ?len :255;
- DebugStr((StringPtr)output);
- }
- else if (gOutputMode == kWriteToFile)
- {
- if (gOutputFile == NULL)
- gOutputFile = CreateNewOutputFile();
- if (gOutputFile)
- {
- long bytesToWrite = len;
- err = FSWrite(gOutputFile, &bytesToWrite, output);
- if (!err && bytesToWrite != len)
- err = 1;
- }
- else
- err = 1;
- }
-
- if( err )
- {
- gOutputMode = kGenerateDebugStrs;
- DebugStr((StringPtr)"\pSOM Message Output: Error writing output -- reverting to DebugStr mode.");
- }
- }
-
- gOutputStart = gOutputEnd; // "clear" buffer
- }
-
- return 1;
- }
-
-
- #else /* if not _PLATFORM_MACINTOSH_: */
-
-
- static int
- OD_SOMOutCharRoutine( char c )
- {
- if( gOutputMode == kWriteToFile )
- return gOld_SOMOutCharRoutine(c);
- else
- return 1;
- }
-
- #endif
-
-
- DebugOutputMode
- GetOutputMode( )
- {
- return gOutputMode;
- }
-
-
- void
- SetOutputMode( DebugOutputMode mode )
- {
- if( gOutputMode == kWriteToDebugWindow )
- if( gOutputEnd != gOutputStart )
- OD_SOMOutCharRoutine(0x0D); // Flush buffer
- gOutputMode = mode;
- }
-
-
- //===================================================================================
- // BREAK
- //===================================================================================
-
- void
- BREAK( const char msg[] )
- {
- somPrintf("%s\n",msg);
-
- #ifdef _PLATFORM_MACINTOSH_
- #if ODDebug
- // Now convert to Pascal string and call DebugStr:
- Str255 pstr;
- long len = strlen(msg);
- pstr[0] = (len>255) ?255 :len;
- for( int i=pstr[0]; i>0; i-- ) {
- char c = msg[i-1];
- if( c==';' ) c=':'; // ";" is bad in DebugStrs
- pstr[i] = c;
- }
- DebugStr(pstr);
- #endif
- #endif
- }
-
-
- //===================================================================================
- // SOMError
- //===================================================================================
-
- static ODBoolean IsOptionKeyDown()
- {
- const ODUShort theKey = 0x3A; // option key
- unsigned char theKeys[16];
- GetKeys((UInt32*)&theKeys);
-
- return ((theKeys[theKey >> 3] >> (theKey & 7)) & 1);
- }
-
- static void
- OD_SOMError( int error, corbastring filename, int linenum )
- {
- const char *kSeverityCode[10] =
- {"error","warning","message","error?","error?",
- "error template","error?","error?","error?","fatal error"};
- int base = error / 10000;
- int errno = (error - base*10000) / 10;
- int severity = error % 10;
-
- char msg[kOutputBufferSize+3];
- sprintf(msg, "SOM %s %d-%03d-%d (%s %d): Press G...",
- kSeverityCode[severity],base,errno,severity,
- filename,linenum);
-
- if( severity == SOM_Fatal ) {
- somPrintf(msg);
- CUsingLibraryResources r;
- DialogPtr d = kODNULL; ODVolatile(d);
- TRY{
- InitCursor();
- ::Alert(kSOMErrorAlertID,kODNULL);
- if( IsOptionKeyDown() ) {
- d = ::GetNewDialog(kSOMErrorDlogID,kODNULL,(WindowPtr)-1L);
- SetDialogDefaultItem(d,ok);
- SetDialogTextStyle(d,kSOMErrorDlogFontInfo, smCurrentScript);
-
- // Copy the entire output buffer, not just the last line:
- ODSShort start = gOutputEnd;
- do{
- ++start;
- if( start >= kOutputBufferSize ) start=0;
- }while( start!=gOutputEnd && gOutputBuffer[start]=='\0' );
- strcpy(msg,"...");
- ODSShort len = ExtractBufferString(start,gOutputEnd, msg+3) +3;
-
- short typ;
- Handle h;
- Rect box;
- ::GetDialogItem(d,kSOMErrorDlogTextItem, &typ,&h,&box);
- PtrToXHand(msg,h,len);
-
- #if !ODDebug
- HideDialogItem(d,kSOMErrorDlogDebugButton);
- #endif
-
- ShowWindow(d);
- SelectWindow(d);
- ODSShort item;
- ModalDialog(kODNULL,&item);
-
- #if ODDebug
- if( item == kSOMErrorDlogDebugButton )
- Debugger(); // Have a look around...
- #endif
- }
- }CATCH_ALL{
- WARN("Caught error %d displaying SOM error dialog",ErrorCode());
- }ENDTRY
- if( d ) DisposeDialog(d);
-
- } else
- BREAK(msg); // Nonfatal error: just break
-
- gOld_SOMError(error,filename,linenum);
- }
-
-
- //===================================================================================
- // ASSERTION-FAILED
- //===================================================================================
-
- #if ODDebug
-
- void _AssertionFailed( char *cond, char *filename,
- ODError error, char *msg /*=NULL*/ )
- {
- char where[300];
- if( ! GetNameOfCaller(where) )
- strcpy(where,filename);
-
- ODUnused(filename);
- char dbg[256];
- if( msg )
- sprintf(dbg,"%s: %s ...NOT! At %s", msg,cond,where);
- else
- sprintf(dbg,"%s ...NOT! At %s", cond,where);
- BREAK(dbg);
-
- if( error!=0 )
- THROW(error, msg ?msg :"Assertion failed");
- }
-
- #else /*not ODDebug*/
-
- extern "C" void _AssertionFailed( char *cond, char *filename,
- ODError error, char *msg );
- void _AssertionFailed( char *cond, char *filename,
- ODError error, char *msg )
- {
- }
-
- #endif /*ODDebug*/
-
-
- //===================================================================================
- // WARN
- //===================================================================================
-
- #if ODDebug
-
- void _Warn( char *fmt, ... )
- {
- char msg[512];
- strcpy(msg, "ODWarning: ");
- va_list args;
- va_start(args,fmt);
- vsprintf(msg+strlen(msg),fmt,args);
- va_end(args);
-
- char caller[300];
-
- // DMc: make sure _Warn() cannot throw an exception (out-of-memory when a stack
- // crawl is allocated), because _Warn is often called in unsafe contexts that
- // are not protected by a TRY block:
- TRY {
- if( GetNameOfCaller(caller) ) {
- strcat(msg," (at ");
- strcat(msg,caller);
- strcat(msg,")");
- }
- } CATCH_ALL {
- } ENDTRY
-
- BREAK(msg);
- }
-
- #else /*not ODDebug*/
-
- extern "C" void _Warn( char *fmt, ... );
- void _Warn( char *fmt, ... )
- {
- }
-
- #endif /*ODDebug*/
-
- //==============================================================================
- // SAFE CAST
- //==============================================================================
-
-
- #if ODDebug
-
- SOMObject*
- _Cast( SOMObject *obj, somClassDataStructure *clsdata, long majorversion, long minorversion )
- {
- SOMClass *cls = (SOMClass*) somGetStaticClassReference(clsdata,majorversion,minorversion);
- if( !somIsObj(obj) )
- WARN("Can't cast: %p is not a SOM object",obj);
- else if( !somIsObj(cls) )
- WARN("Can't cast: %p is not a SOM class",cls);
- else if( !obj->somIsA(cls) )
- WARN("Can't cast: %p is an %s, not an %s",obj, obj->somGetClassName(), cls->somGetName());
- else {
- somReleaseClassReference(cls);
- return obj;
- }
- somReleaseClassReference(cls);
- THROW(kODErrAssertionFailed);
- return NULL; /* keeps compiler quiet */
- }
-
- #else /*not ODDebug*/
-
- extern "C" void _Cast( );
- void _Cast( )
- {
- }
-
- #endif /*ODDebug*/
-