Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
rnshell.cxx
1 //
2 // rnsh (dynashell for one).
3 //
4 // This is a slow, background, low priority effort to have a simple, but
5 // capable shell for RoadNarrows supported products.
6 //
7 // Base Features:
8 // assignment
9 // conditional testing
10 // iteration
11 // variable management
12 // built-in commands (e.g. exit, help, log, quit, wait)
13 // plug-in specific application commands
14 // plug-in special variable ($) support
15 // botsense support
16 //
17 ShExec()
18 {
19  ShLang *pStmt;
20  int rc;
21 
22  while( true )
23  {
24  rc = -DYNA_ECODE_PARSE;
25 
26  pStmt = ShParse(session);
27 
28  if( pStmt != NULL )
29  {
30  rc = pStmt->Eval();
31  delete pStmt;
32  }
33 
34  if( !bIsIteractive (rc != DYNA_OK) )
35  {
36  ShExit(session)
37  }
38  }
39 }
40 
41 void ShError(const char *sFmt, ...)
42 {
43 }
44 
45 enum ShLangToken
46 {
47  TokenNone,
48 
49  // non-terminals
50  TokenCmdStmt,
51  TokenAssignStmt,
52  TokenIfStmt,
53  TokenElifStmt,
54  TokenElseStmt,
55  TokenWhileStmt,
56  TokenBlockStmt,
57  TokenExpr,
58  TokenAddExpr,
59  TokenMulExpr,
60  TokenPrimaryExpr,
61 
62  // arithmetic binary operator terminals
63  TokenBinOpAdd,
64  TokenBinOpSub,
65  TokenBinOpMul,
66  TokenBinOpDiv,
67  TokenBinOpMod,
68 
69  // boolean binary operator terminals
70  TokenBinOpAnd,
71  TokenBinOpOr,
72  TokenBinOpNot,
73 
74  // comparative binary operator terminals
75  TokenBinOpEQ,
76  TokenBinOpNE,
77  TokenBinOpGT,
78  TokenBinOpGE,
79  TokenBinOpLT,
80  TokenBinOpLE,
81 
82  // indentifier/constant terminals
83  TokenIdentifier,
84  TokenBoolean,
85  TokenInteger,
86  TokenReal,
87  TokenString
88 };
89 
90 enum ShDataType
91 {
92  TUndef,
93  TBool = TokenBoolean,
94  TInt = TokenInteger,
95  TReal = TokenReal,
96  TString = TokenString
97 };
98 
99 // -----------------------------------------------------------------------------
100 class ShVal
101 {
102 public:
103  ShVal(ShDataType eObjType, const char *sObjName)
104  {
105  m_nStatus = DYNA_OK;
106  m_eObjType = eObjType;
107  m_sObjName = NEWSTR(sObjName);
108  }
109 
110  virtual ~ShVal()
111  {
112  DELSTR(m_sObjName);
113  }
114 
115  static ShVal *New(bool val);
116  static ShVal *New(int val);
117  static ShVal *New(double val);
118  static ShVal *New(const char *val);
119 
120  ShDataType GetObjType() const
121  {
122  return m_eObjType;
123  }
124 
125  const char *GetObjName() const
126  {
127  return m_sObjName;
128  }
129 
130  int GetStatus() const
131  {
132  return m_nStatus;
133  }
134 
135  int SetStatus(int nStatus)
136  {
137  if( nStatus > 0 )
138  {
139  nStatus = -nStatus;
140  }
141  m_nStatus = nStatus;
142  return m_nStatus;
143  }
144 
145  void ClearStatus()
146  {
147  m_nStatus = DYNA_OK;
148  }
149 
150  virtual bool ToBool() const = 0;
151  virtual int ToInt() const = 0;
152  virtual double ToReal() const = 0;
153  virtual const char *ToString() const = 0;
154 
155  virtual ShVal *Add(const ShVal *pRhs) = 0;
156  virtual ShVal *Sub(const ShVal *pRhs) = 0;
157  virtual ShVal *Mul(const ShVal *pRhs) = 0;
158  virtual ShVal *Div(const ShVal *pRhs) = 0;
159  virtual ShVal *Mod(const ShVal *pRhs) = 0;
160 
161  virtual bool IsEQ(const ShVal *pRhs) = 0;
162  virtual bool IsNotEQ(const ShVal *pRhs) = 0;
163  virtual bool IsGT(const ShVal *pRhs) = 0;
164  virtual bool IsGE(const ShVal *pRhs) = 0;
165  virtual bool IsLT(const ShVal *pRhs) = 0;
166  virtual bool IsLE(const ShVal *pRhs) = 0;
167 
168  virtual ShVal *Dup(const ShVal *pRhs) = 0;
169 
170 protected:
171  ShDataType m_eObjType;
172  const char *m_sObjName;
173  int m_nStatus;
174 };
175 
176 // -----------------------------------------------------------------------------
177 class ShValInt : public ShVal
178 {
179 public:
180  ShValInt(int val = 0) : ShVal(TInt, "int")
181  {
182  m_val = val;
183  }
184 
185  virtual bool ToBool() const
186  {
187  return m_val != 0? true: false;
188  }
189 
190  virtual int ToInt() const
191  {
192  return m_val;
193  }
194 
195  virtual double ToReal() const
196  {
197  return (double)m_val;
198  }
199 
200  virtual const char *ToString() const
201  {
202  return NULL; // TODO
203  }
204 
205  virtual ShValInt &operator=(const ShValInt &rhs)
206  {
207  if( this != &rhs )
208  {
209  copy(&rhs);
210  }
211  return *this;
212  }
213 
214  virtual ShVal *Add(const ShVal *pRhs);
215 
216 protected:
217  int m_val;
218 
219  virtual void copy(const ShVal *pOrig)
220  {
221  m_val = pOrig->ToInt();
222  }
223 };
224 
225 
226 // -----------------------------------------------------------------------------
227 class ShValReal : public ShVal
228 {
229 public:
230  ShValReal(double val = 0.0) : ShVal(TReal, "real")
231  {
232  m_val = val;
233  }
234 
235  virtual bool ToBool() const
236  {
237  return m_val != 0.0? true: false;
238  }
239 
240  virtual int ToInt() const
241  {
242  return (int)m_val;
243  }
244 
245  virtual double ToReal() const
246  {
247  return m_val;
248  }
249 
250  virtual const char *ToString() const
251  {
252  return NULL; // TODO
253  }
254 
255  ShValReal &operator=(const ShValReal &rhs)
256  {
257  if( this != &rhs )
258  {
259  copy(&rhs);
260  }
261  return *this;
262  }
263 
264  virtual ShVal *Add(const ShVal *pRhs);
265 
266 protected:
267  int m_val;
268 
269  virtual void copy(const ShVal *pOrig)
270  {
271  m_val = pOrig->ToReal();
272  }
273 };
274 
275 ShVal *ShValInt::Add(const ShVal *pRhs)
276 {
277  ShVal *pVal;
278 
279  switch( pRhs->GetObjType() )
280  {
281  case TBool:
282  case TInt:
283  pVal = new ShValInt(m_val + pRhs->ToInt());
284  break;
285  case TReal:
286  pVal = new ShValReal(ToReal() + pRhs->ToReal());
287  break;
288  case TString:
289  ShError("Error: Unsupported operand types for 'int' and 'str'.");
290  pVal = new ShValInt();
291  pVal->SetStatus(DYNA_ECODE_PARSE);
292  break;
293  case TUndef:
294  default:
295  ShError("Error: Undefined R.H.S.");
296  pVal = new ShValInt();
297  pVal->SetStatus(DYNA_ECODE_PARSE);
298  break;
299  }
300 
301  return pVal;
302 }
303 
304 ShVal *ShValReal::Add(const ShVal *pRhs)
305 {
306  ShVal *pVal;
307 
308  switch( pRhs->GetObjType() )
309  {
310  case TBool:
311  case TInt:
312  case TReal:
313  pVal = new ShValReal(m_val + pRhs->ToReal());
314  break;
315  case TString:
316  ShError("Error: Unsupported operand types for 'real' and 'string'.");
317  pVal = new ShValReal();
318  pVal->SetStatus(DYNA_ECODE_PARSE);
319  break;
320  case TUndef:
321  default:
322  ShError("Error: Undefined R.H.S.");
323  pVal = new ShValReal();
324  pVal->SetStatus(DYNA_ECODE_PARSE);
325  break;
326  }
327 
328  return pVal;
329 }
330 
331 // abstract base class
332 class ShLang
333 {
334 public:
335  ShLang(ShLangToken eObjType, const char *sObjName)
336  {
337  m_eObjType = eType;
338  m_sObjName = NEWSTR(sObjName);
339  m_pResult = NULL;
340  }
341 
342  virtual ~ShLang()
343  {
344  DELSTR(m_sObjName);
345  }
346 
347  const ShVal *GetResult()
348  {
349  return m_pResult;
350  }
351 
352  int Eval() = 0;
353  int Print() = 0;
354 
355 prottected:
356  ShLangToken m_eObjType;
357  const char *m_sObjName;
358  ShVal *m_pResult;
359 };
360 
361 
362 class ShLangCmdStmt : public ShLang
363 {
364  ShLangCmdStmt(const char *sCmdName, vecArg) : ShLang(TokenCmdStmt, "command");
365 
366  int Eval()
367  {
368  char *argv[m_argc];
369 
370  argv[0] = m_sCmdName;
371 
372  for(i=1, rc=DYNA_OK; i<m_argc; ++i)
373  {
374  if( (rc = m_vecArg[i]->Eval()) == DYNA_OK )
375  {
376  argv[i] = m_pArg->GetResult()->ToString();
377  }
378  }
379 
380  if( rc == DYNA_OK )
381  {
382  rc = Exec(session, argc, argv);
383  }
384 
385  for(i=1; i<m_argc; ++i)
386  {
387  delete[] argv[i];
388  }
389 
390  return m_result.setstatus(rc);
391  }
392 };
393 
394 class ShLangAssignStmt : public ShLang
395 {
396  ShLangAssignStmt(const char *sIdentifier, ShLangExpr *pExpr)
397  : ShLang(TokenAssignStmt, "assignment");
398 
399  int Eval()
400  {
401  if( (rc = m_pExpr->Eval()) == DYNA_OK )
402  {
403  rc = ShHashSet(m_sIdentifier, m_pExpr->GetResult());
404  }
405  return m_result.setstatus(rc);
406  }
407 };
408 
409 class ShLangIfStmt : public ShLang
410 {
411  ShLangIfStmt(ShLangCondExpr *pCond, ShLangBlockStmt *pBlockStmt)
412  : ShLang(TokenIfStmt, "if");
413 
414  int Eval()
415  {
416  if( ((rc = m_pCond->Eval()) == DYNA_OK) &&
417  (m_pCond->GetResult()->ToBool() == true) )
418  {
419  rc = m_pBlockStmt->Eval();
420  }
421  return m_result.setstatus(rc);
422  }
423 };
424 
425 // same for elif
426 
427 class ShLangElseStmt : public ShLang
428 {
429  ShLangElseStmt(ShLangBlockStmt *pBlockStmt) : ShLang(TokenElseStmt, "else");
430 
431  int Eval()
432  {
433  rc = m_pBlockStmt->Eval();
434  return m_result.setstatus(rc);
435  }
436 };
437 
438 class ShLangWhileStmt : public ShLang
439 {
440  ShLangWhileStmt(ShLangCondExpr *pCond, ShLangBlockStmt *pBlockStmt)
441  : ShLang(TokenWhileStmt, "while");
442 
443  int Eval()
444  {
445  int rc;
446 
447  while( ((rc = m_pCond->Eval()) == DYNA_OK) &&
448  (m_pCond->GetResult()->ToBool() == true) )
449  {
450  if( (rc = m_pBlockStmt->Eval()) != DYNA_OK )
451  {
452  break;
453  }
454  }
455  return rc;
456  }
457 };
458 
459 class ShLangBlockStmt : public ShLang
460 {
461  ShLangBlockStmt(vecStmts) : ShLang(TokenBlockStmt, "block");
462 
463  int Eval()
464  {
465  int rc;
466 
467  for(i=0; i<m_vecStmts.size(); ++i)
468  {
469  if( (rc = m_vecStmts[i]->Eval()) != DYNA_OK )
470  {
471  break;
472  }
473  }
474  return m_result.setstatus(rc);
475  }
476 };
477 
478 class ShLangExpr : public ShLang
479 {
480 public:
481  ShLangExpr(ShLangExprArithExpr *p) : ShLang(TokenArithExpr, "arith-expr");
482  ShLangExpr(ShLangExprCondExpr *q) : ShLang(TokenCondExpr, "cond-expr");
483 
484  int Eval()
485  {
486  m_result.clear()
487 
488  if( (rc = m_pAddExpr->Eval()) == DYNA_OK )
489  {
490  m_result = m_pAddExpr->GetResult();
491  }
492  return m_result.setstatus(rc);
493  }
494 
495 protected:
496  ShLangAddExpr *m_pLhs;
497 }
498 
499 class ShLangAddExpr : public ShLang
500 {
501 public:
502  ShLangAddExpr(ShLangAddExpr *pLhsExpr, ShBinOp eOp, ShLangMulExpr *pRhsExpr)
503  : ShLang(TokenAddExpr, "add-expr")
504  {
505  m_pLhsExpr = pLhsExpr;
506  m_eOp = eOp;
507  m_pRhsExpr = pRhsExpr;
508  m_pResult = NULL;
509  }
510 
511  ShLangAddExpr(ShLangMulExpr *pMulExpr) : ShLang(TokenMulExpr, "add-expr")
512  {
513  m_pLhsExpr = NULL;
514  m_eOp = ShBinOpUnary;
515  m_pRhsExpr = pMulExpr;
516  m_pResult = NULL;
517  }
518 
519  virtual ~ShLangAddExpr()
520  {
521  DELOBJ(m_pLhs);
522  DELOBJ(m_pRhs);
523  DELOBJ(m_pResult);
524  }
525 
526  int Eval()
527  {
528  int rc;
529 
530  DELOBJ(m_pResult);
531 
532  if( (rc = pRhs->Eval()) != DYNA_OK )
533  {
534  return rc;
535  }
536  else if( (pLhs != NULL) && (rc = pLhs->Eval()) != DYNA_OK )
537  {
538  return rc;
539  }
540 
541  switch( m_eOp )
542  {
543  case ShBinOpPlus:
544  m_pResult = m_pLhs->GetResult()->Add(m_pRhs);
545  break;
546  case ShBinOpMinus:
547  m_pResult = m_pLhs->GetResult()->Sub(m_pRhs);
548  break;
549  case ShBinOpUnary:
550  m_pResult = m_pRhs->GetResult()->Dup();
551  }
552 
553  return m_pResult->GetStatus();
554  }
555 
556 protected:
557  ShLangAddExpr *m_pLhs;
558  ShBinOp_T eOp;
559  ShLangMulExpr *m_pRhs;
560 };
561 
562 class ShLangMulExpr : public ShLang
563 {
564 public:
565  ShLangMulExpr(ShLangMulExpr *pLhsExpr,
566  ShBinOp eOp,
567  ShLangPrimaryExpr *pRhsExpr) : ShLang(TokenMulExpr, "mul-expr")
568  {
569  m_pLhsExpr = pLhsExpr;
570  m_eOp = eOp;
571  m_pRhsExpr = pRhsExpr;
572  m_pResult = NULL;
573  }
574 
575  ShLangMulExpr(ShLangMulExpr *pPrimaryExpr) : ShLang(TokenMulExpr, "mul-expr")
576  {
577  m_pLhsExpr = NULL;
578  m_eOp = ShBinOpUnary;
579  m_pRhsExpr = pPrimaryExpr;
580  m_pResult = NULL;
581  }
582 
583  virtual ~ShLangAddExpr()
584  {
585  DELOBJ(m_pLhs);
586  DELOBJ(m_pRhs);
587  DELOBJ(m_pResult);
588  }
589 
590  int Eval()
591  {
592  int rc;
593 
594  DELOBJ(m_pResult);
595 
596  if( (rc = pRhs->Eval()) != DYNA_OK )
597  {
598  return rc;
599  }
600  else if( (pLhs != NULL) && (rc = pLhs->Eval()) != DYNA_OK )
601  {
602  return rc;
603  }
604 
605  switch( m_eOp )
606  {
607  case ShBinOpPlus:
608  m_pResult = m_pLhs->Add(m_pRhs);
609  break;
610  case ShBinOpMinus:
611  m_pResult = m_pLhs->Sub(m_pRhs);
612  break;
613  case ShBinOpUnary:
614  m_pResult = m_pRhs->Copy();
615  }
616 
617  return m_pResult->GetStatus();
618  }
619 
620 protected:
621  ShLangMulExpr *m_pLhs;
622  ShBinOp_T eOp;
623  ShLangPrimaryExpr *m_pRhs;
624 };
625 
626 class ShLangPrimaryExpr : public ShLang
627 {
628  ShLangPrimaryExpr(bool val) : ShLang(TokenPrimaryExpr, "constant")
629  {
630  m_eType = CONSTANT;
631  m_sIdentifier = NULL;
632  m_pResult = new ShVal::New(val);
633  }
634 
635  ShLangPrimaryExpr(int val) : ShLang(TokenPrimaryExpr, "constant")
636  {
637  m_eType = CONSTANT;
638  m_sIdentifier = NULL;
639  m_pResult = new ShVal::New(val);
640  }
641 
642  ShLangPrimaryExpr(double val) : ShLang(TokenPrimaryExpr, "constant")
643  {
644  m_eType = CONSTANT;
645  m_sIdentifier = NULL;
646  m_pResult = new ShVal::New(val);
647  }
648 
649  ShLangPrimaryExpr(const char *val) : ShLang(TokenPrimaryExpr, "constant")
650  {
651  m_eType = CONSTANT;
652  m_sIdentifier = NULL;
653  m_pResult = new ShVal::New(val);
654  }
655 
656  ShLangPrimaryExpr(ShLangToken eTokenIdentifier,
657  const char *val)
658  : ShLang(TokenPrimaryExpr, "identifier")
659  {
660  m_eType = INDENTIFIER;
661  m_sIdentifier = newstr(val);
662  m_pResult = NULL;
663  }
664 
665  virtual ~ShLangPrimaryExpr()
666  {
667  delstr(m_sIdentifier);
668  delobj(m_pResult);
669  }
670 
671  virtual int Eval()
672  {
673  switch( m_eType )
674  {
675  case INDENTIFER:
676  delobj(m_pResult);
677  m_pResult = ShHashGet(m_sIdentifier);
678  break;
679 
680  // constant
681  default:
682  break;
683  }
684 
685  return m_pResult->GetStatus();
686  }
687 };
char * newstr(const char *s)
Allocate new duplicated string.
#define NEWSTR(s)
Allocate a new duplicated string convenience macro.
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
#define DELOBJ(p)
Delete an allocated object convenience macro.
#define DYNA_ECODE_PARSE
Shell parse error.
Definition: Dynamixel.h:101
void delstr(const char *s)
A safer string delete utility.
#define DELSTR(s)
Delete an allocated string convenience macro.