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:
parent
3d77dfc508
commit
35d662a02f
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user