Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: default Values work, and small fix with unused ShellCommand_Type

File size: 12.0 KB
Line 
1/*
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.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "shell_command.h"
19#include "shell_command_class.h"
20
21#include "list.h"
22#include "debug.h"
23#include "class_list.h"
24
25#include "key_names.h"
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29
30using namespace std;
31
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 */
38ShellCommand::ShellCommand(const char* commandName, const char* className, Executor* executor)
39{
40  this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
41  this->setName(commandName);
42  this->description = NULL;
43  this->alias = NULL;
44
45//  this->classID = classID;
46  this->shellClass = ShellCommandClass::getCommandClass(className); //ClassList::IDToString(classID);
47  if (this->shellClass != NULL)
48    this->shellClass->commandList->add(this);
49  // handling parameters, and storing them:
50  if (paramCount > FUNCTOR_MAX_ARGUMENTS)
51    paramCount = FUNCTOR_MAX_ARGUMENTS;
52  this->paramCount = paramCount;
53  this->parameters = new unsigned int[paramCount];
54  this->defaultValue = new MultiType[paramCount];
55
56  this->executor = executor;
57}
58
59/**
60 * deconstructs a ShellCommand
61 */
62ShellCommand::~ShellCommand()
63{
64  delete[] this->parameters;
65  delete[] this->defaultValue;
66  if (this->alias != NULL && ShellCommandClass::aliasList != NULL)
67  {
68    ShellCommandClass::aliasList->remove(this->alias);
69    delete this->alias;
70  }
71}
72
73/**
74 * registers a new ShellCommand
75 */
76ShellCommand* ShellCommand::registerCommand(const char* commandName, const char* className, Executor* executor)
77{
78  if (ShellCommand::isRegistered(commandName, className, executor))
79    return NULL;
80  else
81    return new ShellCommand(commandName, className, executor);
82
83}
84
85
86
87
88/**
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 */
93void ShellCommand::unregisterCommand(const char* commandName, const char* className)
94{
95  if (ShellCommandClass::commandClassList == NULL)
96    ShellCommandClass::initCommandClassList();
97
98 const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
99
100 if (checkClass != NULL)
101  {
102    tIterator<ShellCommand>* iterator = checkClass->commandList->getIterator();
103    ShellCommand* elem = iterator->firstElement();
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  }
122}
123
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 */
134bool ShellCommand::isRegistered(const char* commandName, const char* className, Executor* executor)
135{
136  if (ShellCommandClass::commandClassList == NULL)
137  {
138    ShellCommandClass::initCommandClassList();
139    return false;
140  }
141
142  const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
143  if (checkClass != NULL)
144  {
145    tIterator<ShellCommand>* iterator = checkClass->commandList->getIterator();
146    ShellCommand* elem = iterator->firstElement();
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;
159  }
160  else
161    return false;
162}
163
164
165/**
166 * executes commands
167 * @param executionString the string containing the following input
168 * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
169 * @return true on success, false otherwise.
170 */
171bool ShellCommand::execute(const char* executionString)
172{
173  if (ShellCommandClass::commandClassList == NULL)
174    return false;
175
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.
183  SubString inputSplits(executionString, true);
184
185  if (inputSplits.getCount() == 0)
186    return false;
187  if (inputSplits.getCount() >= 1)
188  {
189    // CHECK FOR ALIAS
190    if (ShellCommandClass::aliasList != NULL)
191    {
192      tIterator<ShellCommandAlias>* itAL = ShellCommandClass::aliasList->getIterator();
193      ShellCommandAlias* elemAL = itAL->firstElement();
194      while(elemAL != NULL)
195      {
196        if (elemAL->getName() != NULL && !strcmp(elemAL->getName(), inputSplits.getString(0)) && elemAL->getCommand() != NULL &&
197            elemAL->getCommand()->shellClass != NULL )
198        {
199          objectList = ClassList::getList(elemAL->getCommand()->shellClass->getName());
200          if (objectList != NULL)
201          {
202            if (inputSplits.getCount() > 1)
203              elemAL->getCommand()->executor->execute(objectList->firstElement(), executionString+inputSplits.getOffset(1));
204            else
205              elemAL->getCommand()->executor->execute(objectList->firstElement(), "");
206            delete itAL;
207            return true;
208          }
209        }
210        elemAL = itAL->nextElement();
211      }
212      delete itAL;
213    }
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    }
233
234    if (commandClass != NULL && inputSplits.getCount() >= 2)
235    {
236      if (objectList != NULL)
237      {
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)
242        {
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;
252
253      //
254        if (objectPointer == NULL)
255          objectPointer = objectList->firstElement();
256      }
257      // match a function.
258      if (commandClass != NULL && (fktPos == 1 || (fktPos == 2 && inputSplits.getCount() >= 3)))
259      {
260        tIterator<ShellCommand>* itCMD = commandClass->commandList->getIterator();
261        ShellCommand* enumCMD = itCMD->firstElement();
262        while (enumCMD != NULL)
263        {
264          if (!strcmp(enumCMD->getName(), inputSplits.getString(fktPos)))
265          {
266            if (objectPointer == NULL && enumCMD->executor->getType() == Executor_Objective)
267            {
268              delete itCMD;
269              return false;
270            }
271            if (inputSplits.getCount() > fktPos+1)
272              enumCMD->executor->execute(objectPointer, executionString+inputSplits.getOffset(fktPos +1));
273            else
274              enumCMD->executor->execute(objectPointer, "");
275            delete itCMD;
276            return true;
277          }
278
279          enumCMD = itCMD->nextElement();
280        }
281        delete itCMD;
282      }
283    }
284  }
285}
286
287/**
288 * lets a command be described
289 * @param description the description of the Given command
290 */
291ShellCommand* ShellCommand::describe(const char* description)
292{
293  if (this == NULL)
294    return NULL;
295 else
296 {
297   this->description = description;
298   return this;
299 }
300}
301
302/**
303 * adds an Alias to this Command
304 * @param alias the name of the Alias to set
305 * @returns itself
306 */
307ShellCommand* ShellCommand::setAlias(const char* alias)
308{
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;
326}
327
328/**
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 */
337ShellCommand* ShellCommand::defaultValues(unsigned int count, ...)
338{
339  if (this == NULL)
340    return NULL;
341
342  va_list values;
343  va_start(values, count);
344
345  this->executor->defaultValues(count, values);
346
347  return this;
348}
349
350/**
351 * prints out nice information about the Shells Commands
352 */
353void ShellCommand::debug()
354{
355  if (ShellCommandClass::commandClassList == NULL)
356  {
357    PRINT(0)("No Command registered.\n");
358    return;
359  }
360
361  tIterator<ShellCommandClass>* iteratorCL = ShellCommandClass::commandClassList->getIterator();
362  ShellCommandClass* elemCL = iteratorCL->firstElement();
363  while(elemCL != NULL)
364  {
365    PRINT(0)("Class:'%s' registered %d commands: \n", elemCL->className, elemCL->commandList->getSize());
366    tIterator<ShellCommand>* iterator = elemCL->commandList->getIterator();
367    const ShellCommand* elem = iterator->firstElement();
368    while(elem != NULL)
369    {
370      PRINT(0)("  command:'%s' : params:%d: ", elem->getName(), elem->paramCount);
371      for (unsigned int i = 0; i< elem->paramCount; i++)
372       printf("%s ", ShellCommand::paramToString(elem->parameters[i]));
373      if (elem->description != NULL)
374       printf("- %s", elem->description);
375      printf("\n");
376
377      elem = iterator->nextElement();
378    }
379    delete iterator;
380    elemCL = iteratorCL->nextElement();
381  }
382  delete iteratorCL;
383}
384
385/**
386 * converts a Parameter to a String
387 * @param parameter the Parameter we have.
388 * @returns the Name of the Parameter at Hand
389 */
390const char* ShellCommand::paramToString(long parameter)
391{
392  return MultiType::MultiTypeToString((MT_Type)parameter);
393// FIXME
394  /*  switch (parameter)
395  {
396    case ParameterBool:
397      return "BOOL";
398      break;
399    case ParameterChar:
400      return "CHAR";
401      break;
402    case ParameterString:
403      return "STRING";
404      break;
405    case ParameterInt:
406      return "INT";
407      break;
408    case ParameterUInt:
409      return "UINT";
410      break;
411    case ParameterFloat:
412      return "FLOAT";
413      break;
414    case ParameterLong:
415      return "LONG";
416      break;
417    default:
418      return "NULL";
419      break;
420  }*/
421}
Note: See TracBrowser for help on using the repository browser.