XML_Macros.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // ============================================================================
00004 /**
00005  * @file XML_Macros.h
00006  *
00007  * $Id: XML_Macros.h 79396 2007-08-19 14:04:08Z sowayaa $
00008  *
00009  *   Writing code that is portable between platforms with or without
00010  *   native C++ exceptions is hard.  The following macros offer some
00011  *   help on this task.
00012  *
00013  *  @author Nanbor Wang <nanbor@cs.wustl.edu>
00014  *  @author Aniruddha Gokhale  <gokhale@sahyadri.research.bell-labs.com>
00015  *  @author Carlos O'Ryan  <coryan@uci.edu>
00016  *  @author Krishnakumar B <kitty@cs.wustl.edu>, et al.
00017  */
00018 // ============================================================================
00019 
00020 // Macros for handling exceptions.
00021 
00022 #ifndef _ACEXML_MACROS_H
00023 #define _ACEXML_MACROS_H
00024 
00025 #include /**/ "ace/pre.h"
00026 
00027 #include "ace/config-all.h"
00028 
00029 # if !defined (ACE_LACKS_PRAGMA_ONCE)
00030 #   pragma once
00031 # endif /* ACE_LACKS_PRAGMA_ONCE */
00032 
00033 #include "ace/Exception_Macros.h"
00034 
00035 // The Windows MFC exception mechanism requires that a caught CException
00036 // (including the CMemoryException in use here) be freed using its Delete()
00037 // method. Thus, when MFC is in use and we're catching exceptions as a result
00038 // of new(), the exception's Delete() method has to be called. No other
00039 // platform imposes this sort of restriction/requirement. The Windows
00040 // config stuff (at least for MSVC/MFC) defines a ACE_del_bad_alloc macro
00041 // that works with its ACE_bad_alloc macro to implement this cleanup
00042 // requirement. Since no other platform requires this, define it as
00043 // empty here.
00044 #if !defined (ACE_del_bad_alloc)
00045 #  define ACE_del_bad_alloc
00046 #endif
00047 
00048 // The following macros assume that an environment variable is passed
00049 // in/out of each function that can throw an exception. The type of the
00050 // environment variable is defined by ACEXML_ENV_TYPE.
00051 
00052 #if !defined (ACEXML_ENV_TYPE)
00053 # define ACEXML_ENV_TYPE  ACEXML_Env
00054 #endif /* ACEXML_ENV_TYPE */
00055 
00056 // The name of the variable defined by ACEXML_TRY_ENV. Below is the name
00057 // that we use by default. If you wish to change it you can redefine
00058 // ACEXML_TRY_ENV to change the default name. Also ACEXML_ADOPT_ENV allows the
00059 // use of non-standard name within a scope.
00060 
00061 #if !defined (ACEXML_TRY_ENV)
00062 # define ACEXML_TRY_ENV  _ACEXML_Env_variable
00063 #endif /* ACEXML_TRY_ENV */
00064 
00065 // The base type of Exception from which all the other exception types are
00066 // derived. By default, it is set to ACEXML_Exception.
00067 
00068 #if !defined (ACEXML_EXCEPTION_TYPE)
00069 # define ACEXML_EXCEPTION_TYPE  ACEXML_Exception
00070 #endif /* ACEXML_EXCEPTION_TYPE */
00071 
00072 // This is the exception caught by ACEXML_CATCHANY.
00073 #if !defined (ACEXML_ANY_EXCEPTION)
00074 # define ACEXML_ANY_EXCEPTION ex
00075 #endif /* ACEXML_ANY_EXCEPTION */
00076 
00077 // Declare a new environment variable on the stack. The type of the
00078 // environment variable is determined by ACEXML_ENV_TYPE.
00079 #define ACEXML_DECLARE_NEW_ENV \
00080      ACEXML_ENV_TYPE ACEXML_TRY_ENV
00081 
00082 #if defined (ACE_USES_NATIVE_EXCEPTIONS)
00083 // -----------------------------------------------------------------
00084 
00085 #define ACEXML_ADOPT_ENV (ENV)
00086 
00087 // No need to check. Native exceptions handle the control flow
00088 // automatically when an exception occurs.
00089 # define ACEXML_CHECK
00090 
00091 // Used when the function requires a return value.
00092 # define ACEXML_CHECK_RETURN(RETV)
00093 
00094 // ACEXML_THROW_R_INT should not be used by the user.
00095 # define ACEXML_THROW_R_INT(EXCEPTION) \
00096       throw EXCEPTION
00097 
00098 // Throwing an exception is easy. These two macros should _NOT_ be
00099 // used within try blocks.
00100 # define ACEXML_THROW(EXCEPTION) \
00101       throw EXCEPTION
00102 
00103 // Throwing an exception when the function reqires a return value.
00104 # if defined (__HP_aCC)
00105 #   define ACEXML_THROW_RETURN(EXCEPTION, RETV) \
00106       do \
00107         { \
00108           throw EXCEPTION; \
00109           return RETV; \
00110         } while (0)
00111 # else /* WIN32 */
00112 #   define ACEXML_THROW_RETURN(EXCEPTION,RETV) \
00113         throw EXCEPTION
00114 # endif /* WIN32 */
00115 
00116 // For compilers with native exceptions, we can simply use try to try. ;-)
00117 // do {} while (0) is required to avoid compilation warnings.
00118 # define ACEXML_TRY \
00119    do \
00120      { \
00121        try \
00122          {
00123 # define ACEXML_TRY_NEW_ENV \
00124    do \
00125      { \
00126        ACEXML_ENV_TYPE ACEXML_TRY_ENV; \
00127        try \
00128          {
00129 # define ACEXML_TRY_EX(LABEL) \
00130    do \
00131      { \
00132        try \
00133          {
00134 
00135 // No need to check for exceptions within try block for compilers with
00136 // native exceptions.
00137 # define ACEXML_TRY_CHECK
00138 # define ACEXML_TRY_CHECK_EX(LABEL)
00139 
00140 // Likewise, throwing exceptions within try blocks is easy.
00141 # define ACEXML_TRY_THROW(EXCEPTION) throw EXCEPTION
00142 # define ACEXML_TRY_THROW_EX(EXCEPTION,LABEL) throw EXCEPTION
00143 
00144 // Same thing for catch.
00145 # define ACEXML_CATCH(EXCEPTION,VAR) \
00146          } \
00147        catch (EXCEPTION & VAR) \
00148          { \
00149            ACE_UNUSED_ARG (VAR);
00150 
00151 # define ACEXML_CATCHANY \
00152        ACEXML_CATCH(ACEXML_EXCEPTION_TYPE, ACEXML_ANY_EXCEPTION)
00153 
00154 # define ACEXML_CATCHALL \
00155          } \
00156        catch (...) \
00157          {
00158 
00159 // Rethrowing the exception from catch blocks.
00160 # define ACEXML_RE_THROW throw
00161 # define ACEXML_RE_THROW_EX(LABEL) throw
00162 
00163 // Close the catch block.
00164 # define ACEXML_ENDTRY \
00165          } \
00166      } while (0)
00167 
00168 #else /* ! ACEXML_USES_NATIVE_EXCEPTIONS */
00169 // -----------------------------------------------------------------
00170 
00171 // When handling compilers without native exceptions, things get a bit
00172 // hairy. Exceptions are simulated using ACEXML_ENV_TYPE. The trick here is to
00173 // make sure the flow-of-control can simulate the case when native
00174 // exceptions occur...
00175 
00176 # define ACEXML_ADOPT_ENV(ENV) ACEXML_ENV_TYPE &ACEXML_TRY_ENV = ENV
00177 
00178 // Follow every statement that could throw exceptions with ACEXML_CHECK or
00179 // ACEXML_CHECK_RETURN. These two macros should _NOT_ be used within try
00180 // blocks. Use ACEXML_TRY_CHECK or ACEXML_TRY_CHECK_EX instead.
00181 # define ACEXML_CHECK \
00182     if (ACEXML_TRY_ENV . exception () != 0) \
00183       return
00184 // When function requires a return value
00185 # define ACEXML_CHECK_RETURN(RETV) \
00186     if (ACEXML_TRY_ENV . exception () != 0) \
00187       return RETV
00188 
00189 // ACEXML_THROW_R_INT should not be used by the user.
00190 # define ACEXML_THROW_R_INT(EXCEPTION) ACEXML_TRY_ENV.exception (new EXCEPTION)
00191 
00192 // Throwing exceptions will inevitably cause a return from the current
00193 // function. These two macros should _NOT_ be used within try blocks. Use
00194 // ACEXML_TRY_THROW or ACEXML_TRY_THROW_EX instead.
00195 # define ACEXML_THROW(EXCEPTION) \
00196     do \
00197       { \
00198         ACEXML_TRY_ENV.exception (new EXCEPTION); \
00199         return; \
00200       } while (0)
00201 
00202 # define ACEXML_THROW_RETURN(EXCEPTION,RETV) \
00203     do \
00204       { \
00205         ACEXML_TRY_ENV.exception (new EXCEPTION); \
00206         return RETV; \
00207       } while (0)
00208 
00209 // ACEXML_TRY sets up flags to control program flow. ACEXML_TRY_FLAG acts
00210 // like a one-shot flip-flop. When an exception occurs (detected using
00211 // ACEXML_TRY_CHECK,) ACEXML_TRY_FLAG will be reset and the control goes
00212 // back into ACEXML_TRY_LABEL. Since ACEXML_TRY_FLAG is reset, the try
00213 // block won't get executed again and the control proceeds to the following
00214 // catch blocks. ACEXML_EXCEPTION_NOT_CAUGHT flag is used to prevent
00215 // catching an exception twice. This macro assumes there's already an
00216 // ACEXML_ENV_TYPE variable ACEXML_TRY_ENV defined (which should be the
00217 // case normally)
00218 # define ACEXML_TRY \
00219    do { \
00220      int ACEXML_TRY_FLAG = 1; \
00221      int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \
00222    ACEXML_TRY_LABEL: \
00223      if (ACEXML_TRY_FLAG) \
00224        do {
00225 
00226 // ACEXML_TRY_NEW_ENV functions like the macro ACEXML_TRY but defines a new
00227 // ACEXML_ENV_TYPE variable ACEXML_TRY_ENV. It is most often used in the outer
00228 // most function where no ACEXML_TRY_ENV is available.
00229 # define ACEXML_TRY_NEW_ENV \
00230    do { \
00231      ACEXML_ENV_TYPE ACEXML_TRY_ENV;\
00232      int ACEXML_TRY_FLAG = 1; \
00233      int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \
00234    ACEXML_TRY_LABEL: \
00235      if (ACEXML_TRY_FLAG) \
00236        do {
00237 
00238 // ACEXML_TRY_EX works exactly like ACEXML_TRY macro except the label used
00239 // in the try block is customizable to avoid name clashing. It should be
00240 // used when nested try blocks or multiple try blocks are required, in the
00241 // same function.
00242 # define ACEXML_TRY_EX(LABEL) \
00243    do { \
00244      int ACEXML_TRY_FLAG = 1; \
00245      int ACEXML_EXCEPTION_NOT_CAUGHT = 1; \
00246    ACEXML_TRY_LABEL ## LABEL: \
00247      if (ACEXML_TRY_FLAG) \
00248        do {
00249 
00250 // Check for exceptions within try blocks.
00251 # define ACEXML_TRY_CHECK \
00252     { \
00253       if (ACEXML_TRY_ENV.exception () != 0) \
00254         { \
00255           ACEXML_TRY_FLAG = 0; \
00256           goto ACEXML_TRY_LABEL; \
00257         } \
00258     }
00259 
00260 // Checking exception within EX try blocks.
00261 # define ACEXML_TRY_CHECK_EX(LABEL) \
00262     { \
00263       if (ACEXML_TRY_ENV.exception () != 0) \
00264         { \
00265           ACEXML_TRY_FLAG = 0; \
00266           goto ACEXML_TRY_LABEL ## LABEL; \
00267         } \
00268     }
00269 
00270 // Throwing exception within TRY blocks.
00271 # define ACEXML_TRY_THROW(EXCEPTION) \
00272     { \
00273       ACEXML_TRY_ENV.exception (new EXCEPTION); \
00274       ACEXML_TRY_FLAG = 0; \
00275       goto ACEXML_TRY_LABEL; \
00276     }
00277 
00278 # define ACEXML_TRY_THROW_EX(EXCEPTION,LABEL) \
00279     { \
00280       ACEXML_TRY_ENV.exception (new EXCEPTION); \
00281       ACEXML_TRY_FLAG = 0; \
00282       goto ACEXML_TRY_LABEL ## LABEL; \
00283     }
00284 
00285 // When exceptions occur or try block finishes execution without exception,
00286 // control will continue in the catch block. This macro first checks if
00287 // there's any uncaught exception left. If all the conditions are met, we
00288 // have caught an exception. It then resets ACEXML_EXCEPTION_NOT_CAUGHT to
00289 // prevent subsequent catch blocks from catching the same exception again,
00290 // and extracts out the underlying exception in ACEXML_TRY_ENV. We also make a
00291 // copy of ACEXML_TRY_ENV in ACEXML_CAUGHT_ENV, in case we want to rethrow the
00292 // exception. ACEXML_TRY_ENV is cleared out after the exception is caught so
00293 // you should not use ACEXML_TRY_ENV within the catch block(You should use the
00294 // exception directly).
00295 # define ACEXML_CATCH(TYPE,VAR) \
00296      } while (0); \
00297    do \
00298      if (ACEXML_TRY_ENV.exception () != 0 && ACEXML_EXCEPTION_NOT_CAUGHT && \
00299        TYPE::_downcast(ACEXML_TRY_ENV.exception ()) != 0) \
00300        { \
00301          ACEXML_ENV_TYPE ACEXML_CAUGHT_ENV = ACEXML_TRY_ENV;\
00302          ACEXML_EXCEPTION_NOT_CAUGHT = 0; \
00303          TYPE &VAR = *TYPE::_downcast (ACEXML_CAUGHT_ENV.exception ()); \
00304          ACE_UNUSED_ARG (VAR); \
00305          ACEXML_TRY_ENV.clear ();
00306 
00307 // ACEXML_CATCHANY uses ACEXML_CATCH to catch all exceptions derived from
00308 // ACEXML_EXCEPTION_TYPE
00309 # define ACEXML_CATCHANY ACEXML_CATCH (ACEXML_EXCEPTION_TYPE, ACEXML_ANY_EXCEPTION)
00310 
00311 // Since there's no other exception for compilers without exception
00312 // support, we simply catch all ACEXML_EXCEPTION_TYPE exceptions for
00313 // ACEXML_CATCHALL.
00314 # define ACEXML_CATCHALL ACEXML_CATCHANY
00315 
00316 // Rethrowing exception within catch blocks. Notice that we depend on the
00317 // ACEXML_CHECK/ACEXML_CHECK_RETURN following the ACEXML_ENDTRY, or
00318 // ACEXML_TRY_CHECK/ ACEXML_TRY_CHECK_EX following the ACEXML_ENDTRY when
00319 // the catch block is within another try block, to do the "Right
00320 // Thing[TM]."
00321 # define ACEXML_RE_THROW \
00322     do {\
00323       ACEXML_TRY_ENV = ACEXML_CAUGHT_ENV; \
00324       goto ACEXML_TRY_LABEL; \
00325     } while (0)
00326 # define ACEXML_RE_THROW_EX(LABEL) \
00327     do {\
00328       ACEXML_TRY_ENV = ACEXML_CAUGHT_ENV; \
00329       goto ACEXML_TRY_LABEL ## LABEL; \
00330     } while (0)
00331 
00332 // Close the try block. Since exceptions may not get caught, and exceptions
00333 // can also be rethrown from the catch block, it's always a good idea to
00334 // follow ACEXML_ENDTRY with ACEXML_CHECK or ACEXML_TRY_CHECK (depending on
00335 // the context.)
00336 # define ACEXML_ENDTRY \
00337       } while (0); \
00338     } while (0)
00339 
00340 #endif /* ! ACE_USES_NATIVE_EXCEPTIONS */
00341 
00342 // ACE_HAS_EXCEPTIONS is not the same as ACE_NEW_THROWS_EXCEPTIONS.
00343 #if defined(ACE_NEW_THROWS_EXCEPTIONS)
00344 
00345 #   define ACEXML_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \
00346      do { try { POINTER = new CONSTRUCTOR; } \
00347        catch (ACE_bad_alloc) { ACE_del_bad_alloc errno = ENOMEM; ACEXML_THROW_R_INT (EXCEPTION); } \
00348      } while (0)
00349 
00350 #else /* ! ACE_NEW_THROWS_EXCEPTIONS */
00351 
00352 #   define ACEXML_NEW_THROW_EX(POINTER,CONSTRUCTOR,EXCEPTION) \
00353      do { POINTER = new CONSTRUCTOR; \
00354        if (POINTER == 0) { errno = ENOMEM; ACEXML_THROW_R_INT (EXCEPTION); } \
00355      } while (0)
00356 
00357 #endif /* ACE_NEW_THROWS_EXCEPTIONS */
00358 
00359 # define ACEXML_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
00360   ACE_Guard< MUTEX > OBJ (LOCK); \
00361     if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION);
00362 
00363 # define ACEXML_READ_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
00364   ACE_Read_Guard< MUTEX > OBJ (LOCK); \
00365     if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION);
00366 
00367 # define ACEXML_WRITE_GUARD_THROW_EX(MUTEX,OBJ,LOCK,EXCEPTION) \
00368   ACE_Write_Guard< MUTEX > OBJ (LOCK); \
00369     if (OBJ.locked () == 0) ACEXML_THROW_R_INT (EXCEPTION);
00370 
00371 //@{
00372 /**
00373  * @name Native C++ exceptions portability macros.
00374  *
00375  * The following macros are used to write code portable between platforms
00376  * with and without native C++ exception support. Their main goal is to
00377  * hide the presence of the ACEXML_ENV_TYPE argument, but they collaborate
00378  * with the ACEXML_TRY_* macros to emulate the try/catch blocks.
00379  */
00380 
00381 /// Define a macro to emit code only when ACEXML_ENV_TYPE is used
00382 #if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACEXML_ENV_BKWD_COMPAT)
00383 #  define ACEXML_ENV_EMIT_CODE(X) X
00384 #else
00385 #  define ACEXML_ENV_EMIT_CODE(X)
00386 #endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACEXML_ENV_BKWD_COMPAT */
00387 
00388 /// Another macro to emit code only when ACEXML_ENV_TYPE is used
00389 #if !defined (ACE_USES_NATIVE_EXCEPTIONS) || defined (ACEXML_ENV_BKWD_COMPAT)
00390 #  define ACEXML_ENV_EMIT_CODE2(X,Y) X,Y
00391 #else
00392 #  define ACEXML_ENV_EMIT_CODE2(X,Y)
00393 #endif /* ACE_USES_NATIVE_EXCEPTIONS && ! ACEXML_ENV_BKWD_COMPAT */
00394 
00395 /// Helper macro
00396 #define ACEXML_ENV_EMIT_DUMMY
00397 
00398 /// Declare a ACEXML_ENV_TYPE argument as the last argument of a
00399 /// function
00400 /**
00401  * Normally this macro is used as follows:
00402  *
00403  * <CODE>void my_funct (int x, int y ACEXML_ENV_ARG_DECL);</CODE>
00404  *
00405  * Its purpose is to provide developers (and users) with a mechanism to
00406  * write code that is portable to platforms with and without native C++
00407  * exceptions.
00408  */
00409 #define ACEXML_ENV_ARG_DECL \
00410     ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \
00411                        ACEXML_ENV_TYPE &ACEXML_TRY_ENV)
00412 
00413 /// Declare a ACEXML_ENV_TYPE argument that is not used by the
00414 /// function definition.
00415 /**
00416  * Similar to ACEXML_ENV_ARG_DECL, but the formal parameter name is dropped to
00417  * avoid warnings about unused parameters
00418  */
00419 #define ACEXML_ENV_ARG_DECL_NOT_USED \
00420     ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \
00421                        ACEXML_ENV_TYPE &)
00422 
00423 /// Declare a ACEXML_ENV_TYPE argument for methods that do not take any other
00424 /// parameters
00425 #define ACEXML_ENV_SINGLE_ARG_DECL \
00426     ACEXML_ENV_EMIT_CODE(ACEXML_ENV_TYPE &ACEXML_TRY_ENV)
00427 
00428 /// Declare a ACEXML_ENV_TYPE argument for methods which don't use it.
00429 #define ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED \
00430     ACEXML_ENV_EMIT_CODE(ACEXML_ENV_TYPE &)
00431 
00432 /// Use the ACEXML_ENV_TYPE argument in a nested call
00433 #define ACEXML_ENV_ARG_PARAMETER \
00434     ACEXML_ENV_EMIT_CODE2(ACEXML_ENV_EMIT_DUMMY, \
00435                        ACEXML_TRY_ENV)
00436 
00437 /// Use the ACEXML_ENV_TYPE argument in a nested call, assuming that the
00438 /// called function takes only the ACEXML_TRY_ENV argument.
00439 #define ACEXML_ENV_SINGLE_ARG_PARAMETER \
00440     ACEXML_ENV_EMIT_CODE(ACEXML_TRY_ENV)
00441 
00442 /// Eliminate unused argument warnings about ACEXML_TRY_ENV
00443 #define ACEXML_ENV_ARG_NOT_USED \
00444     ACEXML_ENV_EMIT_CODE(ACE_UNUSED_ARG(ACEXML_TRY_ENV))
00445 //@}
00446 
00447 #if !defined (ACE_USES_NATIVE_EXCEPTIONS)
00448 // This thing can be moved above when we drop ACEXML_ENV_BKWD_COMPAT.
00449 #  define ACEXML_ENV_RAISE(ex) ACEXML_TRY_ENV.exception (ex)
00450 #else
00451 #  define ACEXML_ENV_RAISE(ex) (ex)->_raise ()
00452 #endif /* ACEXML_CORBA_HAS_EXCEPTIONS */
00453 
00454 #include /**/ "ace/post.h"
00455 
00456 #endif /* _ACEXML_MACROS_H */

Generated on Sun Jan 27 13:04:15 2008 for ACEXML by doxygen 1.3.6