Skip to content

Commit 324e64f

Browse files
committed
Changes to CallPlugin to allow multiple arguments
1 parent 21d1ddb commit 324e64f

File tree

2 files changed

+266
-4
lines changed

2 files changed

+266
-4
lines changed

scripting/lua_methods.cpp

Lines changed: 264 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,9 +968,271 @@ static int L_BroadcastPlugin (lua_State *L)
968968
static int L_CallPlugin (lua_State *L)
969969
{
970970
CMUSHclientDoc *pDoc = doc (L);
971+
972+
const char * sPluginID = my_checkstring (L, 1);
973+
const char * sRoutine = my_checkstring (L, 2);
974+
int i; // for iterating through arguments / return values
975+
976+
// preliminary checks ...
977+
978+
// function name given?
979+
if (sRoutine [0] == 0)
980+
{
981+
lua_pushnumber (L, eNoSuchRoutine);
982+
lua_pushstring (L, "No function name supplied");
983+
return 2; // eNoSuchRoutine, explanation
984+
}
985+
986+
// plugin exists?
987+
CPlugin * pPlugin = pDoc->GetPlugin (sPluginID);
988+
if (!pPlugin)
989+
{
990+
lua_pushnumber (L, eNoSuchPlugin);
991+
CString strError = TFormat ("Plugin ID (%s) is not installed",
992+
sPluginID);
993+
lua_pushstring (L, strError);
994+
return 2; // eNoSuchPlugin, explanation
995+
}
996+
997+
// plugin is enabled?
998+
if (!pPlugin->m_bEnabled)
999+
{
1000+
lua_pushnumber (L, ePluginDisabled);
1001+
CString strError = TFormat ("Plugin '%s' (%s) disabled",
1002+
(LPCTSTR) pPlugin->m_strName,
1003+
sPluginID);
1004+
lua_pushstring (L, strError);
1005+
return 2; // ePluginDisabled, explanation
1006+
1007+
}
1008+
1009+
// plugin has a script engine?
1010+
if (pPlugin->m_ScriptEngine == NULL)
1011+
{
1012+
lua_pushnumber (L, eNoSuchRoutine);
1013+
CString strError = TFormat ("Scripting not enabled in plugin '%s' (%s)",
1014+
(LPCTSTR) pPlugin->m_strName,
1015+
sPluginID);
1016+
lua_pushstring (L, strError);
1017+
return 2; // eNoSuchRoutine, explanation
1018+
1019+
}
1020+
1021+
// new in 4.55 - Lua to Lua calls can handle multiple arguments and a return value
1022+
1023+
// don't need to check *our* scripting language, we must be Lua, duh, or we wouldn't be here.
1024+
1025+
if (pPlugin->m_ScriptEngine->IsLua ())
1026+
{
1027+
int n = lua_gettop(L); // number of arguments in calling script
1028+
1029+
lua_State *pL = pPlugin->m_ScriptEngine->L; // plugin's Lua state
1030+
1031+
// don't clear if we are calling ourselves
1032+
if (pL != L)
1033+
lua_settop (pL, 0); // clear stack in target plugin
1034+
1035+
// get wanted function onto stack
1036+
if (!GetNestedFunction (pL, sRoutine, false)) // don't raise error
1037+
{
1038+
lua_pushnumber (L, eNoSuchRoutine);
1039+
CString strError = TFormat ("No function '%s' in plugin '%s' (%s)",
1040+
sRoutine,
1041+
(LPCTSTR) pPlugin->m_strName,
1042+
sPluginID);
1043+
lua_pushstring (L, strError);
1044+
return 2; // eNoSuchRoutine, explanation
1045+
}
1046+
1047+
// if we are calling ourselves, don't make a copy of everything
1048+
if (pL == L)
1049+
{
1050+
lua_insert (L, 3); // move function to be called as third item
1051+
// (after plugin ID and function name), pushing others up
1052+
} // end of calling ourselves
1053+
else
1054+
{ // calling a different plugin
1055+
1056+
// copy all our arguments to destination script space
1057+
// we can handle: nil, boolean, number, string
1058+
// but NOT: table, function, userdata, thread
1059+
1060+
// check we can push our arguments.
1061+
// we have (n - 2) arguments (first two are the plugin ID and the function name)
1062+
// however we need room for the function itself and at least room for the return value
1063+
lua_checkstack (pL, n);
1064+
1065+
for (i = 3; i <= n; i++) // arg 1 is plugin ID, arg 2 is function name, so start at 3
1066+
{
1067+
1068+
switch (lua_type (L, i))
1069+
{
1070+
case LUA_TNIL:
1071+
lua_pushnil (pL);
1072+
break;
1073+
1074+
case LUA_TBOOLEAN:
1075+
{
1076+
int b = lua_toboolean (L, i);
1077+
lua_pushboolean (pL, b);
1078+
}
1079+
break;
1080+
1081+
case LUA_TNUMBER:
1082+
{
1083+
double num = lua_tonumber (L, i);
1084+
lua_pushnumber (pL, num);
1085+
}
1086+
break;
1087+
1088+
case LUA_TSTRING:
1089+
{
1090+
size_t len;
1091+
const char * s = lua_tolstring (L, i, &len);
1092+
lua_pushlstring (pL, s, len);
1093+
}
1094+
break;
1095+
1096+
// not one of those? can't handle it
1097+
default:
1098+
lua_settop (pL, 0); // clear target plugin's stack to remove whatever we pushed onto it
1099+
lua_pushnumber (L, eBadParameter);
1100+
CString strError = TFormat ("Cannot pass argument #%i (%s type) to CallPlugin",
1101+
i,
1102+
lua_typename (L, lua_type (L, i)));
1103+
lua_pushstring (L, strError);
1104+
return 2; // eBadParameter, explanation
1105+
1106+
} // end of switch on type of argument
1107+
1108+
} // end of for each argument
1109+
} // end of not calling ourselves
1110+
1111+
unsigned short iOldStyle = pDoc->m_iNoteStyle;
1112+
pDoc->m_iNoteStyle = NORMAL; // back to default style
1113+
1114+
// do this so plugin can find its own state (eg. with GetPluginID)
1115+
CPlugin * pSavedPlugin = pDoc->m_CurrentPlugin;
1116+
pDoc->m_CurrentPlugin = pPlugin;
1117+
1118+
// now call the routine in the plugin
1119+
1120+
if (CallLuaWithTraceBack (pL, n - 2, LUA_MULTRET)) // true on error
1121+
{
1122+
1123+
// here for executioin error in plugin function ...
1124+
1125+
CString strType = TFormat ("Plugin %s", (LPCTSTR) pPlugin->m_strName);
1126+
CString strReason = TFormat ("Executing plugin %s sub %s",
1127+
(LPCTSTR) pPlugin->m_strName,
1128+
sRoutine );
1129+
1130+
// grab the Lua error from the stack before we clear it
1131+
CString strLuaError (lua_tostring(pL, -1));
1132+
1133+
// this will display the error, and the error context
1134+
LuaError (pL, "Run-time error", sRoutine, strType, strReason, pDoc);
1135+
1136+
// back to who *we* are (had to wait until after LuaError)
1137+
pDoc->m_CurrentPlugin = pSavedPlugin;
1138+
pDoc->m_iNoteStyle = iOldStyle;
1139+
1140+
lua_settop (pL, 0); // clean stack up
1141+
1142+
// the error code for the caller (result value 1)
1143+
lua_pushnumber (L, eErrorCallingPluginRoutine);
1144+
1145+
// a nice error message (result value 2)
1146+
CString strError = TFormat ("Runtime error in function '%s', plugin '%s' (%s)",
1147+
sRoutine,
1148+
(LPCTSTR) pPlugin->m_strName, sPluginID);
1149+
1150+
lua_pushstring (L, strError);
1151+
1152+
// what the exact Lua error message was (result value 3)
1153+
lua_pushstring (L, strLuaError);
1154+
1155+
return 3; // ie. eErrorCallingPluginRoutine, explanation, Lua error message
1156+
}
1157+
1158+
// back to who *we* are (if no error)
1159+
pDoc->m_CurrentPlugin = pSavedPlugin;
1160+
pDoc->m_iNoteStyle = iOldStyle;
1161+
1162+
int ret_n = lua_gettop(pL); // number of returned values (might be zero)
1163+
1164+
lua_pushnumber (L, eOK); // expected behaviour prior to 4.55 (just a single value)
1165+
1166+
// if we are calling ourselves, don't make a copy of everything
1167+
if (pL == L)
1168+
{
1169+
lua_insert (L, 3); // put return code as third item (after plugin ID, function name), pushing others up
1170+
return 1 + ret_n - 2; // eOK plus all returned values, minus plugin ID and function name
1171+
}
1172+
1173+
lua_checkstack (L, ret_n + 1); // check we can push eOK plus all the return results
1174+
1175+
// copy return results back to original script space
1176+
// we can handle: nil, boolean, number, string
1177+
// but NOT: table, function, userdata, thread
1178+
1179+
for (i = 1; i <= ret_n; i++)
1180+
{
1181+
1182+
switch (lua_type (pL, i))
1183+
{
1184+
case LUA_TNIL:
1185+
lua_pushnil (L);
1186+
break;
1187+
1188+
case LUA_TBOOLEAN:
1189+
{
1190+
int b = lua_toboolean (pL, i);
1191+
lua_pushboolean (L, b);
1192+
}
1193+
break;
1194+
1195+
case LUA_TNUMBER:
1196+
{
1197+
double num = lua_tonumber (pL, i);
1198+
lua_pushnumber (L, num);
1199+
}
1200+
break;
1201+
1202+
case LUA_TSTRING:
1203+
{
1204+
size_t len;
1205+
const char * s = lua_tolstring (pL, i, &len);
1206+
lua_pushlstring (L, s, len);
1207+
}
1208+
break;
1209+
1210+
// not one of those? can't handle it
1211+
default:
1212+
lua_pushnumber (L, eErrorCallingPluginRoutine);
1213+
CString strError = CFormat ("Cannot handle return value #%i (%s type) from function '%s' in plugin '%s' (%s)",
1214+
i,
1215+
lua_typename (pL, lua_type (pL, i)),
1216+
sRoutine,
1217+
(LPCTSTR) pPlugin->m_strName,
1218+
sPluginID);
1219+
lua_pushstring (L, strError);
1220+
lua_settop (pL, 0); // clean stack in plugin
1221+
return 2; // eErrorCallingPluginRoutine, explanation
1222+
1223+
} // end of switch on type of argument
1224+
1225+
} // end of for each argument
1226+
1227+
return ret_n + 1; // eOK plus all returned values
1228+
} // end if Lua calling Lua
1229+
1230+
// ------------- end stuff added for version 4.55 -------------------
1231+
1232+
// old fashioned way ...
9711233
lua_pushnumber (L, pDoc->CallPlugin (
972-
my_checkstring (L, 1), // PluginID
973-
my_checkstring (L, 2), // Routine
1234+
sPluginID, // PluginID
1235+
sRoutine, // Routine
9741236
my_optstring (L, 3, "") // Argument - optional
9751237
));
9761238
return 1; // number of result fields

scripting/methods.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5614,7 +5614,7 @@ CPlugin * pPlugin = GetPlugin (PluginID);
56145614
if (!pPlugin)
56155615
return eNoSuchPlugin;
56165616

5617-
if (strlen (Routine) == 0)
5617+
if (strlen (Routine) == 0 || pPlugin->m_ScriptEngine == NULL)
56185618
return eNoSuchRoutine;
56195619

56205620
if (!pPlugin->m_bEnabled)
@@ -5636,7 +5636,7 @@ long nInvocationCount = 0;
56365636
(LPCTSTR) pPlugin->m_strName,
56375637
Routine );
56385638

5639-
if (pPlugin->m_ScriptEngine && pPlugin->m_ScriptEngine->IsLua ())
5639+
if (pPlugin->m_ScriptEngine->IsLua ())
56405640
{
56415641
list<double> nparams;
56425642
list<string> sparams;

0 commit comments

Comments
 (0)