/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ #include "shell_command.h" #include "list.h" #include "debug.h" #include "class_list.h" #include "key_names.h" #include #include using namespace std; ShellCommandBase::ShellCommandBase(const char* commandName, const char* className, unsigned int paramCount, ...) { this->setClassID(CL_SHELL_COMMAND, "ShellCommand"); this->setName(commandName); this->description = NULL; // this->classID = classID; this->className = className; //ClassList::IDToString(classID); // handling parameters, and storing them: if (paramCount > FUNCTOR_MAX_ARGUMENTS) paramCount = FUNCTOR_MAX_ARGUMENTS; this->paramCount = paramCount; this->parameters = new unsigned int[paramCount]; va_list parameterList; va_start(parameterList, paramCount); for (unsigned int i = 0; i < paramCount; i++) { this->parameters[i] = va_arg(parameterList, int); switch (this->parameters[i]) { case ParameterBool: this->defaultBools[i] = va_arg(parameterList, int); break; case ParameterChar: this->defaultStrings[i] = new char[2]; sprintf(this->defaultStrings[0], "%c", va_arg(parameterList, int)); break; case ParameterString: this->defaultStrings[i] = va_arg(parameterList, char*); break; case ParameterInt: this->defaultInts[i] = va_arg(parameterList, int); break; case ParameterUInt: this->defaultInts[i] = va_arg(parameterList, unsigned int); break; case ParameterFloat: this->defaultFloats[i] = va_arg(parameterList, double); break; case ParameterLong: this->defaultInts[i] = va_arg(parameterList, long); break; default: break; } } // adding this ShellCommand to the list of known Commands ShellCommandBase::commandList->add(this); } ShellCommandBase::~ShellCommandBase() { delete[] this->parameters; } tList* ShellCommandBase::commandList = NULL; bool ShellCommandBase::isRegistered(const char* commandName, const char* className, unsigned int paramCount, ...) { va_list parameterList; va_start(parameterList, paramCount); if (ShellCommandBase::commandList == NULL) { ShellCommandBase::commandList = new tList; ShellCommand::registerCommand("debug", "ShellCommand", &ShellCommandBase::debugDyn); return false; } tIterator* iterator = ShellCommandBase::commandList->getIterator(); ShellCommandBase* elem = iterator->firstElement(); while(elem != NULL) { if (!strcmp(className, elem->className) && !strcmp(commandName, elem->getName())) { PRINTF(2)("Command already registered\n"); delete iterator; return true; } elem = iterator->nextElement(); } delete iterator; return false; } /** * executes commands * @param executionString the string containing the following input * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]] * @return true on success, false otherwise. */ bool ShellCommandBase::execute(const char* executionString) { if (ShellCommandBase::commandList == NULL) return false; tIterator* iterator = ShellCommandBase::commandList->getIterator(); ShellCommandBase* elem = iterator->firstElement(); while(elem != NULL) { printf("%s::%s\n", elem->className, elem->getName()); if (!strncasecmp (executionString, elem->className, strlen(elem->className)) && (*(executionString+strlen(elem->className)) == ' ' || *(executionString+strlen(elem->className)) == ':' )) { const char* commandBegin = executionString + strlen(elem->className); PRINTF(4)("Class %s matches\n", elem->className); BaseObject* objectPointer = NULL; if (ClassList::StringToID(elem->className) & CL_MASK_SINGLETON == CL_MASK_SINGLETON) { while(*commandBegin == ' ') commandBegin++; if (strncmp (commandBegin, elem->getName(), strlen(elem->getName())) || *(commandBegin + strlen(elem->getName())) != ' ' && *(commandBegin + strlen(elem->getName())) != '\0') { elem = iterator->nextElement(); continue; } PRINTF(4)("Command %s matches\n", elem->getName()); // getting singleton-reference tList* list = ClassList::getList(elem->className); if (list != NULL) objectPointer = list->firstElement(); } else { // checking for the Object while(*commandBegin == ' ') commandBegin++; tList* list = ClassList::getList(elem->className); if (list == NULL) break; tIterator* iterBO = list->getIterator(); BaseObject* enumBO = iterBO->firstElement(); while(enumBO != NULL) { if(!strncmp(commandBegin, enumBO->getName(), strlen(enumBO->getName()))) { PRINTF(4)("Object %s matches\n", enumBO->getName()); objectPointer = enumBO; break; } enumBO = iterBO->nextElement(); } delete iterBO; // break on no object Found. We cannot operate on Classes, but on Objects if (objectPointer == NULL) break; commandBegin = commandBegin + strlen(objectPointer->getName()); while(*commandBegin == ' ') commandBegin++; // checking for the requested function. if (strncmp (commandBegin, elem->getName(), strlen(elem->getName()))) { elem = iterator->nextElement(); continue; } PRINTF(4)("Function '%s' found\n", commandBegin); } const char* paramBegin = strchr(commandBegin, ' '); if (paramBegin == NULL) paramBegin = commandBegin + strlen(elem->getName()); while (*paramBegin == ' ') paramBegin++; PRINTF(3)("Parameters to Pass: %s\n", paramBegin); if (objectPointer != NULL && paramBegin != NULL) { elem->executeCommand(objectPointer, paramBegin); delete iterator; return true; } } elem = iterator->nextElement(); } delete iterator; return true; } ShellCommandBase* ShellCommandBase::describe(const char* description) { if (this == NULL) return NULL; this->description = description; return this; } void ShellCommandBase::debugDyn() { this->debug(); } void ShellCommandBase::debug() { if (ShellCommandBase::commandList == NULL) { PRINT(0)("No Command registered so far\n"); return; } tIterator* iterator = ShellCommandBase::commandList->getIterator(); ShellCommandBase* elem = iterator->firstElement(); while(elem != NULL) { PRINT(0)("Class %s registered command %s with %d parameters: ", elem->className, elem->getName(), elem->paramCount); for (unsigned int i = 0; i< elem->paramCount; i++) printf("%s ", ShellCommandBase::paramToString(elem->parameters[i])); if (elem->description != NULL) printf("- %s", elem->description); printf("\n"); elem = iterator->nextElement(); } delete iterator; } const char* ShellCommandBase::paramToString(long parameter) { switch (parameter) { case ParameterBool: return "BOOL"; break; case ParameterChar: return "CHAR"; break; case ParameterString: return "STRING"; break; case ParameterInt: return "INT"; break; case ParameterUInt: return "UINT"; break; case ParameterFloat: return "FLOAT"; break; case ParameterLong: return "LONG"; break; default: return "NULL"; break; } }