From 16365f341ec3c7a3bbdb91c1e519bf06964fb742 Mon Sep 17 00:00:00 2001 From: prozessorkern Date: Tue, 30 Jul 2019 23:55:12 +0200 Subject: [PATCH] changed heredoc support now the input string is kept intact until the end of the input is reached this enables the history buffer to store the complete command Still broken: history buffer with heredoc wont execute because the delimiter is not determined correctly editing of multiline things --- api/shellmatta.h | 3 +- example/main.c | 4 +- src/shellmatta.c | 95 +++++++++++++++++++++++++++++++----------------- 3 files changed, 66 insertions(+), 36 deletions(-) diff --git a/api/shellmatta.h b/api/shellmatta.h index 1e9b804..0e55103 100644 --- a/api/shellmatta.h +++ b/api/shellmatta.h @@ -102,7 +102,8 @@ typedef struct uint32_t tabCounter; /**< counts the tabulator key presses */ uint32_t escapeCounter; /**< counts the characters of an escape seq */ char escapeChars[4u]; /**< buffer to save the escape characters */ - char hereDelimiter[16u]; /**< heredoc delimiter */ + uint32_t hereStartIdx; /**< heredoc start of "<<" */ + uint32_t hereDelimiterIdx; /**< heredoc delimiter index in input */ uint32_t hereLength; /**< length of the heredoc delimiter */ bool echoEnabled; /**< if true the input is printed */ bool dirty; /**< dirty flag to show changes */ diff --git a/example/main.c b/example/main.c index 8366255..911ebd0 100644 --- a/example/main.c +++ b/example/main.c @@ -42,7 +42,7 @@ void set_blocking (int fd, int should_block) static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length) { - + shellmatta_printf(handle, "%s - length: %u", arguments, length); return SHELLMATTA_OK; } shellmatta_cmd_t doSomethingCmd = {"doSomething", "do", "Function does something", "use me, please", doSomething, NULL}; @@ -79,7 +79,7 @@ int main(void) static char historyBuffer[4096]; static shellmatta_instance_t instance; - f = open("/dev/pts/1", O_RDWR | O_SYNC); + f = open("/dev/pts/3", O_RDWR | O_SYNC); if (f < 0) { diff --git a/src/shellmatta.c b/src/shellmatta.c index b072856..77f2d96 100644 --- a/src/shellmatta.c +++ b/src/shellmatta.c @@ -88,6 +88,8 @@ shellmatta_retCode_t shellmatta_doInit( inst->dirty = false; inst->tabCounter = 0u; inst->escapeCounter = 0u; + inst->hereStartIdx = 0u; + inst->hereDelimiterIdx = 0u; inst->hereLength = 0u; inst->mode = SHELLMATTA_MODE_INSERT; inst->cmdList = &helpCmd; @@ -197,6 +199,11 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, uint8_t cmdExecuted = 0u; uint32_t cmdLen; char *tempString; + char *argumentString; + uint32_t argumentLength; + uint32_t byteCounter; + uint32_t idx; + shellmatta_retCode_t ret = SHELLMATTA_OK; shellmatta_instance_t *inst = (shellmatta_instance_t*)handle; @@ -205,7 +212,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, && (SHELLMATTA_MAGIC == inst->magic)) { /** -# process byte wise */ - for (uint32_t i = 0u; i < size; i++) + for (byteCounter = 0u; byteCounter < size; byteCounter++) { /** -# handle escape sequences */ if(inst->escapeCounter != 0u) @@ -239,31 +246,41 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, /*' -# check if length of heredoc delimiter is valid */ if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u)) { - inst->hereLength = inst->inputCount - ((uint32_t)(tempString - inst->buffer) + 2u); - - if(sizeof(inst->hereDelimiter) < inst->hereLength) + inst->hereStartIdx = (uint32_t)(tempString - inst->buffer); + inst->hereDelimiterIdx = inst->hereStartIdx + 2u; + while((inst->hereDelimiterIdx < inst->inputCount) + && ( ('\0' == inst->buffer[inst->hereDelimiterIdx]) + || (' ' == inst->buffer[inst->hereDelimiterIdx]))) { - inst->write("\r\nHeredoc delimiter too long\r\n", 30u); - inst->inputCount = 0u; - inst->hereLength = 0u; + inst->hereDelimiterIdx ++; } - else - { - /** -# store delimiter and remove it from the input buffer */ - strncpy(inst->hereDelimiter, &(tempString[2u]), inst->hereLength); - inst->inputCount -= (inst->hereLength + 2u); - inst->cursor = inst->inputCount; - inst->dirty = true; - utils_insertChars(inst, data, 1); - inst->lastNewlineIdx = inst->inputCount; - } + inst->hereLength = inst->inputCount - inst->hereDelimiterIdx; + + inst->dirty = true; + utils_insertChars(inst, data, 1); + inst->lastNewlineIdx = inst->inputCount; } else { inst->hereLength = 0u; + + /** -# store the current command and reset the history buffer */ + inst->dirty = true; + history_storeCmd(inst); + history_reset(inst); } } + else + { + argumentString = inst->buffer; + argumentLength = inst->inputCount; + + /** -# store the current command and reset the history buffer */ + inst->dirty = true; + history_storeCmd(inst); + history_reset(inst); + } } else { @@ -278,11 +295,27 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, } if( (inst->hereLength == cmdLen) - && (0 == strncmp( inst->hereDelimiter, + && (0 == strncmp( &inst->buffer[inst->hereDelimiterIdx], tempString, inst->hereLength))) { - inst->inputCount = inst->lastNewlineIdx; + argumentLength = inst->lastNewlineIdx; + + /** -# store the current command and reset the history buffer */ + inst->dirty = true; + history_storeCmd(inst); + history_reset(inst); + + + /* TODO it is difficult to store the complete command in the history buffer if it is restructured before... + * So this should be an extra function that can be called after parsing the command and before calling the command funktion */ + for(idx = 1u; idx <= inst->hereStartIdx; idx++) + { + inst->buffer[inst->hereDelimiterIdx + inst->hereLength - idx] = inst->buffer[inst->hereStartIdx - idx]; + } + + argumentString = &(inst->buffer[inst->hereDelimiterIdx + inst->hereLength - inst->hereStartIdx]); + argumentLength = inst->lastNewlineIdx - ((inst->hereDelimiterIdx + inst->hereLength) - inst->hereStartIdx); inst->hereLength = 0u; } else @@ -295,18 +328,15 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, if(0u == inst->hereLength) { cmd = inst->cmdList; - inst->buffer[inst->inputCount] = 0u; - - /** -# store the current command and reset the history buffer */ - inst->dirty = true; - history_storeCmd(inst); - history_reset(inst); + argumentString[argumentLength] = 0u; /** -# determine the cmd len (chars until first space or \0 is found */ cmdLen = 0u; - while( (cmdLen < inst->inputCount) - && (' ' != inst->buffer[cmdLen]) - && ('\0' != inst->buffer[cmdLen])) + while( (cmdLen < argumentLength) + && (' ' != argumentString[cmdLen]) + && ('\r' != argumentString[cmdLen]) + && ('\n' != argumentString[cmdLen]) + && ('\0' != argumentString[cmdLen])) { cmdLen ++; } @@ -315,11 +345,11 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, while (NULL != cmd) { /** -# compare command string and length */ - if ( ((0 == strncmp( inst->buffer, + if ( ((0 == strncmp( argumentString, cmd->cmd, cmdLen)) && (cmdLen == strlen(cmd->cmd))) - || ((0 == strncmp( inst->buffer, + || ((0 == strncmp( argumentString, cmd->cmdAlias, cmdLen)) && (cmdLen == strlen(cmd->cmdAlias)))) @@ -327,7 +357,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, inst->write("\r\n", 2u); cmdExecuted = 1u; - cmd->cmdFct(inst, inst->buffer, inst->inputCount); + cmd->cmdFct(inst, argumentString, argumentLength); cmd = NULL; } else @@ -338,9 +368,8 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle, if ((cmdExecuted == 0u) && (inst->inputCount > 0)) { - inst->buffer[inst->inputCount] = '\0'; inst->write("\r\nCommand: ", 11u); - inst->write(inst->buffer, inst->inputCount); + inst->write(argumentString, argumentLength); inst->write(" not found", 10u); } utils_terminateInput(inst);