commit 10fd7ac9a80538e063b21f22f48dcf1e2a41369c
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Mon Dec 16 10:42:16 2019 +0100

    shell: argument buffer is now a stack variable of the thread.

diff --git a/core/src/aos_shell.c b/core/src/aos_shell.c
index 3e4ceea..2342447 100644
--- a/core/src/aos_shell.c
+++ b/core/src/aos_shell.c
@@ -544,7 +544,7 @@ static int _moveCursor(aos_shell_t* shell, const size_t from, const size_t to)
 
   // move cursor right by printing line content
   while (pos < to) {
-    streamPut(&shell->stream, shell->input.line[pos]);
+    streamPut(&shell->stream, (uint8_t)shell->input.line[pos]);
     ++pos;
   }
 
@@ -568,7 +568,7 @@ static inline size_t _printLine(aos_shell_t* shell, const size_t from, const siz
   size_t cnt;
 
   for (cnt = 0; from + cnt < to; ++cnt) {
-    streamPut(&shell->stream, shell->input.line[from + cnt]);
+    streamPut(&shell->stream, (uint8_t)shell->input.line[from + cnt]);
   }
 
   return cnt;
@@ -578,12 +578,12 @@ static int _readChar(aos_shell_t* shell, const char c) {
   aosDbgCheck(shell != NULL);
 
   // check whether input line is already full
-  if (shell->inputdata.lineend + 1 >= shell->input.width) {
+  if (shell->inputdata.lineend + 1 >= shell->input.length) {
     return 0;
   } else {
     // clear old line content on first input
     if (shell->inputdata.noinput) {
-      memset(shell->input.line, '\0', shell->input.width);
+      memset(shell->input.line, '\0', shell->input.length);
       shell->inputdata.noinput = false;
     }
     // overwrite content
@@ -908,12 +908,12 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
           charmatch_t mlvl = CHAR_MATCH_NOT;
           _strccmp(fill, cmd->name, shell->config & AOS_SHELL_CONFIG_MATCH_CASE, (n == 0) ? NULL : &n, &mlvl);
           const int cmp = (n < cmatch) ?
-                            (n - cmatch) :
+                            ((int)n - (int)cmatch) :
                             (cmd->name[n] != '\0') ?
-                              strlen(cmd->name) - n :
+                              (int)strlen(cmd->name) - (int)n :
                               0;
           // if an exact match was found
-          if (cmatch + cmp == shell->inputdata.cursorpos) {
+          if ((size_t)((int)cmatch + cmp) == shell->inputdata.cursorpos) {
             cmatch = shell->inputdata.cursorpos;
             fill = cmd->name;
             // break the loop only if there are no case mismatches with the input
@@ -924,15 +924,15 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
             }
           }
           // if a not exact match was found
-          else if (cmatch + cmp > shell->inputdata.cursorpos) {
+          else if ((size_t)((int)cmatch + cmp) > shell->inputdata.cursorpos) {
             // if this is the first one
             if (fill == shell->input.line) {
-              cmatch += cmp;
+              cmatch = (size_t)((int)cmatch + cmp);
               fill = cmd->name;
             }
             // if this is a worse one
             else if ((cmp < 0) || (cmp == 0 && mlvl == CHAR_MATCH_CASE)) {
-              cmatch += cmp;
+              cmatch = (size_t)((int)cmatch + cmp);
             }
           }
           // non matching commands are ignored
@@ -945,8 +945,8 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
         if (cmatch > shell->inputdata.cursorpos || (cmatch == shell->inputdata.cursorpos && matchlevel == CHAR_MATCH_NCASE)) {
           shell->inputdata.noinput = false;
           // limit auto fill so it will not overflow the line width
-          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.width) {
-            cmatch = shell->input.width - shell->inputdata.lineend + shell->inputdata.cursorpos;
+          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.length) {
+            cmatch = shell->input.length - shell->inputdata.lineend + shell->inputdata.cursorpos;
           }
           // move trailing memory further in the line
           memmove(&(shell->input.line[cmatch]), &(shell->input.line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
@@ -982,9 +982,9 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
             _strccmp(shell->input.line, cmd->name, true, &i, NULL);
           }
           const int cmp = (i < shell->inputdata.cursorpos) ?
-                            (i - shell->inputdata.cursorpos) :
+                            (int)(i - shell->inputdata.cursorpos) :
                             (cmd->name[i] != '\0') ?
-                              strlen(cmd->name) - i :
+                              (int)strlen(cmd->name) - (int)i :
                               0;
           // if a match was found
           if (cmp > 0) {
@@ -1048,11 +1048,11 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
         size_t nul_start = 0;
         size_t nul_end = 0;
         // search line for a NUL byte
-        while (nul_start < shell->input.width) {
+        while (nul_start < shell->input.length) {
           if (shell->input.line[nul_start] == '\0') {
             nul_end = nul_start + 1;
             // keep searcjing for a byte that is not NUL
-            while (nul_end < shell->input.width) {
+            while (nul_end < shell->input.length) {
               if (shell->input.line[nul_end] != '\0') {
                 // an intermediate NUL sequence was found
                 memset(&(shell->input.line[nul_start]), ' ', nul_end - nul_start);
@@ -1149,7 +1149,7 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
         streamPut(&shell->stream, '\n');
         // set the number of read bytes and return
         if (!shell->inputdata.noinput) {
-          *n = shell->input.width - shell->inputdata.lineend;
+          *n = shell->input.length - shell->inputdata.lineend;
           // fill the remainder of the line with NUL bytes
           memset(&(shell->input.line[shell->inputdata.lineend]), '\0', *n);
           // reset static variables
@@ -1192,13 +1192,15 @@ static aos_status_t _readChannel(aos_shell_t* shell, AosShellChannel* channel, s
 /**
  * @brief   Parses the content of the input buffer (line) to separate arguments.
  *
- * @param[in] shell   Pointer to the shell object.
+ * @param[in]   shell   Pointer to the shell object.
+ * @param[out]  argbuf  Buffer to store argument pointers to.
  *
  * @return            Number of arguments found.
  */
-static size_t _parseArguments(aos_shell_t* shell)
+static size_t _parseArguments(aos_shell_t* shell, char** argbuf)
 {
   aosDbgCheck(shell != NULL);
+  aosDbgCheck(argbuf != NULL);
 
   /*
    * States for a very small FSM.
@@ -1212,10 +1214,10 @@ static size_t _parseArguments(aos_shell_t* shell)
 
   // local variables
   state_t state = START;
-  size_t arg = 0;
+  size_t nargs = 0;
 
   // iterate through the line
-  for (char* c = shell->input.line; c < shell->input.line + shell->input.width; ++c) {
+  for (char* c = shell->input.line; c < shell->input.line + shell->input.length; ++c) {
     // terminate at first NUL byte
     if (*c == '\0') {
       state = END;
@@ -1232,14 +1234,13 @@ static size_t _parseArguments(aos_shell_t* shell)
         case START:
         case SPACE:
           // ignore too many arguments
-          if (arg < shell->arglistsize) {
-            shell->arglist[arg] = c;
+          if (nargs < shell->input.nargs) {
+            argbuf[nargs] = c;
           }
-          ++arg;
+          ++nargs;
           break;
         case TEXT:
         case END:
-        default:
           break;
       }
       state = TEXT;
@@ -1247,11 +1248,11 @@ static size_t _parseArguments(aos_shell_t* shell)
   }
 
   // set all remaining argument pointers to NULL
-  for (size_t a = arg; a < shell->arglistsize; ++a) {
-    shell->arglist[a] = NULL;
+  for (size_t a = nargs; a < shell->input.nargs; ++a) {
+    argbuf[a] = NULL;
   }
 
-  return arg;
+  return nargs;
 }
 
 /******************************************************************************/
@@ -1266,15 +1267,13 @@ static size_t _parseArguments(aos_shell_t* shell)
  * @param[in] prompt        Prompt line to print (NULL = use default prompt).
  * @param[in] line          Pointer to the input buffer.
  * @param[in] linesize      Size of the input buffer.
- * @param[in] arglist       Pointer to the argument buffer.
- * @param[in] arglistsize   Size of te argument buffer.
+ * @param[in] numargs       Maximum number of arguments (defines size of internal buffer).
  */
-void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, char** arglist, size_t arglistsize)
+void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, size_t numargs)
 {
   aosDbgCheck(shell != NULL);
   aosDbgCheck(oseventsource != NULL);
   aosDbgCheck(line != NULL);
-  aosDbgCheck(arglist != NULL);
 
   // set parameters
   shell->thread = NULL;
@@ -1286,21 +1285,17 @@ void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char*
   shell->execstatus.command = NULL;
   shell->execstatus.retval = 0;
   shell->input.line = line;
-  shell->input.width = linesize;
+  shell->input.length = linesize;
   shell->inputdata.lastaction = AOS_SHELL_ACTION_NONE;
   memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
   shell->inputdata.cursorpos = 0;
   shell->inputdata.lineend = 0;
   shell->inputdata.noinput = true;
-  shell->arglist = arglist;
-  shell->arglistsize = arglistsize;
+  shell->input.nargs= numargs;
   shell->config = 0x00;
 
   // initialize buffers
-  memset(shell->input.line, '\0', shell->input.width);
-  for (size_t a = 0; a < shell->arglistsize; ++a) {
-    shell->arglist[a] = NULL;
-  }
+  memset(shell->input.line, '\0', shell->input.length);
 
   return;
 }
@@ -1607,9 +1602,14 @@ void aosShellThread(void* shell)
   AosShellChannel* channel;
   aos_status_t readeval;
   size_t nchars = 0;
+  char* args[((aos_shell_t*)shell)->input.nargs];
   size_t nargs = 0;
   aos_shellcommand_t* cmd;
 
+  // initialize variables
+  for (size_t arg = 0; arg < ((aos_shell_t*)shell)->input.nargs; ++arg) {
+    args[arg] = NULL;
+  }
 
   // register OS related events
   chEvtRegisterMask(((aos_shell_t*)shell)->os.eventSource, &(((aos_shell_t*)shell)->os.eventListener), AOS_SHELL_EVENTMASK_OS);
@@ -1658,19 +1658,19 @@ void aosShellThread(void* shell)
             // read input from channel
             readeval = _readChannel((aos_shell_t*)shell, channel, &nchars);
             // parse input line to argument list only if the input shall be executed
-            nargs = (readeval == AOS_SUCCESS && nchars > 0) ? _parseArguments((aos_shell_t*)shell) : 0;
+            nargs = (readeval == AOS_SUCCESS && nchars > 0) ? _parseArguments((aos_shell_t*)shell, args) : 0;
             // check number of arguments
-            if (nargs > ((aos_shell_t*)shell)->arglistsize) {
+            if (nargs > ((aos_shell_t*)shell)->input.nargs) {
               // error too many arguments
               chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\ttoo many arguments\n");
             } else if (nargs > 0) {
               // search command list for arg[0] and execute callback
               cmd = ((aos_shell_t*)shell)->commands;
               while (cmd != NULL) {
-                if (strcmp(((aos_shell_t*)shell)->arglist[0], cmd->name) == 0) {
+                if (strcmp(args[0], cmd->name) == 0) {
                   ((aos_shell_t*)shell)->execstatus.command = cmd;
                   chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_EXEC);
-                  ((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, nargs, ((aos_shell_t*)shell)->arglist);
+                  ((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, (int)nargs, args);
                   chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_DONE);
                   // notify if the command was not successful
                   if (((aos_shell_t*)shell)->execstatus.retval != 0) {
@@ -1683,7 +1683,7 @@ void aosShellThread(void* shell)
 
               // if no matching command was found, print an error
               if (cmd == NULL) {
-                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", ((aos_shell_t*)shell)->arglist[0]);
+                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", args[0]);
               }
             }
 
