Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor bug-fix

File size: 13.2 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
20#include "list.h"
21#include "debug.h"
22#include "class_list.h"
23
24#include "key_names.h"
25#include <stdarg.h>
26#include <stdio.h>
27
28using namespace std;
29
30/**
31 * creates a new ShellCommandClass
32 * @param className the Name of the command-class to create
33 */
34ShellCommandClass::ShellCommandClass(const char* className)
35{
36  this->className = className;
37  this->classID = CL_NULL;
38  this->commandList = new tList<ShellCommandBase>;
39
40  ShellCommandClass::commandClassList->add(this);
41}
42
43/**
44 * destructs the shellCommandClass again
45 */
46ShellCommandClass::~ShellCommandClass()
47{
48  tIterator<ShellCommandBase>* iterator = this->commandList->getIterator();
49  ShellCommandBase* elem = iterator->firstElement();
50  while(elem != NULL)
51  {
52    delete elem;
53    elem = iterator->nextElement();
54  }
55  delete iterator;
56  delete this->commandList;
57}
58
59/**
60 * unregisters all Commands that exist
61 */
62void ShellCommandClass::unregisterAllCommands()
63{
64  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
65  ShellCommandClass* elem = iterator->firstElement();
66  while(elem != NULL)
67  {
68    delete elem;
69
70    elem = iterator->nextElement();
71  }
72  delete iterator;
73
74  delete ShellCommandClass::commandClassList;
75  ShellCommandClass::commandClassList = NULL;
76}
77
78const ShellCommandClass* ShellCommandClass::isRegistered(const char* className)
79{
80  if (ShellCommandClass::commandClassList == NULL)
81    initCommandClassList();
82
83  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
84  ShellCommandClass* elem = iterator->firstElement();
85  while(elem != NULL)
86  {
87    if (!strcmp(className, elem->className))
88    {
89      if (elem->classID == CL_NULL)
90        elem->classID = ClassList::StringToID(className);
91
92      delete iterator;
93      return elem;
94    }
95    elem = iterator->nextElement();
96  }
97  delete iterator;
98  return NULL;
99}
100
101/**
102 * searches for a CommandClass
103 * @param className the name of the CommandClass
104 * @returns the CommandClass if found, or a new CommandClass if not
105 */
106ShellCommandClass* ShellCommandClass::getCommandClass(const char* className)
107{
108  if (ShellCommandClass::commandClassList == NULL)
109    initCommandClassList();
110
111  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
112  ShellCommandClass* elem = iterator->firstElement();
113  while(elem != NULL)
114  {
115    if (!strcmp(className, elem->className))
116    {
117      delete iterator;
118      return elem;
119    }
120    elem = iterator->nextElement();
121  }
122  delete iterator;
123  return new ShellCommandClass(className);
124}
125
126/**
127 * initializes the CommandList (if it is NULL)
128 */
129void ShellCommandClass::initCommandClassList()
130{
131  if (ShellCommandClass::commandClassList == NULL)
132  {
133    ShellCommandClass::commandClassList = new tList<ShellCommandClass>;
134    ShellCommand<ShellCommandBase>::registerCommand("debug", "ShellCommand", &ShellCommandBase::debugDyn);
135  }
136}
137
138tList<ShellCommandClass>* ShellCommandClass::commandClassList = NULL;
139
140/**
141 * constructs and registers a new Command
142 * @param commandName the name of the Command
143 * @param className the name of the class to apply this command to
144 * @param paramCount the count of parameters this command takes
145 * @return self
146 */
147ShellCommandBase::ShellCommandBase(const char* commandName, const char* className, unsigned int paramCount, ...)
148{
149  this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
150  this->setName(commandName);
151  this->description = NULL;
152
153//  this->classID = classID;
154  ShellCommandClass::getCommandClass(className)->commandList->add(this); //ClassList::IDToString(classID);
155
156  // handling parameters, and storing them:
157  if (paramCount > FUNCTOR_MAX_ARGUMENTS)
158    paramCount = FUNCTOR_MAX_ARGUMENTS;
159  this->paramCount = paramCount;
160  this->parameters = new unsigned int[paramCount];
161
162  va_list parameterList;
163  va_start(parameterList, paramCount);
164
165  for (unsigned int i = 0; i < paramCount; i++)
166  {
167    this->parameters[i] = va_arg(parameterList, int);
168
169    switch (this->parameters[i])
170    {
171      case ParameterBool:
172        this->defaultBools[i] = va_arg(parameterList, int);
173        break;
174      case ParameterChar:
175        this->defaultStrings[i] = new char[2];
176        sprintf(this->defaultStrings[0], "%c",  va_arg(parameterList, int));
177        break;
178      case ParameterString:
179        this->defaultStrings[i] = va_arg(parameterList, char*);
180        break;
181      case ParameterInt:
182        this->defaultInts[i] = va_arg(parameterList, int);
183        break;
184      case ParameterUInt:
185        this->defaultInts[i] = va_arg(parameterList, unsigned int);
186        break;
187      case ParameterFloat:
188        this->defaultFloats[i] = va_arg(parameterList, double);
189        break;
190      case ParameterLong:
191        this->defaultInts[i] = va_arg(parameterList, long);
192        break;
193      default:
194        break;
195    }
196  }
197}
198
199/**
200 * deconstructs a ShellCommand
201 * @return
202 */
203ShellCommandBase::~ShellCommandBase()
204{
205  delete[] this->parameters;
206}
207
208/**
209 * unregister an existing commandName
210 * @param className the name of the Class the command belongs to.
211 * @param commandName the name of the command itself
212 *
213 * @todo implement
214 */
215void ShellCommandBase::unregisterCommand(const char* commandName, const char* className)
216{
217  if (ShellCommandClass::commandClassList == NULL)
218    ShellCommandClass::initCommandClassList();
219
220 const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
221
222 if (checkClass != NULL)
223  {
224    tIterator<ShellCommandBase>* iterator = checkClass->commandList->getIterator();
225    ShellCommandBase* elem = iterator->firstElement();
226    while(elem != NULL)
227    {
228      if (!strcmp(commandName, elem->getName()))
229      {
230        checkClass->commandList->remove(elem);
231        delete elem;
232        break;
233      }
234      elem = iterator->nextElement();
235    }
236    delete iterator;
237
238    if (checkClass->commandList->getSize() == 0)
239    {
240      ShellCommandClass::commandClassList->remove(checkClass);
241      delete checkClass;
242    }
243  }
244}
245
246/**
247 * checks if a command has already been registered.
248 * @param commandName the name of the Command
249 * @param className the name of the Class the command should apply to.
250 * @param paramCount how many arguments the Command takes
251 * @returns true, if the command is registered/false otherwise
252 *
253 * This is used internally, to see, if we have multiple command subscriptions.
254 * This is checked in the registerCommand-function.
255 */
256bool ShellCommandBase::isRegistered(const char* commandName, const char* className, unsigned int paramCount, ...)
257{
258  if (ShellCommandClass::commandClassList == NULL)
259  {
260    ShellCommandClass::initCommandClassList();
261    return false;
262  }
263
264  const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
265  if (checkClass != NULL)
266  {
267    tIterator<ShellCommandBase>* iterator = checkClass->commandList->getIterator();
268    ShellCommandBase* elem = iterator->firstElement();
269    while(elem != NULL)
270   {
271     if (!strcmp(commandName, elem->getName()))
272     {
273       PRINTF(2)("Command already registered\n");
274       delete iterator;
275       return true;
276      }
277     elem = iterator->nextElement();
278   }
279   delete iterator;
280   return false;
281  }
282  else
283    return false;
284}
285
286
287/**
288 * executes commands
289 * @param executionString the string containing the following input
290 * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
291 * @return true on success, false otherwise.
292 */
293bool ShellCommandBase::execute(const char* executionString)
294{
295//   if (ShellCommandBase::commandList == NULL)
296//     return false;
297//
298//   tIterator<ShellCommandBase>* iterator = ShellCommandBase::commandList->getIterator();
299//   ShellCommandBase* elem = iterator->firstElement();
300//   while(elem != NULL)
301//   {
302//     printf("%s::%s\n", elem->className, elem->getName());
303//     if (!strncasecmp (executionString, elem->className, strlen(elem->className)) &&
304//          (*(executionString+strlen(elem->className)) == ' ' ||
305//           *(executionString+strlen(elem->className)) == ':' ))
306//     {
307//       const char* commandBegin = executionString + strlen(elem->className);
308//
309//       PRINTF(4)("Class %s matches\n", elem->className);
310//       BaseObject* objectPointer = NULL;
311//       if (ClassList::StringToID(elem->className) & CL_MASK_SINGLETON == CL_MASK_SINGLETON)
312//       {
313//         while(*commandBegin == ' ')
314//           commandBegin++;
315//         if (strncmp (commandBegin, elem->getName(), strlen(elem->getName())) ||
316//             *(commandBegin + strlen(elem->getName())) != ' ' &&
317//             *(commandBegin + strlen(elem->getName())) != '\0')
318//         {
319//           elem = iterator->nextElement();
320//           continue;
321//         }
322//         PRINTF(4)("Command %s matches\n", elem->getName());
323//         // getting singleton-reference
324//         tList<BaseObject>* list =  ClassList::getList(elem->className);
325//         if (list != NULL)
326//           objectPointer = list->firstElement();
327//       }
328//       else
329//       {
330//         // checking for the Object
331//         while(*commandBegin == ' ')
332//           commandBegin++;
333//         tList<BaseObject>* list = ClassList::getList(elem->className);
334//         if (list == NULL)
335//           break;
336//         tIterator<BaseObject>* iterBO = list->getIterator();
337//         BaseObject* enumBO = iterBO->firstElement();
338//         while(enumBO != NULL)
339//         {
340//           if(!strncmp(commandBegin, enumBO->getName(), strlen(enumBO->getName())))
341//           {
342//             PRINTF(4)("Object %s matches\n", enumBO->getName());
343//             objectPointer = enumBO;
344//             break;
345//           }
346//           enumBO = iterBO->nextElement();
347//         }
348//         delete iterBO;
349//
350//         // break on no object Found. We cannot operate on Classes, but on Objects
351//         if (objectPointer == NULL)
352//           break;
353//         commandBegin = commandBegin + strlen(objectPointer->getName());
354//         while(*commandBegin == ' ')
355//           commandBegin++;
356//         // checking for the requested function.
357//         if (strncmp (commandBegin, elem->getName(), strlen(elem->getName())))
358//         {
359//           elem = iterator->nextElement();
360//           continue;
361//         }
362//         PRINTF(4)("Function '%s' found\n", commandBegin);
363//       }
364//       const char* paramBegin = strchr(commandBegin, ' ');
365//       if (paramBegin == NULL)
366//         paramBegin = commandBegin + strlen(elem->getName());
367//       while (*paramBegin == ' ')
368//         paramBegin++;
369//
370//       PRINTF(3)("Parameters to Pass: %s\n", paramBegin);
371//       if (objectPointer != NULL && paramBegin != NULL)
372//       {
373//         elem->executeCommand(objectPointer, paramBegin);
374//         delete iterator;
375//         return true;
376//       }
377//     }
378//     elem = iterator->nextElement();
379//   }
380//   delete iterator;
381//   return true;
382}
383
384/**
385 * lets a command be described
386 * @param description the description of the Given command
387 */
388ShellCommandBase* ShellCommandBase::describe(const char* description)
389{
390  if (this == NULL)
391    return NULL;
392 else
393 {
394   this->description = description;
395   return this;
396 }
397}
398
399/**
400 * see ShellCommandBase::debug()
401 */
402void ShellCommandBase::debugDyn()
403{
404  this->debug();
405}
406
407/**
408 * prints out nice information about the Shells Commands
409 */
410void ShellCommandBase::debug()
411{
412  if (ShellCommandClass::commandClassList == NULL)
413  {
414    PRINT(0)("No Command registered.\n");
415    return;
416  }
417
418  tIterator<ShellCommandClass>* iteratorCL = ShellCommandClass::commandClassList->getIterator();
419  ShellCommandClass* elemCL = iteratorCL->firstElement();
420  while(elemCL != NULL)
421  {
422    PRINT(0)("Class:'%s' registered %d commands: \n", elemCL->className, elemCL->commandList->getSize());
423    tIterator<ShellCommandBase>* iterator = elemCL->commandList->getIterator();
424    const ShellCommandBase* elem = iterator->firstElement();
425    while(elem != NULL)
426    {
427      PRINT(0)("  command:'%s' : params:%d: ", elem->getName(), elem->paramCount);
428      for (unsigned int i = 0; i< elem->paramCount; i++)
429       printf("%s ", ShellCommandBase::paramToString(elem->parameters[i]));
430      if (elem->description != NULL)
431       printf("- %s", elem->description);
432      printf("\n");
433
434      elem = iterator->nextElement();
435    }
436    delete iterator;
437    elemCL = iteratorCL->nextElement();
438  }
439  delete iteratorCL;
440}
441
442/**
443 * converts a Parameter to a String
444 * @param parameter the Parameter we have.
445 * @returns the Name of the Parameter at Hand
446 */
447const char* ShellCommandBase::paramToString(long parameter)
448{
449  switch (parameter)
450  {
451    case ParameterBool:
452      return "BOOL";
453      break;
454    case ParameterChar:
455      return "CHAR";
456      break;
457    case ParameterString:
458      return "STRING";
459      break;
460    case ParameterInt:
461      return "INT";
462      break;
463    case ParameterUInt:
464      return "UINT";
465      break;
466    case ParameterFloat:
467      return "FLOAT";
468      break;
469    case ParameterLong:
470      return "LONG";
471      break;
472    default:
473      return "NULL";
474      break;
475  }
476}
Note: See TracBrowser for help on using the repository browser.