A Command Interpreter with support for used defined commands, subsystems, macros, help and parameter parsing.
Revision 7:269c2445b8f5, committed 2011-02-11
- Comitter:
- wvd_vegt
- Date:
- Fri Feb 11 10:26:33 2011 +0000
- Parent:
- 6:76b033971c3c
- Child:
- 8:83edd6addbd5
- Commit message:
- Version 0.7
Changed in this revision
--- a/cmdb.cpp Fri Feb 11 00:51:37 2011 +0000 +++ b/cmdb.cpp Fri Feb 11 10:26:33 2011 +0000 @@ -14,10 +14,18 @@ -Got a working version. Much work to be done though. -Handle CID_HELP internally (like all system commands (IDLE/MACRO etc). -Defined CID_LAST as Vector Size or Last Command Id fails. + -Removed CMD_TBL_LEN. + -CID_LAST is now defined as CID_HELP+1. + -Added Documentation. + -Added code to take number limits from the C++ Runtime instead of hard defined values. + -Renamed id to cid in cmd. + -Added MAX_LONG and MIN_LONG (long==int on mbed). + -Removed cmdb_ prefix from members. -------- -------------------------------------------------------------- TODO's - 04022011 -ADD Documentation. - - + 10022011 -Tweak and Review Documentation. + 11022011 -Check & Test **PARM masks. + -Remove prefix from class members? -------- -------------------------------------------------------------- _____________________________________________________________________________ */ @@ -32,63 +40,229 @@ #include "cmdb.h" #include "mbed.h" -//Constructor (see http://www.daniweb.com/forums/thread293338.html) -Cmdb::Cmdb(const Serial& serial, const std::vector<cmdb_cmd>& cmds, void (*callback)(Cmdb&,int)) : - _serial(serial), _cmds(cmds) { +//------------------------------------------------------------------------------ + +Cmdb::Cmdb(const Serial& serial, const std::vector<cmd>& cmds, void (*callback)(Cmdb&,int)) : + serial(serial), cmds(cmds) { echo = true; bold = true; + subsystem = -1; - - cmdb_callback = callback; - - //CID_LAST = _cmds.back().id; - CMD_TBL_LEN = _cmds.size(); - cmdb_printf("CID_LAST=%d\r\n",CID_LAST); - cmdb_printf("CMD_TBL_LEN=%d\r\n",CMD_TBL_LEN); + callback = callback; - for (int i=0;i<CMD_TBL_LEN;i++) { - cmdb_printf("%d=%s\r\n",_cmds[i].id, _cmds[i].cmdstr); - } - - cmdb_init(true); + init(true); } -//Public -bool Cmdb::cmdb_macro_hasnext() { +//------------------------------------------------------------------------------ +// Public Stuff. +//------------------------------------------------------------------------------ + +bool Cmdb::macro_hasnext() { return macro_ptr!=-1 && macro_ptr<MAX_CMD_LEN && macro_buf[macro_ptr]; } -char Cmdb::cmdb_macro_next() { +char Cmdb::macro_next() { char ch = macro_buf[macro_ptr++]; if (macro_ptr==MAX_CMD_LEN) { - cmdb_macro_reset(); + macro_reset(); } return ch; } -char Cmdb::cmdb_macro_peek() { +char Cmdb::macro_peek() { return macro_buf[macro_ptr]; } -void Cmdb::cmdb_macro_reset() { +void Cmdb::macro_reset() { macro_ptr = -1; macro_buf[0] = '\0'; } -bool Cmdb::cmdb_hasnext() { - return _serial.readable()==1; +//------------------------------------------------------------------------------ + +bool Cmdb::hasnext() { + return serial.readable()==1; +} + +char Cmdb::next() { + return serial.getc(); } -char Cmdb::cmdb_next() { - return _serial.getc(); +//------------------------------------------------------------------------------ + +bool Cmdb::scan(const char c) { + int i; + + //See http://www.interfacebus.com/ASCII_Table.html + + if (c == '\r') { // cr? + print(crlf); // Output it and ... + if (cmdndx) { + strncpy(lstbuf,cmdbuf,cmdndx); + lstbuf[cmdndx]='\0'; + + cmd_dispatcher(cmdbuf); + } + init(false); + prompt(); + + return true; + } + + //TODO BACKSPACE NOT CORRECT FOR TELNET! + + if (c == '\b') { // Backspace + if (cmdndx != 0) { + print(bs); + cmdbuf [--cmdndx] = '\0'; + } else { + printch(bell); // Output Error + } + return false; + } + + if (c == '\177') { // Delete + while (cmdndx>0) { + print(bs); + cmdbuf [--cmdndx] = '\0'; + } + return false; + } + + //Reset Escape Buffer. + if (c == '\033') { + if (escndx!=0) { + //_putchar(bell); // Output Error + //printf("%s\r\n",escbuf); + } + escndx = 0; + escbuf [escndx] = '\0'; // NULL-Terminate buffer + } + + //Extract Escape Sequence. + if (c == '\033' || escndx ) { // Wait for escape + escbuf [escndx++] = (unsigned char) c; // Add to the buffer + escbuf [escndx] = '\0'; // NULL-Terminate buffer + if (isalpha(c)) { + switch (escid_search(escbuf)) { + case EID_CURSOR_LEFT : { + if (cmdndx != 0) { // Backspace? + print(bs); + cmdbuf [--cmdndx] = '\0'; + } else { + printch(bell); // Output char + } + break; + } + case EID_CURSOR_UP : { + for (i=0;i<cmdndx;i++) { + print(bs); + } + cmdndx=strlen(lstbuf); + strncpy(cmdbuf,lstbuf,cmdndx); + cmdbuf[cmdndx]='\0'; + printf("%s",cmdbuf); + break; + } + case EID_CURSOR_RIGHT: + break; + case EID_CURSOR_DOWN : + break; + case EID_LAST : + break; + default : + printch(bell); + break; + } + escndx=0; + escbuf [escndx] = '\0'; // NULL-Terminate buffer + } + return false; + } + + if (c=='\n') { // LF + return false; // Dump it + } + + if (!isprint (c)) { // Printable character? + printch(bell); + return false; + } + + if (cmdndx >= MAX_CMD_LEN) { // Past buffer length? + printch(bell); + return false; + } + + cmdbuf [cmdndx++] = (unsigned char) c; // Add to the buffer + cmdbuf [cmdndx] = '\0'; // NULL-Terminate buffer + + if (echo) { + printch(c); // Output char + } + + return false; } -//Private Utilities #1 +//------------------------------------------------------------------------------ + +int Cmdb::printf(const char *format, ...) { + int cnt; + + va_list args; + char buf[1024]; + + memset(buf,'\0',sizeof(buf)); + + va_start(args, format); + cnt = vsnprintf(buf, sizeof(buf), format, args); + if (cnt==-1) { + //Error + } + va_end(args); + + return print(buf); +} + +int Cmdb::print(const char *msg) { + return serial.printf(msg); +} + +char Cmdb::printch(const char ch) { + return serial.putc(ch); +} -int Cmdb::cmdb_escid_search(char *escstr) { +//------------------------------------------------------------------------------ + +void Cmdb::init(const char full) { + if (full) { + echo = true; + bold = true; + + subsystem = -1; + + lstbuf [cmdndx] = '\0'; + + macro_reset(); + + prompt(); + } + + cmdndx = 0; + cmdbuf [cmdndx] = '\0'; + + escndx = 0; + escbuf [escndx] = '\0'; +} + +//------------------------------------------------------------------------------ +//Private Stuff. +//------------------------------------------------------------------------------ + +int Cmdb::escid_search(char *escstr) { for (int i=0; i<ESC_TBL_LEN; i++) { if (strcmp (esc_tbl[i].escstr, escstr) == 0) return (esc_tbl[i].id); @@ -97,26 +271,28 @@ return (EID_LAST); } -int Cmdb::cmdb_cmdid_search(char *cmdstr) { +int Cmdb::cmdid_search(char *cmdstr) { //Warning, we return the ID but somewhere assume it's equal to the array index! - for (int i=0; i<CMD_TBL_LEN; i++) { - if ((stricmp(_cmds[i].cmdstr, cmdstr) == 0) && ((_cmds[i].subs == subsystem) || (_cmds[i].subs<0))) - return (_cmds[i].id); + for (int i=0; i<cmds.size(); i++) { + if ((stricmp(cmds[i].cmdstr, cmdstr) == 0) && ((cmds[i].subs == subsystem) || (cmds[i].subs<0))) + return (cmds[i].cid); } return CID_LAST; } -int Cmdb::cmdb_cmdid_index(int cmdid) { - for (int i=0; i<CMD_TBL_LEN; i++) { - if (_cmds[i].id==cmdid) +int Cmdb::cmdid_index(int cmdid) { + for (int i=0; i<cmds.size(); i++) { + if (cmds[i].cid==cmdid) return i; } return -1; } -int Cmdb::cmdb_parse(char *cmd) { +//------------------------------------------------------------------------------ + +int Cmdb::parse(char *cmd) { //Command char cmdstr_buf [1 + MAX_CMD_LEN]; @@ -190,18 +366,18 @@ ------------------------------------------------*/ //1) Find the Command Id - cid = cmdb_cmdid_search(cmdstr_buf); + cid = cmdid_search(cmdstr_buf); if (cid!=CID_LAST) { //2) Tokenize a copy of the parms from the cmd_tbl. - ndx = cmdb_cmdid_index(cid); + ndx = cmdid_index(cid); //Get Format patterns from cmd_tbl[id].parms. - //Note: strtok inserts \0 into the original string. Hence the copy. + //note: strtok inserts \0 into the original string. Hence the copy. zeromemory((char *)(&prmstr_buf),sizeof(prmstr_buf)); - strncpy (prmstr_buf, _cmds[ndx].parms, sizeof (prmstr_buf) - 1); + strncpy (prmstr_buf, cmds[ndx].parms, sizeof (prmstr_buf) - 1); argcnt=0; tok = strtok(prmstr_buf, " "); @@ -209,7 +385,7 @@ //Store Pointers prms[argcnt++] = tok; - //cmdb_printf("prm_%2.2d='%s'\r\n",argcnt, tok); + //printf("prm_%2.2d='%s'\r\n",argcnt, tok); tok = strtok(NULL, " "); } @@ -231,7 +407,7 @@ //Store Pointers toks[argfnd++]=tok; - //cmdb_printf("tok_%2.2d='%s'\r\n",argfnd, tok); + //printf("tok_%2.2d='%s'\r\n",argfnd, tok); tok = strtok(NULL, " "); } @@ -241,7 +417,7 @@ error = 0; for (int i=0;i<argcnt;i++) { - //cmdb_printf("prm_%2.2d=%s\r\n",i, prms[i]); + //printf("prm_%2.2d=%s\r\n",i, prms[i]); switch (strlen(prms[i])) { case 0: @@ -311,7 +487,7 @@ parms[i].val.l=l; break; - default: + default: //int l=strtol((char*)toks[i], &endptr, base); if (l>=MIN_INT && l<=MAX_INT) { parms[i].type=PARM_INT; @@ -370,22 +546,24 @@ } } } else { - cid=CID_LAST; + cid=CID_LAST; } } return cid; } -void Cmdb::cmdb_cmd_dispatcher(char *cmd) { +//------------------------------------------------------------------------------ + +void Cmdb::cmd_dispatcher(char *cmd) { int cid; int ndx; - cid = cmdb_parse(cmd); - ndx = cmdb_cmdid_index(cid); + cid = parse(cmd); + ndx = cmdid_index(cid); if (cid!=-1) { - //cmdb_printf("cmds[%d]=%d\r\n",ndx, cid); + //printf("cmds[%d]=%d\r\n",ndx, cid); /*------------------------------------------------ Process the command and it's arguments that are @@ -396,19 +574,20 @@ ------------------------------------------------*/ if (cid==CID_LAST) { - cmdb_print("Unknown command, type 'Help' for a list of available commands.\r\n"); + print("Unknown command, type 'Help' for a list of available commands.\r\n"); } else { - //cmdb_printf("cmds[%d]=%d [%s]\r\n",ndx, cid, _cmds[ndx].cmdstr); + //printf("cmds[%d]=%d [%s]\r\n",ndx, cid, _cmds[ndx].cmdstr); //Test for more commandline than allowed too. //i.e. run 1 is wrong. - if (argcnt==0 && argfnd==0 && error==0 && ndx!=-1 && _cmds[ndx].subs==SUBSYSTEM) { + if (argcnt==0 && argfnd==0 && error==0 && ndx!=-1 && cmds[ndx].subs==SUBSYSTEM) { //Handle all SubSystems. subsystem=cid; } else if ( ((cid==CID_HELP) || (argcnt==argfnd)) && error==0 ) { switch (cid) { +#ifdef ENABLEMACROS /////// GLOBAL MACRO COMMANDS /////// //Define Macro from commandline @@ -424,17 +603,18 @@ //List Macro's case CID_MACROS: - cmdb_print("[Macro]\r\n"); + print("[Macro]\r\n"); if (macro_buf[0]) { - cmdb_printf("Value=%s\r\n",macro_buf); + printf("Value=%s\r\n",macro_buf); } else { - cmdb_printf(";No Macro Defined\r\n"); + printf(";No Macro Defined\r\n"); } break; - /////// GLOBAL STATEMACHINE COMMANDS /////// +#endif //ENABLEMACROS #ifdef STATEMACHINE + /////// GLOBAL STATEMACHINE COMMANDS /////// //Start State Machine case CID_STATE: @@ -457,12 +637,12 @@ //Warm Boot case CID_BOOT: - //reset(); + mbed_reset(); break; //Sends an ANSI escape code to clear the screen. case CID_CLS: - cmdb_print(cls); + print(cls); break; //Returns to CMD> prompt where most commands are disabled. @@ -472,15 +652,10 @@ //Help case CID_HELP: { - -//TODO Handle Subsystem - -//TODO Call command processor callback and if it returns false we supply help. - - cmdb_print("\r\n"); + print("\r\n"); if (argfnd>0) { - cid = cmdb_cmdid_search(STRINGPARM(0)); + cid = cmdid_search(STRINGPARM(0)); } else { cid=CID_LAST; } @@ -488,243 +663,96 @@ if (argfnd>0 && cid!=CID_LAST) { //Help with a valid command as first parameter - ndx = cmdb_cmdid_index(cid); + ndx = cmdid_index(cid); + + switch (cmds[ndx].subs) { + case SUBSYSTEM: { //Dump whole subsystem + printf("%s subsystem commands:\r\n\r\n",cmds[ndx].cmdstr); - switch (_cmds[ndx].subs) { - case SUBSYSTEM: //Dump whole subsystem - cmdb_printf("%s subsystem commands:\r\n\r\n",_cmds[ndx].cmdstr); - - for (int i=0;i<CMD_TBL_LEN-1;i++) { - if (_cmds[i].subs==ndx) { - cmdb_cmdhelp("",i,",\r\n"); + //Count SubSystem Commands. + int subcmds =0; + for (int i=0;i<cmds.size();i++) { + if (cmds[i].subs==cid) { + subcmds++; } } - break; + //Print SubSystem Commands. + for (int i=0;i<cmds.size()-1;i++) { + if (cmds[i].subs==cid) { + subcmds--; + if (subcmds!=0) { + cmdhelp("",i,",\r\n"); + } else { + cmdhelp("",i,".\r\n"); + } + } + } + } + break; case GLOBALCMD: //Dump command only - //cmdb_print("Global command:\r\n\r\n",cmd_tbl[cmd_tbl[ndx].subs].cmdstr); - cmdb_cmdhelp("Syntax: ",ndx,".\r\n"); + //print("Global command:\r\n\r\n",cmd_tbl[cmd_tbl[ndx].subs].cmdstr); + cmdhelp("Syntax: ",ndx,".\r\n"); break; default: //Dump one subsystem command - cmdb_printf("%s subsystem command:\r\n\r\n",_cmds[_cmds[ndx].subs].cmdstr); - cmdb_cmdhelp("Syntax: ",ndx,".\r\n"); + printf("%s subsystem command:\r\n\r\n",cmds[cmds[ndx].subs].cmdstr); + cmdhelp("Syntax: ",ndx,".\r\n"); break; } } else { if (argfnd>0) { //Help with invalid command as first parameter - cmdb_print("Unknown command, type 'Help' for a list of available commands.\r\n"); + print("Unknown command, type 'Help' for a list of available commands.\r\n"); } else { //Help //Dump Active Subsystem, Global & Other (dormant) Subsystems - for (int i=0;i<CMD_TBL_LEN-1;i++) { - if ((_cmds[i].subs<0) || (_cmds[i].subs==subsystem)) { - cmdb_cmdhelp("",i,",\r\n"); + //-1 because we want comma's and for the last a . + for (int i=0;i<cmds.size()-1;i++) { + if ((cmds[i].subs<0) || (cmds[i].subs==subsystem)) { + cmdhelp("",i,",\r\n"); } } - cmdb_cmdhelp("",CMD_TBL_LEN-1,".\r\n"); + cmdhelp("",cmds.size()-1,".\r\n"); } } - cmdb_print("\r\n"); + print("\r\n"); break; } //CID_HELP - + default : { - (*cmdb_callback)(*this, cid); + // Do a Call to the Application's Command Dispatcher. + (*callback)(*this, cid); } } } else { - cmdb_cmdhelp("Syntax: ",ndx,".\r\n"); + cmdhelp("Syntax: ",ndx,".\r\n"); } - }// else { - // cmdb_print("1Unknown command, type 'Help' for a list of available commands.\r\n"); - //} - }// else { - // cmdb_print("2Unknown command, type 'Help' for a list of available commands.\r\n"); - //} -} - -//Private Utilities #2 - -void Cmdb::cmdb_init(const char full) { - if (full) { - echo = true; - bold = true; - - subsystem = -1; - - lstbuf [cmdndx] = '\0'; + } - cmdb_macro_reset(); - - cmdb_prompt(); - } - - cmdndx = 0; - cmdbuf [cmdndx] = '\0'; - - escndx = 0; - escbuf [escndx] = '\0'; -} - -void Cmdb::cmdb_prompt(void) { - if (subsystem!=-1) { - int ndx = cmdb_cmdid_index(subsystem); - cmdb_printf("%s>",_cmds[ndx].cmdstr); } else { - cmdb_print(prompt); + //cid==-1 } } -bool Cmdb::cmdb_scan(const char c) { - int i; - - //See http://www.interfacebus.com/ASCII_Table.html - - if (c == '\r') { // cr? - cmdb_print(crlf); // Output it and ... - if (cmdndx) { - strncpy(lstbuf,cmdbuf,cmdndx); - lstbuf[cmdndx]='\0'; - - cmdb_cmd_dispatcher(cmdbuf); - } - cmdb_init(false); - cmdb_prompt(); - - return true; - } - - //TODO BACKSPACE NOT CORRECT FOR TELNET! - - if (c == '\b') { // Backspace - if (cmdndx != 0) { - cmdb_print(bs); - cmdbuf [--cmdndx] = '\0'; - } else { - cmdb_printch(bell); // Output Error - } - return false; - } - - if (c == '\177') { // Delete - while (cmdndx>0) { - cmdb_print(bs); - cmdbuf [--cmdndx] = '\0'; - } - return false; - } - - //Reset Escape Buffer. - if (c == '\033') { - if (escndx!=0) { - //_putchar(bell); // Output Error - //printf("%s\r\n",escbuf); - } - escndx = 0; - escbuf [escndx] = '\0'; // NULL-Terminate buffer - } +void Cmdb::prompt(void) { +#ifdef SUBSYSTEMPROMPTS + if (subsystem!=-1) { + int ndx = cmdid_index(subsystem); - //Extract Escape Sequence. - if (c == '\033' || escndx ) { // Wait for escape - escbuf [escndx++] = (unsigned char) c; // Add to the buffer - escbuf [escndx] = '\0'; // NULL-Terminate buffer - if (isalpha(c)) { - switch (cmdb_escid_search(escbuf)) { - case EID_CURSOR_LEFT : { - if (cmdndx != 0) { // Backspace? - cmdb_print(bs); - cmdbuf [--cmdndx] = '\0'; - } else { - cmdb_printch(bell); // Output char - } - break; - } - case EID_CURSOR_UP : { - for (i=0;i<cmdndx;i++) { - cmdb_print(bs); - } - cmdndx=strlen(lstbuf); - strncpy(cmdbuf,lstbuf,cmdndx); - cmdbuf[cmdndx]='\0'; - cmdb_printf("%s",cmdbuf); - break; - } - case EID_CURSOR_RIGHT: - break; - case EID_CURSOR_DOWN : - break; - case EID_LAST : - break; - default : - cmdb_printch(bell); - break; - } - escndx=0; - escbuf [escndx] = '\0'; // NULL-Terminate buffer - } - return false; + printf("%s>",_cmds[ndx].cmdstr); + + return; } - - if (c=='\n') { // LF - return false; // Dump it - } - - if (!isprint (c)) { // Printable character? - cmdb_printch(bell); - return false; - } +#endif //SUBSYSTEMPROMPTS - if (cmdndx >= MAX_CMD_LEN) { // Past buffer length? - cmdb_printch(bell); - return false; - } - - cmdbuf [cmdndx++] = (unsigned char) c; // Add to the buffer - cmdbuf [cmdndx] = '\0'; // NULL-Terminate buffer - - if (echo) { - cmdb_printch(c); // Output char - } - - return false; + printf(PROMPT); } -//Private Utilities #3 - -int Cmdb::cmdb_printf(const char *format, ...) { - int cnt; - - va_list args; - char buf[1024]; - - memset(buf,'\0',sizeof(buf)); - - va_start(args, format); - cnt = vsnprintf(buf, sizeof(buf), format, args); - if (cnt==-1) { - //Error - } - va_end(args); - - return cmdb_print(buf); -} - -//Link to outside world. -int Cmdb::cmdb_print(const char *msg) { - return _serial.printf(msg); -} - -//Link to outside world. -char Cmdb::cmdb_printch(const char ch) { - return _serial.putc(ch); -} - -void Cmdb::cmdb_cmdhelp(char *pre, int ndx, char *post) { +void Cmdb::cmdhelp(char *pre, int ndx, char *post) { int j; int k; int lastmod; @@ -732,7 +760,7 @@ k=0; lastmod=0; - switch (_cmds[ndx].subs) { + switch (cmds[ndx].subs) { case SUBSYSTEM : break; case GLOBALCMD : @@ -741,37 +769,37 @@ return; default : if (strlen(pre)==0 && bold) { - cmdb_print(boldon); + print(boldon); } break; } - cmdb_print(pre); + print(pre); k+=strlen(pre); if (k==0) { - cmdb_printf("%12s",_cmds[ndx].cmdstr); + printf("%12s",cmds[ndx].cmdstr); k+=12; } else { if (strlen(pre)>0 && bold) { - cmdb_print(boldon); + print(boldon); } - cmdb_printf("%s",_cmds[ndx].cmdstr); - k+=strlen(_cmds[ndx].cmdstr); + printf("%s",cmds[ndx].cmdstr); + k+=strlen(cmds[ndx].cmdstr); if (strlen(pre)>0 && bold) { - cmdb_print(boldoff); + print(boldoff); } } - if (strlen(_cmds[ndx].parms)) { - cmdb_printch(sp); + if (strlen(cmds[ndx].parms)) { + printch(sp); k++; } - for (j=0;j<strlen(_cmds[ndx].parms);j++) { - switch (_cmds[ndx].parms[j]) { + for (j=0;j<strlen(cmds[ndx].parms);j++) { + switch (cmds[ndx].parms[j]) { case '%' : lastmod=0; break; @@ -791,15 +819,15 @@ switch (lastmod) { case 0 : case 16 : - cmdb_print("int"); + print("int"); k+=3; break; case 8 : - cmdb_print("shortint"); + print("shortint"); k+=8; break; case 32: - cmdb_print("longint"); + print("longint"); k+=7; break; } @@ -812,26 +840,26 @@ switch (lastmod) { case 0 : case 16 : - cmdb_print("word"); + print("word"); k+=4; break; case 8 : - cmdb_print("byte"); + print("byte"); k+=4; break; case 32 : - cmdb_print("dword"); + print("dword"); k+=5; break; } - switch (_cmds[ndx].parms[j]) { + switch (cmds[ndx].parms[j]) { case 'o' : - cmdb_print("[o]"); + print("[o]"); k+=3; break; case 'x' : - cmdb_print("[h]"); + print("[h]"); k+=3; break; } @@ -842,53 +870,53 @@ case 'e' : case 'f' : case 'g' : - cmdb_print("float"); + print("float"); k+=5; break; case 'c' : - cmdb_print("char"); + print("char"); k+=4; break; case 's' : - cmdb_print("string"); + print("string"); k+=6; break; case ' ' : - cmdb_printch(sp); + printch(sp); k++; break; } } - for (j=k;j<40;j++) cmdb_printch(sp); + for (j=k;j<40;j++) printch(sp); - switch (_cmds[ndx].subs) { + switch (cmds[ndx].subs) { case SUBSYSTEM : if (ndx==subsystem) { - cmdb_printf("- %s (active subsystem)%s",_cmds[ndx].cmddescr,post); + printf("- %s (active subsystem)%s",cmds[ndx].cmddescr,post); } else { - cmdb_printf("- %s (dormant subsystem)%s",_cmds[ndx].cmddescr,post); + printf("- %s (dormant subsystem)%s",cmds[ndx].cmddescr,post); } break; case HIDDENSUB : break; case GLOBALCMD : - cmdb_printf("- %s (global command)%s",_cmds[ndx].cmddescr,post); + printf("- %s (global command)%s",cmds[ndx].cmddescr,post); break; default : - cmdb_printf("- %s%s",_cmds[ndx].cmddescr,post); + printf("- %s%s",cmds[ndx].cmddescr,post); if (strlen(pre)==0 && bold) { - cmdb_print(boldoff); + print(boldoff); } break; } - if (strlen(pre)>0 && strlen(_cmds[ndx].parmdescr)) { - cmdb_printf("Params: %s",_cmds[ndx].parmdescr); - cmdb_print("\r\n"); + if (strlen(pre)>0 && strlen(cmds[ndx].parmdescr)) { + printf("Params: %s",cmds[ndx].parmdescr); + print("\r\n"); } } @@ -917,3 +945,5 @@ return (0); } + +//------------------------------------------------------------------------------
--- a/cmdb.h Fri Feb 11 00:51:37 2011 +0000 +++ b/cmdb.h Fri Feb 11 10:26:33 2011 +0000 @@ -26,48 +26,116 @@ #include "mbed.h" #include <vector> +#include <limits> -//Max size of an Ansi escape code. +//------------------------------------------------------------------------------ + +/** Max size of an Ansi escape code. + */ #define MAX_ESC_LEN 5 -//Max (strlen) of a Param. +/** Max (strlen) of a Param. + */ #define MAX_PARM_LEN 32 -//Max eight parms. -#define MAX_ARGS 8 +/** Max eight parms. + */ +#define MAX_ARGS 8 -//Max 132 characters commandline. +/** Max 132 characters commandline. + */ #define MAX_CMD_LEN 132 -//'Show' hidden subsystems and commands. +/** 'Show' hidden subsystems and commands. + */ #define SHOWHIDDEN -#define MIN_BYTE -128 -#define MAX_BYTE +127 +/** Enable macro commands. + */ +#define ENABLEMACROS + +/** Enable statemachine. + * + * Used to implement a series of commands running at power-up. + * + * @note Not Implemented! + */ +#undef STATEMACHINE -#define MIN_SHORT -32768 -#define MAX_SHORT +32767 +/** Enable subsystem prompts. + * + * When defined, prompts will reflect the SubSystem. + */ +#undef SUBSYSTEMPROMPTS + +//------------------------------------------------------------------------------ + +/** 8 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MIN_BYTE std::numeric_limits<signed char>::min() + +/** 8 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MAX_BYTE std::numeric_limits<signed char>::max() -#define MIN_INT -32768 -#define MAX_INT +32767 +/** 16 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MIN_SHORT std::numeric_limits<short int>::min() + +/** 16 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MAX_SHORT std::numeric_limits<short int>::max() -//TODO Make sure we use id and array index properly!! +/** 32 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MIN_INT std::numeric_limits<int>::min() +#define MAX_INT std::numeric_limits<int>::max() -struct cmdb_cmd { +/** 32 bit limits. + * + * @see http://www.daniweb.com/forums/thread18963.html + */ +#define MIN_LONG std::numeric_limits<long>::min() +#define MAX_LONG std::numeric_limits<long>::max() + +//------------------------------------------------------------------------------ + +/** Description of a command. + */ +struct cmd { public: char *cmdstr; int subs; - int id; //Changed to int as signed char won't compile + int cid; char *parms; char *cmddescr; char *parmdescr; - cmdb_cmd(char *_cmdstr, int _subs, int _id, char *_parms, char *_cmddescr, char *_parmdescr = "") { + /** Command Constructor. + * + * @parm _cmdstr the command, not case sensitive. + * @parm _subs subsystem id + * @parm _cid the command id that will be passed to the dispatcher. + * @parm _parms a scanf alike pattern. + * @parm _cmddescr command description. + * @parm _parmdescr parameter description. + */ + cmd(char *_cmdstr, int _subs, int _cid, char *_parms, char *_cmddescr, char *_parmdescr = "") { cmdstr = (char*)malloc(strlen(_cmdstr)+1); strcpy(cmdstr,_cmdstr); subs = _subs; - id = _id; + cid = _cid; parms = (char*)malloc(strlen(_parms)+1); strcpy(parms,_parms); @@ -80,72 +148,200 @@ } }; -//----Escape Codes and Strings +//------------------------------------------------------------------------------ + +/** Cr. + */ +const char cr = '\r'; -const char cr = '\r'; +/** Lf. + */ const char lf = '\n'; + +/** Bell. + */ const char bell = '\7'; + +/** Escape. + */ const char esc = '\033'; + +/** Space. + */ const char sp = ' '; -const char crlf[] = "\r\n\0"; -const char bs[] = "\b \b\0"; +/** CrLf. + */ +const char crlf[] = "\r\n"; + +/** Backspace that 'tries' to wipe the last character. + */ +const char bs[] = "\b \b"; -const char boldon[] = "\033[1m\0"; -const char boldoff[] = "\033[0m\0"; -const char cls[] = "\033[2J\0"; -const char home[] = "\033[H\0"; +/** VT100 Bold Command. + */ +const char boldon[] = "\033[1m"; + +/** VT100 Normal Command. + */ +const char boldoff[] = "\033[0m"; -const char prompt[] = "CMD>"; +/** VT100 Cls Command. + */ +const char cls[] = "\033[2J"; + +/** VT100 Home Command. + */ +const char home[] = "\033[H"; -//Before including this file, define CID_LAST as the last value from the enum with commands. +/** The default command prompt. + */ +const char PROMPT[] = "CMD>"; + +//------------------------------------------------------------------------------ -//#define CMD_TBL_LEN CID_LAST +/** Subsystem Id for a Subsystem. + */ +#define SUBSYSTEM -1 -#define SUBSYSTEM -1 +/** Subsystem Id for a Global Command (always available). + */ #define GLOBALCMD -2 + +/** Subsystem Id for a Hidden Subsystem (ommitted from help). + */ #define HIDDENSUB -3 +/** Predefined Boot Command. + */ #define CID_BOOT 9990 + +/** Predefined Macro Command. + * + * This command will take a string with spaces replace by _ and cr replace by | for later replay with run. + */ #define CID_MACRO 9991 + +/** Predefined Macro Command. + * + * This command replay a macro. + */ #define CID_RUN 9992 + +/** Predefined Macro Command. + * + * This command print the current macro. + */ #define CID_MACROS 9993 +/** Predefined Echo Command. + * + * This command turn echo on or off. + */ #define CID_ECHO 9994 + +/** Predefined VT100 Bold Command. + * + * This command turn VT100 bold usage on or off. + */ #define CID_BOLD 9995 + +/** Predefined VT100 Cls Command. + * + * This command will clear the screen. + */ #define CID_CLS 9996 + +/** Predefined Idle Command. + * + * This command will return to the global command level, leaving the active subsystem. + */ #define CID_IDLE 9997 + +/** Predefined Help Command. + * + * This command will either print all active command (without parameters) or a more detailed + * help for a command passed as parameter. + */ #define CID_HELP 9998 + +/** Predefided Semi Command. + * + * CID_LAST only functions as a special Commend Id to signal unknown commands. + */ #define CID_LAST 9999 -//You need to add the following commands to your command table. +//------------------------------------------------------------------------------ -//Optional -const cmdb_cmd BOOT("Boot",GLOBALCMD,CID_BOOT,"","Boot"); +/** The Boot Command. + * + * Optional. + */ +const cmd BOOT("Boot",GLOBALCMD,CID_BOOT,"","Boot"); -//Optional -const cmdb_cmd MACRO("Macro",GLOBALCMD,CID_MACRO,"%s","Define macro (sp->_, cr->|)","command(s)"); -const cmdb_cmd RUN("Run",GLOBALCMD,CID_RUN,"","Run a macro"); -const cmdb_cmd MACROS("Macros",GLOBALCMD,CID_MACROS,"","List macro(s)"); +/** The Macro Command. + * + * Optional. + */ +const cmd MACRO("Macro",GLOBALCMD,CID_MACRO,"%s","Define macro (sp->_, cr->|)","command(s)"); + +/** The Run Command. + * + * Optional. + */ +const cmd RUN("Run",GLOBALCMD,CID_RUN,"","Run a macro"); + +/** The Macros Command. + * + * Optional. + */ +const cmd MACROS("Macros",GLOBALCMD,CID_MACROS,"","List macro(s)"); -//Optional -const cmdb_cmd ECHO("Echo",GLOBALCMD,CID_ECHO,"%bu","Echo On|Off (1|0)","state"); -const cmdb_cmd BOLD("Bold",GLOBALCMD,CID_BOLD,"%bu","Bold On|Off (1|0)","state"); -const cmdb_cmd CLS("Cls",GLOBALCMD,CID_CLS,"","Clears the terminal screen"); +/** The Echo Command. + * + * Optional. + */ +const cmd ECHO("Echo",GLOBALCMD,CID_ECHO,"%bu","Echo On|Off (1|0)","state"); + +/** The Bold Command. + * + * Optional. + */ +const cmd BOLD("Bold",GLOBALCMD,CID_BOLD,"%bu","Bold On|Off (1|0)","state"); -//Mandatory! -const cmdb_cmd IDLE("Idle",GLOBALCMD,CID_IDLE,"","Deselect Subsystems"); +/** The Cls Command. + * + * Optional. + */ +const cmd CLS("Cls",GLOBALCMD,CID_CLS,"","Clears the terminal screen"); -//Mandatory! -const cmdb_cmd HELP("Help",GLOBALCMD,CID_HELP,"%s","Help"); +/** The Idle Command. + * + * Mandatory if you use subsystems. + */ +const cmd IDLE("Idle",GLOBALCMD,CID_IDLE,"","Deselect Subsystems"); +/** The Help Command. + * + * Mandatory. + */ +const cmd HELP("Help",GLOBALCMD,CID_HELP,"%s","Help"); + +//------------------------------------------------------------------------------ + +/** We'll only define the 4 cursor codes at the moment. + */ #define ESC_TBL_LEN 4 +/** Escape code definition struct. + */ struct esc_st { char *escstr; int id; }; +/** The Escape Code Id's. + */ enum { EID_CURSOR_UP, EID_CURSOR_DOWN, @@ -154,6 +350,8 @@ EID_LAST }; +/** The Escape Codes Table. + */ const struct esc_st esc_tbl [ESC_TBL_LEN] = { { "\033[A", EID_CURSOR_UP }, { "\033[B", EID_CURSOR_DOWN }, @@ -161,72 +359,88 @@ { "\033[D", EID_CURSOR_LEFT }, }; -//class Cmdb; +//------------------------------------------------------------------------------ -//See http://stackoverflow.com/questions/9410/how-do-you-pass-a-function-as-a-parameter-in-c -//void func ( void (*f)(Cmdb&, int) ); +/** The Command Interpreter Version. + */ +#define CMDB_VERSION 0.7 -//Define a const struct cmbd_cmd cmdb_tbl [CMD_TBL_LEN] {}; that is passed into the constructor. +//------------------------------------------------------------------------------ /** Command Interpreter class.<br/> * <br/> * Steps to take:<br/> * <br/> - * 1) Create a std::vector<cmdb_cmd> and fill it with at least<br/> + * 1) Create a std::vector<cmd> and fill it with at least<br/> * the mandatory commands IDLE and HELP.<br/> - * 2) Create an Cmdb class instance and pass it both the vector and<br/> - * a Serial port object like Serial serial(USBTX, USBRX);<br/> + * <br/> + * 2) Create an Cmdb class instance and pass it the vector,<br/> + * a Serial port object like Serial serial(USBTX, USBRX); <br/> + * and finally a command dispatcher function.<br/> + * <br/> * 3) Feed the interpreter with characters received from your serial port.<br/> * Note Cmdb self does not retrieve input it must be handed to it<br/> + * <br/> * 4) Handle commands added by the application by the Id and parameters passed.<br/> * + * @see main.cpp for a sample. */ class Cmdb { public: /** Create a Command Interpreter. * - * See http://www.newty.de/fpt/fpt.html#chapter2 for function pointers. + * @see http://www.newty.de/fpt/fpt.html#chapter2 for function pointers. + * @see http://stackoverflow.com/questions/9410/how-do-you-pass-a-function-as-a-parameter-in-c + * @see http://www.daniweb.com/forums/thread293338.html * * @param serial a Serial port used for communication. * @param cmds a vector with the command table. */ - Cmdb(const Serial& serial, const std::vector<cmdb_cmd>& cmds, void (*cmdb_callback)(Cmdb&,int) ); + Cmdb(const Serial& serial, const std::vector<cmd>& cmds, void (*callback)(Cmdb&,int) ); + + /** The version of the Command Interpreter. + * + * returns the version. + */ + static float version() { + return CMDB_VERSION; + } /** Checks if the macro buffer has any characters left. * * @returns true if any characters left. */ - bool cmdb_macro_hasnext(); + bool macro_hasnext(); /** Gets the next character from the macro buffer and * advances the macro buffer pointer. * - * Do not call if no more characters are left! + * @note Do not call if no more characters are left! * * @returns the next character. */ - char cmdb_macro_next(); + char macro_next(); /** Gets the next character from the macro buffer * but does not advance the macro buffer pointer. * - * Do not call if no more characters are left! + * @note Do not call if no more characters are left! * * @returns the next character. */ - char cmdb_macro_peek(); + char macro_peek(); /** Resets the macro buffer and macro buffer pointer. * */ - void cmdb_macro_reset(); + void macro_reset(); /** Checks if the serial port has any characters * left to read by calling serial.readable(). * * @returns true if any characters available. */ - bool cmdb_hasnext(); + bool hasnext(); /** Gets the next character from the serial port by * calling serial.getc(). @@ -235,79 +449,188 @@ * * @returns the next character. */ - char cmdb_next(); + char next(); /** Add a character to the command being processed. * If a cr is added, the command is parsed and executed if possible * If supported special keys are encountered (like backspace, delete and cursor up) they are processed. * - * @parmam c the character to add. + * @param c the character to add. * * @returns true if a command was recognized and executed. */ - bool cmdb_scan(const char c); + bool scan(const char c); + + /** printf substitute using the serial parameter passed to the constructor. + * + * @see http://www.cplusplus.com/reference/clibrary/cstdio/printf/ + * + * @parm format the printf format string. + * @parm ... optional paramaters to be merged into the format string. + * + * @returns the printf return value. + */ + int printf(const char *format, ...); - //Output. - int cmdb_printf(const char *format, ...); - int cmdb_print(const char *msg); - char cmdb_printch(const char ch); + /** print is simply printf without parameters using the serial parameter passed to the constructor. + * + * @parm msg the string to print. + * + * @returns the printf return value. + */ + int print(const char *msg); + + /** printch is simply putc subsitute using the serial parameter passed to the constructor. + * + * @parm msg the string to print. + * + * @returns the printf return value. + */ + char printch(const char ch); + +//------------------------------------------------------------------------------ + + /** Initializes the parser (called by the constructor). + * + * @parm full if true the macro buffer is also cleared else only the command interpreter is reset. + */ + void init(const char full); //------------------------------------------------------------------------------ //----These helper functions retieve parameters in the correct format. //------------------------------------------------------------------------------ -//TODO Add tests for correct type of parameter. - + /** Typecasts parameter ndx to a bool. + * + * mask: %bu + * + * @parm the parameter index + * + * @return a bool + */ bool BOOLPARM(int ndx) { return parms[ndx].val.uc!=0; } + /** Typecasts parameter ndx to a byte/unsigned char. + * + * mask: %bu + * + * @parm the parameter index + * + * @return a byte/unsigned char + */ unsigned char BYTEPARM(int ndx) { return parms[ndx].val.uc; } + /** Typecasts parameter ndx to a char. + * + * mask: %c + * + * @parm the parameter index + * + * @return a char + */ char CHARPARM(int ndx) { return parms[ndx].val.c; } + /** Typecasts parameter ndx to word/unsigned int. + * + * mask: %hu + * + * @parm the parameter index + * + * @return a word/unsigned int + */ unsigned int WORDPARM(int ndx) { return parms[ndx].val.ui; } + /** Typecasts parameter ndx to a unsigned int. + * + * mask: %u + * + * @parm the parameter index + * + * @return a unsigned int + */ unsigned int UINTPARM(int ndx) { return parms[ndx].val.ui; } + /** Typecasts parameter ndx to a int. + * + * mask: %i + * + * @parm the parameter index + * + * @return a int + */ int INTPARM(int ndx) { return parms[ndx].val.i; } + /** Typecasts parameter ndx to a bool. + * + * mask: %lu + * + * @parm the parameter index + * + * @return a bool + */ unsigned long DWORDPARM(int ndx) { return parms[ndx].val.ul; } + /** Typecasts parameter ndx to a long. + * + * mask: %li + * + * @parm the parameter index + * + * @return a long + */ long LONGPARM(int ndx) { return parms[ndx].val.l; } + /** Typecasts parameter ndx to a float. + * + * mask: %f + * + * @parm the parameter index + * + * @return a float + */ float FLOATPARM(int ndx) { return parms[ndx].val.f; } + /** Typecasts parameter ndx to a string. + * + * @note spaces are not allowed as it makes parsing so much harder. + * + * mask: %s + * + * @parm the parameter index + * + * @return a string + */ char* STRINGPARM(int ndx) { return parms[ndx].val.s; } private: - //See http://www.newty.de/fpt/fpt.html#chapter2 for function pointers. - - //C++ member - //void (Cmdb::*cmdb_callback)(Cmdb&,int); - //C function - void (*cmdb_callback)(Cmdb&,int); - - //void(*_cmdb_callback)(Cmdb&,int); + /** C callback function + * + * @see See http://www.newty.de/fpt/fpt.html#chapter2 for function pointers. + * + * C++ member equivalent would be void (Cmdb::*callback)(Cmdb&,int); + */ + void (*callback)(Cmdb&,int); /** Searches the escape code list for a match. * @@ -315,7 +638,7 @@ * * @returns the index of the escape code or -1. */ - int cmdb_escid_search(char *escstr); + int escid_search(char *escstr); /** Checks if the command table for a match. * @@ -323,7 +646,7 @@ * * @returns the id of the command or -1. */ - int cmdb_cmdid_search(char *cmdstr); + int cmdid_search(char *cmdstr); /** Converts an command id to an index of the command table. * @@ -331,34 +654,28 @@ * * @returns the index of the command or -1. */ - int cmdb_cmdid_index(int cmdid); - - /** Initializes the parser. - * - * @parm full if true the macro buffer is also cleared else only the command interpreter is reset. - */ - void cmdb_init(const char full); + int cmdid_index(int cmdid); /** Writes a prompt to the serial port. * */ - void cmdb_prompt(void); + void prompt(void); - /** Called by cmdb_cmd_dispatch it parses the command against the command table. + /** Called by cmd_dispatch it parses the command against the command table. * * @param cmd the command and paramaters to parse. * * @returns the id of the parsed command. */ - int cmdb_parse(char *cmd); + int parse(char *cmd); - /** Called by cmdb_scan it processes the arguments and dispatches the command. + /** Called by scan it processes the arguments and dispatches the command. * - * Note: This member calls the cmdb_callback callback function. + * Note: This member calls the callback callback function. * * @param cmd the command to dispatch. */ - void cmdb_cmd_dispatcher(char *cmd); + void cmd_dispatcher(char *cmd); /** Generates Help from the command table and prints it. * @@ -366,24 +683,59 @@ * @param ndx the index of the command in the command table. * @param post trailing text. */ - void cmdb_cmdhelp(char *pre, int ndx, char *post); + void cmdhelp(char *pre, int ndx, char *post); + + /** memset wrapper. + * + * @param p The string to be cleared. + * @param siz The string size. + */ + void zeromemory(char *p,unsigned int siz); - //Utilities. - void zeromemory(char *p,unsigned int siz); + /** Case insensitive compare. + * + * @see strcmp. + * + * @param s1 + * @param s2 the second string to compare. + * + * @returns 0 if s1=s2, -1 if s1<s2 or +1 if s1>s2. + */ int stricmp (char *s1, char *s2); - //Storage, see http://www.cplusplus.com/reference/stl/vector/ - std::vector<cmdb_cmd> _cmds; - Serial _serial; + /** Internal Serial Port Storage. + */ + Serial serial; + + /** Internal Command Table Vector Storage. + * + * @see http://www.cplusplus.com/reference/stl/vector/ + */ + std::vector<cmd> cmds; + + /** Internal Echo Flag Storage. + */ bool echo; + + /** Internal VT100 Bold Flag Storage. + */ bool bold; - int CMD_TBL_LEN; + /** Internal Command Table Length Storage. + */ + //int CMD_TBL_LEN; //Macro's. + /** Internal Macro Pointer. + */ int macro_ptr; + + /** Internal Macro Buffer. + */ char macro_buf[1 + MAX_CMD_LEN]; + /** Used for parsing parameters. + */ enum parmtype { PARM_UNUSED, //0 @@ -397,6 +749,8 @@ PARM_STRING //6 (s) }; + /** Used for parsing parameters. + */ union value { float f; @@ -415,32 +769,62 @@ char s[MAX_PARM_LEN]; }; + /** Used for parsing parameters. + */ struct parm { enum parmtype type; union value val; }; -//------------------------------------------------------------------------------ -//----Buffers -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + //----Buffers & Storage. + //------------------------------------------------------------------------------ + + /** Command Buffer. + */ + char cmdbuf [1 + MAX_CMD_LEN]; // command buffer + + /** Command Buffer Pointer. + */ + char cmdndx; // command index - char cmdbuf [1 + MAX_CMD_LEN]; // command buffer - char cmdndx; // command index + /** Last Command Buffer (Used when pressing Cursor Up). + */ + char lstbuf [1 + MAX_CMD_LEN]; // last command buffer - char lstbuf [1 + MAX_CMD_LEN]; // last command buffer + /** Escape Code Buffer. + */ + char escbuf [1 + MAX_ESC_LEN]; + + /** Escape Code Buffer Pointer. + */ + unsigned char escndx; - char escbuf [1 + MAX_ESC_LEN]; // command buffer - unsigned char escndx; // command index + /** Storage for Parsed Parameters + */ + struct parm parms[MAX_ARGS]; - struct parm parms[MAX_ARGS]; - int noparms; + /** Parsed Parameters Pointer. + */ + int noparms; + + /** Current Selected Subsystem (-1 for Global). + */ + int subsystem; - int subsystem; + /** No of arguments found in command. + */ + int argcnt; - int argcnt; //No of arguments found in command - int argfnd; //No of arguments to find in parameter definition. - int error; //strtoXX() Error detection + /** No of arguments to find in parameter definition (Command Table). + */ + int argfnd; + /** strtoXX() Error detection. + */ + int error; }; +extern "C" void mbed_reset(); + #endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Feb 11 10:26:33 2011 +0000 @@ -0,0 +1,79 @@ +#include <vector> + +#include "mbed.h" +#include "cmdb.h" + +DigitalOut myled(LED1); + +//We'll be using the Usb Serial port +Serial serial(USBTX, USBRX); //tx, rx + +#define CID_TEST 1 +#define CID_INT 2 + +/** Sample User Command Dispatcher. + * + * @parm cmdb the command interpreter object. + * @parm cid the command id. + */ +void my_dispatcher(Cmdb& cmdb, int cid) { + cmdb.printf("my_dispatcher: cid=%d\r\n", cid); + + switch (cid) { + case CID_INT : + cmdb.printf("my_dispatcher: parm 0=%d\r\n",cmdb.INTPARM(0)); + break; + } +} + +const cmd c1("Test",SUBSYSTEM,CID_TEST,"" ,"* Test Subsystem"); +const cmd c2("Int" ,CID_TEST ,CID_INT ,"%i","* Int as parameter" ,"dummy"); + +int main() { + // Set the Baudrate. + serial.baud(115200); + + // Test the serial connection by + serial.printf("\r\n\r\nCmdb Command Interpreter Demo Version %0.2f.\r\n\r\n", Cmdb::version()); + + //Create a Command Table Vector. + std::vector<cmd> cmds; + + //Add some of our own first... + cmds.push_back(c1); //Test Subsystem is handled by Cmdb internally. + cmds.push_back(c2); //The Int Command is handled by our 'my_dispatcher' method. + + //Add some predefined... + cmds.push_back(BOOT); //Handled by Cmdb internally. + + cmds.push_back(ECHO); //Handled by Cmdb internally. + cmds.push_back(BOLD); //Handled by Cmdb internally. + cmds.push_back(CLS); //Handled by Cmdb internally. + + //Add some predefined and mandatory... + cmds.push_back(IDLE); //Handled by Cmdb internally. + cmds.push_back(HELP); //Handled by Cmdb internally. + + //Create and initialize the Command Interpreter. + Cmdb cmdb(serial, cmds, &my_dispatcher); + + while (1) { + //Check for input... + if (cmdb.hasnext()==true) { + + //Supply input to Command Interpreter + if (cmdb.scan(cmdb.next())) { + + //Flash led when a command has been parsed and dispatched. + myled = 1; + wait(0.2); + + //cmdb.print("Command Parsed and Dispatched\r\n"); + + myled = 0; + wait(0.2); + } + } + + } +}