1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Minor additions and fixes to the command system.

This commit is contained in:
Sandu Liviu Catalin 2016-02-21 10:31:10 +02:00
parent 3d77dfc508
commit 35d662a02f

View File

@ -92,7 +92,7 @@ Int32 CmdManager::Run(Int32 invoker, CCStr command)
{ {
// Save the command name // Save the command name
m_Command.assign(command, (split - command)); m_Command.assign(command, (split - command));
// Skip white space until after command name // Skip white space after command name
while (*split == ' ') ++split; while (*split == ' ') ++split;
// Save the command argument // Save the command argument
m_Argument.assign(split); m_Argument.assign(split);
@ -117,18 +117,28 @@ Int32 CmdManager::Run(Int32 invoker, CCStr command)
SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str()); SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str());
return -1; return -1;
} }
// Is the command instance valid? (just in case)
else if (!itr->second) else if (!itr->second)
{ {
m_Commands.erase(itr); m_Commands.erase(itr);
SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str()); SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str());
return -1; return -1;
} }
// Get the command instance // Save the command instance
m_Instance = itr->second; m_Instance = itr->second;
// Place a lock on the command // Place a lock on the command
m_Instance->m_Locked = true; m_Instance->m_Locked = true;
// Value returned by the command // Value returned by the command
Int32 ret = Exec(); Int32 ret = -1;
// Attempt to execute the command
try
{
ret = Exec();
}
catch (...)
{
SqError(CMDERR_EXECUTION_FAILED, _SC("Exceptions occurred during execution"), m_Invoker);
}
// Remove the lock from the command // Remove the lock from the command
m_Instance->m_Protected = false; m_Instance->m_Protected = false;
// Release the command instance // Release the command instance
@ -144,14 +154,14 @@ Int32 CmdManager::Exec()
m_Argv.clear(); m_Argv.clear();
// Reset the argument counter // Reset the argument counter
m_Argc = 0; m_Argc = 0;
// See if the invoker has enough authority to execute this command // Make sure the invoker has enough authority to execute this command
if (!m_Instance->AuthCheckID(m_Invoker)) if (!m_Instance->AuthCheckID(m_Invoker))
{ {
SqError(CMDERR_INSUFFICIENT_AUTH, _SC("Insufficient authority to execute command"), m_Invoker); SqError(CMDERR_INSUFFICIENT_AUTH, _SC("Insufficient authority to execute command"), m_Invoker);
// Command failed // Command failed
return -1; return -1;
} }
// See if an executer was specified // Make sure an executer was specified
else if (m_Instance->GetOnExec().IsNull()) else if (m_Instance->GetOnExec().IsNull())
{ {
SqError(CMDERR_MISSING_EXECUTER, _SC("No executer was specified for this command"), m_Invoker); SqError(CMDERR_MISSING_EXECUTER, _SC("No executer was specified for this command"), m_Invoker);
@ -164,14 +174,14 @@ Int32 CmdManager::Exec()
// The error message was reported while parsing // The error message was reported while parsing
return -1; return -1;
} }
// See if we have enough arguments specified // Make sure we have enough arguments specified
else if (m_Instance->GetMinArgC() > m_Argc) else if (m_Instance->GetMinArgC() > m_Argc)
{ {
SqError(CMDERR_INCOMPLETE_ARGS, _SC("Incomplete command arguments"), m_Instance->GetMinArgC()); SqError(CMDERR_INCOMPLETE_ARGS, _SC("Incomplete command arguments"), m_Instance->GetMinArgC());
// Command failed // Command failed
return -1; return -1;
} }
// The check during the parsing may not count the last argument // The check during the parsing may omit the last argument
else if (m_Instance->GetMaxArgC() < m_Argc) else if (m_Instance->GetMaxArgC() < m_Argc)
{ {
SqError(CMDERR_EXTRANEOUS_ARGS, _SC("Extraneous command arguments"), m_Instance->GetMaxArgC()); SqError(CMDERR_EXTRANEOUS_ARGS, _SC("Extraneous command arguments"), m_Instance->GetMaxArgC());
@ -188,16 +198,43 @@ Int32 CmdManager::Exec()
return -1; return -1;
} }
} }
// Result of the command execution
SQInteger result = -1;
// Do we have to call the command with an associative container?
if (m_Instance->m_Associate)
{
// Create the associative container
Table args(DefaultVM::Get());
// Copy the arguments into the table
for (Uint32 arg = 0; arg < m_Argc; ++arg)
{
// Do we have use the argument index as the key?
if (m_Instance->m_ArgTags[arg].empty())
{
args.SetValue(SQInteger(arg), m_Argv[arg].second);
}
// Nope, we have a name for this argument!
else
{
args.SetValue(m_Instance->m_ArgTags[arg].c_str(), m_Argv[arg].second);
}
}
// Attempt to execute the command with the specified arguments
result = m_Instance->Execute(_Core->GetPlayer(m_Invoker).mObj, args);
}
else
{
// Reserve an array for the extracted arguments // Reserve an array for the extracted arguments
Array args(DefaultVM::Get(), m_Argc); Array args(DefaultVM::Get(), m_Argc);
// Copy the arguments into the array // Copy the arguments into the array
for (Uint32 arg = 0; arg < m_Argc; ++arg) for (Uint32 arg = 0; arg < m_Argc; ++arg)
{ {
args.Bind(arg, m_Argv[arg].second); args.Bind(SQInteger(arg), m_Argv[arg].second);
} }
// Attempt to execute the command with the specified arguments // Attempt to execute the command with the specified arguments
SQInteger result = m_Instance->Execute(_Core->GetPlayer(m_Invoker).mObj, args); result = m_Instance->Execute(_Core->GetPlayer(m_Invoker).mObj, args);
// See if an error occurred }
// See if an error occurred or an exception was thrown
if (Error::Occurred(DefaultVM::Get())) if (Error::Occurred(DefaultVM::Get()))
{ {
SqError(CMDERR_EXECUTION_FAILED, _SC("Command execution failed"), SqError(CMDERR_EXECUTION_FAILED, _SC("Command execution failed"),
@ -209,7 +246,7 @@ Int32 CmdManager::Exec()
// Result is invalid at this point // Result is invalid at this point
result = -1; result = -1;
} }
// See if the command failed // See if the command failed explicitly
else if (!result) else if (!result)
{ {
SqError(CMDERR_EXECUTION_FAILED, _SC("Command execution failed"), SqError(CMDERR_EXECUTION_FAILED, _SC("Command execution failed"),
@ -223,8 +260,8 @@ Int32 CmdManager::Exec()
{ {
m_Instance->m_OnPost.Execute(_Core->GetPlayer(m_Invoker).mObj, result); m_Instance->m_OnPost.Execute(_Core->GetPlayer(m_Invoker).mObj, result);
} }
// Release the command instance // Return the result
return (Int32)result; return Int32(result);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -236,15 +273,15 @@ bool CmdManager::Parse()
return true; /* Done parsing */ return true; /* Done parsing */
} }
// Obtain the flags of the currently processed argument // Obtain the flags of the currently processed argument
Uint8 arg_flags = m_Instance->GetArgFlags(m_Argc); Uint8 arg_flags = m_Instance->m_ArgSpec[m_Argc];
// Adjust the internal buffer if necessary (mostly never) // Adjust the internal buffer if necessary (mostly never)
m_Buffer.Adjust< SQChar >(m_Argument.size()); m_Buffer.Adjust< SQChar >(m_Argument.size());
// The iterator to the currently processed character // The iterator to the currently processed character
String::iterator itr = m_Argument.begin(); String::iterator itr = m_Argument.begin();
// Previously, currently and next processed character // Previous and currently processed character
SQChar prev = 0, elem = 0; SQChar prev = 0, elem = 0;
// Maximum arguments allowed to be processed // Maximum arguments allowed to be processed
const Uint8 max_arg = m_Instance->GetMaxArgC(); const Uint8 max_arg = m_Instance->m_MaxArgc;
// Process loop result // Process loop result
bool good = true; bool good = true;
// Process the specified command text // Process the specified command text
@ -299,7 +336,7 @@ bool CmdManager::Parse()
// Do we have to extract a string argument? // Do we have to extract a string argument?
else if ((elem == '\'' || elem == '"') && prev != '\\') else if ((elem == '\'' || elem == '"') && prev != '\\')
{ {
// Obtain the internal beginning and ending of the internal buffer // Obtain the beginning and ending of the internal buffer
SStr str = m_Buffer.Begin< SQChar >(); SStr str = m_Buffer.Begin< SQChar >();
CSStr end = (m_Buffer.End< SQChar >()-1); /* + null */ CSStr end = (m_Buffer.End< SQChar >()-1); /* + null */
// Save the closing quote type // Save the closing quote type
@ -349,7 +386,7 @@ bool CmdManager::Parse()
} }
// Simply replicate the character to the internal buffer // Simply replicate the character to the internal buffer
*(str++) = elem; *(str++) = elem;
// Move to the next character // Advance to the next character
++itr; ++itr;
} }
// See if the argument was valid // See if the argument was valid
@ -385,15 +422,15 @@ bool CmdManager::Parse()
} }
// Add it to the argument list along with it's type // Add it to the argument list along with it's type
m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value)); m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value));
// Move to the next argument and obtain its flags // Advance to the next argument and obtain its flags
arg_flags = m_Instance->GetArgFlags(++m_Argc); arg_flags = m_Instance->m_ArgSpec[++m_Argc];
} }
// Ignore space characters until another valid argument is found // Ignore space characters until another valid character is found
else if (elem != ' ' && (prev == ' ' || prev == 0)) else if (elem != ' ' && (prev == ' ' || prev == 0))
{ {
// Find the first character that marks the end of the argument // Find the first character that marks the end of the argument
String::iterator pos = std::find(String::iterator(itr), m_Argument.end(), ' '); String::iterator pos = std::find(String::iterator(itr), m_Argument.end(), ' ');
// Copy all elements within range into the internal buffer // Copy all characters within range into the internal buffer
const Uint32 sz = m_Buffer.Write(0, &(*itr), std::distance(itr, pos)); const Uint32 sz = m_Buffer.Write(0, &(*itr), std::distance(itr, pos));
// Update the main iterator position // Update the main iterator position
itr = pos; itr = pos;
@ -414,7 +451,7 @@ bool CmdManager::Parse()
if (next == &m_Buffer.At< SQChar >(sz)) if (next == &m_Buffer.At< SQChar >(sz))
{ {
// Transform it into a script object // Transform it into a script object
Var< SQInteger >::push(DefaultVM::Get(), static_cast< SQInteger >(value)); Var< SQInteger >::push(DefaultVM::Get(), SQInteger(value));
// Get the object from the stack // Get the object from the stack
Var< Object & > var(DefaultVM::Get(), -1); Var< Object & > var(DefaultVM::Get(), -1);
// Pop the created object from the stack // Pop the created object from the stack
@ -433,13 +470,13 @@ bool CmdManager::Parse()
{ {
// Let's us know if the whole argument was part of the resulted value // Let's us know if the whole argument was part of the resulted value
CStr next = NULL; CStr next = NULL;
// Attempt to extract the integer value from the string // Attempt to extract the floating point value from the string
Float64 value = strtod(m_Buffer.Data(), &next); Float64 value = strtod(m_Buffer.Data(), &next);
// See if this whole string was indeed an integer // See if this whole string was indeed an floating point
if (next == &m_Buffer.At< SQChar >(sz)) if (next == &m_Buffer.At< SQChar >(sz))
{ {
// Transform it into a script object // Transform it into a script object
Var< SQFloat >::push(DefaultVM::Get(), static_cast< SQFloat >(value)); Var< SQFloat >::push(DefaultVM::Get(), SQFloat(value));
// Get the object from the stack // Get the object from the stack
Var< Object & > var(DefaultVM::Get(), -1); Var< Object & > var(DefaultVM::Get(), -1);
// Pop the created object from the stack // Pop the created object from the stack
@ -531,15 +568,15 @@ bool CmdManager::Parse()
// Add it to the argument list along with it's type // Add it to the argument list along with it's type
m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value)); m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value));
} }
// Move to the next argument and obtain its flags // Advance to the next argument and obtain its flags
arg_flags = m_Instance->GetArgFlags(++m_Argc); arg_flags = m_Instance->m_ArgSpec[++m_Argc];
} }
// Is there anything left to parse? // Is there anything left to parse?
if (itr >= m_Argument.end()) if (itr >= m_Argument.end())
{ {
break; break;
} }
// Move to the next character // Advance to the next character
++itr; ++itr;
} }
// Return whether the parsing was successful // Return whether the parsing was successful
@ -550,6 +587,7 @@ bool CmdManager::Parse()
void CmdListener::Init(CSStr name, CSStr spec, Array & tags, Uint8 min, Uint8 max) void CmdListener::Init(CSStr name, CSStr spec, Array & tags, Uint8 min, Uint8 max)
{ {
m_Name.assign(""); m_Name.assign("");
// Initialize the specifiers and tags to default values
for (Uint8 n = 0; n < SQMOD_MAX_CMD_ARGS; ++n) for (Uint8 n = 0; n < SQMOD_MAX_CMD_ARGS; ++n)
{ {
m_ArgSpec[n] = CMDARG_ANY; m_ArgSpec[n] = CMDARG_ANY;
@ -1091,7 +1129,7 @@ bool CmdListener::ProcSpec(CSStr str)
// Stop parsing // Stop parsing
break; break;
} }
// Move to the next argument // Advance to the next argument
++idx; ++idx;
} }
// Simply ignore a type specifier delimiter // Simply ignore a type specifier delimiter