Revision c18a848e
core/src/aos_shell.c | ||
---|---|---|
578 | 578 |
aosDbgCheck(shell != NULL); |
579 | 579 |
|
580 | 580 |
// check whether input line is already full |
581 |
if (shell->inputdata.lineend + 1 >= shell->input.length) {
|
|
581 |
if (shell->inputdata.lineend + 1 >= shell->input.size) {
|
|
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.length);
|
|
586 |
memset(shell->input.line, '\0', shell->input.size);
|
|
587 | 587 |
shell->inputdata.noinput = false; |
588 | 588 |
} |
589 | 589 |
// overwrite content |
... | ... | |
716 | 716 |
* |
717 | 717 |
* @param[in] shell Pointer to the shell object. |
718 | 718 |
* @param[in] channel The channel to read from. |
719 |
* @param[out] n Optional pointer to a variable to store the number of read characters to.
|
|
719 |
* @param[out] exec Optional pointer to a flag, which indicates, whether a command shall be executed.
|
|
720 | 720 |
* |
721 |
* @return Indicator, whether the read character(s) indicated, that a command shall be executed.
|
|
721 |
* @return Number of read characters.
|
|
722 | 722 |
*/ |
723 |
static bool _readChannel(aos_shell_t* shell, AosShellChannel* channel, size_t* n)
|
|
723 |
static int _readChannel(aos_shell_t* shell, AosShellChannel* channel, bool* execute)
|
|
724 | 724 |
{ |
725 | 725 |
aosDbgCheck(shell != NULL); |
726 | 726 |
aosDbgCheck(channel != NULL); |
... | ... | |
729 | 729 |
aos_shellaction_t action = AOS_SHELL_ACTION_NONE; |
730 | 730 |
char c; |
731 | 731 |
special_key_t key; |
732 |
|
|
733 |
// initialize output variables |
|
734 |
if (n) { |
|
735 |
*n = 0; |
|
736 |
} |
|
732 |
int nchars = 0; |
|
733 |
bool exec = false; |
|
737 | 734 |
|
738 | 735 |
// read character by character from the channel |
739 | 736 |
while (chnReadTimeout(channel, (uint8_t*)&c, 1, TIME_IMMEDIATE)) { |
740 | 737 |
key = KEY_UNKNOWN; |
741 | 738 |
|
739 |
// drop any input after an execution request was detected |
|
740 |
if (exec) { |
|
741 |
continue; |
|
742 |
} |
|
743 |
|
|
744 |
// incremet character counter |
|
745 |
++nchars; |
|
746 |
|
|
742 | 747 |
// parse escape sequence |
743 | 748 |
if (strlen(shell->inputdata.escseq) > 0) { |
744 | 749 |
shell->inputdata.escseq[strlen(shell->inputdata.escseq)] = c; |
... | ... | |
946 | 951 |
if (cmatch > shell->inputdata.cursorpos || (cmatch == shell->inputdata.cursorpos && matchlevel == CHAR_MATCH_NCASE)) { |
947 | 952 |
shell->inputdata.noinput = false; |
948 | 953 |
// limit auto fill so it will not overflow the line width |
949 |
if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.length) {
|
|
950 |
cmatch = shell->input.length - shell->inputdata.lineend + shell->inputdata.cursorpos;
|
|
954 |
if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.size) {
|
|
955 |
cmatch = shell->input.size - shell->inputdata.lineend + shell->inputdata.cursorpos;
|
|
951 | 956 |
} |
952 | 957 |
// move trailing memory further in the line |
953 | 958 |
memmove(&(shell->input.line[cmatch]), &(shell->input.line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos); |
... | ... | |
1049 | 1054 |
size_t nul_start = 0; |
1050 | 1055 |
size_t nul_end = 0; |
1051 | 1056 |
// search line for a NUL byte |
1052 |
while (nul_start < shell->input.length) {
|
|
1057 |
while (nul_start < shell->input.size) {
|
|
1053 | 1058 |
if (shell->input.line[nul_start] == '\0') { |
1054 | 1059 |
nul_end = nul_start + 1; |
1055 | 1060 |
// keep searcjing for a byte that is not NUL |
1056 |
while (nul_end < shell->input.length) {
|
|
1061 |
while (nul_end < shell->input.size) {
|
|
1057 | 1062 |
if (shell->input.line[nul_end] != '\0') { |
1058 | 1063 |
// an intermediate NUL sequence was found |
1059 | 1064 |
memset(&(shell->input.line[nul_start]), ' ', nul_end - nul_start); |
... | ... | |
1148 | 1153 |
case AOS_SHELL_ACTION_EXECUTE: |
1149 | 1154 |
{ |
1150 | 1155 |
streamPut(&shell->stream, '\n'); |
1151 |
// set the number of read bytes and return
|
|
1156 |
// if there was some input
|
|
1152 | 1157 |
if (!shell->inputdata.noinput) { |
1153 |
if (n) { |
|
1154 |
*n = shell->input.length - shell->inputdata.lineend; |
|
1155 |
} |
|
1156 | 1158 |
// fill the remainder of the line with NUL bytes |
1157 |
memset(&(shell->input.line[shell->inputdata.lineend]), '\0', (shell->input.length - shell->inputdata.lineend));
|
|
1159 |
memset(&(shell->input.line[shell->inputdata.lineend]), '\0', shell->input.size - shell->inputdata.lineend);
|
|
1158 | 1160 |
} |
1159 |
return true; |
|
1161 |
// set the execution flag |
|
1162 |
exec = true; |
|
1163 |
break; |
|
1160 | 1164 |
} |
1161 | 1165 |
|
1162 | 1166 |
case AOS_SHELL_ACTION_ESCSTART: |
... | ... | |
1186 | 1190 |
shell->inputdata.lastaction = action; |
1187 | 1191 |
} /* end of while */ |
1188 | 1192 |
|
1189 |
// no more data could be read from the channel |
|
1190 |
return false; |
|
1193 |
// set the execution output flag |
|
1194 |
if (execute) { |
|
1195 |
*execute = exec; |
|
1196 |
} |
|
1197 |
|
|
1198 |
return nchars; |
|
1191 | 1199 |
} |
1192 | 1200 |
|
1193 | 1201 |
/** |
... | ... | |
1218 | 1226 |
size_t nargs = 0; |
1219 | 1227 |
|
1220 | 1228 |
// iterate through the line |
1221 |
for (char* c = shell->input.line; c < shell->input.line + shell->input.length; ++c) {
|
|
1229 |
for (char* c = shell->input.line; c < shell->input.line + shell->input.size; ++c) {
|
|
1222 | 1230 |
// terminate at first NUL byte |
1223 | 1231 |
if (*c == '\0') { |
1224 | 1232 |
state = END; |
... | ... | |
1601 | 1609 |
eventmask_t eventmask; |
1602 | 1610 |
eventflags_t eventflags; |
1603 | 1611 |
AosShellChannel* channel; |
1604 |
aos_status_t readeval;
|
|
1612 |
bool execute;
|
|
1605 | 1613 |
char* args[((aos_shell_t*)shell)->input.nargs]; |
1606 | 1614 |
size_t nargs = 0; |
1607 | 1615 |
aos_shellcommand_t* cmd; |
... | ... | |
1654 | 1662 |
while (channel != NULL) { |
1655 | 1663 |
eventflags = chEvtGetAndClearFlags(&channel->listener); |
1656 | 1664 |
// if there is new input and a command shall be executed |
1657 |
if ((eventflags & CHN_INPUT_AVAILABLE) && _readChannel((aos_shell_t*)shell, channel, NULL)) { |
|
1658 |
// parse input line to argument list |
|
1659 |
nargs = _parseArguments((aos_shell_t*)shell, args); |
|
1660 |
// check number of arguments |
|
1661 |
if (nargs > ((aos_shell_t*)shell)->input.nargs) { |
|
1662 |
// error too many arguments |
|
1663 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\ttoo many arguments\n"); |
|
1664 |
} else if (nargs > 0) { |
|
1665 |
// search command list for arg[0] and execute callback |
|
1666 |
cmd = ((aos_shell_t*)shell)->commands; |
|
1667 |
while (cmd != NULL) { |
|
1668 |
if (strcmp(args[0], cmd->name) == 0) { |
|
1669 |
((aos_shell_t*)shell)->execstatus.command = cmd; |
|
1670 |
chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_EXEC); |
|
1671 |
((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, (int)nargs, args); |
|
1672 |
chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_DONE); |
|
1673 |
// notify if the command was not successful |
|
1674 |
if (((aos_shell_t*)shell)->execstatus.retval != 0) { |
|
1675 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "command returned exit status %d\n", ((aos_shell_t*)shell)->execstatus.retval); |
|
1665 |
if (eventflags & CHN_INPUT_AVAILABLE) { |
|
1666 |
_readChannel((aos_shell_t*)shell, channel, &execute); |
|
1667 |
// an execution request was detected |
|
1668 |
if (execute && !((aos_shell_t*)shell)->inputdata.noinput) { |
|
1669 |
// parse input line to argument list |
|
1670 |
nargs = _parseArguments((aos_shell_t*)shell, args); |
|
1671 |
// check number of arguments |
|
1672 |
if (nargs > ((aos_shell_t*)shell)->input.nargs) { |
|
1673 |
// error too many arguments |
|
1674 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\ttoo many arguments\n"); |
|
1675 |
} else if (nargs > 0) { |
|
1676 |
// search command list for arg[0] and execute callback |
|
1677 |
cmd = ((aos_shell_t*)shell)->commands; |
|
1678 |
while (cmd != NULL) { |
|
1679 |
if (strcmp(args[0], cmd->name) == 0) { |
|
1680 |
((aos_shell_t*)shell)->execstatus.command = cmd; |
|
1681 |
chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_EXEC); |
|
1682 |
((aos_shell_t*)shell)->execstatus.retval = cmd->callback((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, (int)nargs, args); |
|
1683 |
chEvtBroadcastFlags(&(((aos_shell_t*)shell)->eventSource), AOS_SHELL_EVTFLAG_DONE); |
|
1684 |
// notify if the command was not successful |
|
1685 |
if (((aos_shell_t*)shell)->execstatus.retval != 0) { |
|
1686 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "command returned exit status %d\n", ((aos_shell_t*)shell)->execstatus.retval); |
|
1687 |
} |
|
1688 |
break; |
|
1676 | 1689 |
} |
1677 |
break; |
|
1678 |
} |
|
1679 |
cmd = cmd->next; |
|
1680 |
} /* end of while */ |
|
1690 |
cmd = cmd->next; |
|
1691 |
} /* end of while */ |
|
1681 | 1692 |
|
1682 |
// if no matching command was found, print an error |
|
1683 |
if (cmd == NULL) { |
|
1684 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", args[0]); |
|
1693 |
// if no matching command was found, print an error |
|
1694 |
if (cmd == NULL) { |
|
1695 |
chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", args[0]); |
|
1696 |
} |
|
1685 | 1697 |
} |
1686 | 1698 |
} |
1687 | 1699 |
|
1688 |
// reset some internal variables and eprint a new prompt
|
|
1689 |
if (readeval == AOS_SUCCESS && !chThdShouldTerminateX()) {
|
|
1700 |
// reset some internal variables and print a new prompt |
|
1701 |
if (execute && !chThdShouldTerminateX()) {
|
|
1690 | 1702 |
((aos_shell_t*)shell)->inputdata.cursorpos = 0; |
1691 | 1703 |
((aos_shell_t*)shell)->inputdata.lineend = 0; |
1692 | 1704 |
((aos_shell_t*)shell)->inputdata.noinput = true; |
Also available in: Unified diff