Sfoglia il codice sorgente

changed heredoc to exchange data via a stdin like interface with a read function fix #39

prozessorkern 4 anni fa
parent
commit
17bb88d292
4 ha cambiato i file con 76 aggiunte e 35 eliminazioni
  1. 6 0
      api/shellmatta.h
  2. 57 28
      src/shellmatta.c
  3. 2 0
      src/shellmatta_utils.c
  4. 11 7
      test/integrationtest/test_integration.cpp

+ 6 - 0
api/shellmatta.h

@@ -123,6 +123,8 @@ typedef struct
     uint32_t            inputCount;         /**< offset of the current write operation  */
     uint32_t            lastNewlineIdx;     /**< index of the lest newline              */
     uint32_t            cursor;             /**< offset where the cursor is at          */
+    uint32_t            stdinIdx;           /**< start index of stdin in buffer         */
+    uint32_t            stdinLength;        /**< length of the stdin data               */
     char                *historyBuffer;     /**< buffer to store the last commands      */
     uint32_t            historyBufferSize;  /**< size of the history buffer             */
     uint32_t            historyStart;       /**< index of the oldest stored command     */
@@ -179,6 +181,10 @@ shellmatta_retCode_t shellmatta_write(      shellmatta_handle_t handle,
                                             char                *data,
                                             uint32_t            length);
 
+shellmatta_retCode_t shellmatta_read(       shellmatta_handle_t handle,
+                                            char                **data,
+                                            uint32_t            *length);
+
 shellmatta_retCode_t shellmatta_opt(        shellmatta_handle_t handle,
                                             char                *optionString,
                                             char                *option,

+ 57 - 28
src/shellmatta.c

@@ -77,6 +77,8 @@ shellmatta_retCode_t shellmatta_doInit(
         inst->inputCount            = 0u;
         inst->lastNewlineIdx        = 0u;
         inst->cursor                = 0u;
+        inst->stdinIdx              = 0u;
+        inst->stdinLength           = 0u;
         inst->historyBuffer         = historyBuffer;
         inst->historyBufferSize     = historyBufferSize;
         inst->historyStart          = 0u;
@@ -137,6 +139,8 @@ shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle, bool pri
         inst->inputCount            = 0u;
         inst->lastNewlineIdx        = 0u;
         inst->cursor                = 0u;
+        inst->stdinIdx              = 0u;
+        inst->stdinLength           = 0u;
         inst->historyStart          = 0u;
         inst->historyEnd            = 0u;
         inst->historyRead           = 0u;
@@ -356,10 +360,7 @@ 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;
@@ -371,10 +372,6 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
         /** -# process byte wise */
         for (byteCounter = 0u; byteCounter < size; byteCounter++)
         {
-            /*! -#  set default values for the command argument - can be overwritten by heredoc */
-            argumentString = inst->buffer;
-            argumentLength = inst->inputCount;
-
             /** -# handle escape sequences */
             if(inst->escapeCounter != 0u)
             {
@@ -458,23 +455,28 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                                             tempString,
                                             inst->hereLength)))
                     {
-                        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 function */
-                        for(idx = 1u; idx <= inst->hereStartIdx; idx++)
+                        /*! -# process heredoc as stdin like input  */
+                        /*! -# find start of heredoc data           */
+                        inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
+                        while(      ('\n' == inst->buffer[inst->stdinIdx])
+                                ||  ('\r' == inst->buffer[inst->stdinIdx]))
                         {
-                            inst->buffer[inst->hereDelimiterIdx + inst->hereLength - idx] = inst->buffer[inst->hereStartIdx - idx];
+                            inst->stdinIdx ++;
                         }
-
-                        argumentString = &(inst->buffer[inst->hereDelimiterIdx + inst->hereLength - inst->hereStartIdx]);
-                        argumentLength = inst->lastNewlineIdx - ((inst->hereDelimiterIdx + inst->hereLength) - inst->hereStartIdx);
+                        /** -# calculate length and terminate stdin string */
+                        inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
+                        inst->buffer[inst->lastNewlineIdx] = '\0';
+                        
+                        /** -# calculate length and terminate argument string */
+                        inst->inputCount = inst->hereStartIdx;
+                        inst->buffer[inst->hereStartIdx] = '\0';
+
+                        /** -# terminate heredoc session */
                         inst->hereLength = 0u;
                     }
                     else
@@ -487,16 +489,15 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 
                 if(0u == inst->hereLength)
                 {
-                    cmd                             = inst->cmdList;
-                    argumentString[argumentLength]  = 0u;
+                    cmd = inst->cmdList;
 
                     /** -# determine the cmd len (chars until first space or \0 is found */
                     cmdLen = 0u;
-                    while(      (cmdLen <   argumentLength)
-                            &&  (' '    !=  argumentString[cmdLen])
-                            &&  ('\r'   !=  argumentString[cmdLen])
-                            &&  ('\n'   !=  argumentString[cmdLen])
-                            &&  ('\0'   !=  argumentString[cmdLen]))
+                    while(      (cmdLen <   inst->inputCount)
+                            &&  (' '    !=  inst->buffer[cmdLen])
+                            &&  ('\r'   !=  inst->buffer[cmdLen])
+                            &&  ('\n'   !=  inst->buffer[cmdLen])
+                            &&  ('\0'   !=  inst->buffer[cmdLen]))
                     {
                         cmdLen ++;
                     }
@@ -505,12 +506,12 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                     while (NULL != cmd)
                     {
                         /** -# compare command and alias string and length */
-                        if (    ((0 == strncmp( argumentString,
+                        if (    ((0 == strncmp( inst->buffer,
                                                 cmd->cmd,
                                                 cmdLen))
                                 && (cmdLen == strlen(cmd->cmd)))
                             || ((NULL != cmd->cmdAlias)
-                                && ((0 == strncmp(  argumentString,
+                                && ((0 == strncmp(  inst->buffer,
                                                     cmd->cmdAlias,
                                                     cmdLen))
                                 && (cmdLen == strlen(cmd->cmdAlias)))))
@@ -518,7 +519,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                             utils_writeEcho(inst, "\r\n", 2u);
                             shellmatta_opt_init(inst, cmdLen + 1u);
                             cmdExecuted = 1u;
-                            cmd->cmdFct(inst, argumentString, argumentLength);
+                            cmd->cmdFct(inst, inst->buffer, inst->inputCount);
                             cmd = NULL;
                         }
                         else
@@ -530,7 +531,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                     if ((cmdExecuted == 0u) && (inst->inputCount > 0))
                     {
                         inst->write("\r\nCommand: ", 11u);
-                        inst->write(argumentString, argumentLength);
+                        inst->write(inst->buffer, inst->inputCount);
                         inst->write(" not found", 10u);
                     }
                     utils_terminateInput(inst);
@@ -610,6 +611,34 @@ shellmatta_retCode_t shellmatta_write(  shellmatta_handle_t handle,
     return ret;
 }
 
+/**
+ * @brief       reads the stdin like buffer
+ * @param[in]   handle  shellmatta instance handle
+ * @param[out]  data    pointer to pointer to store ref to the buffer
+ * @param[out]  length  size of the stdin data
+ * @return
+ */
+shellmatta_retCode_t shellmatta_read(   shellmatta_handle_t handle,
+                                        char                **data, 
+                                        uint32_t            *length)
+{
+    shellmatta_retCode_t    ret = SHELLMATTA_USE_FAULT;
+    shellmatta_instance_t   *inst = (shellmatta_instance_t*)handle;
+
+    /** -# check parameters for plausibility  */
+    if(     (NULL               != inst)
+        &&  (SHELLMATTA_MAGIC   == inst->magic)
+        &&  (NULL               != data)
+        &&  (NULL               != length))
+    {
+        /** -# return a pointer to the data */
+        *data   = &(inst->buffer[inst->stdinIdx]);
+        *length = inst->stdinLength;
+    }
+
+    return ret;
+}
+
 #ifndef SHELLMATTA_STRIP_PRINTF
 
 /**

+ 2 - 0
src/shellmatta_utils.c

@@ -364,6 +364,8 @@ void utils_terminateInput(shellmatta_instance_t *inst)
     inst->lastNewlineIdx    = 0u;
     inst->hereLength        = 0u;
     inst->cursor            = 0u;
+    inst->stdinIdx          = 0u;
+    inst->stdinLength       = 0u;
     inst->write("\r\n", 2u);
     inst->write(inst->prompt, strlen(inst->prompt));
 }

+ 11 - 7
test/integrationtest/test_integration.cpp

@@ -9,6 +9,8 @@ static char write_data[1024];
 static uint32_t write_length;
 static const char *doSomethingArguments;
 static uint32_t doSomethingLength;
+static char *doSomethingStdin;
+static uint32_t doSomethingStdinLength;
 
 static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
 {
@@ -28,6 +30,9 @@ static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *
 {
     doSomethingArguments = arguments;
     doSomethingLength = length;
+
+    shellmatta_read(handle, &doSomethingStdin, &doSomethingStdinLength);
+
     shellmatta_printf(handle, "%s - length: %u", arguments, length);
     return SHELLMATTA_OK;
 }
@@ -140,8 +145,8 @@ TEST_CASE( "shellmatta heredoc test" ) {
     shellmatta_handle_t handle;
     char buffer[1024];
     char historyBuffer[1024];
-    char *dummyData =   (char*)"do this \r\n"
-                        "asdf\r\n"
+    char *dummyData =   (char*)"do this ";
+    char *dummyStdin =  (char*)"asdf\r\n"
                         "1234";
 
     shellmatta_doInit(  &inst,
@@ -162,15 +167,14 @@ TEST_CASE( "shellmatta heredoc test" ) {
                                     "asdf\r\n"
                                     "1234\r\n"
                                     "EOF\r\n"
-                                , 34);
-
+                                , 33);
 
-
-    CHECK( doSomethingLength == 20u);
+    CHECK( doSomethingStdinLength == 10u);
+    CHECK( strcmp(dummyStdin, doSomethingStdin) == 0);
+    CHECK( doSomethingLength == 8u);
     REQUIRE( strcmp(dummyData, doSomethingArguments) == 0);
 }
 
-
 TEST_CASE( "shellmatta remove function" ) {
 
     shellmatta_instance_t inst;