coherence/lang/compatibility.hpp

00001 /*
00002 * compatibility.hpp
00003 *
00004 * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
00005 *
00006 * Oracle is a registered trademarks of Oracle Corporation and/or its
00007 * affiliates.
00008 *
00009 * This software is the confidential and proprietary information of Oracle
00010 * Corporation. You shall not disclose such confidential and proprietary
00011 * information and shall use it only in accordance with the terms of the
00012 * license agreement you entered into with Oracle.
00013 *
00014 * This notice may not be removed or altered.
00015 */
00016 #ifndef COH_COMPATIBILITY_HPP
00017 #define COH_COMPATIBILITY_HPP
00018 
00019 /// @cond EXCLUDE
00020 
00021 // ----- identify operating system ------------------------------------------
00022 
00023 #if defined(_WIN32)
00024 #   define COH_OS_WINDOWS
00025 #   define COH_LIB_PREFIX ""
00026 #   define COH_LIB_SUFFIX ".dll"
00027 #   if defined(_WIN64)
00028 #      define COH_OS_WIN64 // Windows 2003/2008/Vista
00029 #      define COH_PLATFORM Microsoft Windows x64
00030 #   else
00031 #      define COH_OS_WIN32 // Windows NT/2000/XP
00032 #      define COH_PLATFORM Microsoft Windows x86
00033 #   endif
00034 #elif defined(__sun) || defined(sun)
00035 #   define COH_OS_SOLARIS // Sun Solaris
00036 #   define COH_OS_UNIX
00037 #   define COH_LIB_PREFIX "lib"
00038 #   define COH_LIB_SUFFIX ".so"
00039 #   include <sys/types.h> // for _LP64 definition
00040 #   if defined(__sparc)
00041 #       if defined(_LP64)
00042 #           define COH_OS_SOLARIS64
00043 #           define COH_PLATFORM Sun Solaris SPARC 64b
00044 #       else
00045 #           define COH_OS_SOLARIS32
00046 #           define COH_PLATFORM Sun Solaris SPARC 32b
00047 #       endif
00048 #   elif defined(__x86)
00049 #       if defined(_LP64)
00050 #           define COH_OS_SOLARIS64
00051 #           define COH_PLATFORM Sun Solaris x64
00052 #       else
00053 #           define COH_OS_SOLARIS32
00054 #           define COH_PLATFORM Sun Solaris x86
00055 #       endif
00056 #   endif
00057 #elif defined(__linux__)
00058 #   define COH_OS_LINUX // Linux
00059 #   define COH_LIB_PREFIX "lib"
00060 #   define COH_LIB_SUFFIX ".so"
00061 #   define COH_OS_UNIX
00062 #   if defined(__x86_64__) || defined(__amd64__)
00063 #       define COH_OS_LINUX64
00064 #       define COH_PLATFORM Linux x64
00065 #   elif defined(__x86_32__) || defined(__i386__)
00066 #       define COH_OS_LINUX32
00067 #       define COH_PLATFORM Linux x86
00068 #   endif
00069 #elif defined(__APPLE__)
00070 #   define COH_OS_DARWIN // Mac OS X
00071 #   define COH_OS_UNIX
00072 #   define COH_LIB_PREFIX "lib"
00073 #   define COH_LIB_SUFFIX ".dylib"
00074 #   if defined(__x86_64__) || defined(__amd64__)
00075 #       define COH_OS_DARWIN64
00076 #       define COH_PLATFORM Apple Mac OS X x64
00077 #   elif defined(__x86_32__) || defined(__i386__)
00078 #       define COH_OS_DARWIN32
00079 #       define COH_PLATFORM Apple Mac OS X x86
00080 #   endif
00081 #endif
00082 
00083 #ifndef COH_PLATFORM
00084 #   error "Coherence for C++ does not support this platform."
00085 #endif
00086 
00087 
00088 // ----- identify compiler --------------------------------------------------
00089 
00090 #if defined(_MSC_VER) && _MSC_VER >= 1400 // Visual C++ 2005
00091 #   define COH_CC_MSVC // Microsoft Visual C/C++
00092 #elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590
00093 #   define COH_CC_SUN // Forte Developer, or Sun Studio C++
00094 #elif defined(__GNUG__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
00095 #   define COH_CC_GNU // GNU C++
00096 #else
00097 #   error "Coherence for C++ does not support this compiler or compiler version."
00098 #endif
00099 
00100 
00101 // ----- disable select warnings --------------------------------------------
00102 
00103 /**
00104 * Macro for disabling select warnings on MSVC. The warnings are automatically
00105 * disabled upon opening a coherence namespace (using the COH_OPEN_NAMESPACE
00106 * macros), and re-enabled when the namespace is exited via
00107 * COH_CLOSE_NAMESPACE.
00108 */
00109 #if defined(COH_CC_MSVC)
00110     #define COH_PRAGMA_PUSH \
00111     __pragma(warning(push)) \
00112     /* Allow multiple interface inheritance (inheritance via dominance) */ \
00113     __pragma(warning(disable : 4250)) \
00114     /* Allow non-exported DLL templates */ \
00115     __pragma(warning(disable : 4251)) \
00116     /* Exported class inheritance from non-exported class, needed for specs */ \
00117     __pragma(warning(disable : 4275)) \
00118     /* TypedHandle/Holder: multiple copy constructors */ \
00119     __pragma(warning(disable : 4521)) \
00120     /* Member/WeakHandle: assignment operators for const/non-const type */ \
00121     __pragma(warning(disable : 4522)) \
00122     /* Lack of return statements are being promoted to errors, when control \
00123        path results in throw */ \
00124     __pragma(warning(disable : 4715; disable : 4716))
00125 
00126     #define COH_PRAGMA_POP __pragma(warning(pop))
00127 #else
00128     #define COH_PRAGMA_PUSH
00129     #define COH_PRAGMA_POP
00130 #endif
00131 
00132 /**
00133 * Macro for temporarily disabling above warnings for the duration of a
00134 * single statement.  This is only needed for code which is not enclosed in a
00135 * COH_OPEN/CLOSE_NAMESPACE block.
00136 */
00137 #define COH_NO_WARN(STMT) COH_PRAGMA_PUSH STMT COH_PRAGMA_POP
00138 
00139 /**
00140 * These macros are used to indicate that a function will not return normally.
00141 *
00142 * Usage example:
00143 * @code
00144 * COH_NO_RETURN_PRE void doSomething() COH_NO_RETURN_POST
00145 *     {
00146 *     COH_NO_RETURN_STMT(doSomething2());
00147 *     }
00148 * @endcode
00149 */
00150 #if defined(COH_CC_MSVC)
00151     #define COH_NO_RETURN_PRE __declspec(noreturn)
00152     #define COH_NO_RETURN_POST
00153     #define COH_NO_RETURN_STMT(expr) expr
00154 #elif defined(COH_CC_GNU)
00155     #define COH_NO_RETURN_PRE
00156     #define COH_NO_RETURN_POST __attribute__((noreturn))
00157     #define COH_NO_RETURN_STMT(expr) expr
00158 #elif defined(COH_CC_SUN)
00159     #define COH_NO_RETURN_PRE
00160     #define COH_NO_RETURN_POST
00161     #define COH_NO_RETURN_STMT(expr)\
00162         do { expr; throw std::exception(); } while (0)
00163 #else
00164     #define COH_NO_RETURN_PRE
00165     #define COH_NO_RETURN_POST
00166     #define COH_NO_RETURN_STMT(expr) expr
00167 #endif
00168 
00169 
00170 // ----- namespace macros ---------------------------------------------------
00171 
00172 /**
00173 * Define the existence of the coherence::lang namespace
00174 */
00175 namespace coherence { namespace lang {}}
00176 
00177 #define COH_OPEN_NAMESPACE(ns) namespace ns { \
00178     COH_PRAGMA_PUSH \
00179     using namespace coherence::lang;
00180 
00181 #define COH_INNER_NAMESPACE(ns) namespace ns {
00182 
00183 #define COH_OPEN_NAMESPACE2(ns1, ns2)\
00184     COH_OPEN_NAMESPACE (ns1) COH_INNER_NAMESPACE (ns2)
00185 
00186 #define COH_OPEN_NAMESPACE3(ns1, ns2, ns3)\
00187     COH_OPEN_NAMESPACE2 (ns1, ns2) COH_INNER_NAMESPACE (ns3)
00188 
00189 #define COH_OPEN_NAMESPACE4(ns1, ns2, ns3, ns4)\
00190     COH_OPEN_NAMESPACE3 (ns1, ns2, ns3) COH_INNER_NAMESPACE (ns4)
00191 
00192 #define COH_OPEN_NAMESPACE5(ns1, ns2, ns3, ns4, ns5)\
00193     COH_OPEN_NAMESPACE4 (ns1, ns2, ns3, ns4) COH_INNER_NAMESPACE (ns5)
00194 
00195 #define COH_OPEN_NAMESPACE6(ns1, ns2, ns3, ns4, ns5, ns6)\
00196     COH_OPEN_NAMESPACE5 (ns1, ns2, ns3, ns4, ns5) COH_INNER_NAMESPACE (ns6)
00197 
00198 #define COH_OPEN_NAMESPACE7(ns1, ns2, ns3, ns4, ns5, ns6, ns7)\
00199     COH_OPEN_NAMESPACE6 (ns1, ns2, ns3, ns4, ns5, ns6) COH_INNER_NAMESPACE (ns7)
00200 
00201 #define COH_CLOSE_NAMESPACE COH_PRAGMA_POP }
00202 
00203 #define COH_CLOSE_NAMESPACE2 COH_PRAGMA_POP } }
00204 
00205 #define COH_CLOSE_NAMESPACE3 COH_PRAGMA_POP } } }
00206 
00207 #define COH_CLOSE_NAMESPACE4 COH_PRAGMA_POP } } } }
00208 
00209 #define COH_CLOSE_NAMESPACE5 COH_PRAGMA_POP } } } } }
00210 
00211 #define COH_CLOSE_NAMESPACE6 COH_PRAGMA_POP } } } } } }
00212 
00213 #define COH_CLOSE_NAMESPACE7 COH_PRAGMA_POP } } } } } } }
00214 
00215 
00216 // ----- general utility macros ---------------------------------------------
00217 
00218 /**
00219 * This macro "mangles" the specified @a Name, producing an identifier which
00220 * is unique in the current file.
00221 *
00222 * Note. This implementation of COH_UNIQUE_IDENTIFIER (as well as macros that
00223 * use it) won't work in MSVC 6.0 when -ZI is on! See Q199057.
00224 *
00225 * @param Name the name to produce a new identifier on its basis
00226 */
00227 #define COH_JOIN(X, Y) COH_DO_JOIN(X, Y)
00228 #define COH_DO_JOIN(X, Y) COH_DO_JOIN2(X, Y)
00229 #define COH_DO_JOIN2(X, Y) X##Y
00230 #ifdef COH_CC_MSVC_NET // MSVC 2002 and later
00231 #   define COH_UNIQUE_IDENTIFIER(Name) COH_JOIN(Name, __COUNTER__)
00232 #else
00233 #   define COH_UNIQUE_IDENTIFIER(Name) COH_JOIN(Name, __LINE__)
00234 #endif
00235 
00236 /**
00237 * This macro will ensure initialization of function local statics at library
00238 * load time. This should be used to force the initialization of statics
00239 * in a thread safe way.  The general form is:
00240 *
00241 * SomeType::Handle staticAccessorFunction()
00242 *     {
00243 *     static FinalHandle<SomeType> hStatic = SomeType::create();
00244 *     return hStatic;
00245 *     }
00246 * COH_STATIC_INIT(staticAccessorFunction());
00247 *
00248 * @param FUNC  The static function and parameters to call that requires
00249 *             initialization.
00250 */
00251 #define COH_STATIC_INIT(FUNC) \
00252     static const bool COH_UNIQUE_IDENTIFIER(coh_static_init_func) = (FUNC, true)
00253 
00254 COH_OPEN_NAMESPACE2(coherence,lang)
00255     template <bool x> struct STATIC_ASSERTION_FAILURE;
00256     template<> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
00257 COH_CLOSE_NAMESPACE2
00258 
00259 /**
00260 * This macro generates a compile time error message if the integral constant
00261 * expression @a B is not true. In other words, it is the compile time
00262 * equivalent of the @c assert macro. Note that if the condition is true, then
00263 * the macro will generate neither code nor data - and the macro can also be
00264 * used at either namespace, class or function scope. When used in a template,
00265 * the static assertion will be evaluated at the time the template is
00266 * instantiated; this is particularly useful for validating template
00267 * parameters.
00268 *
00269 * #COH_STATIC_ASSERT can be used at any place where a declaration can be
00270 * placed, that is at class, function or namespace scope.
00271 *
00272 * @param B an integral constant expression to check its trueness during
00273 *          translation phase
00274 */
00275 #define COH_STATIC_ASSERT(B)                               \
00276     enum { COH_UNIQUE_IDENTIFIER(coh_static_assert_enum_) =\
00277         sizeof(coherence::lang::STATIC_ASSERTION_FAILURE<(bool)(B)>) }
00278 
00279 /**
00280 * DLL import/export macros.
00281 */
00282 #if defined(COH_CC_MSVC)
00283     #ifdef COH_BUILD
00284         #define COH_EXPORT  __declspec(dllexport)
00285     #else
00286         #define COH_EXPORT  __declspec(dllimport)
00287     #endif
00288     #define COH_EXPORT_SPEC  __declspec(dllexport)
00289     #define COH_EXPORT_SPEC_MEMBER(DECL)
00290 #else
00291     #define COH_EXPORT
00292     #define COH_EXPORT_SPEC
00293     #define COH_EXPORT_SPEC_MEMBER(DECL) DECL;
00294 #endif
00295 
00296 /**
00297 * This macro will strongly encourage/force inlining of a method.
00298 */
00299 #if defined(COH_CC_MSVC)
00300     #define COH_INLINE __forceinline
00301 #elif defined(COH_CC_GNU)
00302     #define COH_INLINE __attribute__((always_inline)) inline
00303 #else
00304     #define COH_INLINE inline
00305 #endif
00306 
00307 /**
00308 * This macro expands to the name and signature of the current function.
00309 */
00310 #if defined(__GNUC__)
00311     #define COH_CURRENT_FUNCTION __PRETTY_FUNCTION__
00312 #elif defined(__FUNCSIG__)
00313     #define COH_CURRENT_FUNCTION __FUNCSIG__
00314 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
00315     #define COH_CURRENT_FUNCTION __func__
00316 #else
00317     #define COH_CURRENT_FUNCTION "(unknown function)"
00318 #endif
00319 
00320 
00321 // ----- fixed size types ---------------------------------------------------
00322 
00323 // We need to include an std lib header here in order to detect which library
00324 // is in use (__GLIBC__ may not be defined without this including). Use
00325 // <utility> as it's about the smallest of the std lib headers.
00326 #include <utility>
00327 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901 ||\
00328     defined(_POSIX_VERSION) && _POSIX_VERSION >= 200100 ||\
00329     defined(COH_OS_LINUX) &&\
00330         defined(__GLIBC__) &&\
00331         (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) &&\
00332         defined(__GNUC__) ||\
00333     defined(COH_OS_DARWIN) && __MACH__ && !defined(_MSL_USING_MSL_C)
00334 #       define COH_HAS_STDINT_H
00335 #endif
00336 
00337 #if defined(__GCCXML__) ||\
00338     defined(__GNUC__) ||\
00339     defined(_MSC_VER) && _MSC_VER >= 1310 && defined(_MSC_EXTENSIONS)
00340 #       define COH_HAS_LONG_LONG
00341 #endif
00342 
00343 #if (defined(__GLIBCPP__) || defined(__GLIBCXX__)) &&\
00344         !defined(_GLIBCPP_USE_LONG_LONG) &&          \
00345         !defined(_GLIBCXX_USE_LONG_LONG) &&          \
00346         defined(COH_HAS_LONG_LONG)
00347     // Coming here indicates that the GNU compiler supports long long type,
00348     // but the GNU C++ runtime library does not. Particularly, no global
00349     // operator<<(std::ostream&, long long) implementation is provided. Let us
00350     // provide it, at least with minimum incomplete functionality.
00351 #   include <ostream>
00352     namespace std
00353         {
00354         template<class E, class T>
00355         inline basic_ostream<E, T>& operator<<
00356                 (basic_ostream<E, T>& out, long long l)
00357             {
00358             return out << static_cast<long>(l);
00359             }
00360         template<class E, class T>
00361         inline basic_ostream<E, T>& operator<<
00362                 (basic_ostream<E, T>& out, unsigned long long l)
00363             {
00364             return out << static_cast<unsigned long>(l);
00365             }
00366         }
00367 #   undef COH_HAS_LONG_LONG
00368 #endif
00369 
00370 #if !defined(COH_HAS_LONG_LONG) && !defined(COH_CC_MSVC)
00371 #   include <limits.h>
00372 #   if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) ||\
00373             defined(ULONGLONG_MAX)
00374 #       define COH_HAS_LONG_LONG
00375 #   endif
00376 #endif
00377 
00378 #if defined(_MSC_VER) && _MSC_VER >= 1200
00379 #       define COH_HAS_MS_INT64
00380 #endif
00381 
00382 /**
00383 * Fixed width primitive types.
00384 */
00385 #if defined(COH_HAS_STDINT_H)
00386 #   include <stdint.h>
00387 #elif defined(COH_CC_SUN)
00388 #   include <inttypes.h>
00389 #else
00390 //  This platform does not support the C99 stdint.h types. This code block
00391 //  defines them in the global namespace, alternatively you may define
00392 //  COH_NAMESPACED_FIXED_INTS, in which case these definitions will be within
00393 //  the coherence::lang namespace.
00394 #   include <climits>
00395 #   ifdef COH_NAMESPACED_FIXED_INTS
00396       COH_OPEN_NAMESPACE2(coherence,lang)
00397 #   endif
00398     COH_STATIC_ASSERT(UCHAR_MAX == 0xFF);
00399     typedef signed char   int8_t;
00400     typedef unsigned char uint8_t;
00401     COH_STATIC_ASSERT(USHRT_MAX == 0xFFFF);
00402     typedef short          int16_t;
00403     typedef unsigned short uint16_t;
00404 #   if UINT_MAX == 0xFFFFFFFF
00405         typedef int          int32_t;
00406         typedef unsigned int uint32_t;
00407 #   elif ULONG_MAX == 0xFFFFFFFF
00408         typedef long          int32_t;
00409         typedef unsigned long uint32_t;
00410 #   else
00411 #       error int size not correct
00412 #   endif
00413 #   if defined(COH_HAS_LONG_LONG) &&\
00414         !defined(COH_CC_MSVC) &&\
00415         (!defined(__GLIBCPP__) || defined(_GLIBCPP_USE_LONG_LONG)) && \
00416         (defined(ULLONG_MAX) ||\
00417             defined(ULONG_LONG_MAX) ||\
00418             defined(ULONGLONG_MAX))
00419 #               if defined(ULLONG_MAX)
00420                     COH_STATIC_ASSERT(ULLONG_MAX == 0xFFFFFFFFFFFFFFFFULL);
00421 #               elif defined(ULONG_LONG_MAX)
00422                     COH_STATIC_ASSERT
00423                         (ULONG_LONG_MAX == 0xFFFFFFFFFFFFFFFFULL);
00424 #               elif defined(ULONGLONG_MAX)
00425                     COH_STATIC_ASSERT
00426                         (ULONGLONG_MAX == 0xFFFFFFFFFFFFFFFFULL));
00427 #               else
00428 #                   error long long size not correct
00429 #               endif
00430                 typedef long long          int64_t;
00431                 typedef unsigned long long uint64_t;
00432 #   elif ULONG_MAX != 0xFFFFFFFF
00433         COH_STATIC_ASSERT(ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL);
00434         typedef long          int64_t;
00435         typedef unsigned long uint64_t;
00436 #   elif defined(__GNUC__) && defined(COH_HAS_LONG_LONG)
00437         __extension__ typedef long long          int64_t;
00438         __extension__ typedef unsigned long long uint64_t;
00439 #   elif defined(COH_HAS_MS_INT64)
00440         typedef __int64          int64_t;
00441         typedef unsigned __int64 uint64_t;
00442 #   else
00443 #       error no 64-bit integer support
00444 #   endif
00445 #   ifdef COH_NAMESPACED_FIXED_INTS
00446       COH_CLOSE_NAMESPACE2
00447 #   endif
00448 #endif
00449 
00450 /**
00451 * Non-standard primitive type definitions.
00452 */
00453 COH_OPEN_NAMESPACE2(coherence,lang)
00454     typedef unsigned char octet_t;
00455     typedef uint16_t      char16_t;
00456     typedef uint32_t      size32_t;
00457     typedef uint64_t      size64_t;
00458     typedef float         float32_t; COH_STATIC_ASSERT(sizeof(float32_t) >= sizeof(int32_t));
00459     typedef double        float64_t; COH_STATIC_ASSERT(sizeof(float64_t) >= sizeof(int64_t));
00460 COH_CLOSE_NAMESPACE2
00461 
00462 /**
00463 * Produce a 64b value from two 32b parts.
00464 *
00465 * This is a bit-wise construction, and the supplied values should be the
00466 * bitwise unsigned representations.  For example:
00467 * COH_INT64(0x7FFFFFFFU, 0xFFFFFFFFU) == 0x7FFFFFFFFFFFFFFFLL
00468 */
00469 #define COH_INT64(HIGH, LOW) int64_t(uint64_t(HIGH) << 32 | uint64_t(LOW))
00470 
00471 // macros for turning compiler supplied define into a string
00472 #define COH_SYMB_STRING(SYMB) #SYMB
00473 #define COH_SYMB_TO_STRING(SYMB) COH_SYMB_STRING(SYMB)
00474 
00475 
00476 // ----- helpers ------------------------------------------------------------
00477 
00478 #include <typeinfo>
00479 COH_OPEN_NAMESPACE2(coherence,lang)
00480     /**
00481     * Helper functions for throwing exceptions.
00482     */
00483     extern COH_EXPORT void coh_throw_npe(const std::type_info&);
00484     extern COH_EXPORT void coh_throw_class_cast(const std::type_info&,
00485             const std::type_info&);
00486     extern COH_EXPORT void coh_throw_const_cast(const std::type_info&,
00487             const std::type_info&);
00488     extern COH_EXPORT void coh_throw_illegal_state(const char* achMsg);
00489     extern COH_EXPORT void coh_throw_illegal_argument(const char* achMsg);
00490     extern COH_EXPORT void coh_throw_unsupported_operation(const char* achMsg);
00491 
00492     /**
00493     * Helper class used to test for type assignment compatibility at
00494     * compile time.
00495     *
00496     * This implementation is based on the Conversion example from
00497     * Andrei Alexandrescu's Modern C++ Design.
00498     */
00499     template<class A, class B>
00500     class assignment
00501         {
00502         protected:
00503             typedef char  PathA;
00504             class   Other {char unused[2];}; // sizeof(Other) != sizeof(PathA)
00505             static  PathA route(A*); // PathA taken only for compatible types
00506             static  Other route(...); // incompatible types go this route
00507             static  B*    test(); // "generate" a test object
00508 
00509         public:
00510             /**
00511             * Convert a derived A to an A.
00512             */
00513             static A* safe(A* a)
00514                 {
00515                 return a;
00516                 }
00517 
00518             /**
00519             * Dummy conversion (should never be called)
00520             */
00521             static A* safe(...)
00522                 {
00523                 coh_throw_illegal_state("unsafe cast");
00524                 return 0;
00525                 }
00526 
00527         public:
00528             /**
00529             * True iff A = B is allowed.
00530             */
00531             enum {allowed = (sizeof(route(test())) == sizeof(PathA))};
00532         };
00533 
00534     /**
00535     * Helper class used to test if a type has been declared as const.
00536     */
00537     template<class A>
00538     class constness
00539         {
00540         public:
00541             enum {applied = assignment<A, const A>::allowed};
00542         };
00543 COH_CLOSE_NAMESPACE2
00544 
00545 /// @endcond
00546 
00547 #endif // COH_COMPATIBILITY_HPP
Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.