@@ -968,9 +968,271 @@ static int L_BroadcastPlugin (lua_State *L)
968
968
static int L_CallPlugin (lua_State *L)
969
969
{
970
970
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 ...
971
1233
lua_pushnumber (L, pDoc->CallPlugin (
972
- my_checkstring (L, 1 ) , // PluginID
973
- my_checkstring (L, 2 ) , // Routine
1234
+ sPluginID , // PluginID
1235
+ sRoutine , // Routine
974
1236
my_optstring (L, 3 , " " ) // Argument - optional
975
1237
));
976
1238
return 1 ; // number of result fields
0 commit comments