Revision 10fd7ac9 core/src/aos_shell.c
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 |
|
Also available in: Unified diff