2013-08-14 14:17:44 +02:00
|
|
|
/***************************************************************************
|
|
|
|
|
* Copyright (C) 2013 by Chris Mitchell *
|
2014-08-15 02:11:43 -07:00
|
|
|
* Copyright (C) 2014 by Ahmed Charles - acharles@outlook.com *
|
2013-08-14 14:17:44 +02:00
|
|
|
* *
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
|
* (at your option) any later version. *
|
|
|
|
|
* *
|
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
|
* *
|
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "LuaInterface.h"
|
2014-08-15 02:11:43 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "Host.h"
|
2013-08-14 14:17:44 +02:00
|
|
|
#include "VarUnit.h"
|
2014-08-15 02:11:43 -07:00
|
|
|
|
2018-08-30 13:48:42 +02:00
|
|
|
#include <csetjmp>
|
2014-08-15 02:11:43 -07:00
|
|
|
|
2013-08-14 14:17:44 +02:00
|
|
|
|
|
|
|
|
static jmp_buf buf;
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
LuaInterface::LuaInterface(Host* pH) : mpHost(pH), L(), depth()
|
2013-08-14 14:17:44 +02:00
|
|
|
{
|
|
|
|
|
interpreter = mpHost->getLuaInterpreter();
|
|
|
|
|
mHostID = mpHost->getHostID();
|
2014-09-29 04:08:18 -07:00
|
|
|
varUnit.reset(new VarUnit());
|
2013-08-14 14:17:44 +02:00
|
|
|
//set our panic function
|
2017-04-27 03:55:38 -07:00
|
|
|
lua_atpanic(interpreter->pGlobalLua, &onPanic);
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-06-05 06:50:40 +02:00
|
|
|
LuaInterface::~LuaInterface() = default;
|
2014-09-29 04:08:18 -07:00
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
int LuaInterface::onPanic(lua_State* L)
|
2013-08-14 14:17:44 +02:00
|
|
|
{
|
|
|
|
|
QString error = "Lua Panic, No error information";
|
2017-04-27 03:55:38 -07:00
|
|
|
if (lua_isstring(L, -1)) {
|
2020-10-11 13:26:59 +02:00
|
|
|
error = lua_tostring(L, -1);
|
2014-01-10 21:41:20 -05:00
|
|
|
//there's never anything but the error on the stack, nothing to report
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to user qDebug()<<"PANIC ERROR:"<<error;
|
2013-08-14 14:17:44 +02:00
|
|
|
longjmp(buf, 1);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
VarUnit* LuaInterface::getVarUnit()
|
|
|
|
|
{
|
2014-09-29 04:08:18 -07:00
|
|
|
return varUnit.data();
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
QStringList LuaInterface::varName(TVar* var)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
QStringList names;
|
2017-04-27 03:55:38 -07:00
|
|
|
if (var->getName() == "_G") {
|
2013-08-14 14:17:44 +02:00
|
|
|
names << "";
|
|
|
|
|
return names;
|
|
|
|
|
}
|
|
|
|
|
names << var->getName();
|
2017-04-27 03:55:38 -07:00
|
|
|
TVar* p = var->getParent();
|
|
|
|
|
while (p && p->getName() != "_G") {
|
|
|
|
|
names.insert(0, p->getName());
|
2013-08-14 14:17:44 +02:00
|
|
|
p = p->getParent();
|
|
|
|
|
}
|
|
|
|
|
return names;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::validMove(QTreeWidgetItem* p)
|
|
|
|
|
{
|
|
|
|
|
TVar* newParent = varUnit->getWVar(p);
|
2017-06-26 16:46:54 +02:00
|
|
|
if (newParent && newParent->getValueType() != LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::getAllChildren(TVar* var, QList<TVar*>* list)
|
|
|
|
|
{
|
|
|
|
|
QListIterator<TVar*> it(var->getChildren(true));
|
2017-06-26 16:46:54 +02:00
|
|
|
if (varUnit->isSaved(var) || var->saved) {
|
2013-08-14 14:17:44 +02:00
|
|
|
list->append(var);
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
while (it.hasNext()) {
|
|
|
|
|
TVar* child = it.next();
|
2017-06-26 16:46:54 +02:00
|
|
|
if (child->getValueType() == LUA_TTABLE) {
|
2017-04-27 03:55:38 -07:00
|
|
|
getAllChildren(child, list);
|
2017-06-26 16:46:54 +02:00
|
|
|
} else if (varUnit->isSaved(child) || var->saved) {
|
2013-08-14 14:17:44 +02:00
|
|
|
list->append(child);
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::loadKey(lua_State* L, TVar* var)
|
|
|
|
|
{
|
|
|
|
|
if (setjmp(buf) == 0) {
|
2013-08-14 14:17:44 +02:00
|
|
|
int kType = var->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (var->isReference()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
|
|
|
|
if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
|
|
|
|
} else if (kType == LUA_TBOOLEAN) {
|
|
|
|
|
lua_pushboolean(L, var->getName().toLower() == "true" ? 1 : 0);
|
|
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, var->getName().toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return lua_type(L, -1) == kType;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::loadValue(lua_State* L, TVar* var, int index)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//puts a value on stack
|
2017-04-27 03:55:38 -07:00
|
|
|
if (setjmp(buf) == 0) {
|
|
|
|
|
if (loadKey(L, var)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//everything is tabled in lua, we need to just find what table
|
|
|
|
|
//we're using, if index == 0, we iterate to the closest table
|
2017-06-26 16:46:54 +02:00
|
|
|
if (index) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_gettable(L, index);
|
2017-06-26 16:46:54 +02:00
|
|
|
} else {
|
2017-04-27 03:55:38 -07:00
|
|
|
for (int j = 1; j <= lua_gettop(L); j++) {
|
|
|
|
|
if (lua_type(L, j * -1) == LUA_TTABLE) {
|
|
|
|
|
lua_gettable(L, j * -1);
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
|
|
|
|
if (lua_gettop(L)) {
|
2014-09-15 16:59:25 -04:00
|
|
|
return lua_type(L, -1) == var->getValueType();
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
2014-09-15 16:59:25 -04:00
|
|
|
return false;
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::reparentCVariable(TVar* from, TVar* to, TVar* curVar)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//get the old parent on the stack
|
2017-04-27 03:55:38 -07:00
|
|
|
if (setjmp(buf) == 0) {
|
|
|
|
|
if (!from || !to || (from == to)) {
|
|
|
|
|
// moving from global to global or nowhere
|
2013-08-14 14:17:44 +02:00
|
|
|
return true;
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
int stackSize = lua_gettop(L);
|
|
|
|
|
bool isSaved = varUnit->isSaved(curVar);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (isSaved) {
|
|
|
|
|
QList<TVar*> list;
|
2013-08-14 14:17:44 +02:00
|
|
|
getAllChildren(curVar, &list);
|
2017-04-27 03:55:38 -07:00
|
|
|
QListIterator<TVar*> it(list);
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
TVar* t = it.next();
|
2013-08-14 14:17:44 +02:00
|
|
|
varUnit->removeSavedVar(t);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> vars = varOrder(curVar);
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
int i = 1;
|
|
|
|
|
for (; i < vars.size(); i++) {
|
|
|
|
|
if (!loadValue(L, vars[i], -2)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//redo the parenting in TVar
|
|
|
|
|
from->removeChild(curVar);
|
|
|
|
|
curVar->setParent(to);
|
|
|
|
|
to->addChild(curVar);
|
|
|
|
|
vars = varOrder(curVar);
|
|
|
|
|
//do the actual reparenting part
|
2017-04-27 03:55:38 -07:00
|
|
|
if (to == varUnit->getBase()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//we're going global
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_setglobal(L, curVar->getName().toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
i = 1;
|
|
|
|
|
for (; i < vars.size() - 1; i++) {
|
|
|
|
|
if (!loadValue(L, vars[i], -2)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_remove(L, -2);
|
|
|
|
|
}
|
|
|
|
|
lua_insert(L, -2);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (!loadKey(L, curVar)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_insert(L, -2);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (!lua_istable(L, -3)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_settable(L, -3);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
}
|
|
|
|
|
//delete the old copy
|
2017-04-27 03:55:38 -07:00
|
|
|
if (from == varUnit->getBase()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnil(L);
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_setglobal(L, curVar->getName().toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
|
|
|
|
if (!loadKey(L, curVar)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_pushnil(L);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (!lua_istable(L, -3)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_settable(L, -3);
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
if (isSaved) {
|
|
|
|
|
QList<TVar*> list;
|
2013-08-14 14:17:44 +02:00
|
|
|
list.append(to);
|
|
|
|
|
getAllChildren(curVar, &list);
|
2017-04-27 03:55:38 -07:00
|
|
|
QListIterator<TVar*> it(list);
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
TVar* t = it.next();
|
2013-08-14 14:17:44 +02:00
|
|
|
varUnit->addSavedVar(t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-01-10 21:41:20 -05:00
|
|
|
return false;
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::reparentVariable(QTreeWidgetItem* newP, QTreeWidgetItem* cItem, QTreeWidgetItem* oldP)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//if oldParent doesn't exist:
|
|
|
|
|
//this means we were moved to a table from the global namespace
|
|
|
|
|
//if newParent doesn't exist:
|
|
|
|
|
//we were moved to the global namespace
|
|
|
|
|
//if both exist:
|
|
|
|
|
//this means we were moved from inside a table to inside another table
|
|
|
|
|
//and in both instances, this table was not _G
|
2019-08-13 10:27:54 +02:00
|
|
|
TVar* curVar = varUnit->getWVar(cItem);
|
|
|
|
|
if (!curVar) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 14:17:44 +02:00
|
|
|
L = interpreter->pGlobalLua;
|
2017-04-27 03:55:38 -07:00
|
|
|
TVar* newParent = varUnit->getWVar(newP);
|
|
|
|
|
TVar* oldParent = varUnit->getWVar(oldP);
|
|
|
|
|
TVar* from = oldParent;
|
|
|
|
|
TVar* to = newParent;
|
|
|
|
|
if (newParent && newParent->getValueType() != LUA_TTABLE) {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report why this fails to user
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
if (!newParent && !oldParent) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//happens when we move from _G to _G
|
|
|
|
|
return false;
|
2020-06-01 17:35:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!oldParent) {
|
2013-08-14 14:17:44 +02:00
|
|
|
from = varUnit->getBase();
|
2020-06-01 17:35:35 +01:00
|
|
|
// newParent cannot be a nullptr here as we would have returned in
|
|
|
|
|
// previous if - so to won't be either:
|
2013-08-14 14:17:44 +02:00
|
|
|
to = newParent;
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (!newParent) {
|
2020-06-01 17:35:35 +01:00
|
|
|
// oldParent cannot be a nullptr here as we would have returned in
|
|
|
|
|
// previous if - so from won't be either:
|
2013-08-14 14:17:44 +02:00
|
|
|
from = oldParent;
|
|
|
|
|
to = varUnit->getBase();
|
|
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
|
|
|
|
|
// one of from and to must not be a nullptr here - so prior test for BOTH
|
|
|
|
|
// being a nullptr here and returning false in that case was dead code.
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
return reparentCVariable(from, to, curVar);
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> LuaInterface::varOrder(TVar* var)
|
|
|
|
|
{
|
|
|
|
|
QList<TVar*> vars;
|
|
|
|
|
if (var->getName() == "_G") {
|
2013-08-14 14:17:44 +02:00
|
|
|
return vars;
|
|
|
|
|
}
|
|
|
|
|
vars << var;
|
2017-04-27 03:55:38 -07:00
|
|
|
TVar* p = var->getParent();
|
|
|
|
|
while (p && p->getName() != "_G") {
|
|
|
|
|
vars.insert(0, p);
|
2013-08-14 14:17:44 +02:00
|
|
|
p = p->getParent();
|
|
|
|
|
}
|
|
|
|
|
return vars;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::createVar(TVar* var)
|
|
|
|
|
{
|
|
|
|
|
setValue(var);
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::setCValue(QList<TVar*> vars)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//make the new stack
|
2017-04-27 03:55:38 -07:00
|
|
|
TVar* var = vars.back();
|
|
|
|
|
if (setjmp(buf) == 0) {
|
2013-08-14 14:17:44 +02:00
|
|
|
int stackSize = lua_gettop(L);
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
int i = 1;
|
|
|
|
|
for (; i < vars.size() - 1; i++) {
|
|
|
|
|
if (!loadValue(L, vars[i], -2)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//push our value onto the stack
|
2017-04-27 03:55:38 -07:00
|
|
|
switch (var->getValueType()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
case LUA_TSTRING:
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, var->getValue().toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
break;
|
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
|
lua_pushnumber(L, var->getValue().toInt());
|
|
|
|
|
break;
|
|
|
|
|
case LUA_TBOOLEAN:
|
|
|
|
|
lua_pushboolean(L, var->getValue().toLower() == "true" ? 1 : 0);
|
|
|
|
|
break;
|
|
|
|
|
case LUA_TTABLE:
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//set it up
|
2017-04-27 03:55:38 -07:00
|
|
|
if (lua_type(L, -1) != var->getValueType()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_settop(L, stackSize);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lua_settable(L, -3);
|
|
|
|
|
}
|
2014-01-10 21:41:20 -05:00
|
|
|
return false;
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-01-26 04:07:28 +01:00
|
|
|
// sets the value of a Lua variable by running dynamically-generated Lua code
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::setValue(TVar* var)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//This function assumes the var has been modified and then called
|
|
|
|
|
L = interpreter->pGlobalLua;
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> vars = varOrder(var);
|
2018-01-26 04:07:28 +01:00
|
|
|
QString variableChangeCode = vars[0]->getName();
|
2017-04-27 03:55:38 -07:00
|
|
|
for (int i = 1; i < vars.size(); i++) {
|
2017-06-26 16:46:54 +02:00
|
|
|
if (vars[i]->isReference()) {
|
2017-04-27 03:55:38 -07:00
|
|
|
return setCValue(vars);
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
if (vars[i]->getKeyType() == LUA_TNUMBER) {
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QStringLiteral("[%1]").arg(vars.at(i)->getName()));
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QStringLiteral(R"(["%1"])").arg(vars.at(i)->getName()));
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
switch (var->getValueType()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
case LUA_TSTRING:
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QStringLiteral(" = [[%1]]").arg(var->getValue()));
|
2013-08-14 14:17:44 +02:00
|
|
|
break;
|
|
|
|
|
case LUA_TNUMBER:
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QStringLiteral(" = %1").arg(var->getValue()));
|
2013-08-14 14:17:44 +02:00
|
|
|
break;
|
|
|
|
|
case LUA_TBOOLEAN:
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QStringLiteral(" = %1").arg(var->getValue()));
|
2013-08-14 14:17:44 +02:00
|
|
|
break;
|
|
|
|
|
case LUA_TTABLE:
|
2018-01-26 04:07:28 +01:00
|
|
|
variableChangeCode.append(QLatin1String(" = {}"));
|
2013-08-14 14:17:44 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
int error = luaL_loadstring(L, variableChangeCode.toUtf8().constData());
|
|
|
|
|
if (error) {
|
|
|
|
|
qWarning().noquote().nospace() << "LuaInterface::setValue(...) WARNING - Internal Lua (parsing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< variableChangeCode << "\".";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
error = lua_pcall(L, 0, LUA_MULTRET, 0);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (error) {
|
2020-06-01 17:35:35 +01:00
|
|
|
qWarning().noquote().nospace() << "LuaInterface::setValue(...) WARNING - Internal Lua (executing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< variableChangeCode << "\".";
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::deleteVar(TVar* var)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
L = interpreter->pGlobalLua;
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> vars = varOrder(var);
|
2013-08-14 14:17:44 +02:00
|
|
|
QString oldName = vars[0]->getName();
|
2017-04-27 03:55:38 -07:00
|
|
|
for (int i = 1; i < vars.size(); i++) {
|
|
|
|
|
if (vars[i]->getKeyType() == LUA_TNUMBER) {
|
2020-06-01 17:35:35 +01:00
|
|
|
oldName.append(QStringLiteral("[%1]").arg(vars[i]->getName()));
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2020-06-01 17:35:35 +01:00
|
|
|
oldName.append(QStringLiteral(R"(["%1"])").arg(vars[i]->getName()));
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//delete it
|
2020-06-01 17:35:35 +01:00
|
|
|
oldName.append(QStringLiteral(" = nil"));
|
|
|
|
|
int error = luaL_loadstring(L, oldName.toUtf8().constData());
|
|
|
|
|
if (error) {
|
|
|
|
|
qWarning().noquote().nospace() << "LuaInterface::deleteVar(...) WARNING - Internal Lua (parsing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< oldName << "\".";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
error = lua_pcall(L, 0, LUA_MULTRET, 0);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (error) {
|
2020-06-01 17:35:35 +01:00
|
|
|
qWarning().noquote().nospace() << "LuaInterface::deleteVar(...) WARNING - Internal Lua (executing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< oldName << "\".";
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::renameCVar(QList<TVar*> vars)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//uses C Api to rename a variable.
|
|
|
|
|
//dangerous function since you can get an api panic
|
|
|
|
|
//and trash the stack
|
|
|
|
|
L = interpreter->pGlobalLua;
|
2017-04-27 03:55:38 -07:00
|
|
|
TVar* var = vars.back();
|
2013-08-14 14:17:44 +02:00
|
|
|
//make the new stack
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
if (setjmp(buf) == 0) {
|
|
|
|
|
int i = 1;
|
|
|
|
|
int pushCount = 0;
|
2013-08-14 14:17:44 +02:00
|
|
|
int kType;
|
2017-04-27 03:55:38 -07:00
|
|
|
for (; i < vars.size() - 1; i++) {
|
2013-08-14 14:17:44 +02:00
|
|
|
kType = vars[i]->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, QString(vars[i]->getName()).toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(vars[i]->getName()).toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
lua_gettable(L, -2);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (lua_isnil(L, -1)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//value didn't exist, make it
|
|
|
|
|
lua_pop(L, -1);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, QString(vars[i]->getName()).toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE || kType == LUA_TFUNCTION) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(vars[i]->getName()).toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
lua_settable(L, -3);
|
2017-04-27 03:55:38 -07:00
|
|
|
i--; //decrement since we want to reput this table on the stack on next iteration
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kType = var->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TSTRING) {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getNewName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, var->getNewName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to user qDebug()<<"unknown key type"<<var->getKeyType();
|
2013-08-14 14:17:44 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//put the old value on the stack
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
i = 1;
|
|
|
|
|
for (; i < vars.size() - 1; i++) {
|
2013-08-14 14:17:44 +02:00
|
|
|
kType = vars[i]->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, QString(vars[i]->getName()).toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE || kType == LUA_TFUNCTION) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, vars[i]->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(vars[i]->getName()).toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
|
pushCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kType = var->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TSTRING) {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE || kType == LUA_TFUNCTION) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to user qDebug()<<"unknown key type"<<var->getKeyType();
|
2013-08-14 14:17:44 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
|
pushCount++;
|
|
|
|
|
//old value is @ -1 now
|
|
|
|
|
//we want to put our new named key @ -2
|
|
|
|
|
kType = var->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TSTRING) {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getNewName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, var->getNewName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to userqDebug()<<"unknown key type"<<var->getKeyType();
|
2013-08-14 14:17:44 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
pushCount++;
|
|
|
|
|
lua_insert(L, -2);
|
2017-04-27 03:55:38 -07:00
|
|
|
lua_settable(L, -3 - pushCount);
|
2013-08-14 14:17:44 +02:00
|
|
|
//key & value popped
|
|
|
|
|
//delete it, so we put the old key back on the stack and set to nil
|
|
|
|
|
kType = var->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TSTRING) {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE || kType == LUA_TFUNCTION) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to userqDebug()<<"unknown key type"<<var->getKeyType();
|
2013-08-14 14:17:44 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
lua_settable(L, -3);
|
|
|
|
|
var->clearNewName();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
bool LuaInterface::loadVar(TVar* var)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//puts the value of a variable on the -1 position of the stack
|
2017-04-27 03:55:38 -07:00
|
|
|
if (setjmp(buf) == 0) {
|
2013-08-14 14:17:44 +02:00
|
|
|
L = interpreter->pGlobalLua;
|
|
|
|
|
int kType = var->getKeyType();
|
|
|
|
|
int vType = var->getValueType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (vType == LUA_TTABLE) {
|
|
|
|
|
if (kType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, QString(var->getName()).toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, var->getName().toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getName()).toUtf8().constData());
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
if (lua_istable(L, -2)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_gettable(L, -2);
|
|
|
|
|
return true;
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
|
|
|
|
lua_pop(L, 1);
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (vType == LUA_TNUMBER) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushnumber(L, QString(var->getValue()).toInt());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (vType == LUA_TBOOLEAN) {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pushboolean(L, var->getValue().toLower() == "true" ? 1 : 0);
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (vType == LUA_TSTRING) {
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_pushstring(L, QString(var->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
|
|
|
|
} else {
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: report error to user qDebug()<<"panic in loadVar";
|
2013-08-14 14:17:44 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2013-08-19 12:25:26 +02:00
|
|
|
return true;
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::renameVar(TVar* var)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//this assumes anything like reparenting has been done
|
|
|
|
|
L = interpreter->pGlobalLua;
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> vars = varOrder(var);
|
2018-09-22 08:49:52 +02:00
|
|
|
QString oldVariable = vars.at(0)->getName();
|
2013-08-14 14:17:44 +02:00
|
|
|
QString newName;
|
2017-06-26 16:46:54 +02:00
|
|
|
if (vars.size() > 1) {
|
2013-08-14 14:17:44 +02:00
|
|
|
newName = vars[0]->getName();
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
for (int i = 1; i < vars.size(); i++) {
|
2013-08-14 14:17:44 +02:00
|
|
|
int kType = vars[i]->getKeyType();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TNUMBER) {
|
2018-09-22 08:49:52 +02:00
|
|
|
oldVariable.append(QStringLiteral("[%1]").arg(vars.at(i)->getName()));
|
2017-06-26 16:46:54 +02:00
|
|
|
if (i < vars.size() - 1) {
|
2020-06-01 17:35:35 +01:00
|
|
|
newName.append(QStringLiteral("[%1]").arg(vars[i]->getName()));
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (kType == LUA_TTABLE) {
|
2013-08-14 14:17:44 +02:00
|
|
|
renameCVar(vars);
|
|
|
|
|
return;
|
2020-06-01 17:35:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// That leaves LUA_TSTRING:
|
|
|
|
|
oldVariable.append(QStringLiteral(R"(["%1"])").arg(vars.at(i)->getName()));
|
|
|
|
|
if (i < vars.size() - 1) {
|
|
|
|
|
newName.append(QStringLiteral(R"(["%1"])").arg(vars.at(i)->getName()));
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-22 08:49:52 +02:00
|
|
|
|
|
|
|
|
if (vars.size() <= 1) {
|
|
|
|
|
// this variable is at root level on _G
|
|
|
|
|
newName.append(QStringLiteral("_G[\"%1\"]").arg(vars.last()->getNewName()));
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2018-09-22 08:49:52 +02:00
|
|
|
// this variable is nested in a table
|
|
|
|
|
if (var->getNewKeyType() == LUA_TNUMBER) {
|
|
|
|
|
newName.append(QStringLiteral("[%1]").arg(vars.last()->getNewName()));
|
|
|
|
|
} else {
|
2020-06-01 17:35:35 +01:00
|
|
|
newName.append(QStringLiteral(R"(["%1"])").arg(vars.last()->getNewName()));
|
2018-09-22 08:49:52 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
2018-09-22 08:49:52 +02:00
|
|
|
|
|
|
|
|
auto renameCode = QStringLiteral("%1 = %2").arg(newName, oldVariable);
|
2020-06-01 17:35:35 +01:00
|
|
|
int error = luaL_loadstring(L, renameCode.toUtf8().constData());
|
|
|
|
|
if (error) {
|
|
|
|
|
qWarning().noquote().nospace() << "LuaInterface::renameVar(...) WARNING - In copying (first) stage, internal Lua (parsing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< renameCode << "\".";
|
|
|
|
|
var->clearNewName();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
error = lua_pcall(L, 0, LUA_MULTRET, 0);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (error) {
|
2020-06-01 17:35:35 +01:00
|
|
|
qWarning().noquote().nospace() << "LuaInterface::renameVar(...) WARNING - In copying (first) stage, internal Lua (executing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< renameCode << "\".";
|
2013-08-14 14:17:44 +02:00
|
|
|
var->clearNewName();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-06-01 17:35:35 +01:00
|
|
|
|
2013-08-14 14:17:44 +02:00
|
|
|
//delete it
|
2020-06-01 17:35:35 +01:00
|
|
|
error = luaL_loadstring(L, oldVariable.append(QLatin1String(" = nil")).toUtf8().constData());
|
|
|
|
|
if (error) {
|
|
|
|
|
qWarning().noquote().nospace() << "LuaInterface::renameVar(...) WARNING - In deleting (second) stage, internal Lua (parsing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< renameCode << "\".";
|
|
|
|
|
var->clearNewName();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
error = lua_pcall(L, 0, LUA_MULTRET, 0);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (error) {
|
2020-06-01 17:35:35 +01:00
|
|
|
qWarning().noquote().nospace() << "LuaInterface::renameVar(...) WARNING - In deleting (second) stage, internal Lua (executing) error: \""
|
|
|
|
|
<< lua_tostring(L, -1)
|
|
|
|
|
<< "\" in code:\n\""
|
|
|
|
|
<< renameCode << "\".";
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
var->clearNewName();
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
QString LuaInterface::getValue(TVar* var)
|
|
|
|
|
{
|
|
|
|
|
if (setjmp(buf) == 0) {
|
2013-08-14 14:17:44 +02:00
|
|
|
L = interpreter->pGlobalLua;
|
2017-04-27 03:55:38 -07:00
|
|
|
QList<TVar*> vars = varOrder(var);
|
2017-06-26 16:46:54 +02:00
|
|
|
if (vars.empty()) {
|
2018-01-26 04:07:28 +01:00
|
|
|
return QString();
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
int pCount = vars.size(); //how many things we need to pop at the end
|
2013-08-14 14:17:44 +02:00
|
|
|
//load from _G first
|
2018-01-26 04:07:28 +01:00
|
|
|
lua_getglobal(L, (vars[0]->getName()).toUtf8().constData());
|
2017-04-27 03:55:38 -07:00
|
|
|
for (int i = 1; i < vars.size(); i++) {
|
2017-06-26 16:46:54 +02:00
|
|
|
if (!loadValue(L, vars[i], -2)) {
|
2018-01-26 04:07:28 +01:00
|
|
|
return QString();
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
int vType = lua_type(L, -1);
|
2018-01-26 04:07:28 +01:00
|
|
|
QString value;
|
2017-06-26 16:46:54 +02:00
|
|
|
if (vType == LUA_TBOOLEAN) {
|
2018-01-26 04:07:28 +01:00
|
|
|
value = lua_toboolean(L, -1) == 0 ? QLatin1String("false") : QLatin1String("true");
|
2017-06-26 16:46:54 +02:00
|
|
|
} else if (vType == LUA_TNUMBER || vType == LUA_TSTRING) {
|
2020-10-11 13:26:59 +02:00
|
|
|
value = lua_tostring(L, -1);
|
2017-06-26 16:46:54 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
lua_pop(L, pCount);
|
2013-08-14 14:17:44 +02:00
|
|
|
return value;
|
|
|
|
|
}
|
2018-01-26 04:07:28 +01:00
|
|
|
return QString();
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::iterateTable(lua_State* L, int index, TVar* tVar, bool hide)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
depth++;
|
2017-04-27 03:55:38 -07:00
|
|
|
while (lua_next(L, index)) {
|
2013-08-14 14:17:44 +02:00
|
|
|
int vType = lua_type(L, -1);
|
|
|
|
|
int kType = lua_type(L, -2);
|
2017-04-27 03:55:38 -07:00
|
|
|
lua_pushvalue(L, -2); //we do this because extracting the key with tostring changes it
|
2013-08-14 14:17:44 +02:00
|
|
|
QString keyName;
|
|
|
|
|
QString valueName;
|
2017-04-09 19:49:02 +02:00
|
|
|
auto var = new TVar();
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TTABLE) {
|
|
|
|
|
keyName = QString::number(luaL_ref(L, LUA_REGISTRYINDEX)); //this function pops the top item
|
2013-08-14 14:17:44 +02:00
|
|
|
lrefs.append(keyName.toInt());
|
|
|
|
|
var->setReference(true);
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2020-10-11 13:26:59 +02:00
|
|
|
keyName = lua_tostring(L, -1);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (kType == LUA_TFUNCTION && keyName.isEmpty()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//we lost the reference
|
|
|
|
|
keyName = QString::number(luaL_ref(L, LUA_REGISTRYINDEX));
|
|
|
|
|
lrefs.append(keyName.toInt());
|
|
|
|
|
var->setReference(true);
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pop(L, 1);
|
2017-04-27 03:55:38 -07:00
|
|
|
}
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
if (keyName == "package" && depth == 1) { //don't load in the 'package' table
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
tVar->removeChild(var);
|
|
|
|
|
delete var;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
var->setName(keyName, kType);
|
|
|
|
|
var->setValueType(vType);
|
|
|
|
|
var->setParent(tVar);
|
|
|
|
|
var->hidden = hide;
|
|
|
|
|
tVar->addChild(var);
|
|
|
|
|
const void* kp = lua_topointer(L, -1);
|
|
|
|
|
var->kpointer = kp;
|
|
|
|
|
const void* vp = lua_topointer(L, -2);
|
|
|
|
|
var->vpointer = vp;
|
2017-04-27 03:55:38 -07:00
|
|
|
if (varUnit->varExists(var) || keyName == "_G") {
|
2013-08-14 14:17:44 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
tVar->removeChild(var);
|
|
|
|
|
delete var;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
varUnit->addVariable(var);
|
|
|
|
|
|
|
|
|
|
varUnit->addPointer(kp);
|
|
|
|
|
|
|
|
|
|
varUnit->addPointer(vp);
|
2017-04-27 03:55:38 -07:00
|
|
|
if (vType == LUA_TTABLE) {
|
|
|
|
|
if (depth <= 99 && lua_checkstack(L, 3)) { //depth is historical now
|
2013-08-14 14:17:44 +02:00
|
|
|
//put the table on top
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
var->setValue("{}", LUA_TTABLE);
|
|
|
|
|
iterateTable(L, -2, var, hide);
|
|
|
|
|
depth--;
|
|
|
|
|
}
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (vType == LUA_TSTRING || vType == LUA_TNUMBER) {
|
|
|
|
|
lua_pushvalue(L, -1);
|
2020-10-11 13:26:59 +02:00
|
|
|
valueName = lua_tostring(L, -1);
|
2013-08-14 14:17:44 +02:00
|
|
|
var->setValue(valueName);
|
2017-04-27 03:55:38 -07:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
} else if (vType == LUA_TBOOLEAN) {
|
2013-08-14 14:17:44 +02:00
|
|
|
valueName = lua_toboolean(L, -1) == 0 ? "false" : "true";
|
|
|
|
|
var->setValue(valueName);
|
2017-04-27 03:55:38 -07:00
|
|
|
} else if (vType == LUA_TFUNCTION
|
|
|
|
|
&& (!keyName.toLower().startsWith("alias") && !keyName.toLower().startsWith("trigger") && !keyName.toLower().startsWith("action") && !keyName.toLower().startsWith("timer")
|
|
|
|
|
&& !keyName.toLower().startsWith("key"))) {
|
2013-08-14 14:17:44 +02:00
|
|
|
//functions are compiled to bytecode so there is no reference
|
|
|
|
|
var->setValue("function");
|
2017-04-27 03:55:38 -07:00
|
|
|
} else {
|
2013-08-14 14:17:44 +02:00
|
|
|
tVar->removeChild(var);
|
|
|
|
|
varUnit->removeVariable(var);
|
|
|
|
|
delete var;
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 03:55:38 -07:00
|
|
|
void LuaInterface::getVars(bool hide)
|
|
|
|
|
{
|
2013-08-14 14:17:44 +02:00
|
|
|
//returns the base item
|
|
|
|
|
QTime t;
|
|
|
|
|
t.start();
|
|
|
|
|
L = interpreter->pGlobalLua;
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
depth = 0;
|
2017-04-09 19:49:02 +02:00
|
|
|
auto g = new TVar();
|
2013-08-14 14:17:44 +02:00
|
|
|
g->setName("_G", LUA_TSTRING);
|
|
|
|
|
g->setValue("{}", LUA_TTABLE);
|
|
|
|
|
QListIterator<int> it(lrefs);
|
2017-04-27 03:55:38 -07:00
|
|
|
while (it.hasNext()) {
|
2013-08-14 14:17:44 +02:00
|
|
|
int ref = it.next();
|
|
|
|
|
luaL_unref(L, LUA_REGISTRYINDEX, ref);
|
|
|
|
|
}
|
|
|
|
|
varUnit->clear();
|
|
|
|
|
varUnit->setBase(g);
|
|
|
|
|
varUnit->addVariable(g);
|
2017-04-27 03:55:38 -07:00
|
|
|
iterateTable(L, LUA_GLOBALSINDEX, g, hide);
|
2014-01-10 21:41:20 -05:00
|
|
|
//FIXME: possible to keep and report? qDebug()<<"took"<<t.elapsed()<<"to get variables in";
|
2013-08-14 14:17:44 +02:00
|
|
|
}
|