Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
DynaShell Class Reference

#include <dynashell.h>

Public Member Functions

 DynaShell ()
 
 ~DynaShell ()
 
void PublishMap (const char *sParent, const string &strBrief)
 Publish new command map to shell. More...
 
void PublishCommand (const char *sParent, DynaShellCmd *pNewCmd)
 Publish new command to shell. More...
 
void DeleteCommands (ShCmdMap &cmdMap)
 Delete all published commands in map. More...
 
DynaShellCmdMatchCmd (int argc, char *argv[], ShCmdMap &cmdMap)
 Match command. More...
 
void RecordingInit (int nSamplePeriod, const char *sDate=NULL)
 (Re)Initialize recording. More...
 
void RecordingReplace (DynaRecording *pNewRecording)
 Replace recording. More...
 
void ScriptPush (const char *sScriptFile, FILE *fp)
 Push new script on the stack. More...
 
void ScriptPop ()
 Pop the current script from stack. More...
 
void ScriptFlush ()
 Flush all scripts from stack. More...
 
void ScriptTrace (const char *sLine)
 Trace script execution. More...
 
bool IsRunningScript ()
 Test if executing a script. More...
 
virtual void Ok ()
 Print standard ok success response.
 
void Response (const char *sFmt,...)
 Print formatted success response. More...
 
void Warning (const char *sFmt,...)
 Issue warning. More...
 
void Error (int rc, const char *sFmt,...)
 Raise error on dynamixel error code. More...
 
void Error (int nServoId, uint_t uAlarms)
 Raise error on alarmed servo. More...
 
void Error (const char *sFmt,...)
 Raise error. More...
 
int Run ()
 Command execution loop. More...
 
ShCmdMapGetRootCmds ()
 
char * CmdListGenerator (int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext)
 Command list generator function. More...
 
char * CmdSpecGenerator (int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext)
 Command spec generator function. More...
 

Public Attributes

bool m_bRun
 do [not] run shell
 
bool m_bIsInteractive
 [not] user interactive
 
bool m_bXTrace
 do [not] trace script
 
bool m_bSilent
 do [not] silence non-error responses
 
DynaCommm_pDynaComm
 dynamixel bus communication
 
DynaChainm_pDynaChain
 dynamixel chain
 
DynaBgThreadm_pDynaBgThread
 dynamixel chain
 
DynaRecordingm_pRecording
 dynamixel recording
 

Static Public Attributes

static const int m_nMaxScriptDepth = 5
 maximum script stack depth
 

Protected Types

typedef map< int, DynaShellCmd * > MapTabCompleteGen
 

Protected Member Functions

void InputInit ()
 Initialize input.
 
char * GetInputLine ()
 Get one input line from file stream. More...
 
int GetInput ()
 Get one, non-empty input line. More...
 
bool IsExecStmt (const char *sLine)
 Test if line is a potential executable statement. More...
 
void AddToHistory (char *sLine)
 Add command line to history. More...
 
FILE * InputFp ()
 Get the current input file pointer. More...
 
void ScriptBumpLineNum ()
 Bump the line number of the current executing script, if any, by one.
 
bool IsEOF ()
 Test if input is at End Of File condition. More...
 

Static Protected Member Functions

static char * CmdListGeneratorWrap (int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pArg)
 Command list generator wrapper function. More...
 
static char * CmdSpecGeneratorWrap (int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pArg)
 Command spec generator wrapper function. More...
 

Protected Attributes

const char * m_sShellName
 shell name
 
const char * m_sPS1
 primary user prompt
 
const char * m_sPS2
 secondary user prompt
 
bool m_bNoExec
 parse only, no execution
 
char * m_sInputLine
 working, allocated line of input
 
ReadLine m_ReadLine
 readline object
 
ShCmdMap m_mapCmds
 map of published commnds
 
MapTabCompleteGen m_mapTabGen
 command tab-completion generators map
 
vector< ShScript * > m_vecScripts
 script stack
 
int m_rc
 last command executed return code
 

Detailed Description

The Dynamixel shell class.

Definition at line 350 of file dynashell.h.

Constructor & Destructor Documentation

DynaShell::DynaShell ( )

DynaShell default constructor.

Definition at line 95 of file dynashell.cxx.

References DYNA_OK, InputInit(), m_bIsInteractive, m_bNoExec, m_bRun, m_bSilent, m_bXTrace, m_pDynaBgThread, m_pDynaChain, m_pDynaComm, m_pRecording, and m_rc.

96  : m_sShellName("dynashell"),
97  m_sPS1("dynashell> "),
98  m_sPS2(": "),
100 {
101  m_bIsInteractive = true;
102  m_bXTrace = false;
103  m_bRun = true;
104  m_bNoExec = false;
105  m_bSilent = false;
106  m_pDynaComm = NULL;
107  m_pDynaChain = NULL;
108  m_pDynaBgThread = NULL;
109  m_pRecording = NULL;
110  m_rc = DYNA_OK;
111 
112  InputInit();
113 };
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
const char * m_sPS2
secondary user prompt
Definition: dynashell.h:468
DynaComm * m_pDynaComm
dynamixel bus communication
Definition: dynashell.h:359
void InputInit()
Initialize input.
Definition: dynashell.cxx:271
DynaRecording * m_pRecording
dynamixel recording
Definition: dynashell.h:362
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
bool m_bXTrace
do [not] trace script
Definition: dynashell.h:357
const char * m_sPS1
primary user prompt
Definition: dynashell.h:467
ReadLine m_ReadLine
readline object
Definition: dynashell.h:471
DynaBgThread * m_pDynaBgThread
dynamixel chain
Definition: dynashell.h:361
bool m_bSilent
do [not] silence non-error responses
Definition: dynashell.h:358
bool m_bRun
do [not] run shell
Definition: dynashell.h:355
DynaChain * m_pDynaChain
dynamixel chain
Definition: dynashell.h:360
int m_rc
last command executed return code
Definition: dynashell.h:475
const char * m_sShellName
shell name
Definition: dynashell.h:466
bool m_bNoExec
parse only, no execution
Definition: dynashell.h:469
DynaShell::~DynaShell ( )

