#include "Commands.h" #include namespace Engine { static Commands *CommandsInstance = NULL; void trim_command_str (std::string &command_str) { std::string::size_type start = command_str.find_first_not_of (" \t"); if (start != std::string::npos) command_str = command_str.substr (start); std::string::size_type end = command_str.find_first_of ("#;\n\r\0"); if (end != std::string::npos) command_str = command_str.substr (0, end); } /* * Inherited Module functions */ int Commands::OnInit (int argc, char* argv[]) { LogDebug ("Commands Init"); mErrorString = ""; if (CommandsInstance) { LogError ("Commands module already initialized!"); return -1; } CommandsInstance = this; return 0; } void Commands::OnDestroy () { LogDebug ("Commands Destroy"); if (CommandsInstance) CommandsInstance = NULL; } /* * Module specific functions */ std::string Commands::GetCommandName (const std::string &command) { return command.substr (0, command.find_first_of (" ;\n\0")); } std::vector Commands::ParseArgs (std::string &argument_str) { std::vector args; std::string::size_type pos = argument_str.find_first_not_of (" "); std::string::size_type next_token = 0; while ( argument_str.length ()> pos && argument_str.find_first_of (" \"", pos) != std::string::npos) { next_token = argument_str.find_first_of (" \"", pos); if (next_token != std::string::npos && argument_str[next_token] =='"') { pos = next_token; next_token = argument_str.find_first_of ('"', pos + 1); if (next_token != std::string::npos) { args.push_back (argument_str.substr (pos + 1, next_token - pos - 1)); } pos = argument_str.find_first_not_of (" ", next_token + 1); } else { args.push_back (argument_str.substr (pos, next_token - pos)); pos = argument_str.find_first_not_of (" ", next_token + 1); } } if (pos != std::string::npos) args.push_back (argument_str.substr (pos, argument_str.length ())); return args; } void Commands::AddCommand (const std::string &name, command_cb callback){ LogDebug ("Adding Command '%s' at %x", name.c_str(), (void *) callback); mCommandsCallbacks[name] = callback; return; } bool Commands::RunCommand (const std::string &command){ LogDebug ("Running Command: %s", command.c_str()); std::string cmd_name = GetCommandName (command); std::string args; if (command.length () > cmd_name.length () + 1) args = command.substr (cmd_name.length () + 1, command.length ()); if (mCommandsCallbacks.find (cmd_name) != mCommandsCallbacks.end()) { std::vector argv = ParseArgs (args); if (mCommandsCallbacks[cmd_name] (argv)) { mErrorString = ""; return true; } else { return false; } } else { LogWarning ("Command '%s' not registered!", cmd_name.c_str ()); } SetErrorString ("Command '" + cmd_name + "' does not exist!"); return false; } void Commands::QueueCommand (const std::string &command){ mCommandQueue.push (command); } bool Commands::QueueExecute (){ bool result = true; while (mCommandQueue.size() > 0) { result = RunCommand (mCommandQueue.front()); if (!result) { while (!mCommandQueue.empty()) mCommandQueue.pop(); return false; } mCommandQueue.pop(); } return true; } void Commands::SetErrorString (const std::string &error_str){ mErrorString = error_str; LogWarning ("Command Error: %s", error_str.c_str ()); } std::string Commands::GetErrorString (){ return mErrorString; } /* * Global functions */ bool CommandsInitialized () { if (!CommandsInstance) { LogError ("Commands System not yet initialized!"); return false; } return true; } void AddCommand (const std::string &name, command_cb callback){ if (!CommandsInitialized ()) return; CommandsInstance->AddCommand (name, callback); } bool RunCommand (const std::string &command){ if (!CommandsInitialized ()) return false; return CommandsInstance->RunCommand (command); } void QueueCommand (const std::string &command){ if (!CommandsInitialized ()) return; CommandsInstance->QueueCommand (command); } bool CommandQueueExecute (){ if (!CommandsInitialized ()) return false; return CommandsInstance->QueueExecute (); } void CommandSetErrorString (const std::string &error_str){ if (!CommandsInitialized ()) return; CommandsInstance->SetErrorString (error_str); } std::string CommandGetErrorString (){ if (!CommandsInitialized ()) return false; return CommandsInstance->GetErrorString(); } /** \brief Searches for possible candidates at reasonable places * * In that order: * 1. current directory * 2. user data directory * 3. game data directory * * \returns full path to the file, otherwise only the filename (which will * \returns then cause an error because the file cannot be opened) */ std::string find_exec_file_full_path (const std::string &exec_file) { std::string full_path = exec_file; boost::filesystem::path exec_file_path (full_path); if(boost::filesystem::is_regular_file(exec_file_path)) { return full_path; } full_path = GetUserDirFullPath(std::string("/") + exec_file); exec_file_path = full_path; if(boost::filesystem::is_regular_file(exec_file_path)) { return full_path; } full_path = GetResourceFullPath(std::string("/") + exec_file); exec_file_path = full_path; if(boost::filesystem::is_regular_file(exec_file_path)) { return full_path; } // otherwise just return the normal path which will fail anyway return exec_file; } /* * Commands of the Command system */ bool Cmd_Exec (const std::vector args) { if (!CommandsInitialized()) return false; if (args.size() != 1) { CommandsInstance->SetErrorString("usage: exec "); return false; } std::string full_path = find_exec_file_full_path(args[0]); LogDebug ("Trying to exec file %s", full_path.c_str()); std::ifstream exec_file; exec_file.open(full_path.c_str(), std::ios_base::in); if (!exec_file) { std::ostringstream error_msg; error_msg << "exec failed: could not open file '" << full_path.c_str() << "'"; CommandsInstance->SetErrorString(error_msg.str()); return false; } int linecounter = 0; while (!exec_file.eof()) { std::string line; getline (exec_file, line); linecounter++; trim_command_str (line); if (line.size() == 0) continue; if (!CommandsInstance->RunCommand (line)) { std::ostringstream error_msg; error_msg << "exec failed running command '" << line << "' in file " << args[0] << ":" << linecounter << "."; CommandsInstance->SetErrorString (error_msg.str()); return false; } } exec_file.close(); LogDebug ("exec success for file %s", full_path.c_str()); return true; } void Commands::OnRegisterCommands () { AddCommand ("exec", Cmd_Exec); } }