diff options
Diffstat (limited to 'ACE/ACEXML/common/XML_Macros.h')
-rw-r--r-- | ACE/ACEXML/common/XML_Macros.h | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/ACE/ACEXML/common/XML_Macros.h b/ACE/ACEXML/common/XML_Macros.h new file mode 100644 index 00000000000..9ee1e90c196 --- /dev/null +++ b/ACE/ACEXML/common/XML_Macros.h @@ -0,0 +1,456 @@ +// -*- C++ -*- + +// ============================================================================ +/** + * @file XML_Macros.h + * + * $Id$ + * + * Writing code that is portable between platforms with or without + * native C++ exceptions is hard. The following macros offer some + * help on this task. + * + * @author Nanbor Wang <nanbor@cs.wustl.edu> + * @author Aniruddha Gokhale <gokhale@sahyadri.research.bell-labs.com> + * @author Carlos O'Ryan <coryan@uci.edu> + * @author Krishnakumar B <kitty@cs.wustl.edu>, et al. + */ +// ============================================================================ + +// Macros for handling exceptions. + +#ifndef _ACEXML_MACROS_H +#define _ACEXML_MACROS_H + +#include /**/ "ace/pre.h" + +#include "ace/config-all.h" + +# if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +# endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Exception_Macros.h" + +// The Windows MFC exception mechanism requires that a caught CException +// (including the CMemoryException in use here) be freed using its Delete() +// method. Thus, when MFC is in use and we're catching exceptions as a result +// of new(), the exception's Delete() method has to be called. No other +// platform imposes this sort of restriction/requirement. The Windows +// config stuff (at least for MSVC/MFC) defines a ACE_del_bad_alloc macro +// that works with its ACE_bad_alloc macro to implement this cleanup +// requirement. Since no other platform requires this, define it as +// empty here. +#if !defined (ACE_del_bad_alloc) +# define ACE_del_bad_alloc +#endif + +// The following macros assume that an environment variable is passed +// in/out of each function that can throw an exception. The type of the +// environment variable is defined by ACEXML_ENV_TYPE. + +#if !defined (ACEXML_ENV_TYPE) +# define ACEXML_ENV_TYPE ACEXML_Env +#endif /* ACEXML_ENV_TYPE */ + +// The name of the variable defined by ACEXML_TRY_ENV. Below is the name +// that we use by default. If you wish to change it you can redefine +// ACEXML_TRY_ENV to change the default name. Also ACEXML_ADOPT_ENV allows the +// use of non-standard name within a scope. + +#if !defined (ACEXML_TRY_ENV) +# define ACEXML_TRY_ENV _ACEXML_Env_variable +#endif /* ACEXML_TRY_ENV */ + +// The base type of Exception from which all the other exception types are +// derived. By default, it is set to ACEXML_Exception. + +#if !defined (ACEXML_EXCEPTION_TYPE) +# define ACEXML_EXCEPTION_TYPE ACEXML_Exception +#endif /* ACEXML_EXCEPTION_TYPE */ + +// This is the exception caught by ACEXML_CATCHANY. +#if !defined (ACEXML_ANY_EXCEPTION) +# define ACEXML_ANY_EXCEPTION ex +#endif /* ACEXML_ANY_EXCEPTION */ + +// Declare a new environment variable on the stack. The type of the +// environment variable is determined by ACEXML_ENV_TYPE. +#define ACEXML_DECLARE_NEW_ENV \ + ACEXML_ENV_TYPE ACEXML_TRY_ENV + +#if defined (ACE_USES_NATIVE_EXCEPTIONS) +// ----------------------------------------------------------------- + +#define ACEXML_ADOPT_ENV (ENV) + +// No need to check. Native exceptions handle the control flow +// automatically when an exception occurs. +# define ACEXML_CHECK + +// Used when the function requires a return value. +# define ACEXML_CHECK_RETURN(RETV) + +// ACEXML_THROW_R_INT should not be used by the user. +# define ACEXML_THROW_R_INT(EXCEPTION) \ + throw EXCEPTION + +// Throwing an exception is easy. These two macros should _NOT_ be +// used within try blocks. +# define ACEXML_THROW(EXCEPTION) \ + throw EXCEPTION + +// Throwing an exception when the function reqires a return value. +# if defined (__HP_aCC) +# define ACEXML_THROW_RETURN(EXCEPTION, RETV) \ + do \ + { \ + throw EXCEPTION; \ + return RETV; \ + } while (0) +# else /* WIN32 */ +# define ACEXML_THROW_RETURN(EXCEPTION,RETV) \ + throw EXCEPTION +# endif /* WIN32 */ + +// For compilers with native exceptions, we can simply use try to try. ;-) +// do {} while (0) is required to avoid compilation warnings. +# define ACEXML_TRY \ + do \ + { \ + try \ + { +# define ACEXML_TRY_NEW_ENV \ + do \ + { \ + ACEXML_ENV_TYPE ACEXML_TRY_ENV; \ + try \ + { +# define ACEXML_TRY_EX(LABEL) \ + do \ + { \ + try \ + { + +// No need to check for exceptions within try block for compilers with +// native exceptions. +# define ACEXML_TRY_CHECK +# define ACEXML_TRY_CHECK_EX(LABEL) + +// Likewise, throwing exceptions within try blocks is easy. +# define ACEXML_TRY_THROW(EXCEPTION) throw EXCEPTION +# define ACEXML_TRY_THROW_EX(EXCEPTION,LABEL) throw EXCEPTION + +// Same thing for catch. +# define ACEXML_CATCH(EXCEPTION,VAR) \ + } \ + catch (EXCEPTION & VAR) \ + { \ + ACE_UNUSED_ARG (VAR); + +# define ACEXML_CATCHANY \ + ACEXML_CATCH(ACEXML_EXCEPTION_TYPE, ACEXML_ANY_EXCEPTION) + +# define ACEXML_CATCHALL \ + } \ + catch (...) \ + { + +// Rethrowing the exception from catch blocks. +# define ACEXML_RE_THROW throw +# define ACEXML_RE_THROW_EX(LABEL) throw + +// Close the catch block. +# define ACEXML_ENDTRY \ + } \ + } while (0) + +#else /* ! ACEXML_USES_NATIVE_EXCEPTIONS */ +// ----------------------------------------------------------------- + +// When handling compilers without native exceptions, things get a bit +// hairy. Exceptions are simulated using ACEXML_ENV_TYPE. The trick here is to +// make sure the flow-of-control can simulate the case when native +// exceptions occur... + +# define ACEXML_ADOPT_ENV(ENV) ACEXML_ENV_TYPE &ACEXML_TRY_ENV = ENV + +// Follow every statement that could throw exceptions with ACEXML_CHECK or +// ACEXML_CHECK_RETURN. These two macros should _NOT_ be used within try +// blocks. Use ACEXML_TRY_CHECK or ACEXML_TRY_CHECK_EX instead. +# define ACEXML_CHECK \ + if (ACEXML_TRY_ENV . exception () != 0) \ + return +// When function requires a return value +# define ACEXML_CHECK_RETURN(RETV) \ + if (ACEXML_TRY_ENV . exception () != 0) \ + return RETV + +// ACEXML_THROW_R_INT should not be used by the user. +# define ACEXML_THROW_R_INT(EXCEPTION) ACEXML_TRY_ENV.exception (new EXCEPTION) + +// Throwing exceptions will inevitably cause a return from the current +// function. These two macros should _NOT_ be used within try blocks. Use +// ACEXML_TRY_THROW or ACEXML_TRY_THROW_EX instead. +# define ACEXML_THROW(EXCEPTION) \ + do \ + { \ + ACEXML_TRY_ENV.exception (new EXCEPTION); \ + return; \ + } while (0) + +# define ACEXML_THROW_RETURN(EXCEPTION,RETV) \ + do \ + { \ + ACEXML_TRY_ENV.exception (new EXCEPTION); \ + return RETV; \ + } while (0) + +// ACEXML_TRY sets up flags to control program flow. ACEXML_TRY_FLAG acts +// like a one-shot flip-flop. When an exception occurs (detected using +// ACEXML_TRY_CHECK,) ACEXML_TRY_FLAG will be reset and the control goes +// back into ACEXML_TRY_LABEL. Since ACEXML_TRY_FLAG is reset, the try +// block won't get executed again and the control proceeds to the following +// catch blocks. ACEXML_EXCEPTION_NOT_CAUGHT flag is used to prevent +// catching an exception twice. This macro assumes there's already an +// ACEXML_ENV_TYPE variable ACEXML_TRY_ENV defined (which should be the +// case normally) +# define ACEXML_TRY \ + do { \ + int ACEXML_TRY_FLAG = 1; \ + int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \ + ACEXML_TRY_LABEL: \ + if (ACEXML_TRY_FLAG) \ + do { + +// ACEXML_TRY_NEW_ENV functions like the macro ACEXML_TRY but defines a new +// ACEXML_ENV_TYPE variable ACEXML_TRY_ENV. It is most often used in the outer +// most function where no ACEXML_TRY_ENV is available. +# define ACEXML_TRY_NEW_ENV \ + do { \ + ACEXML_ENV_TYPE ACEXML_TRY_ENV;\ + int ACEXML_TRY_FLAG = 1; \ + int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \ + ACEXML_TRY_LABEL: \ + if (ACEXML_TRY_FLAG) \ + do { + +// ACEXML_TRY_EX works exactly like ACEXML_TRY macro except the label used +// in the try block is customizable to avoid name clashing. It should be +// used when nested try blocks or multiple try blocks are required, in the +// same function. +# define ACEXML_TRY_EX(LABEL) \ + do { \ + int ACEXML_TRY_FLAG = 1; \ + int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \ + ACEXML_TRY_LABEL ## LABEL: \ + if (ACEXML_TRY_FLAG) \ + do { + +// Check for exceptions within try blocks. +# define ACEXML_TRY_CHECK \ + { \ + if (ACEXML_TRY_ENV.exception () != 0) \ + { \ + ACEXML_TRY_FLAG = 0; \ + goto ACEXML_TRY_LABEL; \ + } \ + } + +// Checking exception within EX try blocks. +# define ACEXML_TRY_CHECK_EX(LABEL) \ + { \ + if (ACEXML_TRY_ENV.exception () != 0) \ + { \ + ACEXML_TRY_FLAG = 0; \ + goto ACEXML_TRY_LABEL ## LABEL; \ + } \ + } + +// Throwing exception within TRY blocks. +# define ACEXML_TRY_THROW(EXCEPTION) \ + { \ + ACEXML_TRY_ENV.exception (new EXCEPTION); \ + ACEXML_TRY_FLAG = 0; \ + goto ACEXML_TRY_LABEL; \ + } + +# define ACEXML_TRY_THROW_EX(EXCEPTION,LABEL) \ + { \ + ACEXML_TRY_ENV.exception (new EXCEPTION); \ + ACEXML_TRY_FLAG = 0; \ + goto ACEXML_TRY_LABEL ## LABEL; \ + } + +// When exceptions occur or try block finishes execution without exception, +// control will continue in the catch block. This macro first checks if +// there's any uncaught exception left. If all the conditions are met, we +// have caught an exception. It then resets ACEXML_EXCEPTION_NOT_CAUGHT to +// prevent subsequent catch blocks from catching the same exception again, +// and extracts out the underlying exception in ACEXML_TRY_ENV. We also make a +// copy of ACEXML_TRY_ENV in ACEXML_CAUGHT_ENV, in case we want to rethrow the +// exception. ACEXML_TRY_ENV is cleared out after the exception is caught so +// you should not use ACEXML_TRY_ENV within the catch block(You should use the +// exception directly). +# define ACEXML_CATCH(TYPE,VAR) \ + } while (0); \ + do \ + if (ACEXML_TRY_ENV.exception () != 0 && ACEXML_EXCEPTION_NOT_CAUGHT && \ + TYPE::_downcast(ACEXML_TRY_ENV.exception ()) != 0) \ + { \ + ACEXML_ENV_TYPE ACEXML_CAUGHT_ENV = ACEXML_TRY_ENV;\ + ACEXML_EXCEPTION_NOT_CAUGHT = 0; \ + TYPE &VAR = *TYPE::_downcast (ACEXML_CAUGHT_ENV.exception ()); \ + ACE_UNUSED_ARG (VAR); \ + ACEXML_TRY_ENV.clear (); + +// ACEXML_CATCHANY uses ACEXML_CATCH to catch all exceptions derived from +// ACEXML_EXCEPTION_TYPE +# define ACEXML_CATCHANY ACEXML_CATCH (ACEXML_EXCEPTION_TYPE, ACEXML_ANY_EXCEPTION) + +// Since there's no other exception for compilers without exception +// support, we simply catch all ACEXML_EXCEPTION_TYPE exceptions for +// ACEXML_CATCHALL. +# define ACEXML_CATCHALL ACEXML_CATCHANY + +// Rethrowing exception within catch blocks. Notice that we depend on the +// ACEXML_CHECK/ACEXML_CHECK_RETURN following the ACEXML_ENDTRY, or +// ACEXML_TRY_CHECK/ ACEXML_TRY_CHECK_EX following the ACEXML_ENDTRY when +// the catch block is within another try block, to do the "Right +// Thing[TM]." +# define ACEXML_RE_THROW \ + do {\ + ACEXML_TRY_ENV = ACEXML_CAUGHT_ENV; \ + goto ACEXML_TRY_LABEL; \ + } while (0) +# define ACEXML_RE_THROW_EX(LABEL) \ + do {\ + ACEXML_TRY_ENV = ACEXML_CAUGHT_ENV; \ + goto ACEXML_TRY_LABEL ## LABEL; \ + } while (0) + +// Close the try block. Since exceptions may not get caught, and exceptions +// can also be rethrown from the catch block, it's always a good idea to +// follow ACEXML_ENDTRY with ACEXML_CHECK or ACEXML_TRY_CHECK (depending on +// the context.) +# define ACEXML_ENDTRY \ + } while (0); \ + } while (0) + +#endif /* ! ACE_USES_NATIVE_EXCEPTIONS */ + +// ACE_HAS_EXCEPTIONS is not the same as ACE_NEW_THROWS_EXCEPTIONS. +#if defined(ACE_NEW_THROWS_EXCEPTIONS) + +# define ACEXML_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \ + do { try { POINTER = new CONSTRUCTOR; } \ + catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; ACEXML_THROW_R_INT (EXCEPTION); } \ + } while (0) + +#else /* ! ACE_NEW_THROWS_EXCEPTIONS */ + +# define ACEXML_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \ + do { POINTER = new CONSTRUCTOR; \ + if (POINTER == 0) { errno = ENOMEM; ACEXML_THROW_R_INT (EXCEPTION); } \ + } while (0) + +#endif /* ACE_NEW_THROWS_EXCEPTIONS */ + +# define ACEXML_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \ + ACE_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION); + +# define ACEXML_READ_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \ + ACE_Read_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION); + +# define ACEXML_WRITE_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \ + ACE_Write_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION); + +//@{ +/** + * @name Native C++ exceptions portability macros. + * + * The following macros are used to write code portable between platforms + * with and without native C++ exception support. Their main goal is to + * hide the presence of the ACEXML_ENV_TYPE argument, but they collaborate + * with the ACEXML_TRY_* macros to emulate the try/catch blocks. + */ + +/// Define a macro to emit code only when ACEXML_ENV_TYPE is used +#if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACEXML_ENV_BKWD_COMPAT) +# define ACEXML_ENV_EMIT_CODE(X) X +#else +# define ACEXML_ENV_EMIT_CODE(X) +#endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACEXML_ENV_BKWD_COMPAT */ + +/// Another macro to emit code only when ACEXML_ENV_TYPE is used +#if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACEXML_ENV_BKWD_COMPAT) +# define ACEXML_ENV_EMIT_CODE2(X,Y) X,Y +#else +# define ACEXML_ENV_EMIT_CODE2(X,Y) +#endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACEXML_ENV_BKWD_COMPAT */ + +/// Helper macro +#define ACEXML_ENV_EMIT_DUMMY + +/// Declare a ACEXML_ENV_TYPE argument as the last argument of a +/// function +/** + * Normally this macro is used as follows: + * + * <CODE>void my_funct (int x, int y ACEXML_ENV_ARG_DECL);</CODE> + * + * Its purpose is to provide developers (and users) with a mechanism to + * write code that is portable to platforms with and without native C++ + * exceptions. + */ +#define ACEXML_ENV_ARG_DECL \ + ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \ + ACEXML_ENV_TYPE &ACEXML_TRY_ENV) + +/// Declare a ACEXML_ENV_TYPE argument that is not used by the +/// function definition. +/** + * Similar to ACEXML_ENV_ARG_DECL, but the formal parameter name is dropped to + * avoid warnings about unused parameters + */ +#define ACEXML_ENV_ARG_DECL_NOT_USED \ + ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \ + ACEXML_ENV_TYPE &) + +/// Declare a ACEXML_ENV_TYPE argument for methods that do not take any other +/// parameters +#define ACEXML_ENV_SINGLE_ARG_DECL \ + ACEXML_ENV_EMIT_CODE(ACEXML_ENV_TYPE &ACEXML_TRY_ENV) + +/// Declare a ACEXML_ENV_TYPE argument for methods which don't use it. +#define ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED \ + ACEXML_ENV_EMIT_CODE(ACEXML_ENV_TYPE &) + +/// Use the ACEXML_ENV_TYPE argument in a nested call +#define ACEXML_ENV_ARG_PARAMETER \ + ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \ + ACEXML_TRY_ENV) + +/// Use the ACEXML_ENV_TYPE argument in a nested call, assuming that the +/// called function takes only the ACEXML_TRY_ENV argument. +#define ACEXML_ENV_SINGLE_ARG_PARAMETER \ + ACEXML_ENV_EMIT_CODE(ACEXML_TRY_ENV) + +/// Eliminate unused argument warnings about ACEXML_TRY_ENV +#define ACEXML_ENV_ARG_NOT_USED \ + ACEXML_ENV_EMIT_CODE(ACE_UNUSED_ARG(ACEXML_TRY_ENV)) +//@} + +#if !defined (ACE_USES_NATIVE_EXCEPTIONS) +// This thing can be moved above when we drop ACEXML_ENV_BKWD_COMPAT. +# define ACEXML_ENV_RAISE(ex) ACEXML_TRY_ENV.exception (ex) +#else +# define ACEXML_ENV_RAISE(ex) (ex)->_raise () +#endif /* ACEXML_CORBA_HAS_EXCEPTIONS */ + +#include /**/ "ace/post.h" + +#endif /* _ACEXML_MACROS_H */ |