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

Revision:
0:4d95ee0b4c37
Child:
1:6627eed48db5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmdb.h	Thu Feb 10 18:30:04 2011 +0000
@@ -0,0 +1,335 @@
+/* mbed Command Interpreter Library
+00002  * Copyright (c) 2007-2010 sford, cstyles
+00003  *
+00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
+00005  * of this software and associated documentation files (the "Software"), to deal
+00006  * in the Software without restriction, including without limitation the rights
+00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+00008  * copies of the Software, and to permit persons to whom the Software is
+00009  * furnished to do so, subject to the following conditions:
+00010  *
+00011  * The above copyright notice and this permission notice shall be included in
+00012  * all copies or substantial portions of the Software.
+00013  *
+00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+00020  * THE SOFTWARE.
+00021  */
+
+#ifndef MBED_CMDB_H
+#define MBED_CMDB_H
+
+#include "mbed.h"
+
+#include <vector>
+
+//Max size of an Ansi escape code.
+#define MAX_ESC_LEN   5
+
+//Max (strlen) of a Param.
+#define MAX_PARM_LEN 32
+
+//Max eight parms.
+#define MAX_ARGS 8
+
+//Max 132 characters commandline.
+#define MAX_CMD_LEN 132
+
+//'Show' hidden subsystems and commands.
+#define SHOWHIDDEN
+
+#define MIN_BYTE        -128
+#define MAX_BYTE        +127
+
+#define MIN_SHORT     -32768
+#define MAX_SHORT     +32767
+
+#define MIN_INT       -32768
+#define MAX_INT       +32767
+
+//TODO Make sure we use id and array index properly!!
+
+struct cmdb_cmd {
+    char *cmdstr;
+    int  subs;
+    int  id;                                            //Changed to int as signed char won't compile
+    char *parms;
+    char *cmddescr;
+    char *parmdescr;
+};
+
+//----Escape Codes and Strings
+
+const char cr           = '\r';
+const char lf           = '\n';
+const char bell         = '\7';
+const char esc          = '\033';
+const char sp           = ' ';
+const char crlf[]       = "\r\n\0";
+
+const char bs[]         = "\b \b\0";
+
+const char boldon[]     = "\033[1m\0";
+const char boldoff[]    = "\033[0m\0";
+const char cls[]        = "\033[2J\0";
+const char home[]       = "\033[H\0";
+
+const char prompt[]     = "CMD>";
+
+//Before including this file, define CID_LAST as the last value from the enum with commands.
+
+//#define CMD_TBL_LEN  CID_LAST
+
+#define SUBSYSTEM         -1
+#define GLOBALCMD         -2
+#define HIDDENSUB         -3
+
+#define CID_BOOT    9991
+#define CID_MACRO   9992
+#define CID_RUN     9993
+#define CID_MACROS  9994
+
+#define CID_ECHO    9995
+#define CID_BOLD    9996
+#define CID_CLS     9997
+#define CID_IDLE    9998
+#define CID_HELP    9999
+
+//You need to add the following commands to your command table.
+
+//Optional
+cmdb_cmd BOOT =     { "Boot",           GLOBALCMD    ,CID_BOOT      ,""                 ,"Boot"                         ,""};
+
+//Optional
+cmdb_cmd MACRO =    { "Macro",          GLOBALCMD    ,CID_MACRO     ,"%s"               ,"Define macro (sp->_, cr->|)"  ,"command(s)"};
+cmdb_cmd RUN =      { "Run",            GLOBALCMD    ,CID_RUN       ,""                 ,"Run a macro"                  ,""};
+cmdb_cmd MACROS =   { "Macros",         GLOBALCMD    ,CID_MACROS    ,""                 ,"List macro(s)"                ,""};
+
+//Optional
+cmdb_cmd ECHO =     { "Echo",           GLOBALCMD    ,CID_ECHO      ,"%bu"              ,"Echo On|Off (1|0)"            ,"state"};
+cmdb_cmd BOLD =     { "Bold",           GLOBALCMD    ,CID_BOLD      ,"%bu"              ,"Bold On|Off (1|0)"            ,"state"};
+cmdb_cmd CLS  =     { "Cls",            GLOBALCMD    ,CID_CLS       ,""                 ,"Clears the terminal screen"   ,""};
+
+//Mandatory!
+cmdb_cmd IDLE =     { "Idle",           GLOBALCMD    ,CID_IDLE      ,""                 ,"Deselect Subsystems"          ,""};
+
+//Mandatory!
+cmdb_cmd HELP =     { "Help",           GLOBALCMD    ,CID_HELP      ,"%s"               ,"Help"                         ,""};
+
+#define ESC_TBL_LEN  4
+
+struct esc_st {
+    char     *escstr;
+    int     id;
+};
+
+enum {
+    EID_CURSOR_UP,
+    EID_CURSOR_DOWN,
+    EID_CURSOR_RIGHT,
+    EID_CURSOR_LEFT,
+    EID_LAST
+};
+
+const struct esc_st esc_tbl [ESC_TBL_LEN] = {
+    { "\033[A",    EID_CURSOR_UP    },
+    { "\033[B",    EID_CURSOR_DOWN  },
+    { "\033[C",    EID_CURSOR_RIGHT },
+    { "\033[D",    EID_CURSOR_LEFT  },
+};
+
+//Define a const struct cmbd_cmd cmdb_tbl [CMD_TBL_LEN] {}; that is passed into the constructor.
+
+/** Command Interpreter class.
+ *
+ * Steps to take:
+ *
+ * 1) Create a std::vector<cmdb_cmd> and fill it with at least
+ *    the mandatory commands IDLE and HELP.
+ * 2) Create an Cmdb class instance and pass it both the vector and
+ *    a Serial port object like Serial serial(USBTX, USBRX);
+ * 3) Feed the interpreter with characters received from your serial port.
+ *    Note Cmdb self does not retrieve input it must be handed to it
+ * 4) Handle commands added by the application by the Id and parameters passed.
+ *
+ */
+class Cmdb {
+public:
+    /** Create a Command Interpreter.
+     *
+     * @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);
+
+    /** Checks if the macro buffer has any characters left.
+     *
+     * @returns true if any characters left.
+     */
+    bool cmdb_macro_hasnext();
+    char cmdb_macro_next();
+    char cmdb_macro_peek();
+    void cmdb_macro_reset();
+
+    //Char Input.
+    bool cmdb_hasnext();
+    char cmdb_next();
+
+private:
+    //Utilities.
+    /** Checks if the macro buffer has any characters left.
+     *
+     * @param char* escstr the escape code to lookup.
+     *
+     * @returns the index of the escape code or -1.
+     */
+    int cmdb_escid_search(char *escstr);
+    int cmdb_cmdid_search(char *cmdstr);
+    int  cmdb_cmdid_index(int cmdid);
+
+    //Parser.
+    void cmdb_init(const char full);
+    void cmdb_prompt(void);
+    bool cmdb_scan(const char c);
+    int cmdb_parse(char *cmd);
+
+    //Command Processor.
+    //TODO Must call Callback function.
+    void cmdb_cmd_proc(char *cmd);
+
+    //Help
+    void cmdb_cmdhelp(char *pre, int ndx, char *post);
+
+    //Output.
+    int cmdb_printf(const char *format, ...);
+    int cmdb_print(const char *msg);
+    char cmdb_printch(const char ch);
+
+    //Utilities.
+    void zeromemory(char *p,unsigned int siz);
+    int stricmp (char *s1, char *s2);
+
+
+    //Storage, see http://www.cplusplus.com/reference/stl/vector/
+    std::vector<cmdb_cmd> _cmds;
+    Serial _serial;
+    bool echo;
+    bool bold;
+
+    int CID_LAST;
+    int CMD_TBL_LEN;
+
+    //Macro's.
+    int macro_ptr;
+    char macro_buf[1 + MAX_CMD_LEN];
+
+    enum parmtype {
+        PARM_UNUSED,            //0
+
+        PARM_FLOAT,             //1     (f)
+
+        PARM_LONG,              //2     (l/ul)
+        PARM_INT,               //3     (i/ui)
+        PARM_SHORT,             //4     (w/uw)
+
+        PARM_CHAR,              //5     (c/uc)
+        PARM_STRING             //6     (s)
+    };
+
+    union value {
+        float               f;
+
+        unsigned long       ul;
+        long                 l;
+
+        int                  i;
+        unsigned int        ui;
+
+        short                w;
+        unsigned short      uw;
+
+        char                 c;
+        unsigned char       uc;
+
+        char                 s[MAX_PARM_LEN];
+    };
+
+    struct parm {
+        enum parmtype    type;
+        union value     val;
+    };
+
+//------------------------------------------------------------------------------
+//----These helper functions retieve parameters in the correct format.
+//------------------------------------------------------------------------------
+
+//TODO Add tests for correct type of parameter.
+
+    bool BOOLPARM(int ndx) {
+        return parms[ndx].val.uc!=0;
+    }
+
+    unsigned char BYTEPARM(int ndx) {
+        return parms[ndx].val.uc;
+    }
+
+    char CHARPARM(int ndx) {
+        return parms[ndx].val.c;
+    }
+
+    unsigned int WORDPARM(int ndx) {
+        return parms[ndx].val.ui;
+    }
+
+    unsigned int UINTPARM(int ndx) {
+        return parms[ndx].val.ui;
+    }
+
+    int INTPARM(int ndx) {
+        return parms[ndx].val.i;
+    }
+
+    unsigned long DWORDPARM(int ndx) {
+        return parms[ndx].val.ul;
+    }
+
+    long LONGPARM(int ndx) {
+        return parms[ndx].val.l;
+    }
+
+    float FLOATPARM(int ndx) {
+        return parms[ndx].val.f;
+    }
+
+    char* STRINGPARM(int ndx) {
+        return parms[ndx].val.s;
+    }
+
+//------------------------------------------------------------------------------
+//----Buffers
+//------------------------------------------------------------------------------
+
+    char            cmdbuf [1 + MAX_CMD_LEN];           // command buffer
+    char            cmdndx;                             // command index
+
+    char            lstbuf [1 + MAX_CMD_LEN];           // last command buffer
+
+    char            escbuf [1 + MAX_ESC_LEN];           // command buffer
+    unsigned char   escndx;                             // command index
+
+    struct          parm parms[MAX_ARGS];
+    int             noparms;
+
+    int             subsystem;
+
+    int     argcnt;                                     //No of arguments found in command
+    int     argfnd;                                     //No of arguments to find in parameter definition.
+    int     error;                                      //strtoXX() Error detection
+
+};
+
+#endif
\ No newline at end of file