Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more completion issues

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