- IPS200 display menu with real-time status and parameter settings - Camera image processing and line tracking - IMU attitude solution and PID control - WiFi SPI oscilloscope data transmission
1336 lines
41 KiB
C
1336 lines
41 KiB
C
/**
|
|
* \file Ifx_Shell.c
|
|
* \brief shell functions.
|
|
*
|
|
* \version disabled
|
|
* \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
|
|
*
|
|
*
|
|
* IMPORTANT NOTICE
|
|
*
|
|
*
|
|
* Use of this file is subject to the terms of use agreed between (i) you or
|
|
* the company in which ordinary course of business you are acting and (ii)
|
|
* Infineon Technologies AG or its licensees. If and as long as no such
|
|
* terms of use are agreed, use of this file is subject to following:
|
|
|
|
|
|
* Boost Software License - Version 1.0 - August 17th, 2003
|
|
|
|
* Permission is hereby granted, free of charge, to any person or
|
|
* organization obtaining a copy of the software and accompanying
|
|
* documentation covered by this license (the "Software") to use, reproduce,
|
|
* display, distribute, execute, and transmit the Software, and to prepare
|
|
* derivative works of the Software, and to permit third-parties to whom the
|
|
* Software is furnished to do so, all subject to the following:
|
|
|
|
* The copyright notices in the Software and this entire statement, including
|
|
* the above license grant, this restriction and the following disclaimer, must
|
|
* be included in all copies of the Software, in whole or in part, and all
|
|
* derivative works of the Software, unless such copies or derivative works are
|
|
* solely in the form of machine-executable object code generated by a source
|
|
* language processor.
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
#include "Ifx_Shell.h"
|
|
#include "_Utilities/Ifx_Assert.h"
|
|
#include "Cpu/Std/IfxCpu_Intrinsics.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#define IFX_SHELL_LLD "%lld "
|
|
#define IFX_SHELL_LLX "%llx "
|
|
#define IFX_SHELL_LLU "%llu "
|
|
|
|
//---------------------------------------------------------------------------
|
|
#define IFX_SHELL_MAX_MESSAGE_SIZE 255
|
|
//---------------------------------------------------------------------------
|
|
|
|
/* Macro to detect space character */
|
|
#define ISSPACE(c) (((c) == ' ') || ((c) == '\t'))
|
|
|
|
/* Macro to only execute parameter if echo is enabled for this shell */
|
|
#define IFX_SHELL_IF_ECHO(X) {if (shell->control.echo) {X; }}
|
|
|
|
/* Macro to write lots of spaces */
|
|
#define IFX_SHELL_WRITE_SPACES(X) \
|
|
{int ii; for (ii = 0; ii < (X); ii++) {IfxStdIf_DPipe_print(shell->io, " "); }}
|
|
|
|
/* Macro to write lots of backspaces */
|
|
#define IFX_SHELL_WRITE_BACKSPACES(X) \
|
|
{int ii; for (ii = 0; ii < (X); ii++) {IfxStdIf_DPipe_print(shell->io, "\b"); }}
|
|
|
|
//---------------------------------------------------------------------------
|
|
char Ifx_Shell_cmdBuffer[IFX_CFG_SHELL_CMD_LINE_SIZE * IFX_CFG_SHELL_CMD_HISTORY_SIZE];
|
|
//---------------------------------------------------------------------------
|
|
void Ifx_Shell_execute(Ifx_Shell *shell, pchar commandLine);
|
|
void Ifx_Shell_cmdEscapeProcess(Ifx_Shell *shell, char EscapeChar1, char EscapeChar2);
|
|
const Ifx_Shell_Command *Ifx_Shell_commandListFind(Ifx_Shell *shell, pchar commandLine, pchar *args, Ifx_Shell_CommandListConst *commandList);
|
|
static boolean Ifx_Shell_matchCommand(pchar *argsPtr, pchar *match);
|
|
|
|
//---------------------------------------------------------------------------
|
|
/**
|
|
* \brief Check whether the args is already at the end.
|
|
* \param args The argument null-terminated string
|
|
*/
|
|
boolean Ifx_Shell_isEndOfLine(pchar args)
|
|
{
|
|
return ((args == NULL_PTR) || (*args == IFX_SHELL_NULL_CHAR)) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
static boolean Ifx_Shell_writeResult(Ifx_Shell *shell, Ifx_SizeT Code)
|
|
{
|
|
Ifx_SizeT length = sizeof(Code);
|
|
boolean result = IfxStdIf_DPipe_write(shell->io, &Code, &length, TIME_INFINITE);
|
|
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, result != FALSE);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
boolean Ifx_Shell_showHelpSingle(Ifx_Shell_CommandListConst commandList, IfxStdIf_DPipe *io, boolean briefOnly, boolean singleCommand)
|
|
{
|
|
const Ifx_Shell_Command *command = commandList;
|
|
uint32 index = 0;
|
|
pchar space = "";
|
|
pchar spaceParam = "";
|
|
|
|
while (command->commandLine != NULL_PTR)
|
|
{
|
|
pchar help = command->help;
|
|
pchar chunk;
|
|
boolean isParam = FALSE;
|
|
boolean isSyntax = FALSE;
|
|
IfxStdIf_DPipe_print(io, "%s%s", space, command->commandLine);
|
|
|
|
while (*help != IFX_SHELL_NULL_CHAR)
|
|
{
|
|
Ifx_SizeT count;
|
|
pchar matchp = "/p";
|
|
pchar matchs = "/s";
|
|
spaceParam = "";
|
|
|
|
if (Ifx_Shell_matchCommand(&help, &matchp))
|
|
{ /* Parameter description found */
|
|
isParam = TRUE;
|
|
isSyntax = FALSE,
|
|
spaceParam = " ";
|
|
}
|
|
else if (Ifx_Shell_matchCommand(&help, &matchs))
|
|
{ /* Parameter description found */
|
|
isParam = FALSE;
|
|
isSyntax = TRUE,
|
|
spaceParam = " SYNTAX: ";
|
|
}
|
|
else
|
|
{ /* Other text */
|
|
if (isParam)
|
|
{ /* Show param details*/
|
|
spaceParam = " ";
|
|
}
|
|
else if (isSyntax)
|
|
{ /* Show param details*/
|
|
spaceParam = " ";
|
|
}
|
|
}
|
|
|
|
/* Split print by ENDL */
|
|
chunk = strstr(help, ENDL);
|
|
|
|
if (chunk == NULL_PTR)
|
|
{
|
|
chunk = help + strlen(help);
|
|
}
|
|
else
|
|
{
|
|
if (!briefOnly)
|
|
{
|
|
chunk += strlen(ENDL);
|
|
}
|
|
}
|
|
|
|
count = chunk - help;
|
|
IfxStdIf_DPipe_print(io, "%s%s", space, spaceParam);
|
|
IfxStdIf_DPipe_write(io, (void *)help, &count, TIME_INFINITE);
|
|
|
|
help += count;
|
|
|
|
if (briefOnly)
|
|
{ /* Print Brief only */
|
|
break;
|
|
}
|
|
}
|
|
|
|
IfxStdIf_DPipe_print(io, ENDL);
|
|
|
|
if ((command->call == NULL_PTR) && (index == 0))
|
|
{
|
|
index = 1;
|
|
space = " ";
|
|
}
|
|
|
|
command = &command[1];
|
|
|
|
if (singleCommand)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_showHelpSingleCommand(pchar args, void *shellPtr, IfxStdIf_DPipe *io)
|
|
{
|
|
Ifx_Shell_CommandListConst commandList;
|
|
const Ifx_Shell_Command *shellCommand = Ifx_Shell_commandListFind(shellPtr, args, &args, &commandList);
|
|
|
|
if (shellCommand != NULL_PTR)
|
|
{
|
|
if (shellCommand->call == NULL_PTR)
|
|
{
|
|
Ifx_Shell_showHelpSingle(commandList, io, FALSE, FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (commandList->call == NULL_PTR)
|
|
{
|
|
IfxStdIf_DPipe_print(io, "%s ", commandList->commandLine);
|
|
}
|
|
|
|
Ifx_Shell_showHelpSingle(shellCommand, io, FALSE, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
IfxStdIf_DPipe_print(io, "unknown command");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_showHelp(pchar args, void *shellPtr, IfxStdIf_DPipe *io)
|
|
{
|
|
sint32 i;
|
|
Ifx_Shell *shell = shellPtr;
|
|
boolean result = TRUE;
|
|
|
|
if (*args == IFX_SHELL_NULL_CHAR)
|
|
{
|
|
for (i = 0; i < IFX_CFG_SHELL_COMMAND_LISTS; i++)
|
|
{
|
|
if (shell->commandList[i] != NULL_PTR)
|
|
{
|
|
Ifx_Shell_showHelpSingle(shell->commandList[i], io, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = Ifx_Shell_showHelpSingleCommand(args, shellPtr, io);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_protocolStart(pchar args, void *data, IfxStdIf_DPipe *io)
|
|
{
|
|
Ifx_Shell *shell = data;
|
|
boolean Result = TRUE;
|
|
|
|
if (Ifx_Shell_matchToken(&args, "?") != FALSE)
|
|
{
|
|
IfxStdIf_DPipe_print(io, "Syntax : protocol start" ENDL);
|
|
IfxStdIf_DPipe_print(io, " > start a protocol" ENDL);
|
|
}
|
|
else if (Ifx_Shell_matchToken(&args, "start") != FALSE)
|
|
{
|
|
if ((shell->protocol.start != NULL_PTR) && (shell->protocol.object != NULL_PTR))
|
|
{
|
|
Result = shell->protocol.start(shell->protocol.object, io);
|
|
shell->protocol.started = (Result != FALSE);
|
|
|
|
if (shell->protocol.onStart != NULL_PTR)
|
|
{
|
|
shell->protocol.onStart(shell->protocol.object, shell->protocol.onStartData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Result = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{}
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_bbProtocolStart(pchar args, void *data, IfxStdIf_DPipe *io)
|
|
{
|
|
boolean result = TRUE;
|
|
|
|
if (Ifx_Shell_matchToken(&args, "?") != FALSE)
|
|
{
|
|
IfxStdIf_DPipe_print(io, "Syntax : protocol start" ENDL);
|
|
IfxStdIf_DPipe_print(io, " > start a protocol" ENDL);
|
|
}
|
|
else if (Ifx_Shell_matchToken(&args, "protocol") != FALSE)
|
|
{
|
|
result = Ifx_Shell_protocolStart(args, data, io);
|
|
}
|
|
else
|
|
{}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
void Ifx_Shell_initConfig(Ifx_Shell_Config *config)
|
|
{
|
|
uint32 i;
|
|
|
|
for (i = 0; i < IFX_CFG_SHELL_COMMAND_LISTS; i++)
|
|
{
|
|
config->commandList[i] = NULL_PTR;
|
|
}
|
|
|
|
config->standardIo = NULL_PTR;
|
|
config->echo = TRUE;
|
|
config->protocol.execute = NULL_PTR;
|
|
config->protocol.object = NULL_PTR;
|
|
config->protocol.onStart = NULL_PTR;
|
|
config->protocol.onStartData = NULL_PTR;
|
|
config->protocol.start = NULL_PTR;
|
|
config->protocol.started = FALSE;
|
|
config->sendResultCode = FALSE;
|
|
config->showPrompt = TRUE;
|
|
config->standardIo = NULL_PTR;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_init(Ifx_Shell *shell, const Ifx_Shell_Config *config)
|
|
{
|
|
sint32 i;
|
|
char **CmdHistory = NULL_PTR; /* Pointer to array of pointers for command history items */
|
|
|
|
/* Ensure state variable is cleared */
|
|
memset(shell, 0, sizeof(*shell));
|
|
|
|
shell->protocol = config->protocol;
|
|
shell->protocol.started = FALSE;
|
|
|
|
shell->io = config->standardIo;
|
|
shell->control.showPrompt = config->showPrompt;
|
|
shell->control.sendResultCode = config->sendResultCode;
|
|
shell->control.echo = config->echo;
|
|
shell->control.echoError = TRUE;
|
|
shell->control.enabled = TRUE;
|
|
|
|
shell->locals.escBracketNum = IFX_SHELL_NULL_CHAR; /* Used to cache number in sequence "ESC [ 1/2/3/4 ~" */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_NORMAL;
|
|
|
|
/* Copy command line buffer pointer into state variable */
|
|
shell->cmd.cmdStr = shell->locals.cmdStr;
|
|
|
|
/* Initialize command history space and cache pointer */
|
|
memset(Ifx_Shell_cmdBuffer, 0, sizeof(Ifx_Shell_cmdBuffer));
|
|
shell->cmdHistory[0] = &Ifx_Shell_cmdBuffer[0];
|
|
|
|
for (i = 0; i < IFX_CFG_SHELL_COMMAND_LISTS; i++)
|
|
{
|
|
shell->commandList[i] = config->commandList[i];
|
|
}
|
|
|
|
/* Initialize command history pointers */
|
|
CmdHistory = shell->cmdHistory;
|
|
|
|
for (i = 1; i < IFX_CFG_SHELL_CMD_HISTORY_SIZE; i++)
|
|
{
|
|
CmdHistory[i] = &CmdHistory[i - 1][IFX_CFG_SHELL_CMD_LINE_SIZE]; /* Items are just offsets into a large allocated area */
|
|
}
|
|
|
|
shell->cmd.historyItem = IFX_SHELL_CMD_HISTORY_NO_ITEM;
|
|
|
|
/* Pre-load useful commands into history buffer */
|
|
strcpy(CmdHistory[0], "help");
|
|
//strcpy(CmdHistory[1], "protocol start");
|
|
|
|
if (shell->control.showPrompt != 0)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, ENDL);
|
|
IfxStdIf_DPipe_print(shell->io, IFX_CFG_SHELL_PROMPT);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void Ifx_Shell_process(Ifx_Shell *shell)
|
|
{
|
|
Ifx_SizeT i, j; /* Loop variables */
|
|
Ifx_SizeT count;
|
|
Ifx_SizeT readCount;
|
|
boolean NormalKeyPress; /* Indicates if this is a normal keypress, i.e. not part of an escape code */
|
|
|
|
Ifx_Shell_CmdLine *Cmd = &shell->cmd;
|
|
char *inputbuffer = shell->locals.inputbuffer;
|
|
char *cmdStr = shell->locals.cmdStr;
|
|
char **CmdHistory = shell->cmdHistory;
|
|
|
|
if (shell->control.enabled == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((shell->protocol.object != NULL_PTR) && (shell->protocol.started != FALSE))
|
|
{
|
|
shell->protocol.execute(shell->protocol.object);
|
|
}
|
|
else
|
|
{
|
|
/**** NORMAL MODE ****/
|
|
|
|
/********************************************************************************/
|
|
/* Read all characters until enter inclusive. */
|
|
/* If the command is bigger than IFX_SHELL_CMD_SIZE, the command is ignored. */
|
|
/* */
|
|
/* Escape sequences are handled by a state machine. */
|
|
/* The following escape sequences (prefix "ESC [") are supported: */
|
|
/* */
|
|
/* A - up B - down C - right D - left */
|
|
/* 1~ - HOME 2~ - INSERT 3~ - DELETE 5~ - END */
|
|
/* */
|
|
/* Backspace ('\b') is also supported. */
|
|
/********************************************************************************/
|
|
|
|
count = 0;
|
|
readCount = IFX_CFG_SHELL_CMD_LINE_SIZE - count;
|
|
IfxStdIf_DPipe_read(shell->io, &inputbuffer[count], &readCount, TIME_NULL);
|
|
count += readCount;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
/* By default, we assume character is part of escape sequence */
|
|
NormalKeyPress = FALSE;
|
|
|
|
/* Process key pressed */
|
|
switch (inputbuffer[i])
|
|
{
|
|
/* New line (ENTER) */
|
|
case '\n':
|
|
case '\r':
|
|
/* Print new line to terminal if requested */
|
|
IFX_SHELL_IF_ECHO(IfxStdIf_DPipe_print(shell->io, ENDL))
|
|
|
|
/* Execute command if length is valid - i.e. not an over-full buffer
|
|
* (prevents attempted execution of junk) */
|
|
if (Cmd->length < IFX_CFG_SHELL_CMD_LINE_SIZE)
|
|
{
|
|
cmdStr[Cmd->length] = IFX_SHELL_NULL_CHAR; /* Terminate cmdStr */
|
|
|
|
if (Cmd->historyAdd != FALSE)
|
|
{
|
|
/* Shuffle history up */
|
|
for (j = IFX_CFG_SHELL_CMD_HISTORY_SIZE - 1; j > 0; j--)
|
|
{
|
|
/* Copy text */
|
|
strncpy(CmdHistory[j], CmdHistory[j - 1], IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
}
|
|
|
|
/* Copy in new entry */
|
|
strncpy(CmdHistory[0], cmdStr, IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
}
|
|
|
|
/* Execute command */
|
|
Ifx_Shell_execute(shell, cmdStr);
|
|
}
|
|
|
|
/* Show prompt if in main shell */
|
|
if (shell->control.showPrompt != 0)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, IFX_CFG_SHELL_PROMPT);
|
|
}
|
|
|
|
/* Reset command line buffer length */
|
|
Cmd->length = 0;
|
|
|
|
/* Reset command line buffer cursor position */
|
|
Cmd->cursor = 0;
|
|
|
|
/* Clear flag */
|
|
Cmd->historyAdd = FALSE;
|
|
|
|
/* Ensure we're not in command history list */
|
|
Cmd->historyItem = IFX_SHELL_CMD_HISTORY_NO_ITEM;
|
|
break;
|
|
|
|
/* Backspace (may occur in middle of text if cursor location is not at end) */
|
|
case '\b':
|
|
|
|
if (Cmd->cursor > 0)
|
|
{
|
|
/* Update on screen */
|
|
if (shell->control.echo != 0)
|
|
{
|
|
/* Move left one character */
|
|
IfxStdIf_DPipe_print(shell->io, "\b");
|
|
|
|
/* Update line with new characters */
|
|
for (j = Cmd->cursor; j < Cmd->length; j++)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, "%c", cmdStr[j]);
|
|
}
|
|
|
|
/* Write over duplicated character at end */
|
|
IfxStdIf_DPipe_print(shell->io, " ");
|
|
IFX_SHELL_WRITE_BACKSPACES((Cmd->length - Cmd->cursor) + 1)
|
|
}
|
|
|
|
/* Update in command line variable. Shuffle text left */
|
|
strncpy(&cmdStr[Cmd->cursor - 1], &cmdStr[Cmd->cursor], Cmd->length - Cmd->cursor);
|
|
|
|
/* Terminate string at end of shorter string */
|
|
cmdStr[Cmd->length - 1] = IFX_SHELL_NULL_CHAR;
|
|
|
|
Cmd->length--;
|
|
Cmd->cursor--;
|
|
|
|
/* Command line has been modified */
|
|
Cmd->historyAdd = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
/* Escape character */
|
|
case '\x1B': /*'\x1B': */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_ESCAPE;
|
|
break;
|
|
|
|
/* '[' - check to see if this is second part of an escape sequence */
|
|
case '[':
|
|
|
|
if (shell->locals.cmdState == IFX_SHELL_CMD_STATE_ESCAPE)
|
|
{
|
|
/* ESC [ pressed */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_ESCAPE_BRACKET;
|
|
}
|
|
else
|
|
{
|
|
NormalKeyPress = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
/* Check for supported characters in escape sequences ( ESC [ A/B/C/D ) */
|
|
case 'A':
|
|
case 'B':
|
|
case 'C':
|
|
case 'D':
|
|
|
|
if (shell->locals.cmdState == IFX_SHELL_CMD_STATE_ESCAPE_BRACKET)
|
|
{
|
|
/* Process arrow keys */
|
|
Ifx_Shell_cmdEscapeProcess(shell, inputbuffer[i], 0);
|
|
|
|
/* End of escape sequence */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_NORMAL;
|
|
}
|
|
else
|
|
{
|
|
NormalKeyPress = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
/* Check for supported characters in escape sequences (ESC [ 2/4/5 ~) */
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
|
|
if (shell->locals.cmdState == IFX_SHELL_CMD_STATE_ESCAPE_BRACKET)
|
|
{
|
|
/* Store number for use once complete escape sequence is confirmed (below) */
|
|
shell->locals.escBracketNum = inputbuffer[i];
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_ESCAPE_BRACKET_NUMBER;
|
|
}
|
|
else
|
|
{
|
|
NormalKeyPress = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
/* Check for supported characters in escape sequences (ESC [ 2/4/5 ~) */
|
|
case '~':
|
|
|
|
if (shell->locals.cmdState == IFX_SHELL_CMD_STATE_ESCAPE_BRACKET_NUMBER)
|
|
{
|
|
/* Process home/delete/end */
|
|
Ifx_Shell_cmdEscapeProcess(shell, shell->locals.escBracketNum, '~');
|
|
|
|
/* End of escape sequence */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_NORMAL;
|
|
}
|
|
else
|
|
{
|
|
NormalKeyPress = TRUE;
|
|
}
|
|
|
|
break;
|
|
|
|
/* Normal character - add to command string */
|
|
default:
|
|
NormalKeyPress = TRUE;
|
|
break;
|
|
}
|
|
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, Cmd->length >= Cmd->cursor); /* Sanity check */
|
|
|
|
/* If this was a normal key press (not part of an escape sequence),
|
|
* add it to the command string */
|
|
if (NormalKeyPress != FALSE)
|
|
{
|
|
/* Ensure state machine is reset */
|
|
shell->locals.cmdState = IFX_SHELL_CMD_STATE_NORMAL;
|
|
|
|
/* If not filled buffer, add in this character */
|
|
if (Cmd->length < (IFX_CFG_SHELL_CMD_LINE_SIZE - 1))
|
|
{
|
|
/* Command line has been modified */
|
|
Cmd->historyAdd = TRUE;
|
|
|
|
/* Copy into command line */
|
|
cmdStr[Cmd->cursor] = inputbuffer[i];
|
|
Cmd->cursor++;
|
|
|
|
/* Update length of buffer */
|
|
Cmd->length = __max(Cmd->length, Cmd->cursor);
|
|
|
|
if (shell->control.echo != 0)
|
|
{
|
|
/* echo character to shell output if requested */
|
|
shell->locals.echo[0] = inputbuffer[i];
|
|
IfxStdIf_DPipe_print(shell->io, shell->locals.echo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Line too long - ignore further characters */
|
|
Cmd->historyAdd = FALSE; /* Invalid command line */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Ifx_Shell_deinit(Ifx_Shell *shell)
|
|
{
|
|
(void)shell; /* ignore compiler warning; */
|
|
// tbd free necessary memory
|
|
}
|
|
|
|
|
|
pchar Ifx_Shell_skipWhitespace(pchar args)
|
|
{
|
|
if (args != NULL_PTR)
|
|
{
|
|
while ((*args != IFX_SHELL_NULL_CHAR) && (ISSPACE(*args)))
|
|
{
|
|
args = &args[1];
|
|
}
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_matchToken(pchar *argsPtr, pchar token)
|
|
{
|
|
pchar savedArguments = *argsPtr;
|
|
char buffer[256];
|
|
boolean result = FALSE;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) != FALSE)
|
|
{
|
|
if (strcmp(token, buffer) == 0)
|
|
{
|
|
result = TRUE;
|
|
}
|
|
}
|
|
|
|
if (result == FALSE)
|
|
{
|
|
// No match: don't advance pointer
|
|
*argsPtr = savedArguments;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static boolean Ifx_Shell_matchCommand(pchar *argsPtr, pchar *match)
|
|
{
|
|
boolean result = FALSE;
|
|
pchar savedArguments = *argsPtr;
|
|
pchar savedMatch = *match;
|
|
char buffer0[256];
|
|
char buffer1[256];
|
|
|
|
if ((Ifx_Shell_parseToken(argsPtr, buffer0, Ifx_COUNTOF(buffer0)) != FALSE)
|
|
&& (Ifx_Shell_parseToken(match, buffer1, Ifx_COUNTOF(buffer1)) != FALSE))
|
|
{
|
|
if (strcmp(buffer1, buffer0) == 0)
|
|
{
|
|
result = TRUE;
|
|
}
|
|
}
|
|
|
|
if (result == FALSE)
|
|
{
|
|
// No match: don't advance pointer
|
|
*argsPtr = savedArguments;
|
|
*match = savedMatch;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseToken(pchar *argsPtr, char *tokenBuffer, int bufferLength)
|
|
{
|
|
int mindex = 0;
|
|
pchar args = Ifx_Shell_skipWhitespace(*argsPtr);
|
|
|
|
tokenBuffer[0] = IFX_SHELL_NULL_CHAR;
|
|
|
|
if (args == NULL_PTR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (*args == '\"')
|
|
{
|
|
args = &args[1];
|
|
|
|
while ((*args != IFX_SHELL_NULL_CHAR) && (*args != '\"'))
|
|
{
|
|
if (mindex < bufferLength)
|
|
{
|
|
tokenBuffer[mindex] = *args;
|
|
mindex++;
|
|
}
|
|
|
|
args = &args[1];
|
|
}
|
|
|
|
// error if no closing quote
|
|
if (*args != '\"')
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
args = &args[1];
|
|
}
|
|
else
|
|
{
|
|
// don't allow unquoted empty tokens
|
|
if (*args == IFX_SHELL_NULL_CHAR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
while ((*args != IFX_SHELL_NULL_CHAR) && (!ISSPACE(*args)))
|
|
{
|
|
if (mindex < bufferLength)
|
|
{
|
|
tokenBuffer[mindex] = *args;
|
|
mindex++;
|
|
}
|
|
|
|
args = &args[1];
|
|
}
|
|
}
|
|
|
|
// make sure string is zero terminated
|
|
if (bufferLength > 0)
|
|
{
|
|
tokenBuffer[__min(mindex, bufferLength - 1)] = IFX_SHELL_NULL_CHAR;
|
|
}
|
|
|
|
*argsPtr = Ifx_Shell_skipWhitespace(args);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseAddress(pchar *argsPtr, void **address)
|
|
{
|
|
char buffer[32];
|
|
boolean result;
|
|
|
|
*address = 0;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
result = (buffer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(buffer, "%x ", (unsigned int *)address) == 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseSInt32(pchar *argsPtr, sint32 *value)
|
|
{
|
|
sint64 value64;
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseSInt64(argsPtr, &value64) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
*value = (sint32)value64;
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseUInt32(pchar *argsPtr, uint32 *value, boolean hex)
|
|
{
|
|
uint64 value64;
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseUInt64(argsPtr, &value64, hex) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
*value = (uint32)value64;
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseSInt64(pchar *argsPtr, sint64 *value)
|
|
{
|
|
char buffer[64];
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
result = (buffer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(buffer, IFX_SHELL_LLD, value) == 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseUInt64(pchar *argsPtr, uint64 *value, boolean hex)
|
|
{
|
|
char buffer[64];
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
char *bufferPointer = buffer;
|
|
|
|
if ((buffer[0] == '0') && (buffer[1] == 'x'))
|
|
{
|
|
bufferPointer = &bufferPointer[2];
|
|
hex = TRUE;
|
|
}
|
|
|
|
if (hex != FALSE)
|
|
{
|
|
result = (bufferPointer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(bufferPointer, IFX_SHELL_LLX, value) == 1);
|
|
}
|
|
else
|
|
{
|
|
result = (bufferPointer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(bufferPointer, IFX_SHELL_LLU, value) == 1);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseFloat64(pchar *argsPtr, float64 *value)
|
|
{
|
|
char buffer[64];
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
result = (buffer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(buffer, "%lf ", value) == 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
boolean Ifx_Shell_parseFloat32(pchar *argsPtr, float32 *value)
|
|
{
|
|
char buffer[64];
|
|
boolean result;
|
|
|
|
*value = 0;
|
|
|
|
if (Ifx_Shell_parseToken(argsPtr, buffer, Ifx_COUNTOF(buffer)) == FALSE)
|
|
{
|
|
result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
result = (buffer[0] != IFX_SHELL_NULL_CHAR) && (sscanf(buffer, "%f ", value) == 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
const Ifx_Shell_Command *Ifx_Shell_commandFind(Ifx_Shell_CommandListConst commandList, pchar commandLine, pchar *args, uint32 *match)
|
|
{
|
|
const Ifx_Shell_Command *command = commandList;
|
|
const Ifx_Shell_Command *result = NULL_PTR;
|
|
pchar cmdLineTemp = commandLine;
|
|
uint32 matchInit = 0;
|
|
uint32 index = 0;
|
|
|
|
boolean hasPrefix;
|
|
|
|
hasPrefix = (command->commandLine != NULL_PTR) && (command->call == NULL_PTR);
|
|
*match = 0;
|
|
|
|
while (command->commandLine != NULL_PTR)
|
|
{
|
|
pchar commandTemp = command->commandLine;
|
|
pchar commandLineTemp = cmdLineTemp;
|
|
char buffer[256];
|
|
uint32 matchCount = matchInit;
|
|
|
|
while (Ifx_Shell_matchCommand(&commandLineTemp, &commandTemp) != FALSE)
|
|
{
|
|
matchCount++;
|
|
}
|
|
|
|
if ((matchCount > *match) && (Ifx_Shell_parseToken(&commandTemp, buffer, Ifx_COUNTOF(buffer)) == FALSE))
|
|
{
|
|
if ((index == 0) && (command->call == NULL_PTR))
|
|
{ /* List has a prefix */
|
|
cmdLineTemp = commandLineTemp;
|
|
matchInit = matchCount;
|
|
}
|
|
|
|
*match = matchCount;
|
|
*args = commandLineTemp;
|
|
result = command;
|
|
}
|
|
else
|
|
{
|
|
if ((index == 0) && hasPrefix)
|
|
{
|
|
/* Prefix does not match */
|
|
break;
|
|
}
|
|
}
|
|
|
|
command = &command[1];
|
|
|
|
index++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
const Ifx_Shell_Command *Ifx_Shell_commandListFind(Ifx_Shell *shell, pchar commandLine, pchar *args, Ifx_Shell_CommandListConst *commandList)
|
|
{
|
|
int i;
|
|
const Ifx_Shell_Command *shellCommand = NULL_PTR;
|
|
const Ifx_Shell_Command *Command = NULL_PTR;
|
|
uint32 matchMax = 0;
|
|
uint32 match;
|
|
|
|
for (i = 0; i < IFX_CFG_SHELL_COMMAND_LISTS; i++)
|
|
{
|
|
if (shell->commandList[i] != NULL_PTR)
|
|
{
|
|
shellCommand = Ifx_Shell_commandFind(shell->commandList[i], commandLine, args, &match);
|
|
|
|
if ((shellCommand != NULL_PTR) && (match > matchMax))
|
|
{
|
|
matchMax = match;
|
|
Command = shellCommand;
|
|
*commandList = shell->commandList[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return Command;
|
|
}
|
|
|
|
|
|
void Ifx_Shell_execute(Ifx_Shell *shell, pchar commandLine)
|
|
{
|
|
pchar args = NULL_PTR;
|
|
Ifx_Shell_CommandListConst commandList;
|
|
const Ifx_Shell_Command *shellCommand = Ifx_Shell_commandListFind(shell, commandLine, &args, &commandList);
|
|
|
|
if (shellCommand != NULL_PTR)
|
|
{
|
|
if (shellCommand->call == NULL_PTR)
|
|
{
|
|
Ifx_Shell_showHelp(commandLine, shell, shell->io);
|
|
}
|
|
else if (shellCommand->call(args, shellCommand->data, shell->io) != FALSE)
|
|
{
|
|
if (shell->control.sendResultCode != 0)
|
|
{
|
|
Ifx_Shell_writeResult(shell, Ifx_Shell_ResultCode_ok);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (shell->control.sendResultCode != 0)
|
|
{
|
|
Ifx_Shell_writeResult(shell, Ifx_Shell_ResultCode_nok);
|
|
}
|
|
else if (shell->control.echoError != 0)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, "\r\nShell command error: %s" ENDL, commandLine);
|
|
}
|
|
else
|
|
{}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (commandLine[0] != IFX_SHELL_NULL_CHAR)
|
|
{
|
|
if (shell->control.sendResultCode != 0)
|
|
{
|
|
Ifx_Shell_writeResult(shell, Ifx_Shell_ResultCode_unknown);
|
|
}
|
|
else if (shell->control.echoError != 0)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, "\r\nUnknown command: %s" ENDL, commandLine);
|
|
}
|
|
else
|
|
{}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************************/
|
|
/* Processes escape sequences, including handling command history. */
|
|
/* The following escape sequences (prefix "ESC [") are supported: */
|
|
/* A - up B - down C - right D - left */
|
|
/* 1~ - HOME 2~ - INSERT 3~ - DELETE 4~ - END */
|
|
/* */
|
|
/* Parameters: */
|
|
/* EscapeChar1 - First character to follow ESC [ */
|
|
/* EscapeChar2 - Second character following ESC [ , if applicable */
|
|
/* */
|
|
/****************************************************************************************/
|
|
void Ifx_Shell_cmdEscapeProcess(Ifx_Shell *shell, char EscapeChar1, char EscapeChar2)
|
|
{
|
|
Ifx_Shell_CmdLine *Cmd = NULL_PTR; /* Command line editing state */
|
|
char *cmdStr = NULL_PTR; /* Cached pointer to command line being edited */
|
|
sint32 i = 0; /* Loop variable */
|
|
|
|
/* Validate parameters */
|
|
boolean result = (shell != NULL_PTR);
|
|
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, result != FALSE);
|
|
|
|
if (result == FALSE)
|
|
{
|
|
return; /* ERROR CASE - no thread data available! */
|
|
}
|
|
|
|
/* Cache command state and command line pointer */
|
|
Cmd = &shell->cmd;
|
|
cmdStr = Cmd->cmdStr;
|
|
|
|
/* Validate command line state */
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, cmdStr != NULL_PTR);
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, Cmd->cursor < IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
IFX_ASSERT(IFX_VERBOSE_LEVEL_ERROR, Cmd->length < IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
|
|
/* Switch on first character after ESC [ */
|
|
switch (EscapeChar1)
|
|
{
|
|
case 'A': /* Up arrow */
|
|
|
|
if (Cmd->historyItem == IFX_SHELL_CMD_HISTORY_NO_ITEM)
|
|
{
|
|
/* Not using list at the moment - take most recent item [0] */
|
|
Cmd->historyItem = 0;
|
|
}
|
|
else
|
|
{
|
|
if (Cmd->historyItem < (IFX_CFG_SHELL_CMD_HISTORY_SIZE - 1))
|
|
{
|
|
/* If not already at oldest, go back one in list */
|
|
Cmd->historyItem++;
|
|
}
|
|
}
|
|
|
|
/* Copy text into buffer */
|
|
strncpy(cmdStr, shell->cmdHistory[Cmd->historyItem], IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
|
|
/* echo to screen if requested */
|
|
if (shell->control.echo != 0)
|
|
{
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->cursor) /* Move cursor back to start */
|
|
IFX_SHELL_WRITE_SPACES(Cmd->length) /* Overwrite text with spaces */
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->length) /* Move cursor back to start */
|
|
IfxStdIf_DPipe_print(shell->io, cmdStr); /* Copy buffer to screen */
|
|
}
|
|
|
|
Cmd->cursor = (Ifx_SizeT)strlen(cmdStr); /* Store cursor position */
|
|
Cmd->length = Cmd->cursor; /* Store command line length */
|
|
Cmd->historyAdd = FALSE; /* Don't add back to history unless modified */
|
|
break;
|
|
|
|
case 'B': /* Down arrow */
|
|
|
|
if ((Cmd->historyItem == IFX_SHELL_CMD_HISTORY_NO_ITEM) || (Cmd->historyItem == 0))
|
|
{
|
|
/* Not using list at the moment, or have dropped off the end - just clear command line */
|
|
if (shell->control.echo != 0)
|
|
{
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->cursor) /* Move cursor back to start */
|
|
IFX_SHELL_WRITE_SPACES(Cmd->length) /* Overwrite text with spaces */
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->length) /* Move cursor back to start */
|
|
}
|
|
|
|
Cmd->length = 0; /* Reset command line length */
|
|
Cmd->cursor = 0;
|
|
Cmd->historyItem = IFX_SHELL_CMD_HISTORY_NO_ITEM; /* Ensure we are not using list */
|
|
}
|
|
else
|
|
{
|
|
/* Within list - move to more recent entry */
|
|
Cmd->historyItem--;
|
|
|
|
/* Copy text into buffer */
|
|
strncpy(cmdStr, shell->cmdHistory[Cmd->historyItem], IFX_CFG_SHELL_CMD_LINE_SIZE);
|
|
|
|
if (shell->control.echo != 0)
|
|
{
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->cursor) /* Move cursor back to start */
|
|
IFX_SHELL_WRITE_SPACES(Cmd->length) /* Overwrite text with spaces */
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->length) /* Move cursor back to start */
|
|
IfxStdIf_DPipe_print(shell->io, cmdStr); /* Copy buffer to screen */
|
|
}
|
|
|
|
Cmd->cursor = (Ifx_SizeT)strlen(cmdStr); /* Store cursor position */
|
|
Cmd->length = Cmd->cursor; /* Store command line length */
|
|
}
|
|
|
|
Cmd->historyAdd = FALSE;
|
|
break;
|
|
|
|
case 'C': /* Right arrow */
|
|
|
|
if (Cmd->cursor < Cmd->length)
|
|
{
|
|
/* Move cursor one place to right */
|
|
IFX_SHELL_IF_ECHO(IfxStdIf_DPipe_print(shell->io, "%c", cmdStr[Cmd->cursor])) Cmd->cursor++;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'D': /* Left arrow */
|
|
|
|
if (Cmd->cursor > 0)
|
|
{
|
|
/* Move cursor one place to left */
|
|
IFX_SHELL_IF_ECHO(IfxStdIf_DPipe_print(shell->io, "\b")) Cmd->cursor--;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* If second character after ESC [ is ~ then switch on number */
|
|
if (EscapeChar2 == '~')
|
|
{
|
|
switch (EscapeChar1)
|
|
{
|
|
case '1': /* HOME - move to start of buffer */
|
|
|
|
if (Cmd->cursor > 0)
|
|
{
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->cursor) Cmd->cursor = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case '2': /* INSERT - insert blank character at cursor and move all remaining characters right one */
|
|
|
|
if ((Cmd->cursor < Cmd->length) && (Cmd->length < (IFX_CFG_SHELL_CMD_LINE_SIZE - 1)))
|
|
{
|
|
/* Update on screen */
|
|
if (shell->control.echo != FALSE)
|
|
{
|
|
/* write over duplicated character at cursor */
|
|
IfxStdIf_DPipe_print(shell->io, " ");
|
|
|
|
/* Update line with new characters */
|
|
for (i = Cmd->cursor; i < Cmd->length; i++)
|
|
{
|
|
IfxStdIf_DPipe_print(shell->io, "%c", cmdStr[i]);
|
|
}
|
|
|
|
/* Move cursor back to new place */
|
|
IFX_SHELL_WRITE_BACKSPACES((Cmd->length + 1) - Cmd->cursor)
|
|
}
|
|
|
|
/* Update in command line variable */
|
|
for (i = Cmd->length; i > Cmd->cursor; i--)
|
|
{
|
|
cmdStr[i] = cmdStr[i - 1]; /* Shuffle text right */
|
|
}
|
|
|
|
cmdStr[Cmd->length + 1] = IFX_SHELL_NULL_CHAR; /* Terminate string at end of longer string */
|
|
cmdStr[Cmd->cursor] = ' '; /* Blank character at cursor */
|
|
|
|
Cmd->length++; /* Now one character longer */
|
|
}
|
|
|
|
break;
|
|
|
|
case '3': /* DELETE - delete character to right and move all remaining characters left one */
|
|
|
|
if (Cmd->cursor < Cmd->length)
|
|
{
|
|
/* Update on screen */
|
|
if (shell->control.echo != 0)
|
|
{
|
|
for (i = Cmd->cursor; i < (Cmd->length - 1); i++)
|
|
{
|
|
/* Update line with new characters */
|
|
IfxStdIf_DPipe_print(shell->io, "%c", cmdStr[i + 1]);
|
|
}
|
|
|
|
/* write over duplicated character at end */
|
|
IfxStdIf_DPipe_print(shell->io, " ");
|
|
|
|
/* Move cursor back to right place */
|
|
IFX_SHELL_WRITE_BACKSPACES(Cmd->length - Cmd->cursor)
|
|
}
|
|
|
|
/* Update in command line variable. Shuffle text left */
|
|
strncpy(&cmdStr[Cmd->cursor], &cmdStr[Cmd->cursor + 1], Cmd->length - Cmd->cursor - 1);
|
|
|
|
cmdStr[Cmd->length - 1] = IFX_SHELL_NULL_CHAR; /* Terminate string at end of shorter string */
|
|
Cmd->length--; /* Now one character shorter */
|
|
}
|
|
|
|
break;
|
|
|
|
case '4': /* END - ensure cursor is at end */
|
|
|
|
while (Cmd->cursor < Cmd->length)
|
|
{
|
|
IFX_SHELL_IF_ECHO(IfxStdIf_DPipe_print(shell->io, "%c", cmdStr[Cmd->cursor])) Cmd->cursor++;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Ifx_Shell_enable(Ifx_Shell *shell)
|
|
{
|
|
// Clear the Rx buffer!
|
|
IfxStdIf_DPipe_clearRx(shell->io);
|
|
// Enable the shell
|
|
shell->control.enabled = 1;
|
|
}
|
|
|
|
|
|
void Ifx_Shell_disable(Ifx_Shell *shell)
|
|
{
|
|
shell->control.enabled = 0;
|
|
}
|
|
|
|
|
|
void Ifx_Shell_printSyntax(const Ifx_Shell_Syntax *syntaxList, IfxStdIf_DPipe *io)
|
|
{
|
|
const Ifx_Shell_Syntax *syntax = syntaxList;
|
|
|
|
while (syntax->syntax != NULL_PTR)
|
|
{
|
|
IfxStdIf_DPipe_print(io, "Syntax : %s" ENDL, syntax->syntax);
|
|
IfxStdIf_DPipe_print(io, " > %s" ENDL, syntax->description);
|
|
syntax = &syntax[1];
|
|
}
|
|
}
|