A Command Interpreter with support for used defined commands, subsystems, macros, help and parameter parsing.

Files at this revision

API Documentation at this revision

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

cmdb.cpp Show annotated file Show diff for this revision Revisions of this file
cmdb.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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);
+            }
+        }
+
+    }
+}