First library, its tested and working

This commit is contained in:
2026-09-30 22:28:57 -06:00
commit ba3729a4a1
41 changed files with 7801 additions and 0 deletions
+149
View File
@@ -0,0 +1,149 @@
##############################################################################
# Copyright: Copyright CODESYS Development GmbH
# Program: Extension API for the Linux SL products
##############################################################################
##########################
This is the SDK of the Linux SL products to create an own additional CODESYS runtime component
whose functions that can be called from a CODESYS IEC library.
##########################
##########################
Prerequisites:
- A CODESYS Installation to create an IEC library on a windows machine
- Some buildtools to create a shared object (linux dynamic library), that can be run with the CODESYS Control SL runtimes
- some kind of GCC (for X64 / ARM / AARCH64, depending on your target system)
- make
- m4
- sed
- dos2unix
##########################
##########################
If you want to start a new project, follow these steps:
On the linux system (where you want to build the component)
1) Install the required tools (see prerequisites), e.g. with
sudo apt-get install build-essential m4 sed dos2unix make
2) Copy the SDK to a place of your choice, e.g. in your home directory.
Later we call this directory the "<SDKDIR>", so please remember this location!
Hint: As we are using the tool "make": dont use paths with whitespaces. Make does not like that at all!
3) Create a folder next to the sdk where you want to start your project, e.g. "CmpFirstTest"
mkdir ~/CmpFirstTest
Later we call this directory the "<PROJECT DIR>", so please remember this location!
4) Now create a new project with the following command, and use the makefile from the <SDKDIR>:
make -f <SDKDIR>/makefile newproject
e.g.:
make -f ../sdk/makefile newproject
This creates a makefile within your folder, you might want to take a look at it later ;-)
Your workspace now might look like this:
|
|- SKD <SDKDIR>
| |- include (dir)
| |- m4 (dir)
| |- src (dir)
| |- makefile
| |- makefile_template
| |- README
|
|- CmpFirstTest <PROJECT DIR>
|- makefile
5) Now take a look at the generated makefile.
If you are compiling for X64, you dont need to change anything
If you are compiling for another architecture, you need to set a proper cross compiler via the variable CC (and probably more CFLAGS, INCLUDES and LDLIBS)
On the Windows system (where CODESYS is installed)
1) Open your CODESYS IDE and create a new library unsing the "Empty library" template (do not use the "External CODESYS library" template).
Set the title in the project information to e.g.: "CmpFirstTest"
and store it under the same filename, e.g. "CmpFirstTest.library".
These two must match, otherwise it wont be possible to generate the shared object!
2) Add "externally linked" functions to your library as you wish. You can make a Function "externally linked" by right clicking
on the new function ->Properties->Build and select "External implementation".
This function must include "_cext" in its name, otherwise it wont be loaded by the runtime!
E.g.: TestFunction_cext
3) Now create the runtime system files by selecting Build->"Generate runtime system files".
Choose a suitable path as output directory.
Enable the checkboxes for "M4 interface file" and "C stub file" as you need to generate both: C and M4 files.
Also check that the component name is equal to the name of your library, e.g. "CmpFirstTest"
4) Save or transfer these generated files (*.c and *Itf.m4 file) to the <PROJECT DIR> on your linux system
On the linux system (at <PROJECT DIR>)
1) Go to your <PROJECT DIR> and try to build your component with
make all
2) Now a shared object, with the same name as your IEC library should have been generated in the "out" folder
3) Now you can transfer, copy or symbolically link that to a location on your target system where libraries are normally found (e.g. /usr/lib )
e.g. if you are on the target system:
sudo cp out/libCmpFirstTest.so /usr/lib
4) Stop the runtime on your target e.g. with
sudo /etc/init.d/codesyscontrol stop
5) Open the configuration file CODESYSControl_User.cfg of the runtime, e.g. with nano
and add an entry at the section [ComponentManager], where the components are listed:
[ComponentManager]
Component.1=CmpFirstTest
Component.2=CmpSomeOtherComponent
Component.3=CmpSomeMoreComponent
...
hints:
- the number or index in this setting needs to be incrementing, it might not collide with already existing settings/component indices
- if the line starts with ; it is a comment and the setting is not active
6) Then restart your runtime again, e.g. with
sudo /etc/init.d/codesyscontrol start
7) and check that your component is properly loaded, e.g. check the logfile (via CODESYS IDE), or under codesyscontrol.log
cat /var/opt/codesys/codesyscontrol.log
you should see a message like this:
... Dynamic: <cmp>CmpFirstTest</cmp>, <id>0xffff2000</id> <ver>1.0.0.0</ver>
-> Congratulations! you made your first component and it runs from the CODESYS Control runtime
-> if not: check the FAQs section at the end of this file
On the Windows system (where CODESYS is installed)
1) go to the CODESYS project where you want to use your newly created IEC library, and use your library
2) make a download and check if your code is called (e.g. make a printf there)
##########################
##########################
FAQs:
1) My component does not build, what is going wrong?
- this might have very different reasons. Check what compiler (CC), flags (CFLAGS/LDFLAGS), include paths (INCLUDES) and libraries (LDLIBS) you are setting in your makefile
- check if the code you are writing does compile without this SDK stuff
- check if the functions in the component are named with "_cext"
2) My component is not loaded from the runtime?
- if you see a message in the log, like:
**** ERROR: libCmpFirstTest.so: cannot open shared object file: No such file or directory
or
**** ERROR: *** Error: Component <cmp>CmpFirstTest</cmp> NOT loaded
-> then your shared object is not found. Please double check that you put it somewhere on your linuxsystem, where it can be found (e.g. /usr/lib/)
3) Can I output some messages from my code? Where is this output?
- just use the normal printf() function in your code. This will be output at the "debug logger". To enable the debug logger, just change the file /etc/defaults/codesyscontrol:
set these variables:
DEBUGOUTPUT=1
and
DEBUGLOGFILE=/tmp/codesyscontrol_debug.log
then restart the runtime. Then you can see the output at this logfile
##########################
+16
View File
@@ -0,0 +1,16 @@
/*
* this is a special header for the SL extension API!!!
* <copyright>
* Copyright (c) 2017-2020 CODESYS Development GmbH, Copyright (c) 1994-2016 3S-Smart Software Solutions GmbH. All rights reserved.
* </copyright>
*/
#ifndef __CMPERRORS_H__
#define __CMPERRORS_H__
#define ERR_OK 0
#define ERR_NOTINITIALIZED 0x0003
#endif
+711
View File
@@ -0,0 +1,711 @@
/*
* this is a special header for the SL extension API!!!
* <copyright>
* Copyright (c) 2017-2020 CODESYS Development GmbH, Copyright (c) 1994-2016 3S-Smart Software Solutions GmbH. All rights reserved.
* </copyright>
*/
#ifndef __CMPITF_H__
#define __CMPITF_H__
#include <stdio.h>
#if defined(WIN32) || defined(_WIN32_WCE)
#ifdef _USRDLL
#define DLL_DECL _declspec(dllexport)
#endif
#endif
#if defined(LINUX) || defined(QNX)
#ifdef _USRDLL
#define DLL_DECL __attribute__ ((visibility ("default")))
#endif
#endif
#if !defined(DLL_DECL)
#define DLL_DECL
#endif
#ifndef CDECL
#define CDECL
#endif
#ifndef CDECL_EXT
#define CDECL_EXT
#endif
#ifndef STDCALL
#define STDCALL __stdcall
#endif
#if defined(__cplusplus)
extern "C" {
#endif
typedef RTS_UI32 CMPID; /* Component ID to specify a component. Has the vendor ID as a prefix! */
typedef RTS_UI32 CLASSID; /* Class ID to specify a specific class (C or C++) */
typedef RTS_UI32 OBJID; /* Object ID, typically the instance index starting with 0 */
typedef RTS_UI32 ITFID; /* Interface ID to specify a specific interface (C or C++) */
#define RTS_VENDORID_3S 0x0000
#define RTS_ADDVENDORID(VendorID, ID) (((RTS_UI32)(VendorID) << 16 & UINT32_C(0xFFFF0000)) + (ID))
#define ADDVENDORID RTS_ADDVENDORID
#define RTS_GETVENDORID(ID) ((RTS_UI32)(ID) >> 16 & UINT32_C(0x0000FFFF))
#ifdef TRG_64BIT
#define RTSITF_GET_SIGNATURE(sign32bit, sign64bit) sign64bit
#else
#define RTSITF_GET_SIGNATURE(sign32bit, sign64bit) sign32bit
#endif
/* Function that can be used for all CAL_ macros to return ERR_NOTIMPLEMENTED */
RTS_RESULT CDECL FUNCTION_NOTIMPLEMENTED(unsigned long dummy,...);
RTS_RESULT CDECL FUNCTION_NOTIMPLEMENTED2(void *dummy,...);
/* Structure to handle a mapping of an ID and a name */
typedef struct RTS_ID_TO_NAME_
{
RTS_UI32 id;
char *pszName;
} RTS_ID_TO_NAME;
struct tagIBase;
typedef struct
{
/*pointer to virtual function table*/
void* __VFTABLEPOINTER;
} instance_struct;
typedef struct
{
instance_struct *pInstance;
RTS_IEC_DWORD dwCount;
} addref_struct;
typedef struct
{
instance_struct *pInstance;
RTS_IEC_DWORD dwCount;
} release_struct;
typedef struct
{
instance_struct *pInstance;
RTS_IEC_DWORD iid;
RTS_IEC_RESULT *pResult;
instance_struct **ppInterface;
} queryinterface_struct;
typedef unsigned long (CDECL *PF_ADDREF)(struct tagIBase *pIBase);
typedef unsigned long (CDECL *PF_RELEASE)(struct tagIBase *pIBase);
typedef void *(CDECL *PF_QUERYINTERFACE)(struct tagIBase *pIBase, ITFID iid, RTS_RESULT *pResult);
typedef void (CDECL *PF_IEC_ADDREF)(void);
typedef void (CDECL *PF_IEC_RELEASE)(void);
typedef void (CDECL *PF_IEC_QUERYINTERFACE)(void);
/* <SIL2/> */
typedef struct tagIBase
{
int bIEC;
int iRefCount;
RTS_HANDLE hInstance;
PF_ADDREF AddRef;
PF_RELEASE Release;
PF_QUERYINTERFACE QueryInterface;
CLASSID ClassId;
} IBase_C;
typedef struct tagIBase_IEC
{
int bIEC;
int iRefCount;
RTS_HANDLE hInstance;
PF_IEC_ADDREF *AddRef;
PF_IEC_RELEASE *Release;
PF_IEC_QUERYINTERFACE *QueryInterface;
} IBase_IEC;
#ifndef STATICITF
#define STATICITF static
#endif
#ifndef STATICITF_DEF
#define STATICITF_DEF
#endif
#if defined(CPLUSPLUS) && defined(__cplusplus)
class IBase
{
public:
virtual unsigned long AddRef(IBase *pIBase = NULL) =0;
virtual unsigned long Release(IBase *pIBase = NULL) =0;
virtual void *QueryInterface(IBase *pIBase = NULL, ITFID iid = 0, RTS_RESULT *pResult = NULL) =0;
virtual ~IBase() { };
};
#define DECLARE_ADDREF()\
virtual unsigned long AddRef(IBase *pIBase = NULL);
#define IMPLEMENT_ADDREF()\
virtual unsigned long AddRef(IBase *pIBase = NULL)\
{\
iRefCount++;\
return iRefCount;\
}
#define DECLARE_RELEASE()\
virtual unsigned long Release(IBase *pIBase = NULL);
#define IMPLEMENT_RELEASE()\
virtual unsigned long Release(IBase *pIBase = NULL)\
{\
iRefCount--;\
if (iRefCount == 0)\
{\
delete this;\
return 0;\
}\
return iRefCount;\
}
#define IMPLEMENT_RELEASE_NODELETE()\
virtual unsigned long Release(IBase *pIBase = NULL)\
{\
iRefCount--;\
if (iRefCount == 0)\
{\
return 0;\
}\
return iRefCount;\
}
#else
#define DECLARE_ADDREF\
static unsigned long CDECL AddRef(struct tagIBase *pIBase);
#define IMPLEMENT_ADDREF\
static unsigned long CDECL AddRef(struct tagIBase *pIBase)\
{\
return (pIBase ? ++pIBase->iRefCount : 0);\
}
#define DECLARE_RELEASE\
static unsigned long CDECL Release(struct tagIBase *pIBase);
#define IMPLEMENT_RELEASE\
static unsigned long CDECL Release(struct tagIBase *pIBase)\
{\
return (pIBase ? --pIBase->iRefCount : 0);\
}
#define DECLARE_QUERYINTERFACE\
static void *CDECL QueryInterface(IBase *pBase, ITFID iid, RTS_RESULT *pResult);
typedef IBase_C IBase;
#endif
/* Global function pointer declarations */
typedef int (CDECL *PF_EXPORT_FUNCTIONS)(void);
typedef int (CDECL *PF_IMPORT_FUNCTIONS)(void);
typedef RTS_UI32 (CDECL *PF_GET_VERSION)(void);
typedef RTS_RESULT (CDECL *PF_HOOK_FUNCTION)(RTS_UI32 ulHook, RTS_UINTPTR ulParam1, RTS_UINTPTR ulParam2);
/* typedef RTS_RESULT (CDECL *PF_REGISTER_API)(const char *pszAPIName, RTS_VOID_FCTPTR pfAPIFunction, int bExternalLibrary, RTS_UI32 ulSignatureID); */
typedef RTS_RESULT (CDECL *PF_REGISTER_API)(const CMP_EXT_FUNCTION_REF *pExpTable, RTS_UINTPTR dummy, int bExternalLibrary, RTS_UI32 cmpId);
typedef RTS_RESULT (CDECL *PF_GET_API)(char *pszAPIName, RTS_VOID_FCTPTR *ppfAPIFunction, RTS_UI32 ulSignatureID);
typedef RTS_RESULT (CDECL *PF_REGISTER_API2)(const char *pszAPIName, RTS_VOID_FCTPTR pfAPIFunction, int bExternalLibrary, RTS_UI32 ulSignatureID, RTS_UI32 ulVersion);
typedef RTS_RESULT (CDECL *PF_GET_API2)(char *pszAPIName, RTS_VOID_FCTPTR *ppfAPIFunction, int bExternalLibrary, RTS_UI32 ulSignatureID, RTS_UI32 ulVersion);
typedef RTS_RESULT (CDECL *PF_CALL_HOOK)(RTS_UI32 ulHook, RTS_UINTPTR ulParam1, RTS_UINTPTR ulParam2, int bReverse);
typedef IBase* (CDECL *PF_CREATEINSTANCE)(CLASSID cid, RTS_RESULT *pResult);
typedef RTS_RESULT (CDECL *PF_DELETEINSTANCE)(IBase *pIBase);
typedef RTS_HANDLE (CDECL *PF_REGISTER_CLASS)(CMPID CmpId, CLASSID ClassId);
typedef RTS_RESULT (CDECL *PF_DELETEINSTANCE2)(CLASSID ClassId, IBase *pIBase);
typedef struct tagINIT_STRUCT
{
/* Exported by Component */
CMPID CmpId;
#ifdef TRG_64BIT
RTS_UI32 aligndummy;
#endif
PF_EXPORT_FUNCTIONS pfExportFunctions;
PF_IMPORT_FUNCTIONS pfImportFunctions;
PF_GET_VERSION pfGetVersion;
PF_CREATEINSTANCE pfCreateInstance;
PF_DELETEINSTANCE pfDeleteInstance;
PF_HOOK_FUNCTION pfHookFunction;
/* Import from CM */
PF_REGISTER_API pfCMRegisterAPI;
PF_GET_API pfCMGetAPI;
PF_CALL_HOOK pfCMCallHook;
PF_REGISTER_CLASS pfCMRegisterClass;
PF_CREATEINSTANCE pfCMCreateInstance;
PF_REGISTER_API2 pfCMRegisterAPI2;
PF_GET_API2 pfCMGetAPI2;
PF_DELETEINSTANCE2 pfCMDeleteInstance2;
} INIT_STRUCT;
#define COMPONENT_ENTRY_NAME "ComponentEntry"
#if defined(CPLUSPLUS) && defined(__cplusplus)
extern "C" {
#endif
#if !defined(STATIC_LINK) && !defined(MIXED_LINK) && !defined(DYNAMIC_LINK) && !defined(CPLUSPLUS_STATIC_LINK)
DLL_DECL int CDECL ComponentEntry(INIT_STRUCT *pInitStruct);
#endif
typedef int (CDECL *PF_COMPONENT_ENTRY)(INIT_STRUCT *pInitStruct);
#if defined(CPLUSPLUS) && defined(__cplusplus)
}
#endif
/* Functions exported from main */
RTS_RESULT CDECL MainLoadComponent(char *pszName, char *pszPath, RTS_HANDLE *phModule, PF_COMPONENT_ENTRY* ppfComponentEntry);
RTS_RESULT CDECL MainUnloadComponent(char *pszName, RTS_HANDLE hModule);
/* The following functions are always offered by the component manager */
int CDECL MainExitLoop(RTS_UINTPTR ulPar);
typedef int (CDECL *PFMAINEXITLOOP)(RTS_UINTPTR ulPar);
#ifdef STATIC_LINK
#define USE_CMExitLoop extern int CDECL MainExitLoop(RTS_UINTPTR ulPar);
#define EXT_CMExitLoop extern int CDECL MainExitLoop(RTS_UINTPTR ulPar);
#define GET_CMExitLoop ERR_OK
#define CAL_CMExitLoop MainExitLoop
#define CHK_CMExitLoop TRUE
#define EXP_CMExitLoop TRUE
#else /* DYNAMIC_LINK */
#define USE_CMExitLoop PFMAINEXITLOOP pfMainExitLoop;
#define EXT_CMExitLoop extern PFMAINEXITLOOP pfMainExitLoop;
#define GET_CMExitLoop s_pfGetAPI("CMExitLoop", (void **)&pfMainExitLoop, 0)
#define CAL_CMExitLoop pfMainExitLoop
#define CHK_CMExitLoop (pfMainExitLoop != NULL)
#define EXP_CMExitLoop s_pfRegisterAPI("CMExitLoop", MainExitLoop, 1, 0)
#endif
/**
* <description>Hook definitions to inform all components with a broadcast via HookFunction() ([0..10000] reserved for core components):
* <ul>
* <li>CH_INIT_XXX Hooks: Used for initialization of all components.
* Future range, not yet defined! = [1..1000]</li>
* <li>CH_EXIT_XXX Hooks: Used for deinitialization of all components.
* Future range, not yet defined! = [2000..3000]</li>
* <li>CH_XXX Hooks: Used for broadcast commands (e.g. cyclic operations).
* Future range, not yet defined! = [4000..5000]</li>
* </ul>
* IMPLEMENTATION NOTE:
* Future hooks should be defined in the appropriate range above!
* </description>
*/
/*
CH_INIT_XXX Hooks: Used for initialization of all components.
*/
#define CH_INIT_SYSTEM 1
/* First call at system startup to initialize all system components.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_SYSTEM2 8
/* Second call at system startup to initialize all system components.
(used to resolve dependencies between core components)
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT 2
/* First call at system startup. Compontents should initialize all local variables.
ulParam1: Pointer to int. Parameter name=pbDontCallInitHooksFromCMInit. Content can be set as followed:
0 [Default]: CMInitEnd() is called at the end of CMInit().
1: CMInitEnd (calling hooks from CH_INIT2 to CH_INIT_COMM) can be called asynchronously by your own
component and is not called in the context of CMInit()!
ulParam2: Not used
*/
#define CH_POST_INIT 200
/* Called right after CH_INIT. Use this hook to run initialization between
highly related components (e.g. Register backends or providers to the corresponding components.).
ulParam1: Not used
ulParam2: Not used
*/
#define CH_PRE_INIT2 250
/* Called right before CH_INIT2. Use this hook to finish initialization of a component that is highly
related to an other components. E.g. finish initialization after the providers have registered.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT2 3
/* Called after CH_INIT. All components are initialized. Other components can be used.
NOTE:
Events must be created of the provider in this init step!
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_DONE CH_INIT2
/* Backward compatibility */
#define CH_PRE_INIT3 7
/* Called after CH_INIT2 and before CH_INIT3. All components are initialized. Other components can be used.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT201 CH_PRE_INIT3
/* Backward compatibility */
#define CH_INIT3 4
/* Called after CH_INIT201. All components are initialized. Other components can be used.
NOTE:
Event callbacks must be registered by the consumer in this init step! Events are created in CH_INIT2.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_SYSTEM_TASKS 500
/* Called after CH_INIT3. Tasks can be started that are relevant for the IEC applications.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_TASKS 5
/* Called after CH_INIT_SYSTEM_TASKS. All components should start their tasks.
NOTE:
The IEC bootprojects are loaded here!
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_COMM 6
/* Called after CH_INIT_TASKS. Communication can be started at this point, because all
components are ready and running.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_INIT_FINISHED 1000
/* Called at the end of the complete initialization sequence. This is called after CH_INIT_COMM and right before the runtime system
fall into the cyclic CH_COMM_CYCLE state.
NOTE:
The IEC bootprojects are started here!
ulParam1: Not used
ulParam2: Not used
*/
/*
CH_EXIT_XXX Hooks: Used for deinitialization of all components.
*/
#define CH_EXIT_COMM 10
/* Called at the beginning of the shutdown sequence to disable all communication channels!
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT_TASKS 11
/* Called before CH_EXIT_SYSTEM_TASKS to stop and remove all tasks that are not needed by the IEC application.
NOTE:
IEC applications are unloaded here.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT_SYSTEM_TASKS 2200
/* Called before CH_EXIT3 to stop and remove all running tasks, because at CH_EXIT3 all objects are released and
so no task must run after this point.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT3 12
/* Called before CH_EXIT2 to store data (e.g. retain data).
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT2 13
/* Called before CH_EXIT to store data (e.g. retain data).
ulParam1: Not used
ulParam2: Not used
*/
#define CH_PRE_EXIT CH_EXIT2
/* Backward compatibility */
#define CH_EXIT 14
/* Here all memory of the components should be released.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT_SYSTEM2 17
/* Counter part to CH_INIT_SYSTEM2.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT_SYSTEM 15
/* Called at the end of the shutdown process for the system components to release memory.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_EXIT_GARBAGEMEMORY 16
/* This is the final call for the garbage collector to check, if heap memory was not released.
ulParam1: Not used
ulParam2: Not used
*/
/*
CH_XXX Hooks: Used for broadcast commands (e.g. cyclic operations).
*/
#define CH_COMM_CYCLE 20
/* Called every main cycle period. Can be used for background executions.
ulParam1: Not used
ulParam2: Not used
*/
#define CH_ON_IMPORT 23
/* Called for components to import new functions from a new loaded component
ulParam1: char *: Pointer to component name
ulParam2: Not used
*/
#define CH_ON_IMPORT_RELEASE 24
/* Called for components to release imported functions from a component that will be unloaded
ulParam1: char *: Pointer to component name
ulParam2: Not used
*/
#define CH_ON_LOAD_COMPONENT 25
/* Called after loading a new component
ulParam1: char *: Pointer to component name
ulParam2: Not used
*/
#define CH_ON_UNLOAD_COMPONENT 26
/* Called before unloading a component
ulParam1: char *: Pointer to component name
ulParam2: Not used
*/
#define CH_ON_REGISTER_INSTANCE 27
/* Called after register a new instance
ulParam1: CLASSID: ClassId of instance
ulParam2: IBase *: Pointer to IBase
*/
#define CH_ON_UNREGISTER_INSTANCE 28
/* Called before unregister a new instance
ulParam1: CLASSID: ClassId of instance
ulParam2: IBase *: Pointer to IBase
*/
#define CH_ON_LICENSE_FCTS_REGISTERED 29
/*
Called after the functionpointers from the license-library
have been registered to the runtime.
*/
#define CH_ON_LICENSE_FCTS_REGISTERED2 290
/*
Called after CH_ON_LICENSE_FCTS_REGISTERED.
*/
#define CH_ON_LICENSE_FCTS_LEGACY_REGISTERED 30
/*
Called after the functionpointers from the license-library
have been registered to the runtime.
*/
#define CH_SAFEMODE 4000
/*
Called when a component fails to resolve its required import functions during startup of the runtime system. In this case, the system is not stable any more.
Every component should check safety.
After entering the safemode, at least the communication should work and so for example a service engineer can investigate the reason for this error.
The logger should work too.
IMPORTANT NOTE:
It is important, that the IEC-application(s) are not loaded or at least are not started after entering the safemode! This is still implemented in the CmpApp component.
ulParam1: Not used
ulParam2: Not used
*/
/**
* <category>Hook table</category>
* <description>
* This is the table of all hooks with its corresponding name (see CM_HOOK_TABLE).
*
* NOTE:
* The init and exit hooks are defined here in the order they are executed during startup and shutdown!
*
* </description>
*/
#define CM_INIT_HOOK_TABLE { CH_INIT_SYSTEM, "CH_INIT_SYSTEM" },\
{ CH_INIT_SYSTEM2, "CH_INIT_SYSTEM2" },\
{ CH_INIT, "CH_INIT" },\
{ CH_POST_INIT, "CH_POST_INIT" },\
{ CH_PRE_INIT2, "CH_PRE_INIT2" },\
{ CH_INIT2, "CH_INIT2" },\
{ CH_PRE_INIT3, "CH_PRE_INIT3" },\
{ CH_INIT3, "CH_INIT3" },\
{ CH_INIT_SYSTEM_TASKS, "CH_INIT_SYSTEM_TASKS" },\
{ CH_INIT_TASKS, "CH_INIT_TASKS" },\
{ CH_INIT_COMM, "CH_INIT_COMM" },\
{ CH_INIT_FINISHED, "CH_INIT_FINISHED" }
#define CM_COMM_CYCLE_HOOK { CH_COMM_CYCLE, "CH_COMM_CYCLE" }
#define CM_EXIT_HOOK_TABLE { CH_EXIT_COMM, "CH_EXIT_COMM" },\
{ CH_EXIT_TASKS, "CH_EXIT_TASKS" },\
{ CH_EXIT_SYSTEM_TASKS, "CH_EXIT_SYSTEM_TASKS" },\
{ CH_EXIT3, "CH_EXIT3" },\
{ CH_EXIT2, "CH_EXIT2" },\
{ CH_EXIT, "CH_EXIT" },\
{ CH_EXIT_SYSTEM2, "CH_EXIT_SYSTEM2" },\
{ CH_EXIT_SYSTEM, "CH_EXIT_SYSTEM" },\
{ CH_EXIT_GARBAGEMEMORY, "CH_EXIT_GARBAGEMEMORY" }
#define CM_EXTENDED_HOOK_TABLE { CH_ON_IMPORT, "CH_ON_IMPORT" }, \
{ CH_ON_IMPORT_RELEASE, "CH_ON_IMPORT_RELEASE" }, \
{ CH_ON_LOAD_COMPONENT, "CH_ON_LOAD_COMPONENT" }, \
{ CH_ON_UNLOAD_COMPONENT, "CH_ON_UNLOAD_COMPONENT" }, \
{ CH_ON_REGISTER_INSTANCE, "CH_ON_REGISTER_INSTANCE" }, \
{ CH_ON_UNREGISTER_INSTANCE, "CH_ON_UNREGISTER_INSTANCE" }, \
{ CH_ON_LICENSE_FCTS_REGISTERED, "CH_ON_LICENSE_FCTS_REGISTERED" }, \
{ CH_ON_LICENSE_FCTS_REGISTERED2, "CH_ON_LICENSE_FCTS_REGISTERED2" }, \
{ CH_ON_LICENSE_FCTS_LEGACY_REGISTERED, "CH_ON_LICENSE_FCTS_LEGACY_REGISTERED" }, \
{ CH_SAFEMODE, "CH_SAFEMODE" } \
#define CM_HOOK_TABLE {\
CM_INIT_HOOK_TABLE,\
CM_COMM_CYCLE_HOOK,\
CM_EXIT_HOOK_TABLE,\
CM_EXTENDED_HOOK_TABLE\
}
/**
* <category>Single import of interface functions</category>
* <description>
* These macros are used by the System-Components to import single interface functions without modifying
* the global SysXXXDep.m4 files.
*
* ATTENTION:
* With usage of these macros, the RtsConfiguration cannot resolve this dependency anymore!!!
* So use these macros only in Sys-Components and not in standard or customer components!
*
* Usage:
* #include "<Interface>Itf.h"
* USE_SINGLE_ITF(<Interface>) or USE_SINGLE_ITF(<Class>, <Interface>)
* USE_SINGLE_FUNCTION(<Function>)
*
* static int CDECL ImportFunctions(void)
* {
* IMPORT_SINGLE_ITF(<Interface>);
* IMPORT_SINGLE_FUNCTION(<Function>);
* return ERR_OK;
* }
* </description>
*/
#ifdef CPLUSPLUS
#define USE_SINGLE_ITF(Interface_) ITF_##Interface_
#define IMPORT_SINGLE_ITF(Interface_) \
{\
IBase *pIBase_;\
RTS_RESULT Result_;\
if (pI##Interface_ == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase_ = (IBase *)s_pfCMCreateInstance(CLASSID_C##Interface_, &Result_); \
if (pIBase_ != NULL) \
{\
pI##Interface_ = (I##Interface_ *)pIBase_->QueryInterface(pIBase_, ITFID_I##Interface_, &Result_); \
pIBase_->Release(pIBase_); \
}\
} \
}
#define EXIT_SINGLE_ITF(Interface_) \
{\
IBase *pIBase_;\
RTS_RESULT exitResult_;\
if (pI##Interface_ != NULL) \
{ \
pIBase_ = (IBase *)pI##Interface_->QueryInterface(pI##Interface_, ITFID_IBase, &exitResult_); \
if (pIBase_ != NULL && exitResult_ == ERR_OK) \
{ \
pIBase_->Release(pIBase_); \
if (pIBase_->Release(pIBase_) == 0) /* The object will be deleted here! */ \
pI##Interface_ = NULL; \
} \
} \
}
#define IMPORT_SINGLE_ITF2(Class_, Interface_) \
{\
IBase *pIBase_;\
RTS_RESULT Result_;\
if (pI##Interface_ == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase_ = (IBase *)s_pfCMCreateInstance(CLASSID_C##Class_, &Result_); \
if (pIBase_ != NULL) \
{\
pI##Interface_ = (I##Interface_ *)pIBase_->QueryInterface(pIBase_, ITFID_I##Interface_, &Result_); \
pIBase_->Release(pIBase_); \
}\
} \
}
#define EXIT_SINGLE_ITF2(Class_, Interface_) \
{\
IBase *pIBase_;\
RTS_RESULT exitResult_;\
if (pI##Interface_ != NULL) \
{ \
pIBase_ = (IBase *)pI##Interface_->QueryInterface(pI##Interface_, ITFID_IBase, &exitResult_); \
if (pIBase_ != NULL && exitResult_ == ERR_OK) \
{ \
pIBase_->Release(pIBase_); \
if (pIBase_->Release(pIBase_) == 0) /* The object will be deleted here! */ \
pI##Interface_ = NULL; \
} \
} \
}
#else
#define USE_SINGLE_ITF(Interface_)
#define IMPORT_SINGLE_ITF(Interface_)
#define EXIT_SINGLE_ITF(Interface_)
#define IMPORT_SINGLE_ITF2(Class_, Interface_)
#define EXIT_SINGLE_ITF2(Class_, Interface_)
#endif
#define USE_SINGLE_FUNCTION(Function) USE_##Function
#define IMPORT_SINGLE_FUNCTION(Function) GET_##Function(0)
#define EXIT_SINGLE_FUNCTION(Function)
#if defined(__cplusplus)
}
#endif
#endif /*__CMPITF_H__*/
+641
View File
@@ -0,0 +1,641 @@
/*
* this is a special header for the SL extension API!!!
* <copyright>
* Copyright (c) 2017-2020 CODESYS Development GmbH, Copyright (c) 1994-2016 3S-Smart Software Solutions GmbH. All rights reserved.
* </copyright>
*/
#ifndef __RTSSTD_H__
#define __RTSSTD_H__
#if defined(__amd64__)
#define TRG_X64
#define TRG_64BIT
#elif defined(__arm__)
#define TRG_ARM
#elif defined(__aarch64__)
#define TRG_ARM
#define TRG_64BIT
#elif defined(i386)
#error "32 bit X86 is not supported!"
#else
#error "Unknown architecture!"
#endif
#define LINUX
#define CDECL
#define __cdecl CDECL /*necessary for sqlite in CmpCAAStorage*/
#define STDCALL
#define HUGEPTR
/****** OS *****/
#define SYSTARGET_OS_LINUX
/*** types ***/
#ifndef STDINT_H_UINTPTR_T_DEFINED
#define STDINT_H_UINTPTR_T_DEFINED
#endif
typedef unsigned short RTS_WCHAR;
#define RTS_WCHAR_DEFINED
#define INTEL_BYTE_ORDER
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>
#include <ctype.h>
#include <math.h>
/**
* set default register width
*/
#ifndef RTS_REGISTER_WIDTH
#if defined(TRG_C16X) || defined(TRG_DSP)
#define RTS_REGISTER_WIDTH 16
#elif defined(TRG_64BIT) || defined(TRG_IA64)
#define RTS_REGISTER_WIDTH 64
#else
#define RTS_REGISTER_WIDTH 32
#endif
#endif
#if RTS_REGISTER_WIDTH == 64 && !defined (SIZEOF_LONG)
#if defined (SYSTARGET_OS_WINDOWS) || defined (SYSTARGET_OS_WINDOWS_RTE) || defined (SYSTARGET_OS_WINDOWS_CE)
#define SIZEOF_LONG 4
#else
#define SIZEOF_LONG 8
#endif
#endif
#include <stdint.h>
/**
* Redefine UINT32_C(), INT16_C, ...,
* as many compilers are defining this in a bad way. They
* are using type-casts to get the correct data-width. This
* makes it impossible to use for some pedantic C-Compilers.
*/
#ifdef INT64_C
#undef INT64_C
#endif
#ifdef UINT64_C
#undef UINT64_C
#endif
#ifdef INT32_C
#undef INT32_C
#endif
#ifdef UINT32_C
#undef UINT32_C
#endif
#ifdef INT16_C
#undef INT16_C
#endif
#ifdef UINT16_C
#undef UINT16_C
#endif
#ifdef INT8_C
#undef INT8_C
#endif
#ifdef UINT8_C
#undef UINT8_C
#endif
#define INT64_C(x) (RTS_I64_CONST(x))
#define UINT64_C(x) (RTS_UI64_CONST(x))
#define INT32_C(x) (x ## L)
#define UINT32_C(x) (x ## UL)
#define INT16_C(x) (x)
#define UINT16_C(x) (x ## U)
#define INT8_C(x) (x)
#define UINT8_C(x) (x ## U)
#define RTS_IEC_BOOL_C(x) (x)
#define RTS_IEC_BYTE_C(x) (UINT8_C(x))
#define RTS_IEC_SINT_C(x) (INT8_C(x))
#define RTS_IEC_USINT_C(x) (UINT8_C(x))
#define RTS_IEC_INT_C(x) (INT16_C(x))
#define RTS_IEC_UINT_C(x) (UINT16_C(x))
#define RTS_IEC_DINT_C(x) (INT32_C(x))
#define RTS_IEC_UDINT_C(x) (UINT32_C(x))
#define RTS_IEC_LINT_C(x) (INT64_C(x))
#define RTS_IEC_ULINT_C(x) (UINT64_C(x))
#define RTS_IEC_WORD_C(x) (UINT16_C(x))
#define RTS_IEC_DWORD_C(x) (UINT32_C(x))
#define RTS_IEC_LWORD_C(x) (UINT64_C(x))
#define RTS_IEC_REAL_C(x) (x)
#define RTS_IEC_LREAL_C(x) (x)
#ifdef TRG_64BIT
#define RTS_IEC_XINT_C(x) (INT64_C(x))
#define RTS_IEC_UXINT_C(x) (UINT64_C(x))
#define RTS_IEC_XWORD_C(x) (UINT64_C(x))
#else
#define RTS_IEC_XINT_C(x) (INT32_C(x))
#define RTS_IEC_UXINT_C(x) (UINT32_C(x))
#define RTS_IEC_XWORD_C(x) (UINT32_C(x))
#endif
/**
* Define some more exotic types, which are missing
* in many versions of stdint.h.
*/
#if !defined(STDINT_H_UINTPTR_T_DEFINED)
/* Note: If your compiler complains about a "redefinition"
* or s.th. similar here, you may set the defines
* _UINTPTR_T, _PTRDIFF_T, ... in your sysdefines.h.
*/
#ifndef _UINTPTR_T
typedef uint32_t uintptr_t;
#define _UINTPTR_T
#endif
#ifndef _PTRDIFF_T
typedef int32_t ptrdiff_t;
#define _PTRDIFF_T
#endif
#ifndef _INTPTR_T
typedef ptrdiff_t intptr_t;
#define _INTPTR_T
#endif
#define STDINT_H_UINTPTR_T_DEFINED
#endif /*!defined(STDINT_H_UINTPTR_T_DEFINED)*/
/* Format modifiers for integral types */
#ifndef ULONG_MAX
# include <limits.h>
# ifndef ULONG_MAX
# error ULONG_MAX does not exist in limits.h!
# endif
#endif
/*
* Some basic definitions
*/
#ifndef NULL
# define NULL 0L
#endif
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
/*lint -e666 -e506 */
#ifndef MIN
# define MIN(x,y) ((x)<(y)?(x):(y))
#endif
#ifndef MAX
# define MAX(x,y) ((x)>(y)?(x):(y))
#endif
#ifndef RTS_SETRESULT
# define RTS_SETRESULT(p,r) do { if(p) *(p)=r; } while(0)
#endif
#ifndef RTS_GETRESULT
# define RTS_GETRESULT(Return,Result) (Result == ERR_OK ? (Return) : ((Return) ? Result : Result))
#endif
#ifndef LOWWORD
# define LOWWORD(p) ((uint16_t)((uint32_t)(p) & 0x0000FFFF))
#endif
#ifndef HIGHWORD
# define HIGHWORD(p) ((uint16_t)(((uint32_t)(p)>>16) & 0x0000FFFF))
#endif
/* Operations on flags */
#ifndef RTS_SETFLAGS
#define RTS_SETFLAGS(value, flags) (value |= (flags))
#endif
#ifndef RTS_SETFLAG
#define RTS_SETFLAG(value, flag) RTS_SETFLAGS(value, flag)
#endif
#ifndef RTS_RESETFLAGS
#define RTS_RESETFLAGS(value, flags) (value &= ~(flags))
#endif
#ifndef RTS_RESETFLAG
#define RTS_RESETFLAG(value, flag) RTS_RESETFLAGS(value, flag)
#endif
#ifndef RTS_HASFLAGS
#define RTS_HASFLAGS(value, flags) ((value & (flags)) == (flags))
#endif
#ifndef RTS_HASFLAG
#define RTS_HASFLAG(value, flag) (value & (flag))
#endif
#ifndef ALIGN_MEMORY
# define ALIGN_MEMORY(pMemory) ((void *)(((((uintptr_t)(pMemory) + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*))))
#endif
#ifndef ALIGN_MEMORY_SIZE
# define ALIGN_MEMORY_SIZE(pMemory, iSize) ((iSize) - (((((uintptr_t)(pMemory) + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*)) - (uintptr_t)(pMemory)))
#endif
#ifndef ALIGN_MEMORY2
# define ALIGN_MEMORY2(pMemory, Modulo) ((void *)((((uintptr_t)(pMemory) + (Modulo) - 1) / (uintptr_t)(Modulo)) * (uintptr_t)(Modulo)))
#endif
#ifndef ALIGN_MEMORY2_BACK
# define ALIGN_MEMORY2_BACK(pMemory, Modulo) ((void *)(((uintptr_t)(pMemory) / (uintptr_t)(Modulo)) * (uintptr_t)(Modulo)))
#endif
#ifndef ALIGN_MEMORY_SIZE2
# define ALIGN_MEMORY_SIZE2(pMemory, iSize, Modulo) ((iSize) - (((((uintptr_t)(pMemory) + (Modulo) - 1) / sizeof(void*)) * (Modulo)) - (uintptr_t)(pMemory)))
#endif
#ifndef ALIGN_SIZE
/* NOTE: it seems like this operation can be made without a comparison: */
/* #define ALIGN_SIZE(Size, Modulo) (( (Size) + ((Modulo) - 1) ) / (Modulo)) * (Modulo) */
# define ALIGN_SIZE(Size, Modulo) /*lint -e{506} */(((Size) % (Modulo)) ? ((Size) + ((Modulo) - ((Size) % (Modulo)))) : (Size))
#endif
#ifndef RTS_VSNPRINTF
#if defined(RTS_VSNPRINTF_NOT_AVAILABLE)
#define RTS_VSNPRINTF(s,len,format,arglist) vsprintf(s,format,arglist)
#else
#define RTS_VSNPRINTF(s,len,format,arglist) vsnprintf(s,len,format,arglist)
#endif
#endif
#ifndef va_copy
#define va_copy(destination, source) ((destination) = (source))
#endif
#define CONCAT(x,y) x##y
/* Some preprocessors do not allow to place such a macro within other macros */
/* and/or pragmas. */
#define ____QUOTE____(x) #x
#define QUOTE(x) ____QUOTE____(x)
#ifdef INTEL_BYTE_ORDER
# define SWAP16u(x) (x)
# define SWAP16s(x) (x)
# define SWAP32u(x) (x)
# define SWAP32s(x) (x)
#elif defined(MOTOROLA_BYTE_ORDER)
# define SWAP16u(x) ( (uint16_t)((((x) & 0xFF)<<8) | (((x) & 0xFF00) >> 8)) )
# define SWAP16s(x) ( (int16_t)((((x) & 0xFF)<<8) | (((x) & 0xFF00) >> 8)) )
# define SWAP32u(x) ( (uint32_t)((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) )
# define SWAP32s(x) ((int32_t)((((uint32_t)(x)) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#else
#error "No byte order defined for the current target"
#endif
#include "CmpErrors.h"
#define CAL_CMGETAPI(name) ERR_OK
#define CAL_CMEXPAPI(name) ERR_OK
typedef void HUGEPTR(CDECL *RTS_VOID_FCTPTR)(void);
/*
* Runtime system basic typedefinitions.
* Defines some types with special meaning. Systems not using standard type sizes
* must redefine this types in sysdefines.h and set BASETYPES_DEFINED
*/
#ifndef RTS_I64_CONST
#define RTS_I64_CONST(a) (a##LL)
#endif
#ifndef RTS_UI64_CONST
#define RTS_UI64_CONST(a) (a##ULL)
#endif
#ifndef BASETYPES_DEFINED
# define BASETYPES_DEFINED
typedef int8_t RTS_I8; /* Signed 8 bit value */
typedef int16_t RTS_I16; /* Signed 16 bit value */
#ifndef RTS_I32_DEFINED
#define RTS_I32_DEFINED
typedef int32_t RTS_I32; /* Signed 32 bit value */
#endif
typedef uint8_t RTS_UI8; /* Unsigned 8 bit value */
# define RTS_UI8_MAX (RTS_UI8)(~((RTS_UI8)0))
typedef uint16_t RTS_UI16; /* Unsigned 16 bit value */
# define RTS_UI16_MAX (RTS_UI16)(~((RTS_UI16)0))
#ifndef RTS_UI32_DEFINED
#define RTS_UI32_DEFINED
typedef uint32_t RTS_UI32; /* Unsigned 32 bit value */
#endif
# define RTS_UI32_MAX (RTS_UI32)(~((RTS_UI32)0))
#ifndef IEEE754TYPES_DEFINED
# define IEEE754TYPES_DEFINED
typedef float RTS_REAL32; /* 32 bit floating point value */
typedef double RTS_REAL64; /* 64 bit floating point value */
#define RTS_REAL32_MAX 3.4028234e+38
#define RTS_REAL64_MAX 1.7976931348623157e+308
#endif
typedef void* RTS_HANDLE; /* Handle for files, semaphores, ... Usually the native integer type of the platform*/
#define RTS_INVALID_HANDLE ((RTS_HANDLE)(~((uintptr_t)0)))
typedef RTS_UI32 RTS_RESULT; /* Result type for most functions. At least 16 bit. Should be the natural integer of a platform. */
typedef uintptr_t RTS_UINTPTR; /* Unsigned integral type that can hold a pointer */
#define RTS_UINTPTR_MAX (RTS_UINTPTR)(~((RTS_UINTPTR)0))
typedef intptr_t RTS_INTPTR; /* Signed integral type that can hold a pointer */
#define RTS_INTPTR_MAX (RTS_INTPTR)(~((RTS_INTPTR)0))
typedef ptrdiff_t RTS_PTRDIFF; /* Signed integral type that can hold an array index */
#define RTS_PTRDIFF_MAX (RTS_PTRDIFF)(~((RTS_PTRDIFF)0))
#ifndef RTS_SIZE_DEFINED
#define RTS_SIZE_DEFINED
typedef size_t RTS_SIZE; /* Unsigned integral type that can hold a buffer offset */
#endif
#define RTS_SIZE_MAX (RTS_SIZE)(~((RTS_SIZE)0))
/* Type definition of RTS_SSIZE should be changed to standard datatype ssize_t, if available on any target! */
#ifndef RTS_SSIZE_DEFINED
#define RTS_SSIZE_DEFINED
typedef intptr_t RTS_SSIZE; /* integral type that can hold a buffer offset */
#endif
#define RTS_SSIZE_MAX (RTS_SSIZE)(~((RTS_SSIZE)0))
typedef RTS_UINTPTR RTS_TIME; /* Coordinated Universal Time (UTC) */
typedef int RTS_INT; /* Data type has no constant size, so be careful in sharing shuch datatypes with IEC! */
typedef int RTS_BOOL; /* Boolean value (TRUE or FALSE). For best performance use platform specific int.
Data type has no constant size, so be carful in sharing shuch datatypes with IEC! */
#if defined(RTS_DISABLE_64BIT_SUPPORT) && !defined(SYSINTERNAL_DISABLE_64BIT)
#define SYSINTERNAL_DISABLE_64BIT
#endif
#if !defined(BASE64BITTYPES_DEFINED) && !defined(SYSINTERNAL_DISABLE_64BIT)
# define BASE64BITTYPES_DEFINED
typedef uint64_t RTS_UI64;
typedef int64_t RTS_I64;
#define RTS_UI64_MAX (RTS_UI64)(~((RTS_UI64)0))
#define RTS_I64_MAX (RTS_I64)(~((RTS_I64)0))
#endif
typedef char RTS_CSTRING;
typedef char RTS_UTF8STRING;
# ifndef RTS_WCHAR_DEFINED
# define RTS_WCHAR_DEFINED
typedef wchar_t RTS_WCHAR; /* wide character value. We expect 2 bytes unicode here! */
# endif /*RTS_WCHAR_DEFINED*/
# ifndef RTS_CWCHAR_DEFINED
# define RTS_CWCHAR_DEFINED
# ifdef RTS_UNICODE
typedef RTS_WCHAR RTS_CWCHAR;
# else
typedef RTS_CSTRING RTS_CWCHAR;
# endif
# endif /*RTS_CWCHAR_DEFINED*/
#ifdef RTS_DEFINE_MODE_T
typedef unsigned short mode_t;
#endif
#ifdef RTS_DEFINE_GID_T
typedef short gid_t;
#endif
#ifdef RTS_DEFINE_UID_T
typedef short uid_t;
#endif
#ifdef RTS_DEFINE_ID_T
typedef intptr_t id_t;
#endif
#ifdef RTS_DEFINE_PID_T
typedef uintptr_t pid_t;
#endif
#ifdef RTS_DEFINE_OFF_T
typedef uintptr_t off_t;
#endif
#ifdef RTS_DEFINE_NLINK_T
typedef short nlink_t;
#endif
#endif /*BASETYPES_DEFINED*/
typedef enum
{
RTSTYPE_I8,
RTSTYPE_I16,
RTSTYPE_I32,
RTSTYPE_UI8,
RTSTYPE_UI16,
RTSTYPE_UI32,
RTSTYPE_REAL32,
RTSTYPE_REAL64,
RTSTYPE_HANDLE,
RTSTYPE_RESULT,
RTSTYPE_UINTPTR,
RTSTYPE_INTPTR,
RTSTYPE_SIZE,
RTSTYPE_PTRDIFF,
RTSTYPE_INT,
RTSTYPE_BOOL,
RTSTYPE_UI64,
RTSTYPE_I64,
RTSTYPE_CSTRING,
RTSTYPE_WCHAR,
RTSTYPE_CWCHAR
}RTS_TYPECLASS;
typedef union
{
RTS_I8 i8Value;
RTS_I16 i16Value;
RTS_I32 i32Value;
RTS_UI8 ui8Value;
RTS_UI16 ui16Value;
RTS_UI32 ui32Value;
RTS_REAL32 real32Value;
RTS_REAL64 real64Value;
RTS_HANDLE handleValue;
RTS_RESULT resultValue;
RTS_UINTPTR uintptrValue;
RTS_INTPTR intptrValue;
RTS_SIZE sizeValue;
RTS_PTRDIFF ptrdiffValue;
RTS_INT intValue;
RTS_BOOL boolValue;
RTS_UI64 ui64Value;
RTS_I64 i64Value;
RTS_CSTRING *cstringValue;
RTS_WCHAR *wstringValue;
RTS_CWCHAR *cwstringValue;
}RTS_VALUE;
typedef struct
{
RTS_TYPECLASS typeClass;
RTS_VALUE value;
}RTS_TYPEDVALUE;
/*
* IEC basic typedefinitions.
* Defines all datatypes used in IEC programs. Datatypes must match to CoDeSys compiler.
* Systems that overloads standard types must redefine this types in sysdefines.h and set IECBASETYPES_DEFINED
*/
typedef void HUGEPTR(CDECL *RTS_VOID_FCTPTR)(void);
#ifndef IECBASETYPES_DEFINED
#define IECBASETYPES_DEFINED
# define RTS_IEC_VOID_FCTPTR RTS_VOID_FCTPTR
typedef void* RTS_IEC_VOIDPTR;
typedef RTS_I8 RTS_IEC_BOOL;
typedef RTS_I8 RTS_IEC_SINT;
typedef RTS_UI8 RTS_IEC_USINT;
typedef RTS_UI8 RTS_IEC_BYTE;
typedef RTS_I16 RTS_IEC_INT;
typedef RTS_UI16 RTS_IEC_UINT;
typedef RTS_UI16 RTS_IEC_WORD;
typedef RTS_I32 RTS_IEC_DINT;
typedef RTS_UI32 RTS_IEC_UDINT;
typedef RTS_UI32 RTS_IEC_DWORD;
typedef RTS_UI32 RTS_IEC_TIME;
typedef RTS_UI32 RTS_IEC_TIME_OF_DAY;
typedef RTS_UI32 RTS_IEC_TOD;
typedef RTS_UI32 RTS_IEC_DATE_AND_TIME;
typedef RTS_UI32 RTS_IEC_DT;
typedef RTS_UI32 RTS_IEC_DATE;
typedef RTS_I64 RTS_IEC_LINT;
typedef RTS_UI64 RTS_IEC_ULINT;
typedef RTS_UI64 RTS_IEC_LWORD;
typedef RTS_UI64 RTS_IEC_LTIME;
typedef RTS_SIZE RTS_IEC_XWORD;
typedef RTS_UINTPTR RTS_IEC_UXINT;
typedef RTS_PTRDIFF RTS_IEC_XINT;
typedef RTS_REAL32 RTS_IEC_REAL;
typedef RTS_REAL64 RTS_IEC_LREAL;
typedef RTS_CSTRING RTS_IEC_STRING;
# ifdef RTS_UNICODE
typedef RTS_WCHAR RTS_IEC_WSTRING;
# else
typedef RTS_UI16 RTS_IEC_WSTRING;
# endif
typedef RTS_CWCHAR RTS_IEC_CWCHAR;
typedef RTS_SIZE RTS_IEC_SIZE;
typedef RTS_HANDLE RTS_IEC_HANDLE;
typedef RTS_IEC_UDINT RTS_IEC_RESULT;
#endif /*IECBASETYPES_DEFINED*/
#ifndef RTS_MEM_REGION_DEFINED
#define RTS_MEM_REGION_DEFINED
/**
* <description>
* Abstract Memory Region.
* </description>
*/
typedef struct tagRTS_MEM_REGION
{
/* base address of the region */
RTS_UINTPTR base;
/* region size */
RTS_SIZE size;
} RTS_MEM_REGION;
#endif
#ifndef EXT_FUNCT_REF_DEFINED
#define EXT_FUNCT_REF_DEFINED
/**
* Exported function descriptor
*/
typedef struct tagCMP_EXT_FUNCTION_REF
{
/* pointer to an exported function */
RTS_VOID_FCTPTR pfExtCall;
/* name of an exported function */
const char* pszExtCallName;
/* signature */
RTS_UI32 signature;
/* version */
RTS_UI32 version;
} CMP_EXT_FUNCTION_REF;
#endif
/* The CMGetAPI2/CMGetAPI3 importOptions parameter flag which specifies an import */
/* as a required function (error if it is unresolved) */
#define CM_IMPORT_REQUIRED_FUNCTION 0
/* The CMGetAPI2/CMGetAPI3 importOptions parameter flag which specifies an import */
/* as an external libray function */
#define CM_IMPORT_EXTERNAL_LIB_FUNCTION 1
/* The CMGetAPI2/CMGetAPI3 importOptions parameter flag which specifies an import */
/* as an optional function */
#define CM_IMPORT_OPTIONAL_FUNCTION 2
/* Imported function belongs to an external libray */
#define ImportIsExternalLibFunction(par) (0 != ((par) & CM_IMPORT_EXTERNAL_LIB_FUNCTION))
/* Imported function is optional */
#define ImportIsOptionalFunction(par) (0 != ((par) & CM_IMPORT_OPTIONAL_FUNCTION))
#define RTS_SIZEOF sizeof
#define RTS_GET_WORD_OFFSET(typesize) (typesize)
#define RTS_GET_WORD_SIZE RTS_GET_WORD_OFFSET
#define RTS_GET_BYTE_OFFSET(offset) (offset)
#define RTS_GET_BYTE_SIZE(size) (size)
#define RTS_MEMSET memset
#define RTS_ALIGN_4BYTES 4
#define RTS_BITS_IN_BYTE 8
#define RTS_EMPTY_STRING ""
#define RTS_IS_EMPTY_STRING(s) ((char *)s == NULL || strcmp((char *)s, RTS_EMPTY_STRING) == 0)
#define RTS_TIMEOUT_INFINITE (~(RTS_UI32)0)
#define RTS_TIMEOUT_DEFAULT (RTS_UI32)(-2)
#define RTS_TIMEOUT_NO_WAIT (0)
#define RTS_INVALID_FILETRANSFER (RTS_UI32)(-1)
#include "CmpItf.h"
#ifndef COMPONENT_NAME_POSTFIX
#define COMPONENT_NAME_POSTFIX
#endif
#endif /*__RTSSTD_H__*/
File diff suppressed because it is too large Load Diff
+897
View File
@@ -0,0 +1,897 @@
divert(-1)
% -----------------------------------
% Copyright: Copyright CODESYS Development GmbH
% -----------------------------------
# The following lines ("DO NOT MODIFY...") generate a message in the destination file.
# This comment is not aimed at this file.
divert`'dnl
/***********************************************************************
* DO NOT MODIFY!
* This is a generated file. Do not modify it's contents directly
***********************************************************************/
include(`Util.m4')
divert(-1)
changecom(`%')
% -----------------------------
% Define some diverts that gather information about some special features
% and initialize those diversions
% -----------------------------
define(DIVERT_USE,3)
define(DIVERT_USEIMPORT,4)
define(DIVERT_USEEXTERN,5)
define(DIVERT_INIT,6)
define(DIVERT_RENAME_ENTRYFUN,9)
define(DIVERT_BEGINCLASSDEF,10)
define(DIVERT_CLASSDEF,11)
define(DIVERT_CLASSMEMBERS,12)
define(DIVERT_ENDCLASSDEF,13)
define(DIVERT_ENDMETHODDEF,15)
define(DIVERT_URTS_DEFS, 20)
define(DIVERT_ENDFILE,100)
define(`REF_ITF', `GEN_INCLUDE($1)')
define(`COMPONENT_VERSION',`#define CMP_VERSION UINT32_C(`$1')
#define CMP_VERSION_STRING "_VERSION_MAJOR(`$1')._VERSION_SUB0(`$1')._VERSION_SUB1(`$1')._VERSION_SUB2(`$1')"
#define CMP_VERSION_RC _VERSION_MAJOR(`$1'),_VERSION_SUB0(`$1'),_VERSION_SUB1(`$1'),_VERSION_SUB2(`$1')')
define(`COMPONENT_VENDORID',`#define CMP_VENDORID $1
#ifndef WIN32_RESOURCES')
divert(DIVERT_USE)dnl
#define USE_STMT \
/*lint -save --e{528} --e{551} */ \
static volatile PF_REGISTER_API s_pfCMRegisterAPI; \
static volatile PF_REGISTER_API2 s_pfCMRegisterAPI2; \
static volatile PF_GET_API s_pfCMGetAPI; \
static volatile PF_GET_API2 s_pfCMGetAPI2; \
static volatile PF_REGISTER_CLASS s_pfCMRegisterClass; \
static volatile PF_CREATEINSTANCE s_pfCMCreateInstance; \
static volatile PF_CALL_HOOK s_pfCMCallHook; \
static const CMP_EXT_FUNCTION_REF s_ExternalsTable[] =\
{\
EXPORT_EXTREF_STMT\
EXPORT_EXTREF2_STMT\
{ ((RTS_VOID_FCTPTR)(void *)0), "", 0, 0 }\
};\
static const CMP_EXT_FUNCTION_REF s_ItfTable[] = EXPORT_CMPITF_STMT; \
/*lint -restore */ \
static int CDECL ExportFunctions(void); \
static int CDECL ImportFunctions(void); \
static IBase* CDECL CreateInstance(CLASSID cid, RTS_RESULT *pResult); \
static RTS_RESULT CDECL DeleteInstance(IBase *pIBase); \
static RTS_UI32 CDECL CmpGetVersion(void); \
static RTS_RESULT CDECL HookFunction(RTS_UI32 ulHook, RTS_UINTPTR ulParam1, RTS_UINTPTR ulParam2); \
dnl
divert(-1)
divert(DIVERT_USEIMPORT)
#define USEIMPORT_STMT \
/*lint -save --e{551} */ \
static volatile PF_REGISTER_API s_pfCMRegisterAPI; \
static volatile PF_REGISTER_API2 s_pfCMRegisterAPI2; \
static volatile PF_GET_API s_pfCMGetAPI; \
static volatile PF_GET_API2 s_pfCMGetAPI2; \
static volatile PF_REGISTER_CLASS s_pfCMRegisterClass; \
static volatile PF_CREATEINSTANCE s_pfCMCreateInstance; \
static volatile PF_CALL_HOOK s_pfCMCallHook; \
/*lint -restore */ \
dnl
divert(-1)
divert(DIVERT_USEEXTERN)
#define USEEXTERN_STMT \
dnl
divert(-1)
divert(DIVERT_RENAME_ENTRYFUN)
#ifndef COMPONENT_NAME
#error COMPONENT_NAME is not defined. This prevents the component from being linked statically. Use `SET_COMPONENT_NAME'(<name_of_your_component>) to set the name of the component in your .m4 component description.
#endif
divert(-1)
divert(DIVERT_BEGINCLASSDEF)
#ifdef CPLUSPLUS
divert(-1)
divert(DIVERT_ENDMETHODDEF)
#endif /*CPLUSPLUS*/
divert(-1)
divert(DIVERT_ENDFILE)
`#endif /*WIN32_RESOURCES*/'
`#endif /*_DEP_H_*/'
divert(-1)')
% ---------------------------
% The SET_COMPONENT_NAME directive should reside at the top of each "Itf" file.
% ---------------------------
define(`SET_COMPONENT_NAME',
`define(_COMPONENT_NAME,`$1')dnl
`#ifndef _'_UPPERCASE(_COMPONENT_NAME)`DEP_H_'
`#define _'_UPPERCASE(_COMPONENT_NAME)`DEP_H_'
#define COMPONENT_NAME "$1" COMPONENT_NAME_POSTFIX
#define COMPONENT_ID ADDVENDORID(CMP_VENDORID, CMPID_$1)
#define COMPONENT_NAME_UNQUOTED $1
divert(DIVERT_RENAME_ENTRYFUN)
divert(DIVERT_RENAME_ENTRYFUN)
#if defined(STATIC_LINK) || defined(MIXED_LINK) || defined(DYNAMIC_LINK) || defined(CPLUSPLUS_STATIC_LINK)
#define ComponentEntry $1`'__Entry
#endif
divert
divert(DIVERT_URTS_DEFS)dnl
divert
')
% -----------------------------
% The COMPONENT_SOURCES and COMPONENT_SYSSOURCES macros are to be ignored. They
% are used by the configuration tool only.
% -----------------------------
define(`COMPONENT_SOURCES',`dnl')
define(`EXTERNAL_SOURCES',`dnl')
define(`EXTERNAL_INCLUDES',`dnl')
define(`COMPONENT_INCLUDES',`dnl')
define(`COMPONENT_SYSSOURCES',`dnl')
define(`CONTRIB_SOURCES',`dnl')
define(`CONTRIB_INCLUDES',`dnl')
')
% -----------------------------
% The CATEGORY macro is to be ignored. It
% is used by the configuration tool only.
% -----------------------------
define(`CATEGORY',`dnl')
')
% -----------------------------
% After all input is read, some macros have to be created
% -----------------------------
define(`ADD_IMPORTS',`ifdef(`__IMPORTS',`__IMPORTS popdef(`__IMPORTS') ADD_IMPORTS')')
define(`CREATE_IMPORT_STMT', dnl
`ifdef(`__IMPORTS',`#if defined(STATIC_LINK)
#define IMPORT_STMT
#else
#define IMPORT_STMT \
{\
RTS_RESULT importResult = ERR_OK;\
RTS_RESULT TempResult = ERR_OK;\
INIT_STMT \
TempResult = GET_LogAdd(CM_IMPORT_OPTIONAL_FUNCTION); \
TempResult = GET_CMUtlMemCpy(CM_IMPORT_OPTIONAL_FUNCTION); \
ADD_IMPORTS \
/* To make LINT happy */\
TempResult = TempResult;\
if (ERR_OK != importResult) return importResult;\
}
#endif
',`#define IMPORT_STMT INIT_STMT')
')
% -----------------------------
% This function emits all export statements inside the macro EXPORT_STMT (one after another)
% -----------------------------
define(`ADD_EXPORTS',`ifdef(`__EXPORTS',`__EXPORTS popdef(`__EXPORTS') ADD_EXPORTS')')
define(`ADD_EXTREF_EXPORTS',`ifdef(`__EXPORTS_EXTREF',`__EXPORTS_EXTREF popdef(`__EXPORTS_EXTREF') ADD_EXTREF_EXPORTS')')
define(`ADD_EXTREF_EXPORTS2',`ifdef(`__EXPORTS_EXTREF2',`__EXPORTS_EXTREF2 popdef(`__EXPORTS_EXTREF2') ADD_EXTREF_EXPORTS2')')
define(`ADD_EXPORTS_CPLUSPLUS_ONLY',`ifdef(`__EXPORTS_CPLUSPLUS_ONLY',`__EXPORTS_CPLUSPLUS_ONLY popdef(`__EXPORTS_CPLUSPLUS_ONLY') ADD_EXPORTS_CPLUSPLUS_ONLY')')
% -----------------------------
% Define the EXPORT_STMT macro. the content is filled out by ADD_EXPORTS.
% -----------------------------
define(`CREATE_EXPORT_STMT',dnl
`ifdef(`__EXPORTS_EXTREF',dnl
`#ifndef _UPPERCASE(_COMPONENT_NAME)_DISABLE_EXTREF
#define EXPORT_EXTREF_STMT \
ADD_EXTREF_EXPORTS
#else
#define EXPORT_EXTREF_STMT
#endif',`#define EXPORT_EXTREF_STMT')
'dnl
`ifdef(`__EXPORTS_EXTREF2',dnl
`#ifndef _UPPERCASE(_COMPONENT_NAME)_DISABLE_EXTREF2
#define EXPORT_EXTREF2_STMT \
ADD_EXTREF_EXPORTS2
#else
#define EXPORT_EXTREF2_STMT
#endif',`#define EXPORT_EXTREF2_STMT')
'dnl
`ifdef(`__EXPORTS',dnl
`#if !defined(_UPPERCASE(_COMPONENT_NAME)_DISABLE_CMPITF) && !defined(STATIC_LINK) && !defined(CPLUSPLUS) && !defined(CPLUSPLUS_ONLY)
#define EXPORT_CMPITF_STMT \
{\
ADD_EXPORTS\
{ ((RTS_VOID_FCTPTR)(void *)0), "", 0, 0 }\
}
#else
#define EXPORT_CMPITF_STMT \
{\
{ ((RTS_VOID_FCTPTR)(void *)0), "", 0, 0 }\
}
#endif',`#define EXPORT_CMPITF_STMT {{ ((RTS_VOID_FCTPTR)(void *)0), "", 0, 0 }}')
'dnl
`ifdef(`__EXPORTS_CPLUSPLUS_ONLY', `
#define EXPORT_CPP_STMT \
{\
ADD_EXPORTS_CPLUSPLUS_ONLY \
}
',`#define EXPORT_CPP_STMT')
'dnl
)
% -----------------------------
% This function emits all init statements inside the macro INIT_STMT (one after another)
% -----------------------------
define(`ADD_INITS',`ifdef(`__INITS',`__INITS popdef(`__INITS') ADD_INITS')')
define(`ADD_INIT_LOCALS',`ifdef(`__INIT_LOCALS',`__INIT_LOCALS popdef(`__INIT_LOCALS') ADD_INIT_LOCALS')')
define(`ADD_EXITS',`ifdef(`__EXITS',`__EXITS popdef(`__EXITS') ADD_EXITS')')
% -----------------------------
% Define the INIT_STMT macro.
% -----------------------------
define(`CREATE_INIT_STMT', dnl
`ifdef(`__INITS',``
#ifdef CPLUSPLUS
#define INIT_STMT' \
{\
IBase *pIBase;\
RTS_RESULT initResult;\
if (pICmpLog == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase = (IBase *)s_pfCMCreateInstance(CLASSID_CCmpLog, &initResult); \
if (pIBase != NULL) \
{ \
pICmpLog = (ICmpLog *)pIBase->QueryInterface(pIBase, ITFID_ICmpLog, &initResult); \
pIBase->Release(pIBase); \
} \
} \
if (pICMUtils == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase = (IBase *)s_pfCMCreateInstance(CLASSID_CCMUtils, &initResult); \
if (pIBase != NULL) \
{ \
pICMUtils = (ICMUtils *)pIBase->QueryInterface(pIBase, ITFID_ICMUtils, &initResult); \
pIBase->Release(pIBase); \
} \
} \
ADD_INITS \
}
#define INIT_LOCALS_STMT \
{\
pICmpLog = NULL; \
pICMUtils = NULL; \
ADD_INIT_LOCALS \
}
#define EXIT_STMT \
{\
IBase *pIBase;\
RTS_RESULT exitResult;\
if (pICmpLog != NULL) \
{ \
pIBase = (IBase *)pICmpLog->QueryInterface(pICmpLog, ITFID_IBase, &exitResult); \
if (pIBase != NULL) \
{ \
pIBase->Release(pIBase); \
if (pIBase->Release(pIBase) == 0) /* The object will be deleted here! */ \
pICmpLog = NULL; \
} \
} \
if (pICMUtils != NULL) \
{ \
pIBase = (IBase *)pICMUtils->QueryInterface(pICMUtils, ITFID_IBase, &exitResult); \
if (pIBase != NULL) \
{ \
pIBase->Release(pIBase); \
if (pIBase->Release(pIBase) == 0) /* The object will be deleted here! */ \
pICMUtils = NULL; \
} \
} \
ADD_EXITS \
}
#else
#define INIT_STMT
#define INIT_LOCALS_STMT
#define EXIT_STMT
#endif
',`#ifdef CPLUSPLUS
#define INIT_STMT \
{\
IBase *pIBase;\
RTS_RESULT initResult;\
if (pICmpLog == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase = (IBase *)s_pfCMCreateInstance(CLASSID_CCmpLog, &initResult); \
if (pIBase != NULL) \
{ \
pICmpLog = (ICmpLog *)pIBase->QueryInterface(pIBase, ITFID_ICmpLog, &initResult); \
pIBase->Release(pIBase); \
} \
} \
if (pICMUtils == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase = (IBase *)s_pfCMCreateInstance(CLASSID_CCMUtils, &initResult); \
if (pIBase != NULL) \
{ \
pICMUtils = (ICMUtils *)pIBase->QueryInterface(pIBase, ITFID_ICMUtils, &initResult); \
pIBase->Release(pIBase); \
} \
} \
}
#define INIT_LOCALS_STMT \
{\
pICmpLog = NULL; \
pICMUtils = NULL; \
ADD_INIT_LOCALS \
}
#define EXIT_STMT \
{\
IBase *pIBase;\
RTS_RESULT exitResult;\
if (pICmpLog != NULL) \
{ \
pIBase = (IBase *)pICmpLog->QueryInterface(pICmpLog, ITFID_IBase, &exitResult); \
if (pIBase != NULL) \
{ \
pIBase->Release(pIBase); \
if (pIBase->Release(pIBase) == 0) /* The object will be deleted here! */ \
pICmpLog = NULL; \
} \
} \
if (pICMUtils != NULL) \
{ \
pIBase = (IBase *)pICMUtils->QueryInterface(pICMUtils, ITFID_IBase, &exitResult); \
if (pIBase != NULL) \
{ \
pIBase->Release(pIBase); \
if (pIBase->Release(pIBase) == 0) /* The object will be deleted here! */ \
pICMUtils = NULL; \
} \
} \
}
#else
#define INIT_STMT
#define INIT_LOCALS_STMT
#define EXIT_STMT
#endif')
')
% -----------------------------
% The next lines causes the CREATE_IMPORT_STMT, CREATE_EXPORT_STMT
% and CREATE_INIT_STMT function to be called after all input has been read
% -----------------------------
m4wrap(`
CREATE_EXPORT_STMT
#if defined(STATIC_LINK)
#define EXPORT_STMT\
{\
RTS_RESULT ExpResult;\
if (NULL == s_pfCMRegisterAPI)\
return ERR_NOTINITIALIZED;\
ExpResult = s_pfCMRegisterAPI(s_ExternalsTable, 0, 1, COMPONENT_ID);\
if (ERR_OK != ExpResult)\
return ExpResult;\
}
#else
#define EXPORT_STMT\
{\
RTS_RESULT ExpResult;\
if (NULL == s_pfCMRegisterAPI)\
return ERR_NOTINITIALIZED;\
ExpResult = s_pfCMRegisterAPI(s_ExternalsTable, 0, 1, COMPONENT_ID);\
if (ERR_OK != ExpResult)\
return ExpResult;\
ExpResult = s_pfCMRegisterAPI(s_ItfTable, 0, 0, COMPONENT_ID);\
if (ERR_OK != ExpResult)\
return ExpResult;\
}
#endif
')
m4wrap(`
CREATE_IMPORT_STMT
')
m4wrap(`
CREATE_INIT_STMT
')
% -----------------------------
% Generate an "#include " directive,
% replacing the extension ".m4" with ".h"
% -----------------------------
define(`GET_INCLUDE_FILE', `ifelse(`-1',regexp(`$1',`\.m4$'),`error(`m4:'__file__`('__line__`):The first parameter "'$1`" is not a .m4 file')',dnl
`/**
* \file 'patsubst(`$1',`\.m4$',`\.h')`
*/')')
define(`GEN_INCLUDE', dnl
`ifelse(`-1',regexp(`$1',`\.m4$'), dnl
`error(`m4:'__file__`('__line__`):The first parameter "'$1`" is not a .m4 file
')',dnl
$1,`CmpLogItf.m4', `/*Obsolete include: CmpLogItf.m4*/',dnl
$1,`CMUtilsItf.m4', `/*Obsolete include: CMUtilsItf.m4*/',dnl
`#include "patsubst(`$1',`\.m4$',`\.h')"')')
define(`GEN_INIT_STMT', `pushdef(`__INITS',ifelse($1,`CMUtils',`/*Obsolete include CMUtils*/ \
',
$1,`CmpLog',`/*Obsolete include CmpLog*/ \
',
`if (pI$1 == NULL && s_pfCMCreateInstance != NULL) \
{ \
pIBase = (IBase *)s_pfCMCreateInstance(CLASSID_C$1, &initResult); \
if (pIBase != NULL) \
{ \
pI$1 = (I$1 *)pIBase->QueryInterface(pIBase, ITFID_I$1, &initResult); \
pIBase->Release(pIBase); \
} \
} \
'))')
define(`GEN_INIT_LOCALS_STMT', `pushdef(`__INIT_LOCALS',`ifelse($1,`CMUtils',`/*Obsolete include CMUtils*/ \
',
$1,`CmpLog',`/*Obsolete include CmpLog*/ \
',
`pI$1 = NULL; \
')')')
define(`GEN_EXIT_STMT', `pushdef(`__EXITS',`ifelse($1,`CMUtils',`/*Obsolete include CMUtils*/ \
',
$1,`CmpLog',`/*Obsolete include CmpLog*/ \
',
`if (pI$1 != NULL) \
{ \
pIBase = (IBase *)pI$1->QueryInterface(pI$1, ITFID_IBase, &exitResult); \
if (pIBase != NULL) \
{ \
pIBase->Release(pIBase); \
if (pIBase->Release(pIBase) == 0) /* The object will be deleted here! */ \
pI$1 = NULL; \
} \
} \
')')')
define(`GEN_USED_INTERFACES', dnl
`ifelse(`-1',regexp(`$1',`\.m4$'), dnl
`error(`m4:'__file__`('__line__`):The first parameter "'$1`" is not a .m4 file
')',dnl
`GEN_INCLUDE($1)'dnl
`GEN_INIT_STMT(`'patsubst(`$1',`\Itf.m4$',`'))'dnl
`GEN_INIT_LOCALS_STMT(`'patsubst(`$1',`\Itf.m4$',`'))'dnl
`GEN_EXIT_STMT(`'patsubst(`$1',`\Itf.m4$',`'))')dnl
')
% -----------------------------
% All variations of DEF_*_API
% Depending on the Variable DEF_CPP,
% we are adding them to __EXPORTS or __EXPORTS_CPP.
% -----------------------------
define(`PUSH_ITF', dnl
`ifdef(`DEF_CPP', dnl
`pushdef(`__EXPORTS_CPLUSPLUS_ONLY',` \
if (ERR_OK != EXP_`'_COMPONENT_NAME`'$3) \
{\
if (CHK_LogAdd)\
(void)CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_ERROR, ERR_FAILED, 0, "Export of ApiFunction [$3] failed\n"); \
return ERR_FAILED;\
}')'
, dnl
`pushdef(`__EXPORTS_EXTREF',`ifelse(`$5',1,`ifelse(`$8',1,`', `{ (RTS_VOID_FCTPTR)$3, "$3", ifelse(eval($#>5),1,$6,0), ifelse(eval($#>6),1,$7,0) },\
')',`')')' dnl
`pushdef(`__EXPORTS_EXTREF2',`ifelse(`$8',1,`{ (RTS_VOID_FCTPTR)$3, "$3", $6, $7 }, \
',`')')' dnl
`pushdef(`__EXPORTS',`ifelse(`$5',1,`',`{ (RTS_VOID_FCTPTR)$3, "$3", 0, 0 },\
')')' dnl
)' dnl
)
define(`PUSH_CLASS_ITF', dnl
`ifdef(`DEF_CPP', dnl
`pushdef(`__EXPORTS_CPLUSPLUS_ONLY',` \
if (ERR_OK != EXP_`'_COMPONENT_NAME`'$3) \
{\
if (CHK_LogAdd)\
(void)CAL_LogAdd(STD_LOGGER, COMPONENT_ID, LOG_ERROR, ERR_FAILED, 0, "Export of ApiFunction [$3] failed\n"); \
return ERR_FAILED;\
}')'
, dnl
`pushdef(`__EXPORTS_EXTREF',`ifelse(`$5',1,`ifelse(`$8',1,`',`{ (RTS_VOID_FCTPTR)$3, "$3",ifelse(eval($#>5),1,$6,0),ifelse(eval($#>6),1,$7,0)},\
')',`')')' dnl
`pushdef(`__EXPORTS_EXTREF2',`ifelse(`$8',1,`{ (RTS_VOID_FCTPTR)$3, "$3", $6, $7 }, \
',`')')' dnl
`pushdef(`__EXPORTS',`')' dnl
)' dnl
)
define(`DEF_API', dnl
`PUSH_ITF($@)' dnl
)
define(`DEF_STATIC_API',
`PUSH_ITF($@)' dnl
)
define(`DEF_CREATEITF_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_DELETEITF_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_HANDLEITF_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_HANDLEITF_API2',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_HANDLEITF_API_OWNCPP',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_CREATECLASSITF_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_CREATECLASSITF2_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_PRODUCECLASSITF_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_PRODUCECLASSITF_API_OWNCPP',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_DELETECLASSITF_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_DELETECLASSITF2_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_CLASSITF_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_RETURNHANDLECLASSITF_API',
`PUSH_CLASS_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_HANDLEITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_STATICITF_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) static $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_ITF_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_ITF_API_OWNCPP',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_ITF_API2',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`DEF_ITF_GLOBAL_API',
`PUSH_ITF($@)' dnl
`divert(DIVERT_CLASSMEMBERS) virtual $1 $2 `I'$3(_CONCAT(`_MAKE_ITF_PARAMLIST',_TRIM(`$4')));
divert(-1)'
)
define(`SET_INTERFACE_NAME',`
ifdef(`_IN_IMPLEMENT',`
pushdef(`_INTERFACE_LIST', `$1')
pushdef(`_INTERFACECAST_LIST',`
else if (iid == ITFID_`I'$1)
pItf = dynamic_cast<`I'$1 *>(this);')',
`ifelse($1,`CMUtils',`divert(DIVERT_USE)\
/*obsolete entry ITF_$1*/ dnl divert(-1)',
$1,`CmpLog',`divert(DIVERT_USE)\
/*obsolete entry ITF_$1*/ dnl divert(-1)',
`divert(DIVERT_USE)\
`ITF_'`$1'dnl')
ifelse($1,`CMUtils',`divert(DIVERT_USEIMPORT)\
/*obsolete entry ITF_$1*/ dnl divert(-1)',
$1,`CmpLog',`divert(DIVERT_USEIMPORT)\
/*obsolete entry ITF_$1*/ dnl divert(-1)',
`divert(DIVERT_USEIMPORT)\
`ITF_'`$1'dnl')
ifelse($1,`CMUtils',`divert(DIVERT_USEEXTERN)\
/*obsolete entry EXTITF_$1*/ dnl divert(-1)',
$1,`CmpLog',`divert(DIVERT_USEEXTERN)\
/*obsolete entry EXTITF_$1*/ dnl divert(-1)',
`divert(DIVERT_USEEXTERN)\
`EXTITF_'`$1'dnl')
divert(-1)')
')
define(`WRITE_INTERFACE_LIST2',`ifdef(`_INTERFACE_LIST',`, public `I'_INTERFACE_LIST popdef(`_INTERFACE_LIST')WRITE_INTERFACE_LIST2')')
define(`WRITE_INTERFACE_LIST',`ifdef(`_INTERFACE_LIST',`define(`_FIRST_INTERFACE_NAME',_INTERFACE_LIST)public `I'_INTERFACE_LIST popdef(`_INTERFACE_LIST')WRITE_INTERFACE_LIST2')')
define(`WRITE_INTERFACE_CASTS',`ifdef(`_INTERFACECAST_LIST',`_INTERFACECAST_LIST popdef(`_INTERFACECAST_LIST')WRITE_INTERFACE_CASTS')')
define(`TASK',`#ifndef RTS_TASKNAME_`'_UPPERCASE($1)
#define RTS_TASKNAME_`'_UPPERCASE($1) "$1"
#endif
#ifndef RTS_TASKPRIO_`'_UPPERCASE($1)
#define RTS_TASKPRIO_`'_UPPERCASE($1) $2
#endif
ifelse($3,`',`', `#ifndef RTS_TASKGROUP_`'_UPPERCASE($1)
#define RTS_TASKGROUP_`'_UPPERCASE($1) $3
#endif')
')
define(`TASKPREFIX',`#ifndef RTS_TASKPREFIX_`'_UPPERCASE($1)
#define RTS_TASKPREFIX_`'_UPPERCASE($1) "$1"
#endif
#ifndef RTS_TASKPRIO_`'_UPPERCASE($1)
#define RTS_TASKPRIO_`'_UPPERCASE($1) $2
#endif
ifelse($3,`',`', `#ifndef RTS_TASKGROUP_`'_UPPERCASE($1)
#define RTS_TASKGROUP_`'_UPPERCASE($1) $3
#endif')
')
define(`TASKPLACEHOLDER',`#ifndef RTS_TASKPLACEHOLDER_`'_UPPERCASE($1)
#define RTS_TASKPLACEHOLDER_`'_UPPERCASE($1) ""
#endif
#ifndef RTS_TASKPRIO_`'_UPPERCASE($1)
#define RTS_TASKPRIO_`'_UPPERCASE($1) $2
#endif
ifelse($3,`',`', `#ifndef RTS_TASKGROUP_`'_UPPERCASE($1)
#define RTS_TASKGROUP_`'_UPPERCASE($1) $3
#endif')
')
% -----------------------------
% Get all interfaces, which are implemented by this component.
% Differentiate between C++ and C Interfaces.
% -----------------------------
define(`DO_IMPLEMENT_ITF',`
GET_INCLUDE_FILE($1)
GEN_INCLUDE($1)
ifelse(`$#',1,`',`DO_IMPLEMENT_ITF(shift($@))')
divert(-1)
include($1)
divert
')
define(`IMPLEMENT_QUERY_INTERFACE',`define(`QUERY_INTERFACE', `$1')')
define(`IMPLEMENT_ITF',dnl
`undefine(`DEF_CPP')'dnl
`IMPLEMENT_ITF_AS(``C'_COMPONENT_NAME', $@)'
)
define(`IMPLEMENT_CPP_ITF',
`define(`DEF_CPP')'
`undefine(`_INTERFACE_LIST')undefine(`_INTERFACECAST_LIST')undefine(`_FIRST_INTERFACE_NAME')define(`_IN_IMPLEMENT')define(`_INTERFACE_LIST_INIT')'
`DO_IMPLEMENT_ITF($@)'
)
define(`IMPLEMENT_ITF_AS',
`ifdef(`_INTERFACE_LIST_INIT', `',
`undefine(`_INTERFACE_LIST')undefine(`_INTERFACECAST_LIST')undefine(`_FIRST_INTERFACE_NAME')'
)'
`define(`_IN_IMPLEMENT')define(`_INTERFACE_LIST_INIT')'
`
DO_IMPLEMENT_ITF(shift($@))
divert(DIVERT_CLASSDEF)
class $1 : WRITE_INTERFACE_LIST
{
public:
$1`() : h'_COMPONENT_NAME`'(RTS_INVALID_HANDLE), iRefCount(0)
{
}
virtual ~$1`()'
{
}
virtual unsigned long AddRef(IBase *pIBase = NULL)
{
iRefCount++;
return iRefCount;
}
virtual unsigned long Release(IBase *pIBase = NULL)
{
iRefCount--;
if (iRefCount == 0)
{
delete this;
return 0;
}
return iRefCount;
}
ifdef(`QUERY_INTERFACE', `QUERY_INTERFACE', `
virtual void* QueryInterface(IBase *pIBase, ITFID iid, RTS_RESULT *pResult)
{
void *pItf;
if (iid == ITFID_IBase)
pItf = dynamic_cast<IBase *>((`I'_FIRST_INTERFACE_NAME *)this);dnl
WRITE_INTERFACE_CASTS
else
{
if (pResult != NULL)
*pResult = ERR_NOTIMPLEMENTED;
return NULL;
}
if (pResult != (RTS_RESULT *)1)
(reinterpret_cast<IBase *>(pItf))->AddRef();
if (pResult != NULL && pResult != (RTS_RESULT *)1)
*pResult = ERR_OK;
return pItf;
}')
divert(DIVERT_ENDCLASSDEF)
public:
RTS_HANDLE h`'_COMPONENT_NAME;
int iRefCount;
};
divert(-1)
define(`DIVERT_CLASSDEF',eval(DIVERT_CLASSDEF+3))
define(`DIVERT_CLASSMEMBERS',eval(DIVERT_CLASSMEMBERS+3))
define(`DIVERT_ENDCLASSDEF',eval(DIVERT_ENDCLASSDEF+3))
undefine(`_IN_IMPLEMENT')
divert
')
%define(`IMPLEMENT_ITF', `
%divert(-1)
%include($1)
%divert')
define(`GENERATE_ITF_MACRO', `divert(DIVERT_USE)\
`ITF_'`$1' dnl
divert(-1)')
define(`USE_ITF', `GEN_USED_INTERFACES($1)
divert(-1)
pushdef(`DEF_API',`')
pushdef(`DEF_STATIC_API',`')
pushdef(`DEF_CREATEITF_API',`')
pushdef(`DEF_DELETEITF_API',`')
pushdef(`DEF_HANDLEITF_API',`')
pushdef(`DEF_HANDLEITF_API2',`')
pushdef(`DEF_HANDLEITF_API_OWNCPP',`')
pushdef(`DEF_CREATECLASSITF_API',`')
pushdef(`DEF_CREATECLASSITF2_API',`')
pushdef(`DEF_PRODUCECLASSITF_API',`')
pushdef(`DEF_PRODUCECLASSITF_API_OWNCPP',`')
pushdef(`DEF_DELETECLASSITF_API',`')
pushdef(`DEF_DELETECLASSITF2_API',`')
pushdef(`DEF_CLASSITF_API',`')
pushdef(`DEF_RETURNHANDLECLASSITF_API',`')
pushdef(`DEF_STATICITF_API',`')
pushdef(`DEF_ITF_API',`')
pushdef(`DEF_ITF_API_OWNCPP',`')
pushdef(`DEF_ITF_API2',`')
pushdef(`DEF_ITF_GLOBAL_API',`')
include($1)
popdef(`DEF_API')
popdef(`DEF_STATIC_API')
popdef(`DEF_CREATEITF_API')
popdef(`DEF_DELETEITF_API')
popdef(`DEF_HANDLEITF_API')
popdef(`DEF_HANDLEITF_API_OWNCPP')
popdef(`DEF_HANDLEITF_API2')
popdef(`DEF_CREATECLASSITF_API')
popdef(`DEF_CREATECLASSITF2_API')
popdef(`DEF_PRODUCECLASSITF_API')
popdef(`DEF_PRODUCECLASSITF_API_OWNCPP')
popdef(`DEF_DELETECLASSITF_API')
popdef(`DEF_DELETECLASSITF2_API')
popdef(`DEF_RETURNHANDLECLASSITF_API')
popdef(`DEF_CLASSITF_API')
popdef(`DEF_STATICITF_API')
popdef(`DEF_ITF_API2')
popdef(`DEF_ITF_API')
popdef(`DEF_ITF_API_OWNCPP')
popdef(`DEF_ITF_GLOBAL_API')
divert
')
define(`DOUSE', `divert(DIVERT_USE) \
ifelse($1,`CMUtlMemCpy',`/*obsolete USE_$1*/',
$1,`LogAdd',`/*obsolete USE_$1*/',
USE_$1) dnl
divert(DIVERT_USEIMPORT) \
ifelse($1,`CMUtlMemCpy',`/*obsolete USE_$1*/',
$1,`LogAdd',`/*obsolete USE_$1*/',
USE_$1) dnl
divert(DIVERT_USEEXTERN) \
ifelse($1,`CMUtlMemCpy',`/*obsolete USE_$1*/',
$1,`LogAdd',`/*obsolete EXT_$1*/',
EXT_$1) dnl
divert')
define(`DOIMPORT_REQ', `pushdef(`__IMPORTS',`ifelse($1,`LogAdd', `/*Obsolete required include LogAdd*/ \
',dnl
$1,`CMUtlMemCpy', `/*Obsolete required include CMUtlMemCpy*/ \
',
`if (ERR_OK == importResult ) importResult = GET_$1(0);\
')')')
define(`DOIMPORT_OPT', `pushdef(`__IMPORTS',`ifelse($1,`LogAdd', `/*Obsolete optional include LogAdd*/ \
',dnl
$1,`CMUtlMemCpy', `/*Obsolete optional include CMUtlMemCpy*/ \
',
`if (ERR_OK == importResult ) TempResult = GET_$1(CM_IMPORT_OPTIONAL_FUNCTION);\
')')')
define(`REQUIRED_IMPORTS', dnl
`ifelse($1,`', `', dnl
`_FOREACH(`DOIMPORT_REQ', $@)dnl
_FOREACH(`DOUSE', $@)dnl
')
')
define(`OPTIONAL_IMPORTS', dnl
`ifelse($1,`', `', dnl
`_FOREACH(`DOIMPORT_OPT', $@) dnl
_FOREACH(`DOUSE', $@) dnl
')
')
changecom(`/*', `*/')
divert
+113
View File
@@ -0,0 +1,113 @@
divert(-1)
changecom(`%')
%
% Copyright: Copyright CODESYS Development GmbH
%
define(`_CONCAT',`ifelse($#,0,`',$#,1,`$1',$#,2,`$1$2',`_CONCAT(`$1$2',`_CONCAT(shift(shift($@)))')')')
define(`_UPPERCASE', `translit($1, `a-z', `A-Z')')
define(`_TRIM',`regexp(`$1',`^[ ]*\(.*[^ ]\)[ ]*$',`\1')')
define(`_TRIMCMPPREFIX',`regexp(`$1',`...\(.*\)$',`\1')')
define(`_TRIMPOINTERPARAM', `ifelse(regexp(`$1',`[^,]\*',`RTS_HANDLE'),-1,0,1)')
define(`_TRIMVARPARAMLIST', `ifelse(regexp(`$1',`\.\.\.'),-1,0,1)')
define(`_FUN_PTR', _FUN_PTR1(`_UPPERCASE(`$1')'))
define(`_FUN_PTR_IEC', _FUN_PTR1(`_UPPERCASE(`$1')'_IEC))
define(`_FUN_PTR1', `PF'$1)
define( _CHKSUM, 0)
define(`_EXTRACTFIRSTPARAMTYPE',`_EXTRACTTYPE(_EXTRACTPARAMS(`$1'))')
define(`_EXTRACTTYPE',`regexp(`$1',`\([\w_]*[^ ]*\)',`\1')')
define(`_EXTRACTFIRSTPARAMTYPEPOINTER',`_EXTRACTTYPEPOINTER(_EXTRACTPARAMS(`$1'))')
define(`_EXTRACTTYPEPOINTER',`regexp(`$1',`\([\*]\)',`\1')')
define(`_EXTRACTFIRSTPARAMTYPERTS',`_EXTRACTTYPERTS(_EXTRACTPARAMS(`$1'))')
define(`_EXTRACTTYPERTS',`regexp(`$1',`\(RTS_\)',`\1')')
define(`_EXTRACTPARAMS',`regexp(`$1',`^[ ]*(\(.*\))[ ]*$',`\1')')
define(`_EXTRACTPARAMNAME',`regexp(`$1',`\([a-zA-Z0-9_]+\)$',`\1')')
define(`_HAS_VARIABLEPARAMETER',`regexp(`$1',`\.\.\.')')
define(`_EXTRACT_VARIABLEPARAMETER_FORMAT',`regexp(`$1',` \*?\([a-zA-Z0-9_]+\), \.\.\.',`\1')')
%
% Extract the parameter out of a parameter list.
%
% _EXTRACT_PARAM_LIST(`(int nCount, char *pBuf)') => `nCount,pBuf'
% _EXTRACT_PARAM_LIST(`(void)') => `'
%
define(_EXTRACT_PARAM_LIST_RECURSIVE,`ifelse($#,1,`_EXTRACTPARAMNAME(`$1')',`_EXTRACTPARAMNAME(`$1')`',_EXTRACT_PARAM_LIST_RECURSIVE(shift($@))')')
define(_EXTRACT_PARAM_LIST_,`ifelse(_TRIM(`$1'),`',`',_TRIM(`$1'),`void',`',`_EXTRACT_PARAM_LIST_RECURSIVE($@)')')
define(_EXTRACT_PARAM_LIST,`_EXTRACT_PARAM_LIST_(_EXTRACTPARAMS(`$1'))')
define(_EXTRACT_PARAM_LIST_HANDLE_RECURSIVE,`ifelse($#,1,`,_EXTRACTPARAMNAME(`$1')',`,_EXTRACTPARAMNAME(`$1')`'_EXTRACT_PARAM_LIST_HANDLE_RECURSIVE(shift($@))')')
define(_EXTRACT_PARAM_LIST_HANDLE_,`ifelse(_TRIM(`$1'),`',`',_TRIM(`$1'),`void',`',`_EXTRACT_PARAM_LIST_HANDLE_RECURSIVE($@)')')
define(_EXTRACT_PARAM_LIST_HANDLE,`_EXTRACT_PARAM_LIST_HANDLE_(shift(_EXTRACTPARAMS(`$1')))')
%
% Creates a parameter list for a macro call "(p1, p2, p3)", with one parameter for each parameter
% in the c parameterlist provided as parameter. If the provided parameterlist contains only `void'
% then it is treated as if it was empty.
%
% _MAKE_DUMMYPARAMLIST(`(int nCount, char *pBuf)') => `p0,p1'
% _MAKE_DUMMYPARAMLIST(`(void)') => `'
%
define(_MAKE_DUMMYPARAMLIST1,`ifelse($#,1,`',$#,2,`p$1',`p$1,_MAKE_DUMMYPARAMLIST1(incr($1),shift(shift($@)))')')
define(_MAKE_DUMMYPARAMLIST_,`ifelse(_TRIM(`$1'),`',`',_TRIM(`$1'),`void',`',`_MAKE_DUMMYPARAMLIST1(0,$@)')')
define(_MAKE_DUMMYPARAMLIST_WITHVOID_,`ifelse(_TRIM(`$1'),`',`',`_MAKE_DUMMYPARAMLIST1(0,$@)')')
define(_MAKE_DUMMYPARAMLIST,`_MAKE_DUMMYPARAMLIST_(_EXTRACTPARAMS(`$1'))')
%
% Creates a parameter list for a macro call "(p1, p2, p3)", with one parameter for each parameter
% in the c parameterlist provided as parameter. If the provided parameterlist contains only `void'
% then it is treated as if it had exactly one parameter.
%
% _MAKE_DUMMYPARAMLIST(`(int nCount, char *pBuf)') => `p0,p1'
% _MAKE_DUMMYPARAMLIST(`(void)') => `p0'
%
define(_MAKE_DUMMYPARAMLIST_WITHVOID,`_MAKE_DUMMYPARAMLIST_WITHVOID_(_EXTRACTPARAMS(`$1'))')
%
% Same as _MAKE_DUMMYPARAMLIST, but drops the first parameter
%
% _MAKE_HANDLE_DUMMYPARAMLIST(`(RTS_HANDLE, hHandle, int nCount, char *pBuf)') => `p1,p2'
%
define(_MAKE_HANDLE_DUMMYPARAMLIST,`shift(_MAKE_DUMMYPARAMLIST(`$1'))')
%
% Same as _MAKE_DUMMYPARAMLIST, but drops the first n parameter
%
% _MAKE_HANDLE_DUMMYPARAMLIST2(`(RTS_HANDLE hHandle, int nCount, char *pBuf, int nValue)', 2) => `p2,p3'
%
define(nshift, `ifelse($2, 0, `$1', `nshift(`shift($1)', decr($2))')')
define(_MAKE_HANDLE_DUMMYPARAMLIST2,`nshift(`_MAKE_DUMMYPARAMLIST(`$1')', $2)')
define(_MAKE_PARAMLIST2,`ifelse(_TRIM($@),`',`',`, $1`'_MAKE_PARAMLIST2(shift($@))')')
define(_MAKE_PARAMLIST1,`ifelse(_TRIM($@),`',`',`$1`'_MAKE_PARAMLIST2(shift($@))')')
define(_MAKE_HANDLEITF_PARAMLIST,`ifelse(_TRIM(shift($@)),`',`void',_TRIM(shift($@)),`void',`void',`_MAKE_PARAMLIST1(shift($@))')')
define(_MAKE_ITF_PARAMLIST, `ifelse(_TRIM($@),`',`void',_TRIM($@),`void',`void',`_MAKE_PARAMLIST1($@)')')
define(_MAKE_CREATEITF_PARAMLIST,`ifelse(_TRIM($@),`',`void',_TRIM($@),`void',`void',`_MAKE_PARAMLIST1($@)')')
%
% Ieration over some string elements
%
define(`_FOREACH', `ifelse(1,$#,` ',`$1($2)
ifelse(2,$#, ,`_FOREACH(`$1',shift(shift($@)))')')')
%
% Split component version number
%
% Example:
% $1 = "0x03020104"
% _VERSION_MAJOR => 3
% _VERSION_SUB0 => 2
% _VERSION_SUB1 => 1
% _VERSION_SUB2 => 4
%
define(`_TRIMLEFT_ZERO', `regexp(`$1', `^0*\(.+\)', `\1')')
define(`_VERSION_MAJOR',`_TRIMLEFT_ZERO(regexp(`$1',`^0x\([0-9a-fA-F][0-9a-fA-F]\)', `eval(0x\1)'))')
define(`_VERSION_SUB0',`_TRIMLEFT_ZERO(regexp(`$1',`^0x[0-9a-fA-F][0-9a-fA-F]\([0-9a-fA-F][0-9a-fA-F]\)', `eval(0x\1)'))')
define(`_VERSION_SUB1',`_TRIMLEFT_ZERO(regexp(`$1',`^0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\([0-9a-fA-F][0-9a-fA-F]\)', `eval(0x\1)'))')
define(`_VERSION_SUB2',`_TRIMLEFT_ZERO(regexp(`$1',`^0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\([0-9a-fA-F][0-9a-fA-F]\)', `eval(0x\1)'))')
divert`'dnl
+183
View File
@@ -0,0 +1,183 @@
##############################################################################
# Copyright: Copyright CODESYS Development GmbH
# Program: Extension API for the Linux SL products
##############################################################################
ifeq ($(dir $(lastword $(MAKEFILE_LIST))), ./)
#
# MAKEFILE is used wrong! Never call it from this folder directly
#
.PHONY:help
help:
@echo "**********************"
@echo "Dont work inside this folder! Please go to your library folder and call this makefile e.g.:"
@echo "make -f ../sdk/makefile newproject"
@echo
@echo "**********************"
.PHONY:all
all: help
.PHONY:newproject
newproject: help
.PHONY:makefile
makefile: help
else
#
# NORMAL RULES
#
# get some info from generated files
ITFM4 = $(wildcard *Itf.m4)
CSRC = $(wildcard *.c)
CMPBASENAME=$(CSRC:.c=)
# set some variables
OUTDIR=./out
ITF = $(basename ${ITFM4})
TEMPLATEDEP = $(SDKDIR)/m4/TemplateDep.m4
DEP = ${CMPBASENAME}Dep
# set name of shared object
SONAME= lib${CMPBASENAME}.so
# set sources of component
SRC += ${CSRC} CmpFrame.c
# objects: all sources
OBJS = $(addprefix ${OUTDIR}/,$(SRC:.c=.o))
# set default includes
INCLUDES += -I${SDKDIR}/include/ -I${OUTDIR}/ -I.
CFLAGS += -fPIC -g -O0 -Wall -Wextra -Wno-unused
CFLAGS += -DDEP_H=\"${DEP}.h\"
# set a vendorID
CMPVENDORID=0xFFFF
vpath %.m4 ${SDKDIR}/cmpstub/
vpath %.c ${SDKDIR}/src/
.PHONY:help
help:
@echo "**********************"
@echo "help / usage / available make targets:"
@echo "-all : just do everything needed"
@echo "-clean : cleanup all generated files"
@echo "-newproject : create a new project"
@echo "-showenv : show intern variables (for debugging)"
@echo "**********************"
.PHONY:newproject
newproject: makefile
.PHONY:all
all: ${OUTDIR}/$(SONAME)
SDK_BASE=$(dir $(lastword $(MAKEFILE_LIST)))
.PHONY:showenv
showenv:
@echo "**********************"
@echo "ITFM4: ${ITFM4}"
@echo "CSRC: ${CSRC}"
@echo "SONAME: ${SONAME}"
@echo "ITF: ${ITF}"
@echo "DEP: ${DEP}"
@echo "OBJS: ${OBJS}"
@echo "CC: $(CC)"
@echo "CFLAGS: ${CFLAGS}"
@echo "SDKDIR: ${SDKDIR}"
@echo "CMPBASENAME: ${CMPBASENAME}"
@echo "MAKEFILE_LIST: $(MAKEFILE_LIST)"
@echo "**********************"
@echo ""
# check if there are whitespaces in the SDK BASE DIR
# this causes horrible things in make, so we detect/avoid it directly at creating a new project
ifeq (1,$(words $(MAKEFILE_LIST)))
makefile:
@echo "**********************"
@echo "creating makefile for your project "
cp ${SDK_BASE}/makefile_template $@
@echo "# include of the SDK makefiles" >> $@
@echo "SDKDIR="$(abspath ${SDK_BASE}) >> $@
@echo 'include $${SDKDIR}/makefile' >> $@
@echo "" >> $@
@echo "now check your makefile here"
@echo "**********************"
@echo ""
else
makefile:
@echo "**********************"
@echo "creating makefile for your project FAILED:"
@echo "there are whitespaces in the SDK path"
@echo "this does not work with 'make'!"
@echo "Please put your SDK to a path without whitespaces"
@echo "**********************"
@echo ""
endif
${OUTDIR}/%.o: %.c
@echo "**********************"
@echo "compile: $@ from $<"
@mkdir -p ${OUTDIR}
$(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $<
@echo "**********************"
@echo ""
${OUTDIR}/${SONAME}: ${OUTDIR}/$(DEP).h ${OUTDIR}/$(ITF).h $(OBJS)
@echo "**********************"
@echo "link: $@"
@mkdir -p ${OUTDIR}
$(CC) $(LDFLAGS) -shared $(OBJS) -Wl,-soname,$(SONAME) -o $@ $(LDLIBS)
@echo "**********************"
@echo ""
${OUTDIR}/$(DEP).m4:
@echo "**********************"
@echo "create $@ from template"
@mkdir -p ${OUTDIR}
echo 'SET_COMPONENT_NAME(`'${CMPBASENAME}"')" > $@
echo 'COMPONENT_VERSION(`'${CMPVERSION}"')" >> $@
echo 'COMPONENT_VENDORID(`'${CMPVENDORID}"')" >> $@
echo "#define CMPID_${CMPBASENAME} ${CMPID}" >> $@
echo "IMPLEMENT_ITF("'`'"${CMPBASENAME}Itf.m4')" >> $@
@echo "**********************"
@echo ""
${OUTDIR}/$(DEP).h: ${OUTDIR}/$(DEP).m4 $(ITF).m4
@echo "**********************"
@echo "build dependency header: $@ from $<"
@mkdir -p ${OUTDIR}
$(DOS2UNIX) $<
$(M4) -I$(SDKDIR)/m4 -I. Implementation.m4 - < $< > $@
@echo "**********************"
@echo ""
${OUTDIR}/$(ITF).h: $(ITF).m4
@echo "**********************"
@echo "build interface header: $@ from $<"
@sed -n '/DEF_API/ !d; /_cext/ ! { s/^/ERROR: This functionname does not contain _cext (this is mandatory, see help for details):\n/p;q 1}' $<
@mkdir -p ${OUTDIR}
$(DOS2UNIX) $<
$(M4) -I$(SDKDIR)/m4 Exports.m4 - < $< > $@
@echo "**********************"
@echo ""
.PHONY:clean
clean:
@echo ""
@echo "**********************"
@echo "clean up"
rm -rf ${OUTDIR};
@echo "**********************"
@echo ""
endif
+48
View File
@@ -0,0 +1,48 @@
##############################################################################
# Copyright: Copyright CODESYS Development GmbH
# Program: Extension API for the Linux SL products
##############################################################################
#
# with this makefile you can influence the build of your component
#
#
# Hints:
# - the name of the *Itf.m4 file in this folder will be used as name of the shared object (and component name)
# - all C files in this folder will be compiled by default
#
# set versions of your shared object
# must be single digit, decimal
MAJORVER=0
MINORVER=1
# set a component version (must match your IEC library version)
# must be 4 bytes, hexadecimal
CMPVERSION=0x01000000
# set a component ID
# must be 2 bytes >= 0x2000 and hexadecimal and can be used to differentiate different components
CMPID=0x2000
# set your tools
DOS2UNIX = dos2unix
M4 = m4
# set a compiler
CC ?= gcc
# add some compiler flags (with += )
#CFLAGS += -g
# add some include paths (with +=)
#INCLUDES += -I.
# add some linker flags (with += )
#LDFLAGS +=
# add some libraries that you might need (with += )
#LDLIBS += -lc
+78
View File
@@ -0,0 +1,78 @@
/*****************************************************************************
* Copyright: Copyright CODESYS Development GmbH
* Program: Extension API for the Linux SL products
******************************************************************************/
#include "CmpStd.h"
#include DEP_H
USE_STMT
DLL_DECL int CDECL ComponentEntry(INIT_STRUCT *pInitStruct)
/* Used to exchange function pointers between component manager and components.
Called at startup for each component.
pInitStruct: IN Pointer to structure with:
pfExportFunctions OUT Pointer to function that exports component functions
pfImportFunctions OUT Pointer to function that imports functions from other components
pfGetVersion OUT Pointer to function to get component version
pfRegisterAPI IN Pointer to component manager function to register a API function
pfGetAPI IN Pointer to component manager function to get a API function
pfCallHook IN Pointer to component manager function to call a hook function
Return ERR_OK if library could be initialized, else error code
*/
{
pInitStruct->CmpId = COMPONENT_ID;
pInitStruct->pfExportFunctions = ExportFunctions;
pInitStruct->pfImportFunctions = ImportFunctions;
pInitStruct->pfGetVersion = CmpGetVersion;
pInitStruct->pfHookFunction = HookFunction;
pInitStruct->pfCreateInstance = NULL;
pInitStruct->pfDeleteInstance = NULL;
s_pfCMRegisterAPI = pInitStruct->pfCMRegisterAPI;
s_pfCMRegisterAPI2 = pInitStruct->pfCMRegisterAPI2;
s_pfCMGetAPI = pInitStruct->pfCMGetAPI;
s_pfCMGetAPI2 = pInitStruct->pfCMGetAPI2;
s_pfCMCallHook = pInitStruct->pfCMCallHook;
s_pfCMRegisterClass = pInitStruct->pfCMRegisterClass;
s_pfCMCreateInstance = pInitStruct->pfCMCreateInstance;
return ERR_OK;
}
/**
* <description>Publish exported functions to the component manager, to make them available for other components.
* Use generated macro EXPORT_STMT.</description>
* <result>ERR_OK or error code in case of error</result>
*/
static int CDECL ExportFunctions(void)
{
/* Macro to export functions */
EXPORT_STMT;
return ERR_OK;
}
/**
* <description>Import function pointers from other components. Use generated macro IMPORT_STMT.</description>
* <result>ERR_OK or error code if function name could not be resolved</result>
*/
static int CDECL ImportFunctions(void)
{
/* Macro to import functions */
IMPORT_STMT;
return ERR_OK;
}
/**
* <description>Return the version of our component.</description>
* <result>Version as defined in dep file</result>
*/
static RTS_UI32 CDECL CmpGetVersion(void)
{
return CMP_VERSION;
}
static RTS_RESULT CDECL HookFunction(RTS_UI32 ulHook, RTS_UINTPTR ulParam1, RTS_UINTPTR ulParam2)
{
return ERR_OK;
}