Vergil Cola / SerialShell

Dependents:   FRDM_K64F_IOT lpc1768_blinky

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Shell.cpp Source File

Shell.cpp

00001 #include "mbed.h"
00002 #include "cmsis_os.h"
00003 
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <stdarg.h>
00007 // cpp headers
00008 #include <string>
00009 #include <cctype>
00010 
00011 
00012 
00013 #include "Shell.h"
00014 
00015 
00016 static char *_strtok(char *str, const char *delim, char **saveptr) 
00017 {
00018   char *token;
00019   if (str)
00020     *saveptr = str;
00021   token = *saveptr;
00022 
00023   if (!token)
00024     return NULL;
00025 
00026   token += strspn(token, delim);
00027   *saveptr = strpbrk(token, delim);
00028   if (*saveptr)
00029     *(*saveptr)++ = '\0';
00030 
00031   return *token ? token : NULL;
00032 }
00033 
00034 
00035 Shell::Shell(Stream * channel)
00036     :_chp(channel)
00037 {
00038     _commands.clear();
00039 }
00040 
00041 void Shell::addCommand(std::string name, shellcmd_t func)
00042 {
00043     _commands.insert(std::pair<std::string, shellcmd_t>(name, func));
00044 }
00045 
00046 void Shell::start(osPriority priority,
00047                 int stackSize,
00048                 unsigned char *stack_pointer)
00049 {
00050     _thread = new Thread(Shell::threadHelper, this, priority, stackSize, stack_pointer);
00051 }
00052 
00053 void Shell::threadHelper(const void * arg)
00054 {
00055     Shell * pinstance = static_cast<Shell *>(const_cast<void *>(arg));
00056 
00057     pinstance->shellMain();
00058 }
00059 
00060 void Shell::shellUsage(const char *p) 
00061 {
00062      _chp->printf("Usage: %s\r\n", p);
00063 }
00064 
00065 void Shell::listCommands()
00066 {
00067     std::map<std::string, shellcmd_t>::iterator it;
00068     for (it = _commands.begin(); it != _commands.end(); it++)
00069         _chp->printf("%s ", (*it).first.c_str());
00070 }
00071 
00072 bool Shell::cmdExec(char * name, int argc, char *argv[])
00073 {
00074     std::map<std::string, shellcmd_t>::iterator it;
00075     it = _commands.find(std::string(name));
00076     if (it != _commands.end())
00077     {
00078         it->second(_chp, argc, argv);
00079         return true;
00080     }
00081 
00082     return false;
00083 }
00084 
00085 
00086 void Shell::shellMain() 
00087 {
00088   int n;
00089   char *lp, *cmd, *tokp;
00090 
00091   _chp->printf("\r\nEmbed/RX Shell\r\n");
00092   while (true) {
00093     _chp->printf(">> ");
00094     if (shellGetLine(line, sizeof(line))) {
00095       _chp->printf("\r\nlogout");
00096       break;
00097     }
00098     // Get the command
00099     lp = _strtok(line, " \t", &tokp);
00100     cmd = lp;
00101 
00102     // Get the arguments
00103     n = 0;
00104     while ((lp = _strtok(NULL, " \t", &tokp)) != NULL) {
00105       if (n >= SHELL_MAX_ARGUMENTS) {
00106         _chp->printf("too many arguments\r\n");
00107         cmd = NULL;
00108         break;
00109       }
00110       args[n++] = lp;
00111     }
00112     args[n] = NULL;
00113 
00114     // Determine the command
00115     if (cmd != NULL) 
00116     {
00117       if (strcasecmp(cmd, "exit") == 0)     // If "exit"
00118       {
00119         if (n > 0) {
00120           shellUsage("exit");
00121           continue;
00122         }
00123                 // Break here breaks the outer loop
00124                 // hence, we exit the shell.
00125         break;
00126       }
00127       else if (strcasecmp(cmd, "help") == 0) // If "help"
00128       {
00129         if (n > 0) {
00130           shellUsage("help");
00131           continue;
00132         }
00133         _chp->printf("Commands: help exit ");
00134         listCommands();
00135         _chp->printf("\r\n");
00136       }
00137       else if (!cmdExec(cmd, n, args))       // Finally call exec on the command
00138       {
00139         // If the command is unknown
00140         _chp->printf("%s", cmd);
00141         _chp->printf(" ?\r\n");
00142       }
00143     } // cmd != NULL
00144   }
00145 }
00146 
00147 bool Shell::shellGetLine(char *line, unsigned size) 
00148 {
00149   char *p = line;
00150 
00151   while (true) {
00152     char c;
00153 
00154     if ((c = _chp->getc()) == 0)
00155       return true;
00156     if (c == 4) {
00157       _chp->printf("^D");
00158       return true;
00159     }
00160     if (c == 8) {
00161       if (p != line) {
00162         _chp->putc(c);
00163         _chp->putc(0x20);
00164         _chp->putc(c);
00165         p--;
00166       }
00167       continue;
00168     }
00169     if (c == '\r') {
00170       _chp->printf("\r\n");
00171       *p = 0;
00172       return false;
00173     }
00174     if (c < 0x20)
00175       continue;
00176     if (p < line + size - 1) {
00177       _chp->putc(c);
00178       *p++ = (char)c;
00179     }
00180   }
00181 }