blob: c789cf0f8b4a65f487fcd28502e3e1e6935a23b1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 - 2016 fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Martin Jobst, Monika Wenger
* - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "luaengine.h"
#include "../datatypes/forte_any.h"
#include "../datatypes/forte_bool.h"
#include "../datatypes/forte_sint.h"
#include "../datatypes/forte_int.h"
#include "../datatypes/forte_dint.h"
#include "../datatypes/forte_lint.h"
#include "../datatypes/forte_usint.h"
#include "../datatypes/forte_uint.h"
#include "../datatypes/forte_udint.h"
#include "../datatypes/forte_ulint.h"
#include "../datatypes/forte_byte.h"
#include "../datatypes/forte_word.h"
#include "../datatypes/forte_dword.h"
#include "../datatypes/forte_lword.h"
#include "../datatypes/forte_real.h"
#include "../datatypes/forte_lreal.h"
#include "../datatypes/forte_date.h"
#include "../datatypes/forte_time_of_day.h"
#include "../datatypes/forte_date_and_time.h"
#include "../datatypes/forte_time.h"
#include "../datatypes/forte_array.h"
#include "../../arch/devlog.h"
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
CLuaEngine::CLuaEngine() {
luaState = luaL_newstate();
luaL_openlibs(luaState);
}
CLuaEngine::~CLuaEngine() {
lua_close(luaState);
}
bool CLuaEngine::loadString(const std::string& paStr) {
int err = luaL_loadstring(luaState, paStr.c_str());
if(err) {
switch(err){
case LUA_ERRSYNTAX:
DEVLOG_ERROR("Syntax error loading Lua definitions\n");
break;
case LUA_ERRMEM:
DEVLOG_ERROR("Allocation error loading Lua definitions\n");
break;
default:
DEVLOG_ERROR("Unknown error loading Lua definitions\n");
}
return false;
}
if(!call(0, 1)) {
DEVLOG_ERROR("Error loading definitions\n");
return false;
}
return true;
}
bool CLuaEngine::call(int paArgs, int paResults) {
int err = lua_pcall(luaState, paArgs, paResults, 0);
if(err) {
switch(err){
case LUA_ERRRUN:
DEVLOG_ERROR("Runtime error calling Lua function: %s\n", lua_tostring(luaState, -1));
break;
case LUA_ERRMEM:
DEVLOG_ERROR("Memory allocation error calling Lua function\n");
break;
case LUA_ERRERR:
DEVLOG_ERROR("Message handler error calling Lua function\n");
break;
default:
DEVLOG_ERROR("Unknown error calling Lua function\n");
}
return false;
}
return true;
}
bool CLuaEngine::luaPushAny(lua_State *paLuaState, CIEC_ANY *paValue) {
if(!paValue) {
return false;
}
switch(paValue->getDataTypeID()){
case CIEC_ANY::e_BOOL:
lua_pushboolean(paLuaState, static_cast<bool>(*static_cast<CIEC_BOOL*>(paValue)));
break;
case CIEC_ANY::e_SINT:
lua_pushinteger(paLuaState, static_cast<TForteInt8>(*static_cast<CIEC_SINT*>(paValue)));
break;
case CIEC_ANY::e_INT:
lua_pushinteger(paLuaState, static_cast<TForteInt16>(*static_cast<CIEC_INT*>(paValue)));
break;
case CIEC_ANY::e_DINT:
lua_pushinteger(paLuaState, static_cast<TForteInt32>(*static_cast<CIEC_DINT*>(paValue)));
break;
case CIEC_ANY::e_LINT:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteInt64>(*static_cast<CIEC_LINT*>(paValue))));
break;
case CIEC_ANY::e_USINT:
lua_pushinteger(paLuaState, static_cast<TForteUInt8>(*static_cast<CIEC_USINT*>(paValue)));
break;
case CIEC_ANY::e_UINT:
lua_pushinteger(paLuaState, static_cast<TForteUInt16>(*static_cast<CIEC_UINT*>(paValue)));
break;
case CIEC_ANY::e_UDINT:
lua_pushinteger(paLuaState, static_cast<TForteUInt32>(*static_cast<CIEC_UDINT*>(paValue)));
break;
case CIEC_ANY::e_ULINT:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteUInt64>(*static_cast<CIEC_ULINT*>(paValue))));
break;
case CIEC_ANY::e_BYTE:
lua_pushinteger(paLuaState, static_cast<TForteByte>(*static_cast<CIEC_BYTE*>(paValue)));
break;
case CIEC_ANY::e_WORD:
lua_pushinteger(paLuaState, static_cast<TForteWord>(*static_cast<CIEC_WORD*>(paValue)));
break;
case CIEC_ANY::e_DWORD:
lua_pushinteger(paLuaState, static_cast<TForteDWord>(*static_cast<CIEC_DWORD*>(paValue)));
break;
case CIEC_ANY::e_LWORD:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteLWord>(*static_cast<CIEC_LWORD*>(paValue))));
break;
case CIEC_ANY::e_DATE:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteUInt64>(*static_cast<CIEC_DATE*>(paValue))));
break;
case CIEC_ANY::e_TIME_OF_DAY:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteUInt64>(*static_cast<CIEC_TIME_OF_DAY*>(paValue))));
break;
case CIEC_ANY::e_DATE_AND_TIME:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteUInt64>(*static_cast<CIEC_DATE_AND_TIME*>(paValue))));
break;
case CIEC_ANY::e_TIME:
lua_pushinteger(paLuaState, static_cast<lua_Integer>(static_cast<TForteInt64>(*static_cast<CIEC_TIME*>(paValue))));
break;
case CIEC_ANY::e_REAL:
lua_pushnumber(paLuaState, static_cast<TForteFloat>(*static_cast<CIEC_REAL*>(paValue)));
break;
case CIEC_ANY::e_LREAL:
lua_pushnumber(paLuaState, static_cast<TForteDFloat>(*static_cast<CIEC_LREAL*>(paValue)));
break;
case CIEC_ANY::e_STRING:
lua_pushstring(paLuaState, static_cast<CIEC_STRING*>(paValue)->getValue());
break;
case CIEC_ANY::e_WSTRING:
lua_pushstring(paLuaState, static_cast<CIEC_WSTRING*>(paValue)->getValue());
break;
case CIEC_ANY::e_ARRAY:
return luaPushArray(paLuaState, static_cast<CIEC_ARRAY*>(paValue));
default:
DEVLOG_ERROR("Conversion to Lua datatype unsupported for type with id %s\n", paValue->getDataTypeID());
lua_pushnil(paLuaState);
}
return true;
}
bool CLuaEngine::luaGetAny(lua_State *paLuaState, CIEC_ANY *paValue, int paIndex) {
if(!paValue) {
return false;
}
switch(paValue->getDataTypeID()){
case CIEC_ANY::e_BOOL:
*static_cast<CIEC_BOOL*>(paValue) = static_cast<bool>(lua_toboolean(paLuaState, paIndex));
break;
case CIEC_ANY::e_SINT:
*static_cast<CIEC_SINT*>(paValue) = static_cast<TForteInt8>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_INT:
*static_cast<CIEC_INT*>(paValue) = static_cast<TForteInt16>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_DINT:
*static_cast<CIEC_DINT*>(paValue) = static_cast<TForteInt32>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_LINT:
*static_cast<CIEC_LINT*>(paValue) = static_cast<TForteInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_USINT:
*static_cast<CIEC_USINT*>(paValue) = static_cast<TForteUInt8>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_UINT:
*static_cast<CIEC_UINT*>(paValue) = static_cast<TForteUInt16>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_UDINT:
*static_cast<CIEC_UDINT*>(paValue) = static_cast<TForteUInt32>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_ULINT:
*static_cast<CIEC_ULINT*>(paValue) = static_cast<TForteUInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_BYTE:
*static_cast<CIEC_BYTE*>(paValue) = static_cast<TForteByte>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_WORD:
*static_cast<CIEC_WORD*>(paValue) = static_cast<TForteWord>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_DWORD:
*static_cast<CIEC_DWORD*>(paValue) = static_cast<TForteDWord>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_LWORD:
*static_cast<CIEC_LWORD*>(paValue) = static_cast<TForteLWord>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_DATE:
*static_cast<CIEC_DATE*>(paValue) = static_cast<TForteUInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_TIME_OF_DAY:
*static_cast<CIEC_TIME_OF_DAY*>(paValue) = static_cast<TForteUInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_DATE_AND_TIME:
*static_cast<CIEC_DATE_AND_TIME*>(paValue) = static_cast<TForteUInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_TIME:
*static_cast<CIEC_TIME*>(paValue) = static_cast<TForteInt64>(lua_tointeger(paLuaState, paIndex));
break;
case CIEC_ANY::e_REAL:
*static_cast<CIEC_REAL*>(paValue) = static_cast<TForteFloat>(lua_tonumber(paLuaState, paIndex));
break;
case CIEC_ANY::e_LREAL:
*static_cast<CIEC_LREAL*>(paValue) = static_cast<TForteDFloat>(lua_tonumber(paLuaState, paIndex));
break;
case CIEC_ANY::e_STRING:
*static_cast<CIEC_STRING*>(paValue) = strdup(lua_tostring(paLuaState, paIndex));
break;
case CIEC_ANY::e_WSTRING:
*static_cast<CIEC_WSTRING*>(paValue) = strdup(lua_tostring(paLuaState, paIndex));
break;
case CIEC_ANY::e_ARRAY:
return luaGetArray(paLuaState, static_cast<CIEC_ARRAY*>(paValue), paIndex);
default:
DEVLOG_ERROR("Conversion from Lua datatype unsupported for type with id %s\n", paValue->getDataTypeID());
return false;
}
return true;
}
bool CLuaEngine::luaPushArray(lua_State *paLuaState, CIEC_ARRAY* paArray) {
if(!paArray) {
return false;
}
lua_createtable(paLuaState, paArray->size(), 0);
for(int i = paArray->size(); i > 0; i--) {
if(!luaPushAny(paLuaState, (*paArray)[(TForteUInt16) (i - 1)])) { // index starts at 0
lua_pop(paLuaState, 1); // pop table
return false;
}
lua_rawseti(paLuaState, -2, i); // index starts at 1
}
return true;
}
bool CLuaEngine::luaGetArray(lua_State *paLuaState, CIEC_ARRAY* paArray, int paIndex) {
if(!paArray || !lua_istable(paLuaState, paIndex)) {
return false;
}
for(int i = paArray->size(); i > 0; i--) {
lua_rawgeti(paLuaState, paIndex, i); // index starts at 1
bool res = luaGetAny(paLuaState, (*paArray)[(TForteUInt16) (i - 1)], -1); // index starts at 0
lua_pop(paLuaState, 1); // pop element
if(!res) {
return false;
}
}
return true;
}