//This file was generated by the LASAL2 CodeGenerator  -- 
//Please, do not edit this file (it might be overwritten by the next generator run)
//{{LSL_DECLARATION

(*!
<Class
	Name               = "_Linker"
	Revision           = "0.5"
	GUID               = "{B249DC03-6675-11D6-8832-0048545E88BC}"
	RealtimeTask       = "false"
	CyclicTask         = "false"
	BackgroundTask     = "false"
	Sigmatek           = "true"
	OSInterface        = "true"
	HighPriority       = "false"
	Automatic          = "false"
	UpdateMode         = "Prescan"
	SharedCommandTable = "true"
	Objectsize         = "(284,120)"
	Comment            = "provides functions to get information about variables, objects, etc from the linker">
	<Channels>
		<Server Name="Server0" GUID="{B249DC04-6675-11D6-8832-0048545E88BC}" Visualized="true" Initialize="false" WriteProtected="true" Retentive="false"/>
	</Channels>
	<Dependencies>
		<Files>
			<File Path=".\Source\code\OsiBaseNew.h" Include="false"/>
			<File Path=".\Source\code\OsiBaseNew.st"/>
			<File Path=".\LinkerTypes.h" Include="false"/>
		</Files>
	</Dependencies>
	<RevDoku>
		<Owner Company="Sigmatek GmbH &amp; Co KG" Author="strgue"/>
		<Dokumentation Revision="0.5" Date="2022-09-20" Author="praerw" Company="Sigmatek GmbH &amp; Co KG" Description="Bugfix: under RTK the functions of the linker interface that are provided by the loader were not callable"/>
		<Dokumentation Revision="0.4" Date="2016-11-25" Author="strgue" Company="Sigmatek GmbH &amp; Co KG" Description="Added function GetChkSumByType for platform Salamander"/>
		<Dokumentation Revision="0.3" Date="2016-11-18" Author="laiulr" Company="Sigmatek GmbH &amp; Co KG" Description="Corrected version check for function GetChkSumByType"/>
		<Dokumentation Revision="0.2" Date="2016-06-23" Author="schsas" Company="Sigmatek GmbH &amp; Co KG" Description="Added function GetChkSumByType"/>
		<Dokumentation Revision="0.1" Date="2013-07-04" Author="kiltob" Company="Sigmatek GmbH &amp; Co KG" Description="Added new function GetChkSumFromClassName"/>
	</RevDoku>
</Class>
*)
_Linker : CLASS
	TYPE
	  OS_LINKER : STRUCT
	    GetFirstError : pVoid;
	    GetNextError : pVoid;
	    GetAddressFunction : pVoid;
	    GetAddressVariable : pVoid;
	    GetVariableInfo : pVoid;
	    GetDataMemoryAddress : pVoid;
	    GetCodeMemoryAddress : pVoid;
	    GetProjectState : pVoid;
	    LookupEmbedded : pVoid;
	    GetObjDscList : pVoid;
	    CRC32 : pVoid;
	    AddError2List : pVoid;
	    FreeErrorList : pVoid;
	    GetErrorCount : pVoid;
	    GetNextChannel : pVoid;
	    GetObjectName : pVoid;
	    GetChkByModulID : pVoid;
	    GetPrjCHK : pVoid;
	    XCH_MethPtr : pVoid;
	    LOADER_PrepareLink : pVoid;
	    LOADER_ApplyLink : pVoid;
	    dummy1 : pVoid;
	    dummy2 : pVoid;
	    dummy3 : pVoid;
	    dummy4 : pVoid;
	    GetChkSumFromClassName : pVoid;
	    GetChkSumByType : pVoid;
	  END_STRUCT;
	END_TYPE
  //Servers:
	Server0 	: SvrChCmd_DINT;
  //Clients:
  //Variables:
  //Functions:
	
	FUNCTION _Linker
		VAR_OUTPUT
			ret_code 	: ConfStates;
		END_VAR;
				//! <Function Comment="This function is called to return information of a variable by name." Name="GetVariableInfo"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetVariableInfo
		VAR_INPUT
			varname 	: ^CHAR;			//! <Variable Comment="A pointer to the ASC-ZERO name string of the variable." Name="GetVariableInfo.varname"/>
			infostruct 	: ^LSLLNK_VariableInfo;			//! <Variable Comment="A pointer to a LSLLNK_VARIABLEINFO structure to store the variable information." Name="GetVariableInfo.infostruct"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: DINT;			//! <Variable Comment="If the variable is found its information is copied into the buffer and 0 is returned, otherwise -1 is returned." Name="GetVariableInfo.retval"/>
		END_VAR;
				//! <Function Comment="This function is called to return the address of a function by name." Name="GetAddressFunction"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetAddressFunction
		VAR_INPUT
			functname 	: ^CHAR;			//! <Variable Comment="A pointer to the ASC-ZERO name string of the function" Name="GetAddressFunction.functname"/>
			isexe 	: ^CHAR;			//! <Variable Comment="A pointer to a BYTE to store TRUE if the current project is an EXE project or FALSE if it is a modular project." Name="GetAddressFunction.isexe"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="If the function is found its address is returned, otherwise NIL is returned." Name="GetAddressFunction.retval"/>
		END_VAR;
				//! <Function Comment="This function is called to return the address of a variable by name." Name="GetAddressVariable"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetAddressVariable
		VAR_INPUT
			varname 	: ^CHAR;			//! <Variable Comment="A pointer to the ASC-ZERO name string of the variable." Name="GetAddressVariable.varname"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="If the variable is found its address is returned, otherwise NIL is returned." Name="GetAddressVariable.retval"/>
		END_VAR;
				//! <Function Comment="This function is called to return the starting address of the Lasal application DATA memory area." Name="GetDataMemoryAddress"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetDataMemoryAddress
		VAR_OUTPUT
			retval (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="This function is called to return the starting address of the Lasal application CODE memory area." Name="GetCodeMemoryAddress"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetCodeMemoryAddress
		VAR_OUTPUT
			retval (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="This function is called to return the current project state ENUM value as follows: &#10; PRJ_ISNOTAVAIL: No project is currently loaded. &#10; PRJ_ISEXE: Project is an EXE project and is ready. &#10; PRJ_ISNOTLINKED: Modular project is not linked (error condition) &#10; PRJ_ISLINKED: Modular project loaded and ready." Name="GetProjectState"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetProjectState
		VAR_OUTPUT
			state (AX) 	: LSLLNK_ProjectState;
		END_VAR;
				//! <Function Comment="This function is called to get the CRC32 checksum of a Lasal application module by its module ID." Name="GetChksumByModulID"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetChksumByModulID
		VAR_INPUT
			modulID 	: UDINT;			//! <Variable Comment="The ID of the Lasal application module to check." Name="GetChksumByModulID.modulID"/>
		END_VAR
		VAR_OUTPUT
			chksum (EAX) 	: UDINT;			//! <Variable Comment="The CRC32 checksum of the module, -1 if module ID is not valid or project is not linked." Name="GetChksumByModulID.chksum"/>
		END_VAR;
				//! <Function Comment="This function is called to get the CRC32 checksum of the entire Lasal application project." Name="GetProjectChksum"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetProjectChksum
		VAR_OUTPUT
			chksum (EAX) 	: UDINT;			//! <Variable Comment="The CRC32 checksum of the entire project, -1 if no project is loaded." Name="GetProjectChksum.chksum"/>
		END_VAR;
				//! <Function Comment="This method is called to calculate a CRC-32 check value. The method is passed the current CRC32 value, a pointer to the BYTE data to add to the CRC, and a count of the data, in bytes, to add. The function will add each byte to the CRC32 value." Name="CRC32"/>
	FUNCTION __CDECL VIRTUAL GLOBAL CRC32
		VAR_INPUT
			crc 	: UDINT;			//! <Variable Comment="The starting CRC value. Reset to 0 for first call." Name="CRC32.crc"/>
			buf 	: pVoid;			//! <Variable Comment="A pointer to a buffer containing the BYTE data to add to the CRC." Name="CRC32.buf"/>
			length 	: UDINT;			//! <Variable Comment="The length of the data to add to the CRC." Name="CRC32.length"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="The new CRC32 value." Name="CRC32.retval"/>
		END_VAR;
				//! <Function Comment="This function parses an ASCII - string and returns the address of the object or channel it describes. The result has to be casted to the appropriate data type, which is given by the channel mode." Name="LookupEmbedded"/>
	FUNCTION __CDECL VIRTUAL GLOBAL LookupEmbedded
		VAR_OUTPUT
			retfunc (EAX) 	: pVoid;			//! <Variable Comment="Returns the function pointer or NIL." Name="LookupEmbedded.retfunc"/>
		END_VAR;
				//! <Function Comment="This function just returns a pointer to the first entry of the object descriptor list. This list resides in the far - memory - block. The result has to be casted to the type: OBJDSC." Name="GetObjDscList"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetObjDscList
		VAR_OUTPUT
			retlist (EAX) 	: pVoid;			//! <Variable Comment="Pointer to the start of the object descriptor" Name="GetObjDscList.retlist"/>
		END_VAR;
				//! <Function Comment="This function gets the object name with the appended channel name. The pName-buffer must be sufficiently big, at maximum 255 characters." Name="GetObjectName"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetObjectName
		VAR_INPUT
			obj0 	: pVoid;
			ServerCh 	: pVoid;
			name 	: ^CHAR;
		END_VAR;
				//! <Function Comment="The function checks, if a channel has retentive data." Name="GetNextChannel"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetNextChannel
		VAR_INPUT
			obj0 	: pVoid;			//! <Variable Comment="Parameter Obj0 points to the current object." Name="GetNextChannel.obj0"/>
			server0 	: pVoid;			//! <Variable Comment="Pointer to current channel." Name="GetNextChannel.server0"/>
		END_VAR
		VAR_OUTPUT
			retchannel (EAX) 	: pVoid;			//! <Variable Comment="If the function succeeds, it returns the next (first) channel with retentive data. If it fails, NIL is returned." Name="GetNextChannel.retchannel"/>
		END_VAR;
				//! <Function Comment="This function is called to get the number of error messages currently in the Lasal Linker Error List." Name="GetErrorCount"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetErrorCount
		VAR_OUTPUT
			retcount (EAX) 	: UDINT;			//! <Variable Comment="The number of entries in the Lasal Linker Error List (0 if none)." Name="GetErrorCount.retcount"/>
		END_VAR;
				//! <Function Comment="This method is called to check if the RTOS Runtime Linker has detected any linking errors with the active Lasal application." Name="GetFirstError"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetFirstError
		VAR_INPUT
			msg 	: ^CHAR;			//! <Variable Comment="A pointer to a buffer to store the return" Name="GetFirstError.msg"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="If the RTOS linker has detected no errors with the Lasal application then the function returns FALSE (and the contents of the buffer are invalid). Otherwise, the function copies in the linker error message string (ASC-ZERO) into the passed buffer and returns TRUE." Name="GetFirstError.retval"/>
		END_VAR;
				//! <Function Comment="This method is called after an initial call to Linker.GetFirstError() to obtain the next linker error message. The Linker.GetFirstError() method must be called prior to calling this function." Name="GetNextError"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetNextError
		VAR_INPUT
			msg 	: ^CHAR;			//! <Variable Comment="A pointer to a buffer to store the return" Name="GetNextError.msg"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="This function is called repeatedly to parse through the list of linker error messages. If another linker error is available the function will store the ASC-ZERO string in the specified buffer and return TRUE. The function returns FALSE once all error messages have been read." Name="GetNextError.retval"/>
		END_VAR;
				//! <Function Comment="This method is called to add an error message to the Lasal error list." Name="AddError2List"/>
	FUNCTION __CDECL VIRTUAL GLOBAL AddError2List
		VAR_INPUT
			errnum 	: UDINT;			//! <Variable Comment="The Lasal error ID number of the error." Name="AddError2List.errnum"/>
			errstr 	: ^CHAR;			//! <Variable Comment="A pointer to the error message string." Name="AddError2List.errstr"/>
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;			//! <Variable Comment="0 if message added to the list, -1 if an" Name="AddError2List.retval"/>
		END_VAR;
				//! <Function Comment="This function is called to reset the current Lasal Linker Error list and free all entries. Note that any linker error information will be lost." Name="FreeErrorList"/>
	FUNCTION __CDECL VIRTUAL GLOBAL FreeErrorList;
				//! <Function Comment="This function takes a class name and returns the checksum." Name="GetChkSumFromClassName"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetChkSumFromClassName
		VAR_INPUT
			ClassName 	: ^CHAR;
		END_VAR
		VAR_OUTPUT
			retval (EAX) 	: UDINT;
		END_VAR;
				//! <Function Comment="This function returns the checksum of the modules with the selected module type.&#13;&#10;The checksum calculation only includes modules whose module type is equal to the conjunction of the input parameters modTypeMask and modTypeEq." Name="GetChkSumByType"/>
	FUNCTION __CDECL VIRTUAL GLOBAL GetChkSumByType
		VAR_INPUT
			modTypeMask 	: UDINT;			//! <Variable Comment="Bit mask for masking the module type" Name="GetChkSumByType.modTypeMask"/>
			modTypeEq 	: UDINT;			//! <Variable Comment="Module type for module selection" Name="GetChkSumByType.modTypeEq"/>
			cmtMod 	: ^UDINT;			//! <Variable Comment="Returns the count of the modules included in the crc calculation" Name="GetChkSumByType.cmtMod"/>
		END_VAR
		VAR_OUTPUT
			crc (EAX) 	: UDINT;			//! <Variable Comment="calculated crc" Name="GetChkSumByType.crc"/>
		END_VAR;
  //Tables:
	FUNCTION @STD
		VAR_OUTPUT
			ret_code	: CONFSTATES;
		END_VAR;
	FUNCTION GLOBAL TAB @CT_;
END_CLASS;

//}}LSL_DECLARATION


FUNCTION GLOBAL TAB _Linker::@CT_
0$UINT,
2#0100000000001000$UINT, //TY__LINKER
0$UINT, 5$UINT, (SIZEOF(::_Linker))$UINT, 
1$UINT, 0$UINT, 0$UINT, 
TO_UDINT(1793552568), "_Linker", //Class
TO_UDINT(0), 0, 0$UINT, 0$UINT, //Baseclass
//Servers:
(::_Linker.Server0.pMeth)$UINT, _CH_CMD$UINT, 2#0000000000000000$UINT, TO_UDINT(2759080719), "Server0", 
//Clients:
END_FUNCTION


#define USER_CNT__Linker 20

TYPE
	_LSL_STD_VMETH	: STRUCT
			CmdTable	: CMDMETH;
			UserFcts	: ARRAY[0..USER_CNT__Linker] OF ^Void;
	END_STRUCT;
END_TYPE



//{{LSL_IMPLEMENTATION


//*********************Inserted from <.\OS Interface\code\_Linker_00_00.st>*********************



 



#include <Rtos_interfaces.h> // we need this for the SysCIL functions
#include "..\..\Source\code\OsiBaseNew.h"


FUNCTION __CDECL GetChkSumFromClassNameDummy
#pragma warning (disable:73)
	VAR_INPUT
		ClassName     : ^CHAR;
	END_VAR
	VAR_OUTPUT
		retval (EAX) 	: DINT;
	END_VAR
#pragma warning (default:73)
  
  
  TRACE("ERROR: Function not available with this version/platform! OS >= 01.02.235 required");

	retval := 0;

END_FUNCTION

FUNCTION __CDECL GetChkSumByTypeDummy
#pragma warning (disable:73)
	VAR_INPUT
		modTypeMask   : UINT;
		modTypeEq     : UINT;
	END_VAR
	VAR_OUTPUT
		retval (EAX) 	: DINT;
	END_VAR
#pragma warning (default:73)
  
  
  TRACE("ERROR: Function not available with this version/platform! OS >= 01.03.080 required");

	retval := 0;

END_FUNCTION


FUNCTION  _Linker::_Linker
VAR_OUTPUT
	ret_code		: CONFSTATES;
END_VAR
VAR
    pLink     : ^OS_LINKER;
	aMeths    : ARRAY[0..USER_CNT__Linker] OF ^void;
	retv      : SYS_ERROR;
END_VAR;

  (* 8D-6160:
    Unter RTK (und LARS) kam es beim Aufruf von GetObjectName zu einer Exception.
    Der Grund dafür war, weil in der OS_LINKER Schnittstelle bei dieser Funktion 
    ein NULL Pointer steht, wenn man die Schnittstelle mit OS_CILGet holt (anstatt 
    mit _LSL_POS^.piLINKER). 
    Beim RTK macht das nämlich einen Unterschied: In _LSL_POS^.piLINKER steht 
    ein Zeiger auf eine Kopie der Schnittstellenstruktur. Mit OS_CILGet bekommt 
    man das Original. Wenn der Loader startet, dann trägt er Funktionspointer 
    wie z.B. GetObjectName in die _LSL_POS^.piLINKER Struktur ein. 
    Im Original steht weiterhin der NULL-Pointer.
    Daher wird hier kein 'OS_CILGet("SYSLINKER", #pLink$void)' gemacht, sondern 
    der _LSL_POS^.piLINKER verwendet.
   *)
  pLink$^LSL_LINKER := _LSL_POS^.piLINKER;
  if pLink = NIL then
    retv := SYS_ERR_INOEXISTS;
  else
    retv := SYS_ERR_NONE;
  end_if;

	if retv <> SYS_ERR_NONE then

		TRACE("ERROR: LINKER Interface not available with this version/platform!");
		ret_code	:= C_UNKNOWN_CONSTR;
    else

		aMeths [0]	:= pLink^.GetVariableInfo;
		aMeths [1]	:= pLink^.GetAddressFunction;
		aMeths [2]	:= pLink^.GetAddressVariable;
		aMeths [3]	:= pLink^.GetDataMemoryAddress;
		aMeths [4]	:= pLink^.GetCodeMemoryAddress;
		aMeths [5]	:= pLink^.GetProjectState;
		aMeths [6]	:= pLink^.GetChkByModulID;
		aMeths [7]	:= pLink^.GetPrjCHK;
		aMeths [8]	:= pLink^.CRC32;

		aMeths [9]	:= pLink^.LookupEmbedded;
		aMeths [10]	:= pLink^.GetObjDscList;
		aMeths [11]	:= pLink^.GetObjectName;
		aMeths [12]	:= pLink^.GetNextChannel;

		aMeths [13]	:= pLink^.GetErrorCount;
		aMeths [14]	:= pLink^.GetFirstError;
		aMeths [15]	:= pLink^.GetNextError;
		aMeths [16]	:= pLink^.AddError2List;
		aMeths [17]	:= pLink^.FreeErrorList;
    
    if _RtOSVersion >= 16#12EA then         // requires >= 01.02.234
      aMeths [18] := pLink^.GetChkSumFromClassName;
    else 
      aMeths [18] := #GetChkSumFromClassNameDummy();
    end_if;
    // requires RTK >= 01.03.080 or Salamander >= 09.01.250 or >= 09.03.070
    if (_RtOSVersion < 16#9000) & (_RtOSVersion >= 16#1350) |
       (_RtOSVersion >= 16#91FA) & (_RtOSVersion < 16#9300) |
       (_RtOSVersion >= 16#9346) then
      aMeths [19] := pLink^.GetChkSumByType;
    else 
      aMeths [19] := #GetChkSumByTypeDummy();
    end_if;
    
		ret_code	:= InitOsiM_new(#aMeths[0]$void, USER_CNT__Linker);
	end_if;

END_FUNCTION //  _Linker::_Linker

