Revision 10fd7ac9

View differences:

core/inc/aos_shell.h
324 324
    /**
325 325
     * @brief   Size of the input buffer.
326 326
     */
327
    size_t width;
327
    size_t length;
328

  
329
    /**
330
     * @brief   Size of the argument buffer.
331
     */
332
    size_t nargs;
328 333
  } input;
329 334

  
330 335
  /**
......
357 362
    bool noinput;
358 363
  } inputdata;
359 364

  
360
  /**
361
   * @brief   Argument buffer.
362
   */
363
  char** arglist;
364 365

  
365
  /**
366
   * @brief   Size of the argument buffer.
367
   */
368
  size_t arglistsize;
369 366

  
370 367
  /**
371 368
   * @brief   Configuration flags.
......
397 394
#if defined(__cplusplus)
398 395
extern "C" {
399 396
#endif /* defined(__cplusplus) */
400
  void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, char** arglist, size_t arglistsize);
397
  void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, size_t numargs);
401 398
  void aosShellStreamInit(AosShellStream* stream);
402 399
  void aosShellChannelInit(AosShellChannel* channel, BaseAsynchronousChannel* asyncchannel);
403 400
  aos_status_t aosShellAddCommand(aos_shell_t* shell, aos_shellcommand_t* cmd);
core/src/aos_shell.c
544 544

  
545 545
  // move cursor right by printing line content
546 546
  while (pos < to) {
547
    streamPut(&shell->stream, shell->input.line[pos]);
547
    streamPut(&shell->stream, (uint8_t)shell->input.line[pos]);
548 548
    ++pos;
549 549
  }
550 550

  
......
568 568
  size_t cnt;
569 569

  
570 570
  for (cnt = 0; from + cnt < to; ++cnt) {
571
    streamPut(&shell->stream, shell->input.line[from + cnt]);
571
    streamPut(&shell->stream, (uint8_t)shell->input.line[from + cnt]);
572 572
  }
573 573

  
574 574
  return cnt;
......
578 578
  aosDbgCheck(shell != NULL);
579 579

  
580 580
  // check whether input line is already full
