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
|
||||
m_Command.assign(command, (split - command));
|
||||
// Skip white space until after command name
|
||||
// Skip white space after command name
|
||||
while (*split == ' ') ++split;
|
||||
// Save the command argument
|
||||
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());
|
||||
return -1;
|
||||
}
|
||||
// Is the command instance valid? (just in case)
|
||||
else if (!itr->second)
|
||||
{
|
||||
m_Commands.erase(itr);
|
||||
SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str());
|
||||
return -1;
|
||||
}
|
||||
// Get the command instance
|
||||
// Save the command instance
|
||||
m_Instance = itr->second;
|
||||
// Place a lock on the command
|
||||
m_Instance->m_Locked = true;
|
||||
// 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
|
||||
m_Instance->m_Protected = false;
|
||||
// Release the command instance
|
||||
@ -144,14 +154,14 @@ Int32 CmdManager::Exec()
|
||||
m_Argv.clear();
|
||||
// Reset the argument counter
|
||||
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))
|
||||
{
|
||||
SqError(CMDERR_INSUFFICIENT_AUTH, _SC("Insufficient authority to execute command"), m_Invoker);
|
||||
// Command failed
|
||||
return -1;
|
||||
}
|
||||
// See if an executer was specified
|
||||
// Make sure an executer was specified
|
||||
else if (m_Instance->GetOnExec().IsNull())
|
||||
{
|
||||
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
|
||||
return -1;
|
||||
}
|
||||
// See if we have enough arguments specified
|
||||
// Make sure we have enough arguments specified
|
||||
else if (m_Instance->GetMinArgC() > m_Argc)
|
||||
{
|
||||
SqError(CMDERR_INCOMPLETE_ARGS, _SC("Incomplete command arguments"), m_Instance->GetMinArgC());
|
||||
// Command failed
|
||||
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)
|
||||
{
|
||||
SqError(CMDERR_EXTRANEOUS_ARGS, _SC("Extraneous command arguments"), m_Instance->GetMaxArgC());
|
||||
@ -188,16 +198,43 @@ Int32 CmdManager::Exec()
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// Reserve an array for the extracted arguments
|
||||
Array args(DefaultVM::Get(), m_Argc);
|
||||
// Copy the arguments into the array
|
||||
for (Uint32 arg = 0; arg < m_Argc; ++arg)
|
||||
// Result of the command execution
|
||||
SQInteger result = -1;
|
||||
// Do we have to call the command with an associative container?
|
||||
if (m_Instance->m_Associate)
|
||||
{
|
||||
args.Bind(arg, m_Argv[arg].second);
|
||||
// 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);
|
||||
}
|
||||
// Attempt to execute the command with the specified arguments
|
||||
SQInteger result = m_Instance->Execute(_Core->GetPlayer(m_Invoker).mObj, args);
|
||||
// See if an error occurred
|
||||
else
|
||||
{
|
||||
// Reserve an array for the extracted arguments
|
||||
Array args(DefaultVM::Get(), m_Argc);
|
||||
// Copy the arguments into the array
|
||||
for (Uint32 arg = 0; arg < m_Argc; ++arg)
|
||||
{
|
||||
args.Bind(SQInteger(arg), m_Argv[arg].second);
|
||||
}
|
||||
// Attempt to execute the command with the specified arguments
|
||||
result = m_Instance->Execute(_Core->GetPlayer(m_Invoker).mObj, args);
|
||||
}
|
||||
// See if an error occurred or an exception was thrown
|
||||
if (Error::Occurred(DefaultVM::Get()))
|
||||
{
|
||||
SqError(CMDERR_EXECUTION_FAILED, _SC("Command execution failed"),
|
||||
@ -209,7 +246,7 @@ Int32 CmdManager::Exec()
|
||||
// Result is invalid at this point
|
||||
result = -1;
|
||||
}
|
||||
// See if the command failed
|
||||
// See if the command failed explicitly
|
||||
else if (!result)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// Release the command instance
|
||||
return (Int32)result;
|
||||
// Return the result
|
||||
return Int32(result);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -236,15 +273,15 @@ bool CmdManager::Parse()
|
||||
return true; /* Done parsing */
|
||||
}
|
||||
// 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)
|
||||
m_Buffer.Adjust< SQChar >(m_Argument.size());
|
||||
// The iterator to the currently processed character
|
||||
String::iterator itr = m_Argument.begin();
|
||||
// Previously, currently and next processed character
|
||||
// Previous and currently processed character
|
||||
SQChar prev = 0, elem = 0;
|
||||
// Maximum arguments allowed to be processed
|
||||
const Uint8 max_arg = m_Instance->GetMaxArgC();
|
||||
const Uint8 max_arg = m_Instance->m_MaxArgc;
|
||||
// Process loop result
|
||||
bool good = true;
|
||||
// Process the specified command text
|
||||
@ -299,7 +336,7 @@ bool CmdManager::Parse()
|
||||
// Do we have to extract a string argument?
|
||||
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 >();
|
||||
CSStr end = (m_Buffer.End< SQChar >()-1); /* + null */
|
||||
// Save the closing quote type
|
||||
@ -349,7 +386,7 @@ bool CmdManager::Parse()
|
||||
}
|
||||
// Simply replicate the character to the internal buffer
|
||||
*(str++) = elem;
|
||||
// Move to the next character
|
||||
// Advance to the next character
|
||||
++itr;
|
||||
}
|
||||
// See if the argument was valid
|
||||
@ -385,15 +422,15 @@ bool CmdManager::Parse()
|
||||
}
|
||||
// Add it to the argument list along with it's type
|
||||
m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value));
|
||||
// Move to the next argument and obtain its flags
|
||||
arg_flags = m_Instance->GetArgFlags(++m_Argc);
|
||||
// Advance to the next argument and obtain its flags
|
||||
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))
|
||||
{
|
||||
// Find the first character that marks the end of the argument
|
||||
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));
|
||||
// Update the main iterator position
|
||||
itr = pos;
|
||||
@ -414,7 +451,7 @@ bool CmdManager::Parse()
|
||||
if (next == &m_Buffer.At< SQChar >(sz))
|
||||
{
|
||||
// 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
|
||||
Var< Object & > var(DefaultVM::Get(), -1);
|
||||
// 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
|
||||
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);
|
||||
// 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))
|
||||
{
|
||||
// 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
|
||||
Var< Object & > var(DefaultVM::Get(), -1);
|
||||
// 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
|
||||
m_Argv.push_back(CmdArgs::value_type(CMDARG_STRING, var.value));
|
||||
}
|
||||
// Move to the next argument and obtain its flags
|
||||
arg_flags = m_Instance->GetArgFlags(++m_Argc);
|
||||
// Advance to the next argument and obtain its flags
|
||||
arg_flags = m_Instance->m_ArgSpec[++m_Argc];
|
||||
}
|
||||
// Is there anything left to parse?
|
||||
if (itr >= m_Argument.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Move to the next character
|
||||
// Advance to the next character
|
||||
++itr;
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
m_Name.assign("");
|
||||
// Initialize the specifiers and tags to default values
|
||||
for (Uint8 n = 0; n < SQMOD_MAX_CMD_ARGS; ++n)
|
||||
{
|
||||
m_ArgSpec[n] = CMDARG_ANY;
|
||||
@ -1091,7 +1129,7 @@ bool CmdListener::ProcSpec(CSStr str)
|
||||
// Stop parsing
|
||||
break;
|
||||
}
|
||||
// Move to the next argument
|
||||
// Advance to the next argument
|
||||
++idx;
|
||||
}
|
||||
// Simply ignore a type specifier delimiter
|
||||
|
Loading…
Reference in New Issue
Block a user