XML_Macros.h

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

Generated on Thu Nov 9 11:45:40 2006 for ACEXML by doxygen 1.3.6