581
  if (shell->inputdata.lineend + 1 >= shell->input.width) {
581
  if (shell->inputdata.lineend + 1 >= shell->input.length) {
582 582
    return 0;
583 583
  } else {
584 584
    // clear old line content on first input
585 585
    if (shell->inputdata.noinput) {
586
      memset(shell->input.line, '\0', shell->input.width);
586
      memset(shell->input.line, '\0', shell->input.length);
587 587
      shell->inputdata.noinput = false;
588 588
    }
589 589
    // overwrite content
......
908 908
          charmatch_t mlvl = CHAR_MATCH_NOT;
909 909
          _strccmp(fill, cmd->name, shell->config & AOS_SHELL_CONFIG_MATCH_CASE, (n == 0) ? NULL : &n, &mlvl);
910 910
          const int cmp = (n < cmatch) ?
911
                            (n - cmatch) :
911
                            ((int)n - (int)cmatch) :
912 912
                            (cmd->name[n] != '\0') ?
913
                              strlen(cmd->name) - n :
913
                              (int)strlen(cmd->name) - (int)n :
914 914
                              0;
915 915
          // if an exact match was found
916
          if (cmatch + cmp == shell->inputdata.cursorpos) {
916
          if ((size_t)((int)cmatch + cmp) == shell->inputdata.cursorpos) {
917 917
            cmatch = shell->inputdata.cursorpos;
918 918
            fill = cmd->name;
919 919
            // break the loop only if there are no case mismatches with the input
......
924 924
            }
925 925
          }
926 926
          // if a not exact match was found
927
          else if (cmatch + cmp > shell->inputdata.cursorpos) {
927
          else if ((size_t)((int)cmatch + cmp) > shell->inputdata.cursorpos) {
928 928
            // if this is the first one
929 929
            if (fill == shell->input.line) {
930
              cmatch += cmp;
930
              cmatch = (size_t)((int)cmatch + cmp);
931 931
              fill = cmd->name;
932 932
            }
933 933
            // if this is a worse one
934 934
            else if ((cmp < 0) || (cmp == 0 && mlvl == CHAR_MATCH_CASE)) {
935
              cmatch += cmp;
935
              cmatch = (size_t)((int)cmatch + cmp);
936 936
            }
937 937
          }
938 938
          // non matching commands are ignored
......
945 945
        if (cmatch > shell->inputdata.cursorpos || (cmatch == shell->inputdata.cursorpos && matchlevel == CHAR_MATCH_NCASE)) {
946 946
          shell->inputdata.noinput = false;
947 947
          // limit auto fill so it will not overflow the line width
948
          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.width) {
949
            cmatch = shell->input.width - shell->inputdata.lineend + shell->inputdata.cursorpos;
948
          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.length) {
949
            cmatch = shell->input.length - shell->inputdata.lineend + shell->inputdata.cursorpos;
950 950
          }
951 951
          // move trailing memory further in the line
952 952
          memmove(&(shell->input.line[cmatch]), &(shell->input.line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
......
982 982
            _strccmp(shell->input.line, cmd->name, true, &i, NULL);
983 983
          }
984 984
          const int cmp = (i < shell->inputdata.cursorpos) ?
985
                            (i - shell->inputdata.cursorpos) :
985
                            (int)(i - shell->inputdata.cursorpos) :
986 986
                            (cmd->name[i] != '\0') ?
987
                              strlen(cmd->name) - i :
987
                              (int)strlen(cmd->name) - (int)i :
988 988
                              0;
989 989
          // if a match was found
990 990
          if (cmp > 0) {
......
1048 1048
        size_t nul_start = 0;
1049 1049
        size_t nul_end = 0;
1050 1050
        // search line for a NUL byte
1051
        while (nul_start < shell->input.width) {
1051
        while (nul_start < shell->input.length) {
1052 1052
          if (shell->input.line[nul_start] == '\0') {
1053 1053
            nul_end = nul_start + 1;
1054 1054
            // keep searcjing for a byte that is not NUL
1055
            while (nul_end < shell->input.width) {
1055
            while (nul_end < shell->input.length) {
1056 1056
              if (shell->input.line[nul_end] != '\0') {
1057 1057
                // an intermediate NUL sequence was found
1058 1058
                memset(&(shell->input.line[nul_start]), ' ', nul_end - nul_start);
......
1149 1149
        streamPut(&shell->stream, '\n');
1150 1150
        // set the number of read bytes and return
1151 1151
        if (!shell->inputdata.noinput) {
1152
          *n = shell->input.width - shell->inputdata.lineend;
1152
          *n = shell->input.length - shell->inputdata.lineend;
1153 1153
          // fill the remainder of the line with NUL bytes
1154 1154
          memset(&(shell->input.line[shell->inputdata.lineend]), '\0', *n);
1155 1155
          // reset static variables
......
1192 1192
/**
1193 1193
 * @brief   Parses the content of the input buffer (line) to separate arguments.
1194 1194
 *
1195
 * @param[in] shell   Pointer to the shell object.
1195
 * @param[in]   shell   Pointer to the shell object.
1196
 * @param[out]  argbuf  Buffer to store argument pointers to.
1196 1197
 *
1197 1198
 * @return            Number of arguments found.
1198 1199
 */
1199
static size_t _parseArguments(aos_shell_t* shell)
1200
static size_t _parseArguments(aos_shell_t* shell, char** argbuf)
1200 1201
{
1201 1202
  aosDbgCheck(shell != NULL);
1203
  aosDbgCheck(argbuf != NULL);
1202 1204

  
1203 1205
  /*
1204 1206
   * States for a very small FSM.
......
1212 1214

  
1213 1215
  // local variables
1214 1216
  state_t state = START;
1215
  size_t arg = 0;
1217
  size_t nargs = 0;
1216 1218

  
1217 1219
  // iterate through the line
1218
  for (char* c = shell->input.line; c < shell->input.line + shell->input.width; ++c) {
1220
  for (char* c = shell->input.line; c < shell->input.line + shell->input.length; ++c) {
1219 1221
    // terminate at first NUL byte
1220 1222
    if (*c == '\0') {
1221 1223
      state = END;
......
1232 1234
        case START:
1233 1235
        case SPACE:
1234 1236
          // ignore too many arguments
1235
          if (arg < shell->arglistsize) {
1236
            shell->arglist[arg] = c;
1237
          if (nargs < shell->input.nargs) {
1238
            argbuf[nargs] = c;
1237 1239
          }
1238
          ++arg;
1240
          ++nargs;
1239 1241
          break;
1240 1242
        case TEXT:
1241 1243
        case END:
1242
        default:
1243 1244
          break;
1244 1245
      }
1245 1246
      state = TEXT;
......
1247 1248
  }
1248 1249

  
1249 1250
  // set all remaining argument pointers to NULL
1250
  for (size_t a = arg; a < shell->arglistsize; ++a) {
1251
    shell->arglist[a] = NULL;
1251
  for (size_t a = nargs; a < shell->input.nargs; ++a) {
1252
    argbuf[a] = NULL;
1252 1253
  }
1253 1254

  
1254
  return arg;
1255
  return nargs;
1255 1256
}
1256 1257

  
1257 1258
/******************************************************************************/
......
1266 1267
 * @param[in] prompt        Prompt line to print (NULL = use default prompt).
1267 1268
 * @param[in] line          Pointer to the input buffer.
1268 1269
 * @param[in] linesize      Size of the input buffer.
1269
 * @param[in] arglist       Pointer to the argument buffer.
1270
 * @param[in] arglistsize   Size of te argument buffer.
1270
 * @param[in] numargs       Maximum number of arguments (defines size of internal buffer).
1271 1271
 */
1272
void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, char** arglist, size_t arglistsize)
1272
void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, size_t numargs)
1273 1273
{
1274 1274
  aosDbgCheck(shell != NULL);
1275 1275
  aosDbgCheck(oseventsource != NULL);
1276 1276
  aosDbgCheck(line != NULL);
1277
  aosDbgCheck(arglist != NULL);
1278 1277

  
1279 1278
  // set parameters
1280 1279
  shell->thread = NULL;
......
1286 1285
  shell->execstatus.command = NULL;
1287 1286
  shell->execstatus.retval = 0;
1288 1287
  shell->input.line = line;
1289
  shell->input.width = linesize;
1288
  shell->input.length = linesize;
1290 1289
  shell->inputdata.lastaction = AOS_SHELL_ACTION_NONE;
1291 1290
  memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
1292 1291
  shell->inputdata.cursorpos = 0;
1293 1292
  shell->inputdata.lineend = 0;
1294 1293
  shell->inputdata.noinput = true;
1295
  shell->arglist = arglist;
1296
  shell->arglistsize = arglistsize;
1294
  shell->input.nargs= numargs;
1297 1295
  shell->config = 0x00;
1298 1296

  
1299 1297
  // initialize buffers
1300
  memset(shell->input.line, '\0', shell->input.width);
1301
  for (size_t a = 0; a < shell->arglistsize; ++a) {
1302
    shell->arglist[a] = NULL;
1303
  }
1298
  memset(shell->input.line, '\0', shell->input.length);
1304 1299

  
1305 1300
  return;
1306 1301
}
......
1607 1602
  AosShellChannel* channel;
1608 1603
  aos_status_t readeval;
1609 1604
  size_t nchars = 0;
1605
  char* args[((aos_shell_t*)shell)->input.nargs];
1610 1606
  size_t nargs = 0;
1611 1607
  aos_shellcommand_t* cmd;
1612 1608

  
1609
  // initialize variables
1610
  for (size_t arg = 0; arg < ((aos_shell_t*)shell)->input.nargs; ++arg) {
1611
    args[arg] = NULL;
1612
  }
1613 1613

  
1614 1614
  // register OS related events
1615 1615
  chEvtRegisterMask(((aos_shell_t*)shell)->os.eventSource, &(((aos_shell_t*)shell)->os.eventListener), AOS_SHELL_EVENTMASK_OS);
......
1658 1658
            // read input from channel
1659 1659
            readeval = _readChannel((aos_shell_t*)shell, channel, &nchars);
1660 1660
            // parse input line to argument list only if the input shall be executed
1661
            nargs = (readeval == AOS_SUCCESS && nchars > 0) ? _parseArguments((aos_shell_t*)shell) : 0;
1661
            nargs = (readeval == AOS_SUCCESS && nchars > 0) ? _parseArguments((aos_shell_t*)shell, args) : 0;
1662 1662
            // check number of arguments
1663
            if (nargs > ((aos_shell_t*)shell)->arglistsize) {
1663
            if (nargs > ((aos_shell_t*)shell)->input.nargs) {
1664 1664
              // error too many arguments
1665 1665
              chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\ttoo many arguments\n");
1666 1666
            } else if (nargs > 0) {
1667 1667
              // search command list for arg[0] and execute callback
1668 1668
              cmd = ((aos_shell_t*)shell)->commands;
1669 1669
              while (cmd != NULL) {
1670
                if (strcmp(((aos_shell_t*)shell)->arglist[0], cmd->name) == 0) {
1670
                if (strcmp(args[0], cmd->name) == 0) {
1671 1671
                  ((aos_shell_t*)shell)->execstatus.command = cmd;
1672 1672
                  chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_EXEC);
1673
                  ((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, nargs, ((aos_shell_t*)shell)->arglist);
1673
                  ((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, (int)nargs, args);
1674 1674
                  chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_DONE);
1675 1675
                  // notify if the command was not successful
1676 1676
                  if (((aos_shell_t*)shell)->execstatus.retval != 0) {
......
1683 1683

  
1684 1684
              // if no matching command was found, print an error
1685 1685
              if (cmd == NULL) {
1686
                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", ((aos_shell_t*)shell)->arglist[0]);
1686
                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", args[0]);
1687 1687
              }
1688 1688
            }
1689 1689

  
core/src/aos_system.c
104 104
/**
105 105
 * @brief   Shell thread working area.
106 106
 */
107
THD_WORKING_AREA(_shell_wa, AMIROOS_CFG_SHELL_STACKSIZE);
107
static THD_WORKING_AREA(_shell_wa, AMIROOS_CFG_SHELL_STACKSIZE);
108 108

  
109 109
/**
110 110
 * @brief   Shell input buffer.
......
112 112
static char _shell_line[AMIROOS_CFG_SHELL_LINEWIDTH];
113 113

  
114 114
/**
115
 * @brief   Shell argument buffer.
116
 */
117
static char* _shell_arglist[AMIROOS_CFG_SHELL_MAXARGS];
118

  
119
/**
120 115
 * @brief   Shell command to retrieve system information.
121 116
 */
122 117
static AOS_SHELL_COMMAND(_shellcmd_info, "module:info", _shellcmd_infocb);
......
512 507
  // print shell info
513 508
  chprintf(stream, "System shell information:\n");
514 509
  chprintf(stream, "\tcommands available:     %u\n", aosShellCountCommands(&aos.shell));
515
  chprintf(stream, "\tline width:             %u characters\n", aos.shell.input.width);
516
  chprintf(stream, "\tmaximum arguments:      %u\n", aos.shell.arglistsize);
510
  chprintf(stream, "\tline width:             %u characters\n", aos.shell.input.length);
511
  chprintf(stream, "\tmaximum arguments:      %u\n", aos.shell.input.nargs);
517 512
#if (AMIROOS_CFG_DBG == true)
518 513
  chprintf(stream, "\tthread stack size:      %u bytes\n", aosThdGetStacksize(aos.shell.thread));
519 514
#if (CH_DBG_FILL_THREADS == TRUE)
......
747 742
               shellPrompt,
748 743
               _shell_line,
749 744
               AMIROOS_CFG_SHELL_LINEWIDTH,
750
               _shell_arglist,
751 745
               AMIROOS_CFG_SHELL_MAXARGS);
752 746
  // add system commands
753 747
  aosShellAddCommand(&aos.shell, &_shellcmd_config);

Also available in: Unified diff