Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/lib/shell/shell_command.cc @ 7857

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

orxonox/trunk: added new Files shell_completion_plugin for the new Plugin Structure.
Also created the first namespace: OrxShell

File size: 11.5 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_SHELL
17
18#include "shell_command.h"
19#include "shell_command_class.h"
20
21#include "compiler.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
30namespace OrxShell
31{
32
33  /**
34   * constructs and registers a new Command
35   * @param commandName the name of the Command
36   * @param className the name of the class to apply this command to
37   * @param paramCount the count of parameters this command takes
38   */
39  ShellCommand::ShellCommand(const std::string& commandName, const std::string& className, const Executor& executor)
40  {
41    this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
42    PRINTF(5)("create shellcommand %s %s\n", commandName, className);
43    this->setName(commandName);
44    this->executor = executor.clone();
45    this->executor->setName(commandName);
46
47    //  this->classID = classID;
48    this->shellClass = ShellCommandClass::getCommandClass(className); //ClassList::IDToString(classID);
49    if (this->shellClass != NULL)
50      this->shellClass->commandList.push_back(this);
51  }
52
53  /**
54   * deconstructs a ShellCommand
55   */
56  ShellCommand::~ShellCommand()
57  {
58    if (this->alias != NULL && ShellCommandClass::aliasList != NULL)
59    {
60      ShellCommandClass::aliasList->remove(this->alias);
61      delete this->alias;
62    }
63    delete this->executor;
64  }
65
66  /**
67   * registers a new ShellCommand
68   */
69  ShellCommand* ShellCommand::registerCommand(const std::string& commandName, const std::string& className, const Executor& executor)
70  {
71    if (ShellCommand::isRegistered(commandName, className))
72      return NULL;
73    else
74      return new ShellCommand(commandName, className, executor);
75
76  }
77
78  /**
79   * unregister an existing commandName
80   * @param className the name of the Class the command belongs to.
81   * @param commandName the name of the command itself
82   */
83  void ShellCommand::unregisterCommand(const std::string& commandName, const std::string& className)
84  {
85    /// FIXME
86    /*  if (ShellCommandClass::commandClassList == NULL)
87        ShellCommandClass::initCommandClassList();
88
89     const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
90
91     if (checkClass != NULL)
92      {
93        std::list<ShellCommand*>::iterator elem;
94        for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
95        {
96          if (!strcmp(commandName, (*elem)->getName()))
97          {
98            delete (*elem);
99            checkClass->commandList.remove(*elem);
100            break;
101          }
102        }
103
104        if (checkClass->commandList->size() == 0)
105        {
106          ShellCommandClass::commandClassList->remove(checkClass);
107          delete checkClass;
108        }
109      }*/
110  }
111
112  /**
113   * checks if a command has already been registered.
114   * @param commandName the name of the Command
115   * @param className the name of the Class the command should apply to.
116   * @returns true, if the command is registered/false otherwise
117   *
118   * This is used internally, to see, if we have multiple command subscriptions.
119   * This is checked in the registerCommand-function.
120   */
121  bool ShellCommand::isRegistered(const std::string& commandName, const std::string& className)
122  {
123    if (ShellCommandClass::commandClassList == NULL)
124    {
125      ShellCommandClass::initCommandClassList();
126      return false;
127    }
128
129    const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
130    if (checkClass != NULL)
131    {
132      std::list<ShellCommand*>::const_iterator elem;
133      for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
134      {
135        if (commandName == (*elem)->getName())
136        {
137          PRINTF(2)("Command '%s::%s' already registered\n", className.c_str(), commandName.c_str());
138          return true;
139        }
140      }
141      return false;
142    }
143    else
144      return false;
145  }
146
147
148  /**
149   * executes commands
150   * @param executionString the string containing the following input
151   * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
152   * @return true on success, false otherwise.
153   */
154  bool ShellCommand::execute(const std::string& executionString)
155  {
156    if (ShellCommandClass::commandClassList == NULL)
157      return false;
158
159    long classID = CL_NULL;                      //< the classID retrieved from the Class.
160    ShellCommandClass* commandClass = NULL;      //< the command class this command applies to.
161    const std::list<BaseObject*>* objectList = NULL;   //< the list of Objects stored in classID
162    BaseObject* objectPointer = NULL;            //< a pointer to th Object to Execute the command on
163    bool emptyComplete = false;                  //< if the completion input is empty string. e.g ""
164    //  long completeType = SHELLC_NONE;           //< the Type we'd like to complete.
165    SubString inputSplits(executionString, SubString::WhiteSpacesWithComma);
166
167
168    // if we do not have any input return
169    if (inputSplits.empty())
170      return false;
171
172    // if we only have one input (!MUST BE AN ALIAS)
173    if (inputSplits.size() >= 1)
174    {
175      // CHECK FOR ALIAS
176      if (ShellCommandClass::aliasList != NULL)
177      {
178        std::list<ShellCommandAlias*>::iterator alias;
179        for (alias = ShellCommandClass::aliasList->begin(); alias != ShellCommandClass::aliasList->end(); alias++ )
180        {
181          if (inputSplits.getString(0) == (*alias)->getName() && (*alias)->getCommand() != NULL &&
182              (*alias)->getCommand()->shellClass != NULL )
183          {
184            objectList = ClassList::getList((*alias)->getCommand()->shellClass->getName());
185            if (objectList != NULL)
186            {
187              (*(*alias)->getCommand()->executor)(objectList->front(), inputSplits.getSubSet(1).join()); /// TODO CHECK IF OK
188              return true;
189            }
190            /// TODO CHECK FOR STATIC functions.
191          }
192        }
193      }
194
195      // looking for a Matching Class
196      if (likely(ShellCommandClass::commandClassList != NULL))
197      {
198        std::list<ShellCommandClass*>::iterator commandClassIT;
199        for (commandClassIT = ShellCommandClass::commandClassList->begin(); commandClassIT != ShellCommandClass::commandClassList->end(); commandClassIT++)
200        {
201          if ((*commandClassIT)->getName() && inputSplits[0] == (*commandClassIT)->getName())
202          {
203            //elemCL->getName();
204            classID = ClassList::StringToID((*commandClassIT)->getName());
205            commandClass = (*commandClassIT);
206            objectList = ClassList::getList((ClassID)classID);
207            break;
208          }
209        }
210      }
211
212      // Second Agument. (either Object, or Function)
213      if (commandClass != NULL && inputSplits.size() >= 2)
214      {
215        int fktPos = 1; // The position of the Function (either at pos 1, or 2)
216        // If we have an ObjectList.
217        if (objectList != NULL)
218        {
219          // Checking for a Match in the Objects of classID (else take the first)
220          std::list<BaseObject*>::const_iterator object;
221          for (object = objectList->begin(); object != objectList->end(); object++)
222          {
223            if ((*object)->getName() != NULL && inputSplits[1] == (*object)->getName())
224            {
225              objectPointer = (*object);
226              fktPos = 2;
227              break;
228            }
229          }
230
231          // if we did not find an Object with matching name, take the first.
232          if (objectPointer == NULL)
233            objectPointer = objectList->front();
234        }
235
236        // match a function.
237        if (commandClass != NULL && (fktPos == 1 || (fktPos == 2 && inputSplits.size() >= 3)))
238        {
239          std::list<ShellCommand*>::iterator cmdIT;
240          for (cmdIT = commandClass->commandList.begin(); cmdIT != commandClass->commandList.end(); cmdIT++)
241          {
242            if (inputSplits[fktPos] == (*cmdIT)->getName())
243            {
244              if (objectPointer == NULL && (*cmdIT)->executor->getType() & Executor_Objective)
245                return false;
246              else
247              {
248                (*(*cmdIT)->executor)(objectPointer, inputSplits.getSubSet(fktPos+1).join()); /// TODO CHECK IF OK
249                return true;
250              }
251            }
252          }
253        }
254      }
255    }
256    return false;
257  }
258
259  /**
260   * lets a command be described
261   * @param description the description of the Given command
262   */
263  ShellCommand* ShellCommand::describe(const std::string& description)
264  {
265    if (this == NULL)
266      return NULL;
267    else
268    {
269      this->description = description;
270      return this;
271    }
272  }
273
274  /**
275   * adds an Alias to this Command
276   * @param alias the name of the Alias to set
277   * @returns itself
278   */
279  ShellCommand* ShellCommand::setAlias(const std::string& alias)
280  {
281    if (this == NULL)
282      return NULL;
283
284    if (this->alias != NULL)
285    {
286      PRINTF(2)("not more than one Alias allowed for functions (%s::%s)\n", this->getName(), this->shellClass->getName());
287    }
288    else
289    {
290      if (ShellCommandClass::aliasList == NULL)
291        ShellCommandClass::aliasList = new std::list<ShellCommandAlias*>;
292
293      ShellCommandAlias* aliasCMD = new ShellCommandAlias(alias, this);
294      ShellCommandClass::aliasList->push_back(aliasCMD);
295      this->alias = aliasCMD;
296    }
297    return this;
298  }
299
300  /**
301   * @brief set the default values of the executor
302   * @param value0 the first default value
303   * @param value1 the second default value
304   * @param value2 the third default value
305   * @param value3 the fourth default value
306   * @param value4 the fifth default value
307   */
308  ShellCommand* ShellCommand::defaultValues(const MultiType& value0, const MultiType& value1,
309      const MultiType& value2, const MultiType& value3,
310      const MultiType& value4)
311  {
312    if (this == NULL || this->executor == NULL)
313      return NULL;
314
315    this->executor->defaultValues(value0, value1, value2, value3, value4);
316
317    return this;
318  }
319
320  /**
321   * prints out nice information about the Shells Commands
322   */
323  void ShellCommand::debug()
324  {
325    if (ShellCommandClass::commandClassList == NULL)
326    {
327      PRINT(0)("No Command registered.\n");
328      return;
329    }
330
331    std::list<ShellCommandClass*>::iterator classIT;
332    for (classIT = ShellCommandClass::commandClassList->begin(); classIT != ShellCommandClass::commandClassList->end(); classIT++)
333    {
334      PRINT(0)("Class:'%s' registered %d commands: \n", (*classIT)->className.c_str(), (*classIT)->commandList.size());
335
336      std::list<ShellCommand*>::iterator cmdIT;
337      for (cmdIT = (*classIT)->commandList.begin(); cmdIT != (*classIT)->commandList.end(); cmdIT++)
338      {
339        PRINT(0)("  command:'%s' : params:%d: ", (*cmdIT)->getName(), (*cmdIT)->executor->getParamCount());
340        /// FIXME
341        /*      for (unsigned int i = 0; i< elem->paramCount; i++)
342         printf("%s ", ShellCommand::paramToString(elem->parameters[i]));*/
343        if (!(*cmdIT)->description.empty())
344          printf("- %s", (*cmdIT)->description.c_str());
345        printf("\n");
346
347      }
348    }
349  }
350
351  /**
352   * converts a Parameter to a String
353   * @param parameter the Parameter we have.
354   * @returns the Name of the Parameter at Hand
355   */
356  const char* ShellCommand::paramToString(long parameter)
357  {
358    return MultiType::MultiTypeToString((MT_Type)parameter);
359  }
360
361}
Note: See TracBrowser for help on using the repository browser.