/*********************************************************************
ADOBE SYSTEMS INCORPORATED
Copyright (C) 1994-2006 Adobe Systems Incorporated
All rights reserved.
NOTICE: Adobe permits you to use, modify, and distribute this file
in accordance with the terms of the Adobe license agreement
accompanying it. If you have received this file from a source other
than Adobe, then your use, modification, or distribution of it
requires the prior written permission of Adobe.
---------------------------------------------------------------------
CorCalls.h
- Exception handling methods (ASPushExceptionFrame and
ASPopExceptionFrame) should typically be accessed through the
DURING/HANDLER/END_HANDLER macros.
******************************************************************************************
**** Instructions for Plugin Developers ****
(In the instructions below ~ is used to refer to the HFT this file is for. For
example, this file would be called "~Calls.h")
To use this file you must declare two global variables: g~HFT and g~Version. You can
see them declared as extern about one page down from here. Your plugin should set a
#define of PI_~_VERSION to some non zero value. Suggested values are given below in
the "for public use" section. ~HFT_LATEST_VERSION is not recommended because you will
not be able to support backwards compatible versions. It is recommended that you use the lowest
~HFT_VERSION you require. Later versions are compatible with earlier versions, so if
you require ~HFT_VERSION_4, your plugin will work with ~HFT_VERSION_5, ~HFT_VERSION_6, and so on.
You can support old versions and still use newer versions of this HFT by checking the
value of g~Version. If you use the standard PiMain.c supplied in the SDK, this will be
set to the actual version of the HFT returned to you (For example, if you require version 4,
you are returned version 7, which is compatible, and g~Version is set to 7). You can write
code that looks something like this:
if (g~Version >= ~HFT_VERSION_5)
CallNewSpeedyCode();
else {
assert(g~Version >= ~HFT_VERSION_4); //PI_~_VERSION was defined as ~HFT_VERSION_4
CallOldSlowCode();
}
******************************************************************************************
**** Instructions for HFT Developer ****
(In the instructions below ~ is used to refer to the HFT this file is for. For
example, this file would be called "~Calls.h")
Important: routines that have been released can never be deleted or changed.
If you want to make a new version, create a new call, add it to the end of this file and
increment _~_LATEST_VERSION (note the leading underscore).
If this is the first new routine in a new version, change the _~_IS_BETA flag
to 1. Next, create a new ~_VERSION_# for plugins to use and set it to
~HFT_LATEST_VERSION. For example, suppose the last release of Acrobat was version 20, version 21
is under development, and you add a new routine for version 21. Increment _~HFT_LATEST_VERSION
to 0x00200001 and set _~_IS_BETA to 1. Add "#define ~HFT_VERSION_21 ~HFT_LATEST_VERSION".
Add your routine and assert that g~Version >= ~HFT_VERSION_21. Leave
_~_LAST_BETA_COMPATIBLE_VERSION unchanged (0x00200000 in this example).
If the ~_IS_BETA flag is set to 1, you may change or delete the beta routines at will.
Before checking in the modifications, however, increment the _~HFT_LATEST_VERSION number.
If the change is not compatible (delete, change, and so on) set _~_LAST_BETA_COMPATIBLE_VERSION equal
to the new _~HFT_LATEST_VERSION. If the change is compatible, leave the LAST_BETA version
as is.
Plugins that require a BETA HFT will be refused unless they ask for a beta version greater than or equal to
(>=) LAST_BETA_COMPATIBLE_VERSION and less than or equal to (<=) HFT_LATEST_VERSION.
By incrementing the version number, you ensure the plugin will refuse to load until it
has been recompiled with your changes. You also ensure plugins compiled with your changes
will not load on older versions of Acrobat. In other words, it makes sure both sides are in sync.
Important: Whenever you make a change to this file, you must increment _~HFT_LATEST_VERSION.
Once the product reaches RC or a similar milestone, change the _~_IS_BETA flag to 0, jump
the _~HFT_LATEST_VERSION to the final version (0x00210000 in our example), do the same for
_~_LAST_BETA_COMPATIBLE_VERSION, and set the
~HFT_VERSION_# to the final version number (0x00210000 in this example). Once the HFT
has left beta, the routines cannot be changed and a new beta must ensue (beta for version
22 in this example).
*********************************************************************/
#ifndef _H_CorCalls
#define _H_CorCalls
#include "acroassert.h"
/* This header includes templates and hence would not compile if
included inside of a extern "C" block. Hence CorCalls.h must
not be included inside of a extern "C" block */
#include "EReturnValidator.h"
/* for Adobe use only */
#define _CoreHFT_LATEST_VERSION 0x00050000
#define _CoreHFT_LAST_BETA_COMPATIBLE_VERSION 0x00050000
#define _CoreHFT_IS_BETA 0
/* for public use */
#define CoreHFT_LATEST_VERSION (_CoreHFT_IS_BETA ? (kHFT_IN_BETA_FLAG | _CoreHFT_LATEST_VERSION) : _CoreHFT_LATEST_VERSION)
#define CoreHFT_VERSION_2 0x00020000
#define CoreHFT_VERSION_4 0x00040000
#define CoreHFT_VERSION_5 0x00050000 /* note: version 5 is same as 4. Provided to support old plugins that erroneously required 5 */
#ifndef _CORVERSION_ID_ONLY
#include "PIExcept.h"
#include "CoreExpT.h"
#include "ASExpT.h"
#if PRAGMA_STRUCT_ALIGN
#pragma options align=power
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS)
#if MAC_PLATFORM
#define USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS 1
#elif UNIX_PLATFORM
#define USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS 1
#else
#define USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS 0
#endif
#endif
#if USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS
#ifdef __cplusplus
/* The C++ version of the exception frame structure contains only the
information necessary to execute a successful throw. The exception
error code and message are tracked in a separate class defined
here. */
struct _miExceptionInfo {
_miExceptionInfo() {}
int dummy;
};
/* This routine knows how to take an exception and 'throw' it to
a C++ DURING frame.
*/
extern void miThrowExceptionToHandler(void *asEnviron);
#endif /* __cplusplus */
#endif /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if ACROBAT_LIBRARY
/* Toolkit specific Error-handling function prototypes */
/* RestorePlugInFrame
** This is a function that the plug-in must provide (if you are using the
** standard government-issue PIMain.c, this function is implemented there.)
** It takes a jmp_buf as registered through ASPushExceptionFrame and restores
** state based on that jmp_buf, usually through using longjmp.
*/
extern ACCB1 void ACCB2 RestorePlugInFrame(void *environ);
typedef ACCBPROTO1 void (ACCBPROTO2 *ACRestoreEnvironProc)(void *excEnviron);
extern ACCB1 void ACCB2 ACPushExceptionFrame(void *excEnviron, ACRestoreEnvironProc restoreFunc);
extern ACCB1 void ACCB2 ACPopExceptionFrame(void);
extern ACCB1 ASInt32 ACCB2 ACGetExceptionErrorCode(void);
#if USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS
#ifdef __cplusplus
struct _miExceptionPushPop {
_miExceptionPushPop() { ACPushExceptionFrame(NULL, (ACRestoreEnvironProc)&miThrowExceptionToHandler); }
~_miExceptionPushPop() { ACPopExceptionFrame(); }
};
/**
Begins the section of code where Acrobat APIs may throw an exception. After calling an Acrobat API method, execution may jump into the HANDLER
clause.
This macro is similar to the try
clause in the C++ language.
@see END_HANDLER
@see E_RETURN
@see E_RTRN_VOID
@see HANDLER
*/
#define DURING { \
try { \
_miExceptionPushPop __exceptionPushPop;
#define _E_RESTORE /*int _E_RESTORE__BogusLocalDoesNothing = 0*/
#define _E_HANDLER } catch (_miExceptionInfo Exception) {
/**
Follows a DURING
macro. Code inserted between HANDLER
and END_HANDLER
macros will be executed only if an Acrobat function or other function
throws an exception. This macro is similar to the catch
clause in the C++ language.
@see END_HANDLER
@see DURING
@see E_RTRN_VOID
@see E_RETURN
*/
#define HANDLER _E_RESTORE; _E_HANDLER _E_RESTORE;
/**
Ends a DURING/HANDLER/END_HANDLER
clause.
@see DURING
@see END_HANDLER
@see E_RETURN
@see HANDLER
*/
#define END_HANDLER }}
#else /* __cplusplus */
#define DURING DURING usage must be compiled with C++
#define HANDLER HANDLER usage must be compiled with C++
#define END_HANDLER END_HANDLER usage must be compiled with C++
#endif /* __cplusplus */
#else /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if MAC_PLATFORM
#error Mac Xcode should no longer use this
#endif
#if UNIX_PLATFORM
#error Unix should no longer use this
#endif
/**
Begins the section of code where Acrobat APIs may throw an exception. After calling an Acrobat API method, execution may jump into the HANDLER
clause.
This macro is similar to the try
clause in the C++ language.
@see END_HANDLER
@see E_RETURN
@see E_RTRN_VOID
@see HANDLER
*/
#define DURING { \
ACROjmp_buf ASException; \
ACPushExceptionFrame(&ASException, (ACRestoreEnvironProc)&RestorePlugInFrame); \
if (!ACROsetjmp(ASException)) {
#define _E_RESTORE ACPopExceptionFrame()
/**
Follows a DURING
macro. Code inserted between HANDLER
and END_HANDLER
macros will be executed only if an Acrobat function or other function
throws an exception. This macro is similar to the catch
clause in the C++ language.
@see END_HANDLER
@see DURING
@see E_RTRN_VOID
@see E_RETURN
*/
#define HANDLER _E_RESTORE; } else { _E_RESTORE;
/**
Ends a DURING/HANDLER/END_HANDLER
clause.
@see DURING
@see END_HANDLER
@see E_RETURN
@see HANDLER
*/
#define END_HANDLER }}
#endif /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
/**
A macro defined to call ASGetExceptionErrorCode(). It returns an ASInt32 object containing an exception error code.
@see DURING
@see END_HANDLER
@see E_RTRN_VOID
@see HANDLER
*/
#define ERRORCODE (ACGetExceptionErrorCode())
/**
Returns a value from an enclosing function when nested inside a DURING/HANDLER clause.
@see DURING
@see END_HANDLER
@see E_RTRN_VOID
@see HANDLER
*/
#define E_RETURN(x) { _E_RESTORE; return(x); }
/**
Returns from an enclosing function when nested inside a DURING/HANDLER clause, without returning a value.
@see ErrGetCode
@see ErrGetSeverity
@see ErrGetSignedCode
@see ErrGetSystem
*/
#define E_RTRN_VOID { _E_RESTORE; return; }
#else /* ACROBAT_LIBRARY */
#define ACRestoreEnvironProc restoreEnvironProc
#if !STATIC_HFT
#define ACPushExceptionFrame ASPushExceptionFrame
#define ACPopExceptionFrame ASPopExceptionFrame
#define ACGetExceptionErrorCode ASGetExceptionErrorCode
#endif /* STATIC_HFT */
#endif /* ACROBAT_LIBRARY */
#ifdef NPROC /* may be defined in sys/procs.h */
#undef NPROC
#endif /* NPROC */
#if !PLUGIN
/* Static link */
#define NPROC(returnType, name, params) \
ACEX1 returnType ACEX2 name params;
#define SPROC(returnType, name, params, stubProc) \
extern ACEX1 returnType ACEX2 stubProc params;
#define ANPROC NPROC
#include "CorProcs.h"
#undef NPROC
#undef ANPROC
#undef SPROC
#define ASCallbackCreateProto(proto, proc) (proc)
#define ASCallbackCreate(proc) (proc)
#define ASCallbackDestroy(proc)
/* These functions have a different name internally */
#define ASPushExceptionFrame ACPushExceptionFrame
#define ASPopExceptionFrame ACPopExceptionFrame
#define ASGetExceptionErrorCode ACGetExceptionErrorCode
#define ASExtensionMgrGetHFT ASGetHFTByNameAndVersion
#endif /* !PLUGIN */
#if PLUGIN
/* HFT version */
#include "PIRequir.h"
/* Enumerate the selectors */
#define NPROC(returnType, name, params) \
name##SEL,
#define SPROC(returnType, name, params, stubProc) \
name##SEL,
#define ANPROC NPROC
enum {
CoreBAD_SELECTOR,
#include "CorProcs.h"
CoreNUMSELECTORSplusOne
};
#define CoreNUMSELECTORS (CoreNUMSELECTORSplusOne - 1)
/* Create the prototypes */
#undef NPROC
#undef ANPROC
#undef SPROC
#define NPROC(returnType, name, params) \
typedef ACCBPROTO1 returnType (ACCBPROTO2 *name##SELPROTO)params;
#define SPROC(returnType, name, params, stubProc) \
typedef ACCBPROTO1 returnType (ACCBPROTO2 *name##SELPROTO)params;
#define ANPROC NPROC
#include "CorProcs.h"
#undef NPROC
#undef ANPROC
#undef SPROC
#if PI_CORE_VERSION != 0
#ifdef THREAD_SAFE_PDFL
#define gCoreHFT (GetHFTLocations()->coreHFT)
#define gCoreVersion (GetHFTLocations()->coreVersion)
#include "PDFLInitHFT.h"
#else
extern HFT gCoreHFT;
extern ASUns32 gCoreVersion;
#endif
#include "PICommon.h"
#include "PIExcept.h"
#if !STATIC_HFT
/* Exception-handling functions */
/* ASRaise
** Raises an exception. Subsequent calls to ASGetExceptionErrorCode() will
** return the error value passed in to this function.
** This function is called directly by the macro RERAISE().
*/
#define ASRaise (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASRaiseSELPROTO)(gCoreHFT[ASRaiseSEL])))
/* ASPushExceptionFrame
**
** Push an exception frame buffer and a frame-restoration callback onto the stack.
** The restoreFunc should be a function matching the following prototype:
**
** ACCB1 void ACCB2 RestorePlugInFrame(void *asEnviron);
**
** You will probably never call ASPushExceptionFrame() directly; use the DURING
** macro instead.
*/
#define ASPushExceptionFrame (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASPushExceptionFrameSELPROTO)(gCoreHFT[ASPushExceptionFrameSEL])))
/* ASPopExceptionFrame
** Pop and exception frame off the stack.
** You will probably never call ASPopExceptionFrame() directly; it is called for
** you as appropriate from within the HANDLER, E_RETURN and E_RTRN_VOID macros.
*/
#define ASPopExceptionFrame (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASPopExceptionFrameSELPROTO)(gCoreHFT[ASPopExceptionFrameSEL])))
/* ASGetExceptionErrorCode
** Returns the value of the error parameter as passed in to the most
** recent call to ASRaise(). You might then pass this value to ASGetErrorString()
** in order to report the exception to the user.
*/
#define ASGetExceptionErrorCode (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASGetExceptionErrorCodeSELPROTO)(gCoreHFT[ASGetExceptionErrorCodeSEL])))
/* ASAtom management */
/* ASAtomFromString
** Returns the ASAtom associated with the given string. You can compare
** ASAtoms directly, rather than passing their associated strings to
** strcmp().
*/
#define ASAtomFromString (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASAtomFromStringSELPROTO)(gCoreHFT[ASAtomFromStringSEL])))
/* ASAtomExistsForString
** Returns true if and only if there already exists an ASAtom for the
** given string. You might use this to prevent capricious overpopulation
** of the internal ASAtom table (a non-renewable resource!)
*/
#define ASAtomExistsForString (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASAtomExistsForStringSELPROTO)(gCoreHFT[ASAtomExistsForStringSEL])))
/* ASAtomGetString
** Returns the char * associated with the given ASAtom. This routine
** permanently allocates storage for new strings, so don't call this function
** unnecessarily!
*/
#define ASAtomGetString (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASAtomGetStringSELPROTO)(gCoreHFT[ASAtomGetStringSEL])))
/* ASCallbackCreate
** Takes a pointer to a function and returns an ASCallback--a universally
** entrant function pointer which can be called from any globals context.
*/
/**
Deprecated in Acrobat 8.0.
*/
#define ASCallbackCreate(x) (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASCallbackCreateSELPROTO)(gCoreHFT[ASCallbackCreateSEL])))(gExtensionID, (void *)(x))
/* ASCallbackCreateProto
** Type-checking callback creation. Will cause a compiler error if the
** proc is not of the given function-type. DEBUG must be on for checking to occur.
** Requires four bytes of scratch global space in which to make a bogus
** assignment; this is declared in PIMain.c.
*/
/**
Deprecated in Acrobat 8.0.
*/
#if DEBUG
#define ASCallbackCreateProto(funcType, proc) \
((funcType)ASCallbackCreate((CHECKTYPE(funcType, proc))))
#else
#define ASCallbackCreateProto(funcType, proc) \
((funcType)ASCallbackCreate(((void*)proc)))
#endif
/* ASCallbackDestroy
** De-allocates memory associated with an ASCallback. Use this if you're
** sure you're completely done with an ASCallback.
*/
/**
Deprecated in Acrobat 8.0.
*/
#define ASCallbackDestroy (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASCallbackDestroySELPROTO)(gCoreHFT[ASCallbackDestroySEL])))
/* ASExtensionMgrGetHFT
** Get an HFT object with the given name and version number.
*/
#define ASExtensionMgrGetHFT (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASExtensionMgrGetHFTSELPROTO)(gCoreHFT[ASExtensionMgrGetHFTSEL])))
/* ASGetConfiguration
** Returns a void * based on the ASAtom passed in. The void *
** may be cast to a meaningful value based on the input parameter:
**
** key result return type
** Product Name of product type const char *
** (Exchange, Reader, etc.)
** CanEdit Whether or not editing ASBool
** is allowed
** <> UNDEFINED_CONFIGURATION_SELECTOR
*/
#define ASGetConfiguration (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_2), *((ASGetConfigurationSELPROTO)(gCoreHFT[ASGetConfigurationSEL])))
/* begin PI_CORE_VERSION >= 0x00040000 */
/* ASEnumExtensions */
#define ASEnumExtensions (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_4), *((ASEnumExtensionsSELPROTO)(gCoreHFT[ASEnumExtensionsSEL])))
/* ASExtensionGetFileName */
#define ASExtensionGetFileName (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_4), *((ASExtensionGetFileNameSELPROTO) (gCoreHFT[ASExtensionGetFileNameSEL])))
/* ASExtensionGetRegisteredName */
#define ASExtensionGetRegisteredName (ACROASSERT(gCoreVersion >=CoreHFT_VERSION_4), *((ASExtensionGetRegisteredNameSELPROTO) (gCoreHFT[ASExtensionGetRegisteredNameSEL])))
/* end PI_CORE_VERSION >= 0x00040000 */
/* If you add, delete, or modify procs listed in this file please read the instructions at the top about how to properly change the version number */
#endif /* !STATIC_HFT */
/* Exception-handling macros */
/**
Re-raises the most recently raised exception and passes it to the next exception handler in the stack.
@see ErrGetCode
@see ErrGetSeverity
@see ErrGetSignedCode
@see ErrGetSystem
@see ASRaise
*/
#define RERAISE() ASRaise(ERRORCODE)
#if USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS
#ifdef __cplusplus
struct _miExceptionPushPop {
_miExceptionPushPop() { ACPushExceptionFrame(NULL, (ACRestoreEnvironProc)&miThrowExceptionToHandler); }
~_miExceptionPushPop() { ACPopExceptionFrame(); }
};
#endif /* __cplusplus */
#else /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if MAC_PLATFORM
#error Mac Xcode should no longer use this
#elif UNIX_PLATFORM
#error Unix should no longer use this
#endif
/* RestorePlugInFrame
** This is a function that the plug-in must provide (if you are using the
** standard government-issue PIMain.c, this function is implemented there.)
** It takes a jmp_buf as registered through ASPushExceptionFrame and restores
** state based on that jmp_buf, usually through using longjmp.
*/
extern ACCB1 void ACCB2 RestorePlugInFrame(void *asEnviron);
#define _E_RESTORE ASPopExceptionFrame()
#endif /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if DEBUG
/* **ER - 11/29/1997
For debug builds, the macros below enable compile-time checking of common problems
with DURING and HANDLER blocks (in order of frequency):
1. "normal" return statements inside DURING blocks
2. E_RETURN or E_RTRN_VOID statements outside any DURING block
3. E_RETURN or E_RTRN_VOID statements in HANDLER blocks
4. HANDLER without matching DURING
5. HANDLER without matching END_HANDLER
*/
/* Declaration of global integer used below. This variable needs to be defined
somewhere in the plug-in. If you are using the standard government-issue PIMain.c,
it will already be defined there. */
extern int gBadReturnCatcher;
struct _BadReturnCatcherStruct {
int E_RETURNOutsideDURINGBlock; /* This name chosen so it rings a bell if you
see it in the compiler output */
};
/* What's the point of this? Since E_RETURN and E_RTRN_VOID need to actually
call return, we need to redefine gBadReturnCatcher as an integer in the
scope around the actual call to return so our macro-replaced version of
return will work. Otherwise, when the "return" in the E_RETURN macro
(for example), was replaced by our redefined macro, it'd fail to compile
just as if return was placed inside the DURING block */
#define DO_RETURN(x) { int gBadReturnCatcher; return(x); }
#define DO_RETURN_NO_ARGS { int gBadReturnCatcher; return; }
#if USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS
#ifdef __cplusplus
#define DURING { \
try { \
_miExceptionPushPop __exceptionPushPop; \
struct _BadReturnCatcherStruct gBadReturnCatcher;
#define _E_RESTORE /*int _E_RESTORE__BogusLocalDoesNothing = 0*/
#define _E_HANDLER } catch (_miExceptionInfo Exception) {
#else /* __cplusplus */
#define DURING DURING usage must be compiled with C++
#define _E_RESTORE HANDLER usage must be compiled with C++
#define _E_HANDLER HANDLER usage must be compiled with C++
#endif /* __cplusplus */
#else /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if MAC_PLATFORM
#error Mac Xcode should no longer use this
#elif UNIX_PLATFORM
#error Unix should no longer use this
#endif
/* This definition of DURING includes a struct with the same name as the global
integer above. The struct must be declared inside the inner scope of the DURING
so it is NOT defined in the HANDLER! */
#define DURING { \
ACROjmp_buf ASException; \
ASPushExceptionFrame(&ASException, &RestorePlugInFrame); \
if (!ACROsetjmp(ASException)) { \
struct _BadReturnCatcherStruct gBadReturnCatcher;
#define _E_HANDLER } else {
#endif /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if DO_ADDITIONAL_RAISEAWARE_CHECKS
/* Make sure that ASRaiseAware classes are not returned as part of the E_RETURN
mechanism as it leaves the wrong handler on the top of the exception stack.*/
#define E_RETURN(x) { IsNotRaiseAwareClassHelperFunction( x ); gBadReturnCatcher.E_RETURNOutsideDURINGBlock = 1; _E_RESTORE; DO_RETURN(x); }
#else
/* Return calls which are legal inside a DURING block attempt
to modify the member field of the gBadReturnCatcher struct in the local
scope. This will cause a compile-time error if there is no such struct
(and thus, the return call is not enclosed by a DURING block) */
#define E_RETURN(x) { gBadReturnCatcher.E_RETURNOutsideDURINGBlock = 1; _E_RESTORE; DO_RETURN(x); }
#endif
#define E_RTRN_VOID { gBadReturnCatcher.E_RETURNOutsideDURINGBlock = 1; _E_RESTORE; DO_RETURN_NO_ARGS; }
/* returns which are illegal inside a DURING block attempt
to modify the global integer gBadReturnCatcher. This will cause a
compile-time error if the return is inside a DURING block because
it will actually be an attempt to modify the local-scope struct of the
same name. The = operator is not defined for assigning constant integers to structs.
Why are we using a for loop? Here are the considerations involved in choosing
this macro:
1. It must support return statements of the forms "return;", "return ;", and
"return( );". This is why "return" is present at the end of the macro
2. We must use only 1 statement in replacing return. Why? Consider this code:
if ( )
return;
else {
...
}
In order to support this case, we must not replace the "return" statement with
more than one statement, because this will cause the "else" statement to become
untied from the "if" statement. The following code snippet is an example of
the above code snippet after a macro expansion where return is defined as multiple
statements.
if ( )
gBadReturnCatcher = 1;
return;
else {
...
}
3. If we are constrained to replace the "return" statement with only one statement,
there may only be one path of control, and it must reach the return statement
at the end of the macro (so that it can pick up its arguments, if there are any)
The do-nothing for loop below meets these criteria.
*/
#define return for( gBadReturnCatcher = 1;; ) return
/* Why is HANDLER redefined?
1. So you can't put a HANDLER in without a matching DURING. This would likely be caught
by the compiler anyhow, since there'd likely be an "else" without a matching "if"
2. To facilitate catching END_HANDLERs without matching HANDLERs
3) To get rid of pesky "unreferenced local variable" warnings stemming from
DURING blocks which don't contain E_RETURN or E_RTRN_VOID and thus don't
reference the local gBadReturnCatcher structure. */
#define HANDLER _E_RESTORE; gBadReturnCatcher.E_RETURNOutsideDURINGBlock = 1; _E_HANDLER int ENDHANDLEROutsideHANDLER; _E_RESTORE;
/* END_HANDLER is redefined to modify the BadEndHandlerCatcher variable defined by the HANDLER
macro. This will prevent END_HANDLERs without matching HANDLERs (unless, of course,
multiple END_HANDLER statements are found inside the same HANDLER, END_HANDLER block */
#define END_HANDLER ENDHANDLEROutsideHANDLER = 1; }}
#else /* !DEBUG */
#if USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS
#ifdef __cplusplus
#define DURING { \
try { \
_miExceptionPushPop __exceptionPushPop;
#define _E_RESTORE /*int _E_RESTORE__BogusLocalDoesNothing = 0*/
#define _E_HANDLER } catch (_miExceptionInfo Exception) {
#define HANDLER _E_RESTORE; _E_HANDLER _E_RESTORE;
#define END_HANDLER }}
#else /* __cplusplus */
#define DURING DURING usage must be compiled with C++
#define HANDLER HANDLER usage must be compiled with C++
#define END_HANDLER END_HANDLER usage must be compiled with C++
#endif /* __cplusplus */
#else /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#if MAC_PLATFORM
#error Mac Xcode should no longer use this
#elif UNIX_PLATFORM
#error Unix should no longer use this
#endif
#define DURING { \
ACROjmp_buf ASException; \
ASPushExceptionFrame(&ASException, &RestorePlugInFrame); \
if (!ACROsetjmp(ASException)) {
#define HANDLER _E_RESTORE; } else { _E_RESTORE;
#define END_HANDLER }}
#endif /* USE_CPLUSPLUS_EXCEPTIONS_FOR_ASEXCEPTIONS */
#define E_RETURN(x) { _E_RESTORE; return(x); }
#define E_RTRN_VOID { _E_RESTORE; return; }
#endif /* DEBUG */
#define ERRORCODE (ASGetExceptionErrorCode())
#endif /* PI_CORE_VERSION != 0 */
#endif /* PLUGIN */
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
#ifdef __cplusplus
}
#endif
#endif /* _CORVERSION_ID_ONLY */
#endif /* !defined(_H_CorCalls) */