Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_command.cc @ 5639

Last change on this file since 5639 was 5639, checked in by bensch, 19 years ago

orxonox/trunk: splitted shell_command into shell_command and shell_command_class

File size: 12.9 KB
RevLine 
[4744]1/*
[1853]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
[1855]10
11   ### File Specific:
[5068]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[3955]16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
[1853]17
[5129]18#include "shell_command.h"
[5639]19#include "shell_command_class.h"
[1853]20
[5072]21#include "list.h"
[5129]22#include "debug.h"
[5113]23#include "class_list.h"
24
25#include "key_names.h"
[5075]26#include <stdarg.h>
27#include <stdio.h>
[5174]28#include <string.h>
[5075]29
[1856]30using namespace std;
[1853]31
[5166]32/**
33 * constructs and registers a new Command
34 * @param commandName the name of the Command
35 * @param className the name of the class to apply this command to
36 * @param paramCount the count of parameters this command takes
37 */
[5637]38ShellCommand::ShellCommand(const char* commandName, const char* className, Executor* executor)
[3365]39{
[5141]40  this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
41  this->setName(commandName);
[5164]42  this->description = NULL;
[5196]43  this->alias = NULL;
[5141]44
[5161]45//  this->classID = classID;
[5198]46  this->shellClass = ShellCommandClass::getCommandClass(className); //ClassList::IDToString(classID);
47  if (this->shellClass != NULL)
48    this->shellClass->commandList->add(this);
[5130]49  // handling parameters, and storing them:
[5142]50  if (paramCount > FUNCTOR_MAX_ARGUMENTS)
51    paramCount = FUNCTOR_MAX_ARGUMENTS;
[5130]52  this->paramCount = paramCount;
[5148]53  this->parameters = new unsigned int[paramCount];
[5552]54  this->defaultValue = new MultiType[paramCount];
[5130]55
[5637]56  this->executor = executor;
[5068]57}
[4320]58
[5166]59/**
60 * deconstructs a ShellCommand
61 */
[5636]62ShellCommand::~ShellCommand()
[5130]63{
64  delete[] this->parameters;
[5552]65  delete[] this->defaultValue;
[5196]66  if (this->alias != NULL && ShellCommandClass::aliasList != NULL)
67  {
68    ShellCommandClass::aliasList->remove(this->alias);
69    delete this->alias;
70  }
[5130]71}
[1853]72
[5166]73/**
[5636]74 * registers a new ShellCommand
75 */
76ShellCommand* ShellCommand::registerCommand(const char* commandName, const char* className, Executor* executor)
77{
[5637]78  if (ShellCommand::isRegistered(commandName, className, executor))
79    return NULL;
80  else
81    return new ShellCommand(commandName, className, executor);
[5636]82
83}
84
85
86
87
88/**
[5166]89 * unregister an existing commandName
90 * @param className the name of the Class the command belongs to.
91 * @param commandName the name of the command itself
92 */
[5636]93void ShellCommand::unregisterCommand(const char* commandName, const char* className)
[5165]94{
[5171]95  if (ShellCommandClass::commandClassList == NULL)
96    ShellCommandClass::initCommandClassList();
97
[5172]98 const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
[5171]99
[5172]100 if (checkClass != NULL)
[5171]101  {
[5636]102    tIterator<ShellCommand>* iterator = checkClass->commandList->getIterator();
103    ShellCommand* elem = iterator->firstElement();
[5171]104    while(elem != NULL)
105    {
106      if (!strcmp(commandName, elem->getName()))
107      {
108        checkClass->commandList->remove(elem);
109        delete elem;
110        break;
111      }
112      elem = iterator->nextElement();
113    }
114    delete iterator;
115
116    if (checkClass->commandList->getSize() == 0)
117    {
118      ShellCommandClass::commandClassList->remove(checkClass);
119      delete checkClass;
120    }
121  }
[5165]122}
123
[5166]124/**
125 * checks if a command has already been registered.
126 * @param commandName the name of the Command
127 * @param className the name of the Class the command should apply to.
128 * @param paramCount how many arguments the Command takes
129 * @returns true, if the command is registered/false otherwise
130 *
131 * This is used internally, to see, if we have multiple command subscriptions.
132 * This is checked in the registerCommand-function.
133 */
[5637]134bool ShellCommand::isRegistered(const char* commandName, const char* className, Executor* executor)
[5113]135{
[5170]136  if (ShellCommandClass::commandClassList == NULL)
[5072]137  {
[5170]138    ShellCommandClass::initCommandClassList();
[5113]139    return false;
140  }
[5105]141
[5170]142  const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
143  if (checkClass != NULL)
[5113]144  {
[5636]145    tIterator<ShellCommand>* iterator = checkClass->commandList->getIterator();
146    ShellCommand* elem = iterator->firstElement();
[5170]147    while(elem != NULL)
148   {
149     if (!strcmp(commandName, elem->getName()))
150     {
151       PRINTF(2)("Command already registered\n");
152       delete iterator;
153       return true;
154      }
155     elem = iterator->nextElement();
156   }
157   delete iterator;
158   return false;
[5113]159  }
[5170]160  else
161    return false;
[5113]162}
163
[5140]164
[5145]165/**
166 * executes commands
167 * @param executionString the string containing the following input
[5148]168 * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
[5145]169 * @return true on success, false otherwise.
170 */
[5636]171bool ShellCommand::execute(const char* executionString)
[5135]172{
[5198]173  if (ShellCommandClass::commandClassList == NULL)
174    return false;
175
[5203]176  long classID = CL_NULL;                 //< the classID retrieved from the Class.
177  ShellCommandClass* commandClass = NULL; //< the command class this command applies to.
178  tList<BaseObject>* objectList = NULL;   //< the list of Objects stored in classID
179  BaseObject* objectPointer = NULL;       //< a pointer to th Object to Execute the command on
180  bool emptyComplete = false;             //< if the completion input is empty string. e.g ""
181  unsigned int fktPos = 1;                //< the position of the function (needed for finding it)
182//  long completeType = SHELLC_NONE;      //< the Type we'd like to complete.
[5198]183  SubString inputSplits(executionString, true);
184
185  if (inputSplits.getCount() == 0)
186    return false;
187  if (inputSplits.getCount() >= 1)
188  {
[5200]189    // CHECK FOR ALIAS
[5198]190    if (ShellCommandClass::aliasList != NULL)
191    {
192      tIterator<ShellCommandAlias>* itAL = ShellCommandClass::aliasList->getIterator();
193      ShellCommandAlias* elemAL = itAL->firstElement();
194      while(elemAL != NULL)
195      {
[5199]196        if (elemAL->getName() != NULL && !strcmp(elemAL->getName(), inputSplits.getString(0)) && elemAL->getCommand() != NULL &&
197            elemAL->getCommand()->shellClass != NULL )
[5198]198        {
[5199]199          objectList = ClassList::getList(elemAL->getCommand()->shellClass->getName());
200          if (objectList != NULL)
201          {
[5204]202            if (inputSplits.getCount() > 1)
[5637]203              elemAL->getCommand()->executor->execute(objectList->firstElement(), executionString+inputSplits.getOffset(1));
[5204]204            else
[5637]205              elemAL->getCommand()->executor->execute(objectList->firstElement(), "");
[5200]206            delete itAL;
[5199]207            return true;
208          }
[5198]209        }
210        elemAL = itAL->nextElement();
211      }
212      delete itAL;
213    }
[5203]214    // looking for a Matching Class
215    if (likely(ShellCommandClass::commandClassList != NULL))
216    {
217      tIterator<ShellCommandClass>* itCL = ShellCommandClass::commandClassList->getIterator();
218      ShellCommandClass* elemCL = itCL->firstElement();
219      while(elemCL != NULL)
220      {
221        if (elemCL->getName() && !strcasecmp(inputSplits.getString(0), elemCL->getName()))
222        {
223          //elemCL->getName();
224          classID = ClassList::StringToID(elemCL->getName());
225          commandClass = elemCL;
226          objectList = ClassList::getList(classID);
227          break;
228        }
229        elemCL = itCL->nextElement();
230      }
231      delete itCL;
232    }
[5200]233
[5329]234    if (commandClass != NULL && inputSplits.getCount() >= 2)
[5203]235    {
[5329]236      if (objectList != NULL)
[5203]237      {
[5329]238        // Checking for a Match in the Objects of classID (else take the first)
239        tIterator<BaseObject>* itBO = objectList->getIterator();
240        BaseObject* enumBO = itBO->firstElement();
241        while(enumBO)
[5203]242        {
[5329]243          if (enumBO->getName() != NULL && !strcasecmp(enumBO->getName(), inputSplits.getString(1)))
244          {
245            objectPointer = enumBO;
246            fktPos = 2;
247            break;
248          }
249          enumBO = itBO->nextElement();
250         }
251         delete itBO;
[5203]252
253      //
[5329]254        if (objectPointer == NULL)
255          objectPointer = objectList->firstElement();
256      }
[5203]257      // match a function.
[5329]258      if (commandClass != NULL && (fktPos == 1 || (fktPos == 2 && inputSplits.getCount() >= 3)))
[5203]259      {
[5636]260        tIterator<ShellCommand>* itCMD = commandClass->commandList->getIterator();
261        ShellCommand* enumCMD = itCMD->firstElement();
[5203]262        while (enumCMD != NULL)
263        {
264          if (!strcmp(enumCMD->getName(), inputSplits.getString(fktPos)))
265          {
[5329]266            if (objectPointer == NULL && enumCMD->functorType == ShellCommand_Objective)
267            {
268              delete itCMD;
269              return false;
270            }
[5203]271            if (inputSplits.getCount() > fktPos+1)
[5637]272              enumCMD->executor->execute(objectPointer, executionString+inputSplits.getOffset(fktPos +1));
[5203]273            else
[5637]274              enumCMD->executor->execute(objectPointer, "");
[5203]275            delete itCMD;
276            return true;
277          }
278
279          enumCMD = itCMD->nextElement();
280        }
281        delete itCMD;
282      }
283    }
[5198]284  }
[5135]285}
[5148]286
[5166]287/**
288 * lets a command be described
289 * @param description the description of the Given command
290 */
[5636]291ShellCommand* ShellCommand::describe(const char* description)
[5164]292{
293  if (this == NULL)
294    return NULL;
[5165]295 else
296 {
297   this->description = description;
298   return this;
299 }
[5164]300}
301
[5197]302/**
303 * adds an Alias to this Command
304 * @param alias the name of the Alias to set
305 * @returns itself
306 */
[5636]307ShellCommand* ShellCommand::setAlias(const char* alias)
[5195]308{
[5196]309  if (this == NULL)
310    return NULL;
311
312  if (this->alias != NULL)
313  {
314    PRINTF(2)("not more than one Alias allowed for functions (%s::%s)\n", this->getName(), this->shellClass->getName());
315  }
316  else
317  {
318    if (ShellCommandClass::aliasList == NULL)
319      ShellCommandClass::aliasList = new tList<ShellCommandAlias>;
320
321    ShellCommandAlias* aliasCMD = new ShellCommandAlias(alias, this);
322    ShellCommandClass::aliasList->add(aliasCMD);
323    this->alias = aliasCMD;
324  }
325  return this;
[5195]326}
327
[5166]328/**
[5207]329 * sets default Values of the Commands
330 * @param count how many default Values to set.
331 * @param ... the default Values in order. They will be cast to the right type
332 * @returns itself
333 *
334 * Be aware, that when you use this Function, you !!MUST!! match the input as
335 * count, [EXACTLY THE SAME AS IF YOU WOULD CALL THE FUNCTION UP TO count ARGUMENTS]
336 */
[5636]337ShellCommand* ShellCommand::defaultValues(unsigned int count, ...)
[5207]338{
339  if (this == NULL)
340    return NULL;
341  if (count == 0)
342    return this;
343  if (count > this->paramCount)
344    count = this->paramCount;
345
346  va_list defaultList;
347  va_start(defaultList, count);
348
349  for (unsigned int i = 0; i < count; i++)
350  {
[5552]351
352
[5207]353    switch (this->parameters[i])
354    {
[5634]355      case MT_BOOL:
[5552]356        this->defaultValue[i].setInt(va_arg(defaultList, int));
[5207]357        break;
[5634]358      case MT_CHAR:
[5552]359        this->defaultValue[i].setChar((char)va_arg(defaultList, int));
[5207]360        break;
[5634]361      case MT_STRING:
[5552]362        this->defaultValue[i].setString(va_arg(defaultList, char*));
[5207]363        break;
[5634]364      case MT_INT:
[5552]365        this->defaultValue[i].setInt(va_arg(defaultList, int));
[5207]366        break;
[5634]367/*      case MT_UINT:
[5552]368        this->defaultValue[i].setInt((int)va_arg(defaultList, unsigned int));
[5634]369        break;*/
370      case MT_FLOAT:
[5552]371        this->defaultValue[i].setFloat(va_arg(defaultList, double));
[5207]372        break;
[5634]373/*      case MT_LONG:
[5552]374        this->defaultValue[i].setInt((int) va_arg(defaultList, long));
[5634]375        break;*/
[5207]376      default:
377        break;
378    }
379  }
380  return this;
381}
382
383/**
[5166]384 * prints out nice information about the Shells Commands
385 */
[5636]386void ShellCommand::debug()
[5148]387{
[5170]388  if (ShellCommandClass::commandClassList == NULL)
[5148]389  {
[5171]390    PRINT(0)("No Command registered.\n");
[5148]391    return;
392  }
393
[5170]394  tIterator<ShellCommandClass>* iteratorCL = ShellCommandClass::commandClassList->getIterator();
395  ShellCommandClass* elemCL = iteratorCL->firstElement();
396  while(elemCL != NULL)
[5148]397  {
[5171]398    PRINT(0)("Class:'%s' registered %d commands: \n", elemCL->className, elemCL->commandList->getSize());
[5636]399    tIterator<ShellCommand>* iterator = elemCL->commandList->getIterator();
400    const ShellCommand* elem = iterator->firstElement();
[5172]401    while(elem != NULL)
[5170]402    {
[5171]403      PRINT(0)("  command:'%s' : params:%d: ", elem->getName(), elem->paramCount);
[5170]404      for (unsigned int i = 0; i< elem->paramCount; i++)
[5636]405       printf("%s ", ShellCommand::paramToString(elem->parameters[i]));
[5170]406      if (elem->description != NULL)
407       printf("- %s", elem->description);
408      printf("\n");
[5148]409
[5170]410      elem = iterator->nextElement();
411    }
412    delete iterator;
413    elemCL = iteratorCL->nextElement();
[5148]414  }
[5170]415  delete iteratorCL;
[5148]416}
417
[5166]418/**
419 * converts a Parameter to a String
420 * @param parameter the Parameter we have.
421 * @returns the Name of the Parameter at Hand
422 */
[5636]423const char* ShellCommand::paramToString(long parameter)
[5148]424{
[5634]425  return MultiType::MultiTypeToString((MT_Type)parameter);
426// FIXME
427  /*  switch (parameter)
[5148]428  {
429    case ParameterBool:
430      return "BOOL";
431      break;
432    case ParameterChar:
433      return "CHAR";
434      break;
435    case ParameterString:
436      return "STRING";
437      break;
438    case ParameterInt:
439      return "INT";
440      break;
441    case ParameterUInt:
442      return "UINT";
443      break;
444    case ParameterFloat:
445      return "FLOAT";
446      break;
447    case ParameterLong:
448      return "LONG";
449      break;
450    default:
451      return "NULL";
452      break;
[5634]453  }*/
[5148]454}
Note: See TracBrowser for help on using the repository browser.