/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
*     National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
*     Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution. 
\*************************************************************************/
/*
 * Compiler specific key words to set up external symbols and entry points
 *
 * Currently this is only necessary for WIN32 DLLs and for VAXC on VMS but
 * other systems with similar requirements could be supported.
 *
 * USAGE:
 * There are two distinct classes of keywords in this file:
 *
 * 1) epicsShareAPI - specifies a multi-language calling mechanism. On windows 
 * this is the pascal calling convention which is used by visual basic and other
 * high level tools. This is only necessary if a C/C++ function needs to be called
 * from other languages or from high level tools. The epicsShareAPI keyword
 * must be present between the function's returned data type and the function's 
 * name. All compilers targeting windows accept the __stdcall keyword in this 
 * location. Functions with variable argument lists should not use the epicsShareAPI
 * keyword because __stdcall (pascal) calling convention cannot support variable
 * length ed argument lists.
 *
 * int epicsShareAPI myExtFunc ( int arg );   
 * int epicsShareAPI myExtFunc ( int arg ) {}
 *
 * ** NOTE **  epicsShareAPI is deprecated for new routines, don't use it!
 *             In a future major release (R3.15) we will remove this keyword
 *             from most EPICS APIs, although CA may continue to use it.
 *             This is a major release though, since it affects the order
 *             that arguments are pushed onto the stack on Windows and we
 *             don't want a replacement DLL to silent cause mayhem...
 *
 * 2) epicsShare{Func,Class,Extern,Def} - specifies shareable library (DLL) 
 * export/import related information in the source code. On windows these keywords 
 * allow faster dispatching of calls to DLLs because more is known at compile time. 
 * It is also not necessary to maintain a linker input files specifying the DLL
 * entry points. This maintenance can be more laborious with C++ decorated symbol 
 * names. These keywords are only necessary if the address of a function or data 
 * internal to a shareable library (DLL) needs to be visible outside of this shareable 
 * library (DLL). All compilers targeting windows accept the __declspec(dllexport)
 * and __declspec(dllimport) keywords.
 *
 * In header files declare references to externally visible variables, classes and 
 * functions like this:
 *
 * #include "shareLib.h"
 * epicsShareFunc int myExtFunc ( int arg );   
 * epicsShareExtern int myExtVar; 
 * class epicsShareClass myClass { int func ( void ); };
 *
 * In the implementation file, however, you write:
 *
 * #include <interfaces_imported_from_other_shareable_libraries.h>
 * #define epicsExportSharedSymbols
 * #include <interfaces_implemented_in_this_shareable_library.h>
 *
 * epicsShareDef int myExtVar = 4;       
 * int myExtFunc ( int arg ) {} 
 * int myClass::func ( void ) {}
 *
 * By default shareLib.h sets the DLL import / export keywords to import from
 * a DLL so that, for DLL consumers (users), nothing special must be done. However,
 * DLL implementors must set epicsExportSharedSymbols as above to specify
 * which functions are exported from the DLL and which of them are imported
 * from other DLLs.
 *
 * You must first #include what you import and then define epicsExportSharedSymbols 
 * only right before you #include the prototypes for what you implement! You must 
 * include shareLib.h again each time that the state of the import/ export keywords 
 * changes, but this usually occurs as a side effect of including the shareable
 * libraries header file(s).
 *
 * Frequently a header file for a shareable library exported interface will
 * have some preprocessor switches like this if this header file must also  
 * include header files describing interfaces to other shareable libraries.
 *
 * #ifdef epicsExportSharedSymbols
 * #   define interfacePDQ_epicsExportSharedSymbols
 * #   undef epicsExportSharedSymbols
 * #endif
 *
 * #include "epicsTypes.h"
 * #include "epicsTime.h"
 *
 * #ifdef interfacePDQ_epicsExportSharedSymbols
 * #   define epicsExportSharedSymbols
 * #   include "shareLib.h"
 * #endif
 *
 * epicsShareFunc int myExtFunc ( int arg );   
 * epicsShareExtern int myExtVar; 
 * class epicsShareClass myClass {};
 *
 * Fortunately, the above is only the concern of library authors and will have no 
 * impact on persons using functions and or external data from a library.
 */

#undef epicsShareExtern
#undef epicsShareDef
#undef epicsShareClass
#undef epicsShareFunc
#undef epicsShareAPI
#undef READONLY

/*
 *
 * Also check for "EPICS_DLL_NO" not defined so that we will not use these
 * keywords if it is an object library build of base under WIN32.
 */
#if defined(_WIN32) || defined(__CYGWIN__)

#   if defined(epicsExportSharedSymbols)
#       if defined(EPICS_DLL_NO) /* this indicates that we are not building a DLL */
#           define epicsShareExtern extern 
#           define epicsShareClass 
#           define epicsShareFunc
#       else
#           define epicsShareExtern __declspec(dllexport) extern 
#           define epicsShareClass  __declspec(dllexport) 
#           define epicsShareFunc  __declspec(dllexport)
#       endif
#   else
#       if !defined(EPICS_DLL_NO) /* this indicates that we are being compiled to call DLLs */
#           define epicsShareExtern __declspec(dllimport) extern 
#           define epicsShareClass  __declspec(dllimport) 
#           define epicsShareFunc  __declspec(dllimport)
#       else
#           define epicsShareExtern extern
#           define epicsShareClass
#           define epicsShareFunc
#       endif
#   endif
#   define epicsShareDef 
#   define epicsShareAPI __stdcall /* function removes arguments */
#   define READONLY const
/*
 * if its the old VAX C Compiler (not DEC C)
 */
#elif defined(VAXC)

    /* 
     * VAXC creates FORTRAN common blocks when
     * we use "extern int fred"/"int fred=4". Therefore,
     * the initialization is not loaded unless we
     * call a function in that object module.
     *
     * DEC CXX does not have this problem.
     * We suspect (but do not know) that DEC C 
     *  also does not have this problem.
     */
#   define epicsShareExtern globalref 
#   define epicsShareDef globaldef 
#   define READONLY const
#   define epicsShareClass
#   define epicsShareFunc
#   define epicsShareAPI

#else

/* else => no import/export specifiers */

#   define epicsShareExtern extern
#   define epicsShareAPI
#   define epicsShareClass
#   define epicsShareDef

#   define epicsShareFunc
#   if defined(__STDC__) || defined (__cplusplus)
#       define READONLY const
#   else
#       define READONLY
#   endif

#endif

#ifndef INLINE_defs_EPICS
#define INLINE_defs_EPICS
#   ifndef __cplusplus
#       if defined (__GNUC__)
#           define INLINE static __inline__
#       elif defined (_MSC_VER)
#           define INLINE __inline
#       elif defined (_SUNPRO_C)
#           pragma error_messages (off, E_EXTERN_PRIOR_REDECL_STATIC)
#           define INLINE static
#       else
#           define INLINE static
#       endif
#   endif /* ifndef __cplusplus */
#endif /* ifdef INLINE_defs_EPICS */