DynaShell destructor.

Definition at line 118 of file dynashell.cxx.

References DeleteCommands(), m_mapCmds, m_pDynaBgThread, m_pDynaChain, m_pDynaComm, m_pRecording, ScriptFlush(), and DynaBgThread::Stop().

119 {
120  if( m_pDynaBgThread != NULL )
121  {
123  delete m_pDynaBgThread;
124  }
125 
126  if( m_pDynaChain != NULL )
127  {
128  delete m_pDynaChain;
129  }
130 
131  if( m_pDynaComm != NULL )
132  {
133  delete m_pDynaComm;
134  }
135 
136  if( m_pRecording != NULL )
137  {
138  delete m_pRecording;
139  }
140 
141  ScriptFlush();
142 
144 }
DynaComm * m_pDynaComm
dynamixel bus communication
Definition: dynashell.h:359
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
DynaRecording * m_pRecording
dynamixel recording
Definition: dynashell.h:362
virtual int Stop()
Stop control and monitoring tasks.
void ScriptFlush()
Flush all scripts from stack.
Definition: dynashell.cxx:716
DynaBgThread * m_pDynaBgThread
dynamixel chain
Definition: dynashell.h:361
void DeleteCommands(ShCmdMap &cmdMap)
Delete all published commands in map.
Definition: dynashell.cxx:249
DynaChain * m_pDynaChain
dynamixel chain
Definition: dynashell.h:360

Member Function Documentation

void DynaShell::AddToHistory ( char *  sLine)
protected

Add command line to history.

Parameters
sLineNull-terminated line string.

Definition at line 443 of file dynashell.cxx.

References ReadLine::AddToHistory(), InputFp(), IsExecStmt(), m_bIsInteractive, and m_ReadLine.

Referenced by GetInput().

444 {
445  if( IsExecStmt(sLine) && m_bIsInteractive && isatty(fileno(InputFp())) )
446  {
447  m_ReadLine.AddToHistory(sLine);
448  }
449 }
FILE * InputFp()
Get the current input file pointer.
Definition: dynashell.h:518
bool IsExecStmt(const char *sLine)
Test if line is a potential executable statement.
Definition: dynashell.h:492
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
ReadLine m_ReadLine
readline object
Definition: dynashell.h:471
void AddToHistory(const char *sInput)
Add line to history.
char * DynaShell::CmdListGenerator ( int  nUid,
const char *  sText,
size_t  uTextLen,
int  nState,
const char *  sContext 
)

Command list generator function.

Parameters
nUidReadLine registered unique id.
sTextText string to complete as a command.
uTextLenLength of text.
nStateGenerator state. State lets us know whether to start from scratch. If state == START(0), then we start at the top of the command list.
sContextParent command path.
Returns
On command partial matching, returns allocated full command name string.
If no matches found, return NULL.

Definition at line 319 of file dynashell.cxx.

References ReadLine::dupstr(), ReadLine::FIRST, and m_mapCmds.

Referenced by CmdListGeneratorWrap(), and DynaShellCmdHelp::TabCompletion().

324 {
325  static ShCmdMap *pMap; // command map
326  static ShCmdMap::iterator iterCmd; // command map iterator
327 
328  const char *sCmdName; // command name
329 
330  //
331  // New command to complete - initialize.
332  //
333  if( nState == ReadLine::FIRST )
334  {
335  pMap = NULL;
336  iterCmd = m_mapCmds.end();
337 
338  // root commands
339  if( (sContext == NULL) || (*sContext == 0) )
340  {
341  pMap = &m_mapCmds;
342  iterCmd = pMap->begin();
343  }
344 
345  // level 1 commands
346  else
347  {
348  iterCmd = m_mapCmds.find(sContext);
349  if( iterCmd != m_mapCmds.end() )
350  {
351  pMap = iterCmd->second.GetMap();
352  if( pMap != NULL )
353  {
354  iterCmd = pMap->begin();
355  }
356  }
357  }
358  }
359 
360  // return the next command which partially matches text
361  while( (pMap != NULL) && (iterCmd != pMap->end()) )
362  {
363  sCmdName = iterCmd->first;
364  iterCmd++;
365  if( !strncmp(sCmdName, sText, uTextLen) )
366  {
367  return ReadLine::dupstr(sCmdName);
368  }
369  }
370 
371  // no matches
372  return NULL;
373 }
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
static const int FIRST
first state
static char * dupstr(const string &str)
Duplicate string.
map< const char *, ShCmdNode, ShCmdNodeKeyCmp > ShCmdMap
Shell command map type.
Definition: dynashell.h:107
char * DynaShell::CmdListGeneratorWrap ( int  nUid,
const char *  sText,
size_t  uTextLen,
int  nState,
const char *  sContext,
void *  pArg 
)
staticprotected

Command list generator wrapper function.

Parameters
nUidReadLine registered unique id.
sTextText string to complete as a command.
uTextLenLength of text.
nStateGenerator state. State lets us know whether to start from scratch. If state == START(0), then we start at the top of the command list.
sContextParent command path.
pArgPointer to this shell instance.
Returns
On command partial matching, returns allocated full command name string.
If no matches found, return NULL.

Definition at line 292 of file dynashell.cxx.

References CmdListGenerator().

