Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: alias-completion works too now :)

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