/* 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, ClassID classID, unsigned int paramCount, ...) { this->setClassID(CL_SHELL_COMMAND, "ShellCommand"); this->setName(commandName); va_list parameters; va_start(parameters, paramCount); this->classID = classID; this->className = ClassList::IDToString(classID); if (classID & CL_MASK_SINGLETON == CL_MASK_SINGLETON) this->isSingleton = true; else this->isSingleton = false; // handling parameters, and storing them: if (paramCount > FUNCTOR_MAX_ARGUMENTS) paramCount = FUNCTOR_MAX_ARGUMENTS; this->paramCount = paramCount; this->parameters = new long[paramCount]; for (unsigned int i = 0; i < paramCount; i++) { this->parameters[i] = va_arg(parameters, long); switch (this->parameters[i]) { case ParameterBool: this->defaultBools[i] = va_arg(parameters, int); break; case ParameterChar: this->defaultStrings[i] = new char[2]; sprintf(this->defaultStrings[0], "%c", va_arg(parameters, int)); break; case ParameterString: this->defaultStrings[i] = va_arg(parameters, char*); break; case ParameterInt: this->defaultInts[i] = va_arg(parameters, int); break; case ParameterUInt: this->defaultInts[i] = va_arg(parameters, unsigned int); break; case ParameterFloat: this->defaultFloats[i] = va_arg(parameters, double); break; case ParameterLong: this->defaultInts[i] = va_arg(parameters, 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, ClassID classID, unsigned int paramCount, ...) { va_list parameters; va_start(parameters, paramCount); if (ShellCommandBase::commandList == NULL) { ShellCommandBase::commandList = new tList; return false; } tIterator* iterator = ShellCommandBase::commandList->getIterator(); ShellCommandBase* elem = iterator->firstElement(); while(elem != NULL) { if (classID == elem->classID && !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 * [] [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\n", 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 (elem->isSingleton) { while(*commandBegin == ' ') commandBegin++; if (strncmp (commandBegin, elem->getName(), strlen(elem->getName()))) { elem = iterator->nextElement(); continue; } // getting singleton-reference tList* list = ClassList::getList(elem->classID); if (list) objectPointer = list->firstElement(); } else { // checking for the Object while(*commandBegin == ' ') commandBegin++; tList* list = ClassList::getList(elem->classID); 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(5)("Function '%s' found\n", commandBegin); } const char* paramBegin = strchr(commandBegin, ' '); if (paramBegin == NULL) paramBegin = commandBegin + strlen(elem->getName()); while (*paramBegin == ' ') paramBegin++; if (objectPointer != NULL && paramBegin != NULL) { elem->executeCommand(objectPointer, paramBegin); delete iterator; return true; } } elem = iterator->nextElement(); } delete iterator; return true; }