Referenced by InputInit(), PublishCommand(), and PublishMap().

298 {
299  DynaShell *pShell = (DynaShell *)pArg;
300 
301  return pShell->CmdListGenerator(nUid, sText, uTextLen, nState, sContext);
302 }
char * CmdListGenerator(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command list generator function.
Definition: dynashell.cxx:319
char * DynaShell::CmdSpecGenerator ( int  nUid,
const char *  sText,
size_t  uTextLen,
int  nState,
const char *  sContext 
)

Command spec generator function.

Parameters
nUidReadLine registered unique id.
sTextText string to complete as a command.
uTextLenLength of text.
nStateGenerator state. State lets us know whether to start from scratch. If state == START(0), then we start at the top of the command list.
sContextParent command path.
Returns
On command partial matching, returns allocated full command name string.
If no matches found, return NULL.

Definition at line 418 of file dynashell.cxx.

References m_mapTabGen.

Referenced by CmdSpecGeneratorWrap().

423 {
424  MapTabCompleteGen::iterator pos;
425 
426  if( (pos = m_mapTabGen.find(nUid)) != m_mapTabGen.end() )
427  {
428  return pos->second->TabCompletion(*this, sText, uTextLen, nState, sContext);
429  }
430 
431  // no matches
432  else
433  {
434  return NULL;
435  }
436 }
MapTabCompleteGen m_mapTabGen
command tab-completion generators map
Definition: dynashell.h:473
char * DynaShell::CmdSpecGeneratorWrap ( int  nUid,
const char *  sText,
size_t  uTextLen,
int  nState,
const char *  sContext,
void *  pArg 
)
staticprotected

Command spec generator wrapper function.

Parameters
nUidReadLine registered unique id.
sTextText string to complete as a command.
uTextLenLength of text.
nStateGenerator state. State lets us know whether to start from scratch. If state == START(0), then we start at the top of the command list.
sContextParent command path.
pArgPointer to this shell instance.
Returns
On command partial matching, returns allocated full command name string.
If no matches found, return NULL.

Definition at line 391 of file dynashell.cxx.

References CmdSpecGenerator().

Referenced by PublishCommand().

397 {
398  DynaShell *pShell = (DynaShell *)pArg;
399 
400  return pShell->CmdSpecGenerator(nUid, sText, uTextLen, nState, sContext);
401 }
char * CmdSpecGenerator(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command spec generator function.
Definition: dynashell.cxx:418
void DynaShell::DeleteCommands ( ShCmdMap cmdMap)

Delete all published commands in map.

Parameters
cmdMapMap of published commands.

Definition at line 249 of file dynashell.cxx.

References m_mapTabGen.

Referenced by ~DynaShell().

250 {
251  ShCmdMap::iterator iter;
252 
253  m_mapTabGen.clear();
254 
255  for(iter=cmdMap.begin(); iter!=cmdMap.end(); iter++)
256  {
257  if( iter->second.IsCmd() )
258  {
259  delete iter->second.GetCmd();
260  }
261  else if( iter->second.IsMap() )
262  {
263  DeleteCommands(*iter->second.GetMap());
264  }
265  }
266 }
MapTabCompleteGen m_mapTabGen
command tab-completion generators map
Definition: dynashell.h:473
void DeleteCommands(ShCmdMap &cmdMap)
Delete all published commands in map.
Definition: dynashell.cxx:249
void DynaShell::Error ( int  rc,
const char *  sFmt,
  ... 
)

Raise error on dynamixel error code.

Parameters
rcPackage Error Codes.
sFmtFormat string.
...Optional format string arguments.

Definition at line 808 of file dynashell.cxx.

References DynaStrError().

Referenced by DynaShellCmdCfgWriteServoMode::ArgToInt(), DynaShellCmdWriteTorqueEnable::ArgToInt(), DynaShellCmd::ChkArgCnt0(), DynaShellCmd::ChkArgCntEQ(), DynaShellCmd::ChkArgCntGE(), DynaShellCmd::ChkArgCntLE(), DynaShellCmd::ChkChain(), DynaShellCmd::ChkChainHasServo(), DynaShellCmd::ChkChainIsMasterServo(), DynaShellCmd::ChkChainNotEmpty(), DynaShellCmd::ChkComm(), DynaShellCmdCreate::CommNew(), DynaShellCmdMegaScan::CommNew(), DynaShellCmdMoveTo::doExec(), DynaShellCmdMoveAtSpeedTo::doExec(), DynaShellCmdCfgWriteServoMode::doExec(), DynaShellCmdReadTorqueEnable::doExec(), DynaShellCmdWriteTorqueEnable::doExec(), DynaShellCmdReadGoalPos::doExec(), DynaShellCmdReadGoalSpeed::doExec(), DynaShellCmdWriteGoalSpeed::doExec(), DynaShellCmdReadMaxTorqueLimit::doExec(), DynaShellCmdWriteMaxTorqueLimit::doExec(), DynaShellCmdReadCurPos::doExec(), DynaShellCmdReadCurSpeed::doExec(), DynaShellCmdReadDynamics::doExec(), DynaShellCmdReadHealth::doExec(), DynaShellCmdReadIsMoving::doExec(), DynaShellCmdClearAlarms::doExec(), DynaShellCmdReadByte::doExec(), DynaShellCmdWriteByte::doExec(), DynaShellCmdReadWord::doExec(), DynaShellCmdWriteWord::doExec(), Error(), DynaShellCmdCreate::Exec(), DynaShellCmdHelp::Exec(), DynaShellCmdMoveAtSpeedTo::Exec(), DynaShellCmdSetPid::Exec(), DynaShellCmdDestroy::Exec(), DynaShellCmdEStop::Exec(), DynaShellCmdFreeze::Exec(), DynaShellCmdRelease::Exec(), DynaShellCmdLink::Exec(), DynaShellCmdSetOdometer::Exec(), DynaShellCmdScript::Exec(), DynaShellCmdChainOut::Exec(), DynaShellCmdUnlink::Exec(), DynaShellCmdBgtStart::Exec(), DynaShellCmdSaveRecording::Exec(), DynaShellCmdBgtStop::Exec(), DynaShellCmdReadMaxTorqueLimit::Exec(), DynaShellCmdSetHalfDuplexCtl::Exec(), DynaShellCmdWriteMaxTorqueLimit::Exec(), DynaShellCmdPlay::Exec(), DynaShellCmdSetSoftTorqueTh::Exec(), DynaShellCmdWriteByte::Exec(), GetInput(), DynaShellCmdLoadRecording::Init(), DynaShellCmdLoadRecording::Load(), MatchCmd(), DynaShellCmdHelp::MatchHelp(), DynaShellCmdLoadRecording::ParseIntField(), DynaShellCmdLoadRecording::ParseRecordedData(), DynaShellCmdLoadRecording::ParseServoList(), DynaShellCmdTrain::RecordTraining(), ScriptPush(), DynaShellCmd::ToBool(), DynaShellCmd::ToDouble(), and DynaShellCmd::ToInt().

809 {
810  char buf[256];
811  va_list ap;
812 
813  va_start(ap, sFmt);
814 
815  vsnprintf(buf, sizeof(buf), sFmt, ap);
816  buf[sizeof(buf)-1] = 0;
817 
818  va_end(ap);
819 
820  Error("%s: %s", DynaStrError(rc), buf);
821 }
const char * DynaStrError(int ecode)
Get the error string describing the Dynamixel error code.
Definition: DynaError.cxx:141
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
void DynaShell::Error ( int  nServoId,
uint_t  uAlarms 
)

Raise error on alarmed servo.

Parameters
nServoIdServo id.
uAlarmsEEPROM Alarm Shutdown.

Definition at line 829 of file dynashell.cxx.

References Error(), and DynaComm::GetAlarmsString().

830 {
831  string strAlarms;
832 
833  strAlarms = DynaComm::GetAlarmsString(uAlarms);
834 
835  Error("Servo %d: Alarms: %s.", nServoId, strAlarms.c_str());
836 }
static std::string GetAlarmsString(const uint_t uAlarms, const std::string &strSep="; ")
Get a formatted servo alarms string associated with the alarms.
Definition: DynaComm.cxx:312
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
void DynaShell::Error ( const char *  sFmt,
  ... 
)

Raise error.

If the error occurred while running a script, the script is aborted. If the shell is non-interactive, the shell is terminated.

Parameters
sFmtFormat string.
...Optional format string arguments.

Definition at line 847 of file dynashell.cxx.

References DYNA_ECODE_RUNTIME, m_bIsInteractive, m_bRun, m_rc, m_vecScripts, and ScriptFlush().

848 {
849  va_list ap;
850 
851  if( !m_vecScripts.empty() )
852  {
853  fprintf(stderr, "%s[%d]: ",
854  m_vecScripts.back()->GetScriptName(),
855  m_vecScripts.back()->GetLineNum());
856  }
857 
858  fprintf(stderr, "Error: ");
859 
860  va_start(ap, sFmt);
861  vfprintf(stderr, sFmt, ap);
862  va_end(ap);
863 
864  fprintf(stderr, "\n");
865 
867 
868  ScriptFlush();
869 
870  if( !m_bIsInteractive )
871  {
872  m_bRun = false;
873  }
874 }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
#define DYNA_ECODE_RUNTIME
Shell run-time error.
Definition: Dynamixel.h:102
void ScriptFlush()
Flush all scripts from stack.
Definition: dynashell.cxx:716
bool m_bRun
do [not] run shell
Definition: dynashell.h:355
int m_rc
last command executed return code
Definition: dynashell.h:475
int DynaShell::GetInput ( )
protected

Get one, non-empty input line.

Returns
On success, returns SH_RC_OK).
On end of file, returns SH_RC_EOF.
On system error, returns SH_RC_SYS_ERROR.

Definition at line 505 of file dynashell.cxx.

References AddToHistory(), Error(), GetInputLine(), IsEOF(), IsExecStmt(), m_bIsInteractive, m_bNoExec, m_bXTrace, m_sInputLine, ScriptTrace(), SH_RC_EOF, SH_RC_OK, SH_RC_OK_NOEXEC, and SH_RC_SYS_ERROR.

Referenced by Run().

506 {
507  char *sLine;
508 
509  m_sInputLine = NULL;
510 
511  while( true )
512  {
513  // get one logical line of input
514  sLine = GetInputLine();
515 
516  // eof or system error
517  if( sLine == NULL )
518  {
519  if( IsEOF() )
520  {
521  return SH_RC_EOF;
522  }
523  else
524  {
525  Error("%s.", strerror(errno));
526  return SH_RC_SYS_ERROR;
527  }
528  }
529 
530  // skip leading whitespace
531  while(*sLine && isspace(*sLine))
532  {
533  sLine++;
534  }
535 
536  if( IsExecStmt(sLine) )
537  {
538  // add non-blnak input line to command history
539  AddToHistory(sLine);
540 
541  // trace script
542  if( IsExecStmt(sLine) && (m_bIsInteractive || m_bXTrace) )
543  {
544  ScriptTrace(sLine);
545  }
546 
547  m_sInputLine = sLine;
548 
550  }
551  else
552  {
553  return SH_RC_OK_NOEXEC;
554  }
555  }
556 }
char * GetInputLine()
Get one input line from file stream.
Definition: dynashell.cxx:469
void ScriptTrace(const char *sLine)
Trace script execution.
Definition: dynashell.cxx:739
#define SH_RC_OK_NOEXEC
shell input ok, but don&#39;t execute command
Definition: dynashell.cxx:82
bool IsExecStmt(const char *sLine)
Test if line is a potential executable statement.
Definition: dynashell.h:492
#define SH_RC_SYS_ERROR
system error on shell input
Definition: dynashell.cxx:84
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
void AddToHistory(char *sLine)
Add command line to history.
Definition: dynashell.cxx:443
bool m_bXTrace
do [not] trace script
Definition: dynashell.h:357
bool IsEOF()
Test if input is at End Of File condition.
Definition: dynashell.h:540
#define SH_RC_EOF
end of file
Definition: dynashell.cxx:83
#define SH_RC_OK
shell input ok
Definition: dynashell.cxx:81
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
bool m_bNoExec
parse only, no execution
Definition: dynashell.h:469
char * m_sInputLine
working, allocated line of input
Definition: dynashell.h:470
char * DynaShell::GetInputLine ( )
protected

Get one input line from file stream.

Characters will be read from the input of the given file pointer using the prompt string to prompt the user. If the prompt is NULL or an empty string then no prompt is issued. The line returned is allocated, so the caller must free it when finished.

If the readline free library is available, then command line editing is supported for terminal input.

Todo:
TODO add '\' parsing for line continuation.
Returns
If no errors occurred and EOF is not encountered, an allocated, null-terminated line buffer is return. If the input only contained non-executable characters (white-space and comments), then the line buffer will be empty. On EOF or errors, NULL is returned.

Definition at line 469 of file dynashell.cxx.

References ReadLine::fReadLine(), InputFp(), ReadLine::iReadLine(), m_ReadLine, m_sPS1, and ScriptBumpLineNum().

Referenced by GetInput().

470 {
471  static const char *sPrompt = m_sPS1;
472 
473  char *sLine = NULL;
474 
475  //
476  // Get malloc'd line of input (fragment)
477  //
478  if( isatty(fileno(InputFp())) )
479  {
480  sLine = m_ReadLine.iReadLine(sPrompt);
481  }
482  else
483  {
484  sLine = m_ReadLine.fReadLine(InputFp(), NULL);
486  }
487 
488  // EOF or I/O error
489  if( sLine == NULL )
490  {
491  return NULL;
492  }
493 
494  return sLine;
495 }
void ScriptBumpLineNum()
Bump the line number of the current executing script, if any, by one.
Definition: dynashell.h:527
FILE * InputFp()
Get the current input file pointer.
Definition: dynashell.h:518
static char * fReadLine(FILE *fp, const char *sPrompt)
Read one input line from the given input stream.
const char * m_sPS1
primary user prompt
Definition: dynashell.h:467
ReadLine m_ReadLine
readline object
Definition: dynashell.h:471
char * iReadLine(const char *sPrompt)
Interactively read a line of input from standard input.
ShCmdMap& DynaShell::GetRootCmds ( )
inline

Get map of shell root commands.

Returns
Returns command map.

Definition at line 446 of file dynashell.h.

Referenced by DynaShellCmdHelp::Exec().

447  {
448  return m_mapCmds;
449  }
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
FILE* DynaShell::InputFp ( )
inlineprotected

Get the current input file pointer.

Returns
File pointer.

Definition at line 518 of file dynashell.h.

Referenced by AddToHistory(), and GetInputLine().

519  {
520  return !m_vecScripts.empty()? m_vecScripts.back()->GetFp(): stdin;
521  }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
bool DynaShell::IsEOF ( )
inlineprotected

Test if input is at End Of File condition.

Returns
Returns true or false.

Definition at line 540 of file dynashell.h.

Referenced by GetInput().

541  {
542  return feof(InputFp())? true: false;
543  }
FILE * InputFp()
Get the current input file pointer.
Definition: dynashell.h:518
bool DynaShell::IsExecStmt ( const char *  sLine)
inlineprotected

Test if line is a potential executable statement.

Note
Assumes line has been stripped of leading white space.
Parameters
sLineLine to test.
Returns
true or false.

Definition at line 492 of file dynashell.h.

Referenced by AddToHistory(), and GetInput().

493  {
494  return (sLine!=NULL) && (*sLine!=0) && (*sLine!=SH_C_COMMENT)? true: false;
495  }
bool DynaShell::IsRunningScript ( )
inline

Test if executing a script.

Returns
true or false.

Definition at line 416 of file dynashell.h.

Referenced by ScriptTrace().

417  {
418  return m_vecScripts.empty()? false: true;
419  }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
DynaShellCmd * DynaShell::MatchCmd ( int  argc,
char *  argv[],
ShCmdMap cmdMap 
)

Match command.

Parameters
argcCommand argument count.
argvArray of arguments.
cmdMapCommand map to search.
Returns
Returns pointer to matched command on success. NULL otherwise.

Definition at line 567 of file dynashell.cxx.

References Error().

Referenced by Run().

568 {
569  ShCmdMap::iterator iter1, iter2;
570  char *sPattern;
571  const char *sCmdName1, *sCmdName2;
572  size_t n;
573  bool_t bIsUnique = true;
574  int cnt;
575 
576  if( argc == 0 )
577  {
578  Error("No Command.");
579  return NULL;
580  }
581 
582  sPattern = argv[0];
583 
584  n = strlen(sPattern);
585 
586  // find command
587  for(iter1=cmdMap.begin(); iter1!=cmdMap.end(); iter1++)
588  {
589  sCmdName1 = iter1->first;
590  if( !strncmp(sPattern, sCmdName1, n) )
591  {
592  break;
593  }
594  }
595 
596  // no matching command found
597  if( iter1 == cmdMap.end() )
598  {
599  Error("%s: Command not found.\n", sPattern);
600  return NULL;
601  }
602 
603  // verify uniqueness
604  for(iter2=cmdMap.begin(); iter2!=cmdMap.end(); iter2++)
605  {
606  if( iter2 == iter1 )
607  {
608  continue;
609  }
610 
611  sCmdName2 = iter2->first;
612 
613  // another match
614  if( !strncmp(sPattern, sCmdName2, n) )
615  {
616  cnt++;
617 
618  // first non-unique
619  if( bIsUnique )
620  {
621  fprintf(stderr, "%s: Command not unique: Matches %s %s",
622  sPattern, sCmdName1, sCmdName2);
623  bIsUnique = false;
624  }
625 
626  // subsequent non-uniques
627  else if( cnt < 8 )
628  {
629  fprintf(stderr, " %s", sCmdName2);
630  }
631 
632  // too many to print
633  else
634  {
635  fprintf(stderr, " ...");
636  break;
637  }
638  }
639  }
640 
641  if( !bIsUnique )
642  {
643  fprintf(stderr, "\n");
644  return NULL;
645  }
646 
647  if( iter1->second.IsCmd() )
648  {
649  return iter1->second.GetCmd();
650  }
651  else if( iter1->second.IsMap() )
652  {
653  return MatchCmd(argc-1, argv+1, *iter1->second.GetMap());
654  }
655  else
656  {
657  return NULL;
658  }
659 }
DynaShellCmd * MatchCmd(int argc, char *argv[], ShCmdMap &cmdMap)
Match command.
Definition: dynashell.cxx:567
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
void DynaShell::PublishCommand ( const char *  sParent,
DynaShellCmd pNewCmd 
)

Publish new command to shell.

The new command is inserted into the map of commands. The map is kept in lexicogrphahical increasing order.

Note
Published commands currently only support two levels. However, this can be readily extended given some command separator convention.
Parameters
sParentParent command. Set to NULL or "" to publish the command at the root(0) level.
pNewCmdAllocated new command. The shell owns the command and will delete it when the shell is destroyed.

Definition at line 192 of file dynashell.cxx.

References CmdListGeneratorWrap(), CmdSpecGeneratorWrap(), DynaShellCmd::GetCmdHelpBrief(), DynaShellCmd::GetCmdName(), DynaShellCmd::GetPublishedName(), m_mapCmds, m_mapTabGen, m_ReadLine, ReadLine::NOT_REG, ReadLine::RegisterGenerator(), and DynaShellCmd::SetPublishedInfo().

Referenced by PublishShellCoreCommands(), PublishShellInterfaceCommands(), PublishShellServoCommands(), and PublishShellTrainCommands().

193 {
194  const char *sCmdName = pNewCmd->GetCmdName();
195  string strRegEx;
196  int nUid;
197 
198  // new root command
199  if( (sParent == NULL) || (*sParent == 0) )
200  {
201  pNewCmd->SetPublishedInfo(0);
202  m_mapCmds[sCmdName] = pNewCmd;
203  m_mapCmds[sCmdName].SetMapBrief(pNewCmd->GetCmdHelpBrief());
204  }
205 
206  // new command published to existing root group
207  else if( m_mapCmds.find(sParent) != m_mapCmds.end() )
208  {
209  pNewCmd->SetPublishedInfo(1, sParent);
210 
211  (*m_mapCmds[sParent].GetMap())[sCmdName] = pNewCmd;
212  (*m_mapCmds[sParent].GetMap())[sCmdName].SetMapBrief(
213  pNewCmd->GetCmdHelpBrief());
214  }
215 
216  // new command published to new root group
217  else
218  {
219  pNewCmd->SetPublishedInfo(1, sParent);
220 
221  m_mapCmds[sParent] = new ShCmdMap;
222 
223  (*m_mapCmds[sParent].GetMap())[sCmdName] = pNewCmd;
224 
225  strRegEx = "^";
226  strRegEx += sParent;
227  strRegEx += "$";
228 
229  nUid = m_ReadLine.RegisterGenerator(strRegEx, CmdListGeneratorWrap, this);
230  }
231 
232  // register new command for readline tab-completion
233  strRegEx = pNewCmd->GetPublishedName();
234  strRegEx += ".*";
235 
236  nUid = m_ReadLine.RegisterGenerator(strRegEx, CmdSpecGeneratorWrap, this);
237 
238  if( nUid != ReadLine::NOT_REG )
239  {
240  m_mapTabGen[nUid] = pNewCmd;
241  }
242 }
int RegisterGenerator(const string strRegEx, ReadLineAppGenFunc_T fnAppGen, void *pAppArg)
Register application-specific tab-completion generator associated.
static char * CmdSpecGeneratorWrap(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pArg)
Command spec generator wrapper function.
Definition: dynashell.cxx:391
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
MapTabCompleteGen m_mapTabGen
command tab-completion generators map
Definition: dynashell.h:473
static char * CmdListGeneratorWrap(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pArg)
Command list generator wrapper function.
Definition: dynashell.cxx:292
int SetPublishedInfo(int nLevel, const char *sParent=NULL)
map< const char *, ShCmdNode, ShCmdNodeKeyCmp > ShCmdMap
Shell command map type.
Definition: dynashell.h:107
ReadLine m_ReadLine
readline object
Definition: dynashell.h:471
const char * GetCmdName()
Get dynamixel shell command name.
static const int NOT_REG
not registered return value
const char * GetCmdHelpBrief()
Get shell command name brief description.
const char * GetPublishedName() const
void DynaShell::PublishMap ( const char *  sParent,
const string &  strBrief 
)

Publish new command map to shell.

The new map is inserted into the map of root commands. The map is kept in lexicogrphahical increasing order.

Note
Published commands currently only support two levels. However, this can be readily extended given some command separator convention.
Parameters
sParentParent command. Set to NULL or "" to publish the command at the root(0) level.
strBriefMap brief description.

Definition at line 159 of file dynashell.cxx.

References CmdListGeneratorWrap(), m_mapCmds, m_ReadLine, and ReadLine::RegisterGenerator().

Referenced by MainInit().

160 {
161  string strRegEx;
162  int nUid;
163 
164  // publish only if map does not exist
165  if( m_mapCmds.find(sParent) == m_mapCmds.end() )
166  {
167  m_mapCmds[sParent] = new ShCmdMap;
168  m_mapCmds[sParent].SetMapBrief(strBrief);
169 
170  strRegEx = "^";
171  strRegEx += sParent;
172  strRegEx += "$";
173 
174  nUid = m_ReadLine.RegisterGenerator(strRegEx, CmdListGeneratorWrap, this);
175  }
176 }
int RegisterGenerator(const string strRegEx, ReadLineAppGenFunc_T fnAppGen, void *pAppArg)
Register application-specific tab-completion generator associated.
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
static char * CmdListGeneratorWrap(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pArg)
Command list generator wrapper function.
Definition: dynashell.cxx:292
map< const char *, ShCmdNode, ShCmdNodeKeyCmp > ShCmdMap
Shell command map type.
Definition: dynashell.h:107
ReadLine m_ReadLine
readline object
Definition: dynashell.h:471
void DynaShell::RecordingInit ( int  nSamplePeriod,
const char *  sDate = NULL 
)
inline

(Re)Initialize recording.

If the shell does not have a recording object, it is created. Any previously recorded data is 'erased'.

Parameters
nSamplePeriodRecording sample period (msec).
sDataRecording date string.

Definition at line 383 of file dynashell.h.

References DynaRecording::Init().

Referenced by DynaShellCmdTrain::Exec().

384  {
385  if( m_pRecording == NULL )
386  {
388  }
389  m_pRecording->Init(nSamplePeriod, sDate);
390  }
DynaRecording * m_pRecording
dynamixel recording
Definition: dynashell.h:362
virtual void Init(int nSamplePeriod, const char *sDate=NULL)
(Re)Initialize recording.
void DynaShell::RecordingReplace ( DynaRecording pNewRecording)
inline

Replace recording.

Parameters
pNewRecordingAllocated new recording.

Definition at line 397 of file dynashell.h.

Referenced by DynaShellCmdLoadRecording::Load().

398  {
399  if( m_pRecording != NULL )
400  {
401  delete m_pRecording;
402  }
403  m_pRecording = pNewRecording;
404  }
DynaRecording * m_pRecording
dynamixel recording
Definition: dynashell.h:362
int DynaShell::Run ( )

Command execution loop.

Loop through all commands from input intil EOF, error, or user commanded termination.

Returns
DYNA_OK on successful execution, < 0 on failure.

Definition at line 884 of file dynashell.cxx.

References DYNA_ECODE_SYS, DYNA_OK, DynaShellCmd::Exec(), GetInput(), DynaShellCmd::GetPublishedLevel(), m_bIsInteractive, m_bRun, m_mapCmds, m_rc, m_sInputLine, MatchCmd(), ScriptPop(), SH_RC_EOF, SH_RC_OK, SH_RC_OK_NOEXEC, SH_RC_SYS_ERROR, and ReadLine::tokenize().

Referenced by main().

885 {
886  int tokc;
887  char *tokv[1024];
888  DynaShellCmd *pCmd;
889  int nOffset; // command-line arguments start offset
890  int rc;
891 
892  if( m_bIsInteractive )
893  {
894  printf(" Dynamixel Simple Shell\n");
895  printf("(enter 'help' for list of commands; "
896  "partial command matching supported)\n\n");
897  }
898 
899  while( m_bRun )
900  {
901  // clear any old shell command return code
902  m_rc = DYNA_OK;
903 
904  // parse [compound] statement
905  rc = GetInput();
906 
907  //
908  // test terminating conditions
909  //
910  switch( rc )
911  {
912  // parse and execute
913  case SH_RC_OK:
914  // tokenize input
915  tokc = ReadLine::tokenize(m_sInputLine, tokv, arraysize(tokv));
916 
917  if( tokc <= 0 )
918  {
919  continue;
920  }
921 
922  // find command
923  pCmd = MatchCmd(tokc, tokv, m_mapCmds);
924 
925  if( pCmd != NULL )
926  {
927  nOffset = pCmd->GetPublishedLevel() + 1;
928 
929  // execute command
930  pCmd->Exec(*this, tokc-nOffset, tokv+nOffset);
931  }
932  break;
933 
934  // parse but don't execute
935  case SH_RC_OK_NOEXEC:
936  break;
937 
938  // end-of-file
939  case SH_RC_EOF:
940  ScriptPop();
941  break;
942 
943  // system or other error
944  case SH_RC_SYS_ERROR:
945  default:
946  // if not interactive terminate loop
947  if( !m_bIsInteractive )
948  {
949  m_rc = -DYNA_ECODE_SYS;
950  m_bRun = false;
951  }
952  break;
953  }
954  }
955 
956  return m_rc;
957 }
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
DynaShellCmd * MatchCmd(int argc, char *argv[], ShCmdMap &cmdMap)
Match command.
Definition: dynashell.cxx:567
#define SH_RC_OK_NOEXEC
shell input ok, but don&#39;t execute command
Definition: dynashell.cxx:82
ShCmdMap m_mapCmds
map of published commnds
Definition: dynashell.h:472
Dynamixel shell command abstract base class.
Definition: dynashell_cmd.h:80
#define DYNA_ECODE_SYS
system (errno) error
Definition: Dynamixel.h:81
static int tokenize(char *s, char *tokv[], size_t tokmax)
Tokenize input.
#define SH_RC_SYS_ERROR
system error on shell input
Definition: dynashell.cxx:84
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
void ScriptPop()
Pop the current script from stack.
Definition: dynashell.cxx:693
int GetPublishedLevel() const
#define SH_RC_EOF
end of file
Definition: dynashell.cxx:83
bool m_bRun
do [not] run shell
Definition: dynashell.h:355
#define SH_RC_OK
shell input ok
Definition: dynashell.cxx:81
int m_rc
last command executed return code
Definition: dynashell.h:475
int GetInput()
Get one, non-empty input line.
Definition: dynashell.cxx:505
char * m_sInputLine
working, allocated line of input
Definition: dynashell.h:470
virtual void Exec(DynaShell &shell, int argc, char *argv[])=0
Execute command abstract function.
void DynaShell::ScriptFlush ( )

Flush all scripts from stack.

If this shell is not user interactive, the shell will marked for termination. Otherwise, standard input becomes the point of execution.

Definition at line 716 of file dynashell.cxx.

References m_bIsInteractive, m_bRun, and m_vecScripts.

Referenced by Error(), and ~DynaShell().

717 {
718  ShScript *pScript;
719  int i;
720 
721  for(i=0; i<(int)m_vecScripts.size(); ++i)
722  {
723  pScript = m_vecScripts.back();
724  m_vecScripts.pop_back();
725  delete pScript;
726  }
727 
728  if( !m_bIsInteractive )
729  {
730  m_bRun = false;
731  }
732 }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
Shell Script Class.
Definition: dynashell.h:270
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
bool m_bRun
do [not] run shell
Definition: dynashell.h:355
void DynaShell::ScriptPop ( )

Pop the current script from stack.

The new top-of-stack script resumes execution. If there are no more scripts on the stack and this shell is not user interactive, then the shell will marked for termination. Otherwise, if the stack is empty, standard input becomes the point of execution.

Definition at line 693 of file dynashell.cxx.

References m_bIsInteractive, m_bRun, and m_vecScripts.

Referenced by Run().

694 {
695  ShScript *pScript;
696 
697  if( (int)m_vecScripts.size() > 0 )
698  {
699  pScript = m_vecScripts.back();
700  m_vecScripts.pop_back();
701  delete pScript;
702  }
703 
704  if( !m_bIsInteractive && m_vecScripts.empty() )
705  {
706  m_bRun = false;
707  }
708 }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
Shell Script Class.
Definition: dynashell.h:270
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
bool m_bRun
do [not] run shell
Definition: dynashell.h:355
void DynaShell::ScriptPush ( const char *  sScriptFile,
FILE *  fp 
)

Push new script on the stack.

The new script becomes the point of execution.

Parameters
sScriptFileScript file path name.
fpScript file opened file pointer.

Definition at line 669 of file dynashell.cxx.

References Error(), m_nMaxScriptDepth, and m_vecScripts.

Referenced by DynaShellCmdScript::Exec(), and MainInitArgs().

670 {
671  ShScript *pScript;
672 
673  if( (int)m_vecScripts.size() >= m_nMaxScriptDepth )
674  {
675  Error("Cannot execute script %s: At maximum script depth of %d",
676  sScriptFile, m_nMaxScriptDepth);
677  }
678  else
679  {
680  pScript = new ShScript(sScriptFile, fp);
681  m_vecScripts.push_back(pScript);
682  }
683 }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
Shell Script Class.
Definition: dynashell.h:270
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
static const int m_nMaxScriptDepth
maximum script stack depth
Definition: dynashell.h:353
void DynaShell::ScriptTrace ( const char *  sLine)

Trace script execution.

Parameters
sLineExecutable script statement.

Definition at line 739 of file dynashell.cxx.

References IsRunningScript(), m_bIsInteractive, and m_vecScripts.

Referenced by GetInput().

740 {
741  if( IsRunningScript() )
742  {
743  if( m_bIsInteractive )
744  {
745  printf(": %s\n", sLine);
746  }
747  else
748  {
749  printf("%s[%d]: %s\n",
750  m_vecScripts.back()->GetScriptName(),
751  m_vecScripts.back()->GetLineNum(),
752  sLine);
753  }
754  }
755 }
bool IsRunningScript()
Test if executing a script.
Definition: dynashell.h:416
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474
bool m_bIsInteractive
[not] user interactive
Definition: dynashell.h:356
void DynaShell::Warning ( const char *  sFmt,
  ... 
)

Issue warning.

Parameters
sFmtFormat string.
...Optional format string arguments.

Definition at line 781 of file dynashell.cxx.

References m_vecScripts.

Referenced by DynaShellCmdLoadRecording::Load().

782 {
783  va_list ap;
784 
785  if( !m_vecScripts.empty() )
786  {
787  fprintf(stderr, "%s[%d]: ",
788  m_vecScripts.back()->GetScriptName(),
789  m_vecScripts.back()->GetLineNum());
790  }
791 
792  fprintf(stderr, "Warning: ");
793 
794  va_start(ap, sFmt);
795  vfprintf(stderr, sFmt, ap);
796  va_end(ap);
797 
798  fprintf(stderr, "\n");
799 }
vector< ShScript * > m_vecScripts
script stack
Definition: dynashell.h:474

The documentation for this class was generated from the following files: