浏览代码

added first working option parser for short options

prozessorkern 4 年之前
父节点
当前提交
ecc43307af

+ 2 - 0
api/shellmatta.h

@@ -77,6 +77,8 @@ typedef struct
 typedef struct
 {
     uint32_t    offset;     /**< current offset of the option parser    */
+    uint32_t    nextOffset; /**< offset of the next hunk                */
+    uint32_t    len;        /**< length of the current hunk             */
 } shellmatta_opt_t;
 
 /**

+ 1 - 0
makefile

@@ -22,6 +22,7 @@ SOURCES :=  src/shellmatta.c                \
 INCLUDES    := api .
 
 UNITTEST_SOURCES := test/unittest/test_main.cpp                                         \
+                    test/unittest/shellmatta_opt/test_opt_findNextHunk.cpp              \
                     test/unittest/shellmatta_utils/test_utils_writeEcho.cpp             \
                     test/unittest/shellmatta_utils/test_utils_shellItoa.cpp             \
                     test/unittest/shellmatta_utils/test_utils_saveCursorPos.cpp         \

+ 4 - 3
src/shellmatta.c

@@ -22,6 +22,7 @@
 #include "shellmatta_history.h"
 #include "shellmatta_utils.h"
 #include "shellmatta_escape.h"
+#include "shellmatta_opt.h"
 #include <stddef.h>
 #include <string.h>
 #include <stdarg.h>
@@ -502,8 +503,8 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                     {
                         /** -# compare command and alias string and length */
                         if (    ((0 == strncmp( argumentString,
-                                            cmd->cmd,
-                                            cmdLen))
+                                                cmd->cmd,
+                                                cmdLen))
                                 && (cmdLen == strlen(cmd->cmd)))
                             || ((NULL != cmd->cmdAlias)
                                 && ((0 == strncmp(  argumentString,
@@ -512,7 +513,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                                 && (cmdLen == strlen(cmd->cmdAlias)))))
                         {
                             utils_writeEcho(inst, "\r\n", 2u);
-
+                            shellmatta_opt_init(inst, cmdLen + 1u);
                             cmdExecuted = 1u;
                             cmd->cmdFct(inst, argumentString, argumentLength);
                             cmd = NULL;

+ 200 - 6
src/shellmatta_opt.c

@@ -22,6 +22,151 @@
 #include "shellmatta.h"
 #include <string.h>
 
+
+/**
+ * @brief       finds the next parsable hunk of data in the input
+ * @param[in]   inst            shellmatta instance
+ * @return      errorcode       #SHELLMATTA_OK      - new hunk found
+ *                              #SHELLMATTA_ERROR   - error parsing or end of input
+ */
+static shellmatta_retCode_t findNextHunk(shellmatta_instance_t *inst)
+{
+    shellmatta_retCode_t ret = SHELLMATTA_ERROR;
+    uint32_t newOffset = inst->optionParser.nextOffset;
+    uint32_t exeptionOffset = 0u;
+    char quotation = '\0';  /* holds the current quotation mark if any */
+
+    /*! -# find beginning of next hunk */
+    while(  (newOffset  < inst->inputCount)
+        &&     ((' '        == inst->buffer[newOffset])
+            ||  ('\0'       == inst->buffer[newOffset])))
+    {
+        newOffset ++;
+    }
+
+    inst->optionParser.offset = newOffset;
+
+    /*! -# determine length */
+    while((newOffset < inst->inputCount)
+        && (((' ' != inst->buffer[newOffset]) && ('\0' != inst->buffer[newOffset])) || '\0' != quotation))
+    {
+        /*! -# check for new quotation */
+        if((('\'' == inst->buffer[newOffset]) || ('"' == inst->buffer[newOffset])) && (quotation == '\0'))
+        {
+            quotation = inst->buffer[newOffset];
+            exeptionOffset ++;
+        }
+        /*! -# check if quotation has ended */
+        else if(quotation == inst->buffer[newOffset])
+        {
+            exeptionOffset ++;
+            /*!  -# check if quotation is excaped */
+            if('\\' != inst->buffer[newOffset - 1u])
+            {
+                quotation = '\0';
+            }
+            else
+            {
+                inst->buffer[newOffset - exeptionOffset] = inst->buffer[newOffset];
+            }
+        }
+        else
+        {
+            /*! -# shift back chars */
+            if(0u != exeptionOffset)
+            {
+                inst->buffer[newOffset - exeptionOffset] = inst->buffer[newOffset];
+            }
+        }
+        newOffset ++;
+    }
+
+    inst->optionParser.nextOffset   = newOffset;
+    inst->optionParser.len          = newOffset - inst->optionParser.offset - exeptionOffset;
+
+    /*! -# add terminating 0 */
+    inst->buffer[inst->optionParser.offset + inst->optionParser.len] = '\0';
+
+    if((inst->optionParser.offset < inst->inputCount) && (0u != inst->optionParser.len) && ('\0' == quotation))
+    {
+        ret = SHELLMATTA_OK;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief       peeks the first char of the next hunk
+ * @param[in]   inst        shellmatta instance
+ * @return      char        first char of next hunk \0 if not existing
+ */
+static char peekNextHunk(shellmatta_instance_t *inst)
+{
+    uint32_t newOffset = inst->optionParser.nextOffset;
+
+    /*! -# find beginning of next hunk */
+    while(  (newOffset  < inst->inputCount)
+        &&     ((' '        == inst->buffer[newOffset])
+            ||  ('\0'       == inst->buffer[newOffset])))
+    {
+        newOffset ++;
+    }
+    return inst->buffer[newOffset];
+}
+
+/**
+ * @brief       tries to parse the current input hunk and check if this is a configured option
+ * @param[in]   handle          shellmatta handle
+ * @param[in]   optionString    option string e.g. "cd:e::"
+ * @param[out]  option          pointer to store the detected option to
+ * @param[out]  argtype         pointer to store the argument string to (can be NULL)
+ * @return      errorcode       #SHELLMATTA_OK      - option parsable and found in option String
+ *                              #SHELLMATTA_ERROR   - format error or option unknown
+ */
+static shellmatta_retCode_t parseShortOpt(  shellmatta_instance_t       *inst,
+                                            char                        *optionString,
+                                            char                        *option,
+                                            shellmatta_opt_argtype_t    *argtype)
+{
+    shellmatta_retCode_t ret = SHELLMATTA_ERROR;
+    char *buffer = &inst->buffer[inst->optionParser.offset];
+    uint32_t i;
+
+    /*! -# check for correct syntax */
+    if((2u == inst->optionParser.len) && ('-' == buffer[0u]) && ('-' != buffer[1u]) && ('\0' != buffer[1u]))
+    {
+        /*! -# search for option character in option string */
+        for(i = 0u; ('\0' != optionString[i]) && (buffer[1u] != optionString[i]); i ++);
+        
+        if(buffer[1u] == optionString[i])
+        {
+            /*! -# return found option character */
+            *option = buffer[1u];
+            ret = SHELLMATTA_OK;
+
+            /*! -# check if an argument is required or optional */
+            if(':' == optionString[i + 1u])
+            {
+                *argtype = SHELLMATTA_OPT_ARG_REQUIRED;
+                if(':' == optionString[i + 2u])
+                {
+                    *argtype = SHELLMATTA_OPT_ARG_OPTIONAL;
+                }
+            }
+            else
+            {
+                *argtype = SHELLMATTA_OPT_ARG_NONE;
+            }
+        }
+    }
+    else
+    {
+        *option = '\0';
+    }
+
+    return ret;
+}
+
 /**
  * @brief       scans the current input and parses options in getopt style
  * @param[in]   handle          shellmatta handle
@@ -29,6 +174,8 @@
  * @param[out]  option          pointer to store the detected option to
  * @param[out]  argument        pointer to store the argument string to (can be NULL)
  * @param[out]  argLen          pointer to store the argument lengh to (can be NULL)
+ * @return      errorcode       #SHELLMATTA_OK      - no error - keep on calling
+ *                              #SHELLMATTA_ERROR   - error occured - e.g. argument missing
  */
 shellmatta_retCode_t shellmatta_opt(        shellmatta_handle_t handle,
                                             char                *optionString,
@@ -36,8 +183,9 @@ shellmatta_retCode_t shellmatta_opt(        shellmatta_handle_t handle,
                                             char                **argument,
                                             uint32_t            *argLen)
 {
-    shellmatta_retCode_t    ret     = SHELLMATTA_USE_FAULT;
-    shellmatta_instance_t   *inst   = (shellmatta_instance_t*)handle;
+    shellmatta_retCode_t        ret     = SHELLMATTA_USE_FAULT;
+    shellmatta_instance_t       *inst   = (shellmatta_instance_t*)handle;
+    shellmatta_opt_argtype_t    argtype = SHELLMATTA_OPT_ARG_NONE;
 
     /** -# check parameters for plausibility  */
     if(     (NULL               != inst)
@@ -45,7 +193,52 @@ shellmatta_retCode_t shellmatta_opt(        shellmatta_handle_t handle,
         &&  (NULL               != optionString)
         &&  (NULL               != option))
     {
-        
+        *option     = '\0';
+        *argument   = NULL;
+        *argLen     = 0u;
+
+        ret = findNextHunk(inst);
+        if(SHELLMATTA_OK == ret)
+        {
+            ret = parseShortOpt(inst, optionString, option, &argtype);
+
+            /*! -# when no option is found return this as raw argument */
+            if(SHELLMATTA_ERROR == ret)
+            {
+                *argument   = &(inst->buffer[inst->optionParser.offset]);
+                *argLen     = inst->optionParser.len;
+                ret         = SHELLMATTA_OK;
+            }
+            else
+            {
+                switch(argtype)
+                {
+                    case SHELLMATTA_OPT_ARG_REQUIRED:
+                        ret = findNextHunk(inst);
+                        if(SHELLMATTA_OK == ret)
+                        {
+                            *argument   = &(inst->buffer[inst->optionParser.offset]);
+                            *argLen     = inst->optionParser.len;
+                        }
+                        break;
+                    case SHELLMATTA_OPT_ARG_OPTIONAL:
+                        /*! -# treat anything not starting with '-' as argument */
+                        if('-' != peekNextHunk(inst))
+                        {
+                            ret = findNextHunk(inst);
+                            if(SHELLMATTA_OK == ret)
+                            {
+                                *argument   = &(inst->buffer[inst->optionParser.offset]);
+                                *argLen     = inst->optionParser.len;
+                            }
+                        }
+                        break;
+                    default:
+                        /* nothing to do */
+                        break;
+                }
+            }
+        }
     }
 
     (void)argument;
@@ -88,12 +281,13 @@ shellmatta_retCode_t shellmatta_opt_long(   shellmatta_handle_t     handle,
 
 /**
  * @brief           initializes the option parser instance
- * @param[in, out]  inst    pointer to a shellmatta instance
+ * @param[in, out]  inst        pointer to a shellmatta instance
+ * @param[in]       argStart    start offset of the arguments (after command name/alias)
  */
-shellmatta_retCode_t shellmatta_opt_init(shellmatta_instance_t *inst)
+shellmatta_retCode_t shellmatta_opt_init(shellmatta_instance_t *inst, uint32_t argStart)
 {
     /*! -# initialize all relevant option parser variables */
-    inst->optionParser.offset = 0u;
+    inst->optionParser.nextOffset = argStart;
 
     return SHELLMATTA_OK;
 }

+ 2 - 1
src/shellmatta_opt.h

@@ -34,7 +34,8 @@ shellmatta_retCode_t shellmatta_opt_long(   shellmatta_handle_t     handle,
                                             char                    **argument,
                                             uint32_t                *argLen);
 
-shellmatta_retCode_t shellmatta_opt_init(   shellmatta_instance_t   *inst);
+shellmatta_retCode_t shellmatta_opt_init(   shellmatta_instance_t   *inst,
+                                            uint32_t argStart);
 
 #endif
 

+ 85 - 6
test/integrationtest/test_integration_opt.cpp

@@ -21,7 +21,52 @@ extern "C" {
 static uint32_t write_callCnt = 0u;
 static char write_data[1024];
 static uint32_t write_length;
-
+static uint32_t cntA = 0u;
+static uint32_t cntB = 0u;
+static uint32_t cntC = 0u;
+static uint32_t cntD = 0u;
+static uint32_t cntE = 0u;
+static uint32_t cntF = 0u;
+static uint32_t cntDef = 0u;
+static char *argA = NULL;
+static char *argB = NULL;
+static char *argC = NULL;
+static char *argD = NULL;
+static char *argE = NULL;
+static char *argF = NULL;
+static char *argDef = NULL;
+static uint32_t lenA = 0u;
+static uint32_t lenB = 0u;
+static uint32_t lenC = 0u;
+static uint32_t lenD = 0u;
+static uint32_t lenE = 0u;
+static uint32_t lenF = 0u;
+static uint32_t lenDef = 0u;
+
+static void initTestcase(void)
+{
+    cntA = 0u;
+    cntB = 0u;
+    cntC = 0u;
+    cntD = 0u;
+    cntE = 0u;
+    cntF = 0u;
+    cntDef = 0u;
+    argA = NULL;
+    argB = NULL;
+    argC = NULL;
+    argD = NULL;
+    argE = NULL;
+    argF = NULL;
+    argDef = NULL;
+    lenA = 0u;
+    lenB = 0u;
+    lenC = 0u;
+    lenD = 0u;
+    lenE = 0u;
+    lenF = 0u;
+    lenDef = 0u;
+}
 
 static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
 {
@@ -44,28 +89,53 @@ static shellmatta_retCode_t parseOpts(shellmatta_handle_t handle, const char *ar
     char        option;
     char        *argumentString;
     uint32_t    argumentLength;
+    uint32_t    optionCount = 0u;
 
     while(SHELLMATTA_OK == shellmatta_opt(handle, (char*)"abcde:f::", &option, &argumentString, &argumentLength))
     {
+        optionCount ++;
         switch(option)
         {
             case 'a':
+                cntA ++;
+                argA = argumentString;
+                lenA = argumentLength;
                 break;
             case 'b':
+                cntB ++;
+                argB = argumentString;
+                lenB = argumentLength;
                 break;
             case 'c':
+                cntC ++;
+                argC = argumentString;
+                lenC = argumentLength;
                 break;
             case 'd':
+                cntD ++;
+                argD = argumentString;
+                lenD = argumentLength;
                 break;
             case 'e':
+                cntE ++;
+                argE = argumentString;
+                lenE = argumentLength;
                 break;
             case 'f':
+                cntF ++;
+                argF = argumentString;
+                lenF = argumentLength;
                 break;
             default:
+                cntDef ++;
+                argDef = argumentString;
+                lenDef = argumentLength;
                 break;
         }
     }
 
+    shellmatta_printf(handle, "parseOpts - cnt: %u\r\n", optionCount);
+
     return SHELLMATTA_OK;
 }
 shellmatta_cmd_t parseOptsCmd = {(char*)"parseOpts", (char*)"opt", NULL, NULL, parseOpts, NULL};
@@ -83,7 +153,7 @@ TEST_CASE( "shellmatta option parser 1" ) {
     shellmatta_handle_t handle;
     char buffer[1024];
     char historyBuffer[1024];
-    //char *dummyData =   (char*)"\r\nshellmatta->";
+    char *dummyData =   (char*)"parseOpts -a -e meow\r\nparseOpts - cnt: 2\r\n\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
                         &handle,
@@ -95,13 +165,22 @@ TEST_CASE( "shellmatta option parser 1" ) {
                         NULL,
                         writeFct);
 
+    initTestcase();
     write_callCnt = 0u;
     memset(write_data, 0, sizeof(write_data));
     write_length = 0u;
 
-    shellmatta_processData(handle, (char*)"parseOpts -a -e meow\r", 1);
+    shellmatta_addCmd(handle, &parseOptsCmd);
+
+    shellmatta_processData(handle, (char*)"parseOpts -a -e meow\r", 21);
 
-    // CHECK( write_length == 14u);
-    // REQUIRE( strcmp(dummyData, write_data) == 0);
-    REQUIRE( 1 == 1 );
+    CHECK( cntA == 1u );
+    CHECK( NULL == argA);
+    CHECK( 0u == lenA );
+    CHECK( cntE == 1u );
+    CHECK(((NULL != argE) && (0u == memcmp(argE, "meow", 4))));
+    CHECK( lenE == 4u );
+    CHECK( (cntB == 0u && cntC == 0u && cntD == 0u && cntF == 0u && cntDef == 0u) );
+    CHECK( write_length == 56u);
+    REQUIRE( strcmp(dummyData, write_data) == 0);
 }

+ 162 - 0
test/unittest/shellmatta_opt/test_opt_findNextHunk.cpp

@@ -0,0 +1,162 @@
+#include "test/framework/catch.hpp"
+#include "src/shellmatta_opt.c"
+#include <string.h>
+
+
+TEST_CASE( "shellmatta_opt findNextHunk easy" ) {
+
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t inst;
+    char *dummyData = (char*) "This is Sparta";
+    char buffer[1024u];
+
+    memcpy(buffer, dummyData, strlen(dummyData));
+
+    inst.buffer = buffer;
+    inst.bufferSize = sizeof(buffer);
+    inst.inputCount = 14;
+    inst.optionParser.nextOffset = 4u;
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 5u);
+    CHECK( inst.optionParser.len == 2u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 8u);
+    CHECK( inst.optionParser.len == 6u);
+
+    ret = findNextHunk(&inst);
+    REQUIRE( ret == SHELLMATTA_ERROR );
+}
+
+TEST_CASE( "shellmatta_opt findNextHunk quotation 1" ) {
+
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t inst;
+    char *dummyData = (char*) "This is Sparta \"argument with spaces\"";
+    char buffer[1024u];
+
+    memcpy(buffer, dummyData, strlen(dummyData));
+
+    inst.buffer = buffer;
+    inst.bufferSize = sizeof(buffer);
+    inst.inputCount = strlen(dummyData);
+    inst.optionParser.nextOffset = 4u;
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 5u);
+    CHECK( inst.optionParser.len == 2u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 8u);
+    CHECK( inst.optionParser.len == 6u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 15u);
+    CHECK( inst.optionParser.len == 20u);
+    CHECK( 0 == memcmp(&(inst.buffer[inst.optionParser.offset]), "argument with spaces", 20));
+
+    ret = findNextHunk(&inst);
+    REQUIRE( ret == SHELLMATTA_ERROR );
+}
+
+TEST_CASE( "shellmatta_opt findNextHunk quotation 2" ) {
+
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t inst;
+    char *dummyData = (char*) "This is Sparta 'argument with spaces'";
+    char buffer[1024u];
+
+    memcpy(buffer, dummyData, strlen(dummyData));
+
+    inst.buffer = buffer;
+    inst.bufferSize = sizeof(buffer);
+    inst.inputCount = strlen(dummyData);
+    inst.optionParser.nextOffset = 4u;
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 5u);
+    CHECK( inst.optionParser.len == 2u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 8u);
+    CHECK( inst.optionParser.len == 6u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 15u);
+    CHECK( inst.optionParser.len == 20u);
+    CHECK( 0 == memcmp(&(inst.buffer[inst.optionParser.offset]), "argument with spaces", 20));
+
+    ret = findNextHunk(&inst);
+    REQUIRE( ret == SHELLMATTA_ERROR );
+}
+
+TEST_CASE( "shellmatta_opt findNextHunk quotation escaped" ) {
+
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t inst;
+    char *dummyData = (char*) "This is Sparta \"argument with \\\"spaces\"";
+    char buffer[1024u];
+
+    memcpy(buffer, dummyData, strlen(dummyData));
+
+    inst.buffer = buffer;
+    inst.bufferSize = sizeof(buffer);
+    inst.inputCount = strlen(dummyData);
+    inst.optionParser.nextOffset = 4u;
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 5u);
+    CHECK( inst.optionParser.len == 2u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 8u);
+    CHECK( inst.optionParser.len == 6u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 15u);
+    CHECK( inst.optionParser.len == 21u);
+    CHECK( 0 == memcmp(&(inst.buffer[inst.optionParser.offset]), "argument with \"spaces", 21));
+
+    ret = findNextHunk(&inst);
+    REQUIRE( ret == SHELLMATTA_ERROR );
+}
+
+TEST_CASE( "shellmatta_opt findNextHunk quotation missing closing quotation" ) {
+
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+    shellmatta_instance_t inst;
+    char *dummyData = (char*) "This is Sparta \"argument with \\\"spaces";
+    char buffer[1024u];
+
+    memcpy(buffer, dummyData, strlen(dummyData));
+
+    inst.buffer = buffer;
+    inst.bufferSize = sizeof(buffer);
+    inst.inputCount = strlen(dummyData);
+    inst.optionParser.nextOffset = 4u;
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 5u);
+    CHECK( inst.optionParser.len == 2u);
+
+    ret = findNextHunk(&inst);
+    CHECK( ret == SHELLMATTA_OK );
+    CHECK( inst.optionParser.offset == 8u);
+    CHECK( inst.optionParser.len == 6u);
+
+    ret = findNextHunk(&inst);
+    REQUIRE( ret == SHELLMATTA_ERROR );
+}

+ 4 - 0
test/unittest/shellmatta_utils/test_utils_insertChars.cpp

@@ -19,6 +19,7 @@ TEST_CASE( "shellmatta_insertChars normal call" ) {
     shellmatta_instance_t inst;
     char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 
+    memset(&inst, 0, sizeof(inst));
     inst.buffer = buffer;
     inst.bufferSize = 20;
     inst.cursor = 8;
@@ -45,6 +46,7 @@ TEST_CASE( "shellmatta_insertChars overwrite" ) {
     shellmatta_instance_t inst;
     char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 
+    memset(&inst, 0, sizeof(inst));
     inst.buffer = buffer;
     inst.bufferSize = 20;
     inst.cursor = 8;
@@ -72,6 +74,7 @@ TEST_CASE( "shellmatta_insertChars append" ) {
     shellmatta_instance_t inst;
     char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 
+    memset(&inst, 0, sizeof(inst));
     inst.buffer = buffer;
     inst.bufferSize = 20;
     inst.cursor = 10;
@@ -99,6 +102,7 @@ TEST_CASE( "shellmatta_insertChars 0 length" ) {
     shellmatta_instance_t inst;
     char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 
+    memset(&inst, 0, sizeof(inst));
     inst.buffer = buffer;
     inst.bufferSize = 20;
     inst.cursor = 8;