Compare commits
52 Commits
ad60578aab
...
73e8f0af03
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73e8f0af03 | ||
|
|
c74e37b846 | ||
|
|
ebf65d7448 | ||
|
|
0fa2e5d1f8 | ||
|
|
3f54a989f3 | ||
|
|
6c76dfc7ae | ||
|
|
785d73306d | ||
|
|
96cf0c8d65 | ||
|
|
d7962a54dc | ||
|
|
3b99ad2a56 | ||
|
|
c2e4324236 | ||
|
|
5e84f1b022 | ||
|
|
17bb88d292 | ||
|
|
5a00f22e31 | ||
|
|
2d130e2ee1 | ||
|
|
ecc43307af | ||
|
|
60c4c7dadd | ||
|
|
2921f9791b | ||
|
|
e970b6c941 | ||
|
|
bf1d91eca7 | ||
|
|
48fcf05b7d | ||
|
|
4f7fbff2e8 | ||
|
|
72777a6ac8 | ||
|
|
e27ba5317a | ||
|
|
b1b16b1f0d | ||
|
|
d2617a4f86 | ||
|
|
c807372bce | ||
|
|
c04accdb55 | ||
|
|
4f9ff4fe3c | ||
|
|
d1649e5e86 | ||
|
|
1c294bb7d1 | ||
|
|
34ec2d9b45 | ||
|
|
ea3c90f305 | ||
|
|
017c3c050e | ||
|
|
11bf2d2671 | ||
|
|
5f96d86892 | ||
|
|
8cedf30925 | ||
| fe3c1e3a43 | |||
| cf7ac4d116 | |||
| 3194012bae | |||
|
|
af8fea78da | ||
|
|
33e4e20474 | ||
|
|
16365f341e | ||
|
|
c9252029fd | ||
|
|
280e512746 | ||
|
|
fc8a34dd1c | ||
|
|
5ff3bfa12e | ||
|
|
d65765371b | ||
|
|
f65f86d8e2 | ||
|
|
bafc178caf | ||
|
|
175bb7bafb | ||
|
|
adcce55e83 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
output
|
||||
output
|
||||
|
||||
71
.vscode/launch.json
vendored
Normal file
71
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "debug example",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/output/example/example",
|
||||
"args": ["/dev/pts/4"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "make example",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
},
|
||||
{
|
||||
"name": "debug unittest",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/output/test/unittest/unittest",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "make test",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
},
|
||||
{
|
||||
"name": "debug integrationtest",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/output/test/integrationtest/integrationtest",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "make integrationtest",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"random": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"string": "cpp",
|
||||
"vector": "cpp",
|
||||
"fstream": "cpp",
|
||||
"limits": "cpp",
|
||||
"sstream": "cpp",
|
||||
"utility": "cpp",
|
||||
"algorithm": "cpp"
|
||||
}
|
||||
}
|
||||
68
.vscode/tasks.json
vendored
Normal file
68
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "make example",
|
||||
"type": "shell",
|
||||
"command": "make example",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "make clean",
|
||||
"type": "shell",
|
||||
"command": "make clean",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "make unittest",
|
||||
"type": "shell",
|
||||
"command": "make unittest",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "make integrationtest",
|
||||
"type": "shell",
|
||||
"command": "make integrationtest",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "make test",
|
||||
"type": "shell",
|
||||
"command": "make test",
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "gcc build active file",
|
||||
"command": "/usr/bin/gcc",
|
||||
"args": [
|
||||
"-g",
|
||||
"${file}",
|
||||
"-o",
|
||||
"${fileDirname}/${fileBasenameNoExtension}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "/usr/bin"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -39,7 +39,8 @@ typedef enum
|
||||
SHELLMATTA_ERROR , /**< error occured */
|
||||
SHELLMATTA_CONTINUE , /**< the function is not over */
|
||||
SHELLMATTA_USE_FAULT , /**< parameter error - wrong usage */
|
||||
SHELLMATTA_DUPLICATE /**< duplicate command */
|
||||
SHELLMATTA_DUPLICATE , /**< duplicate command */
|
||||
SHELLMATTA_BUSY /**< command is busy keep calling */
|
||||
} shellmatta_retCode_t;
|
||||
|
||||
/**
|
||||
@@ -51,6 +52,37 @@ typedef enum
|
||||
SHELLMATTA_MODE_OVERWRITE , /**< overwrite mode */
|
||||
} shellmatta_mode_t;
|
||||
|
||||
/**
|
||||
* @brief definition of shellmatta optionparser agument type
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SHELLMATTA_OPT_ARG_NONE = 0u, /**< no argument expected */
|
||||
SHELLMATTA_OPT_ARG_REQUIRED, /**< argument is required */
|
||||
SHELLMATTA_OPT_ARG_OPTIONAL, /**< argument is optional */
|
||||
} shellmatta_opt_argtype_t;
|
||||
|
||||
/**
|
||||
* @brief definition of shellmatta optionparser agument type
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char *paramLong; /**< long parameter string */
|
||||
const char paramShort; /**< short parameter char */
|
||||
shellmatta_opt_argtype_t argtype; /**< argument type expected */
|
||||
} shellmatta_opt_long_t;
|
||||
|
||||
/**
|
||||
* @brief definition of shellmatta optionparser structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t argStart; /**< start of the arguments of the command */
|
||||
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;
|
||||
|
||||
/**
|
||||
* @brief shellmatta command function definition
|
||||
* @param[in] handle pointer to the instance which is calling the cmd
|
||||
@@ -91,7 +123,11 @@ typedef struct
|
||||
char *buffer; /**< input buffer */
|
||||
uint32_t bufferSize; /**< size of the input buffer */
|
||||
uint32_t inputCount; /**< offset of the current write operation */
|
||||
uint32_t byteCounter; /**< counter used to loop over input data */
|
||||
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 */
|
||||
@@ -100,15 +136,23 @@ typedef struct
|
||||
bool historyReadUp; /**< flag to show the last history dir */
|
||||
uint32_t tabCounter; /**< counts the tabulator key presses */
|
||||
uint32_t escapeCounter; /**< counts the characters of an escape seq */
|
||||
char escapeChars[4]; /**< buffer to save the escape characters */
|
||||
char escapeChars[4u]; /**< buffer to save the escape characters */
|
||||
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 */
|
||||
const char *prompt; /**< prompt is printed after every command */
|
||||
char delimiter; /**< delimiter (return) to terminate a cmd */
|
||||
shellmatta_mode_t mode; /**< mode of the shell */
|
||||
shellmatta_write_t write; /**< pointer to write function */
|
||||
shellmatta_cmd_t helpCmd; /**< help command structure */
|
||||
shellmatta_cmd_t *cmdList; /**< pointer to the first command */
|
||||
shellmatta_cmd_t *continuousCmd; /**< command to be called continuously */
|
||||
shellmatta_cmd_t *busyCmd; /**< command to be polled (busy mode) */
|
||||
bool cmdListIsConst; /**< true if the #cmdList was passed during
|
||||
initialization */
|
||||
shellmatta_opt_t optionParser; /**< option parser sructure */
|
||||
} shellmatta_instance_t;
|
||||
|
||||
|
||||
@@ -121,14 +165,45 @@ shellmatta_retCode_t shellmatta_doInit( shellmatta_instance_t *inst,
|
||||
const char *prompt,
|
||||
const shellmatta_cmd_t *cmdList,
|
||||
shellmatta_write_t writeFct);
|
||||
|
||||
shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle,
|
||||
bool printPrompt);
|
||||
|
||||
shellmatta_retCode_t shellmatta_addCmd( shellmatta_handle_t handle,
|
||||
shellmatta_cmd_t *cmd);
|
||||
|
||||
shellmatta_retCode_t shellmatta_removeCmd( shellmatta_handle_t handle,
|
||||
shellmatta_cmd_t *cmd);
|
||||
|
||||
shellmatta_retCode_t shellmatta_configure( shellmatta_handle_t handle,
|
||||
shellmatta_mode_t mode,
|
||||
bool echoEnabled,
|
||||
char delimiter);
|
||||
|
||||
shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
||||
char *data,
|
||||
uint32_t size);
|
||||
|
||||
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,
|
||||
const char *optionString,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen);
|
||||
|
||||
shellmatta_retCode_t shellmatta_opt_long( shellmatta_handle_t handle,
|
||||
const shellmatta_opt_long_t *longOptions,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen);
|
||||
|
||||
#ifndef SHELLMATTA_STRIP_PRINTF
|
||||
shellmatta_retCode_t shellmatta_printf( shellmatta_handle_t handle,
|
||||
const char *fmt,
|
||||
|
||||
2547
cfg/doxygen/doxyfile
Normal file
2547
cfg/doxygen/doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
247
example/main.c
Normal file
247
example/main.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file main.c
|
||||
* @brief main module to demonstrate use of the shellmatta.
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
#include "shellmatta.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static bool exitRequest = false;
|
||||
int f;
|
||||
shellmatta_handle_t handle;
|
||||
|
||||
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};
|
||||
|
||||
static shellmatta_retCode_t doSome(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
|
||||
shellmatta_write(handle, "blubb\r\n", 7u);
|
||||
|
||||
shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
|
||||
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t doSomeCmd = {"adoSome2", "adof2", "Function does something", "use me, please", doSome, NULL};
|
||||
|
||||
static shellmatta_retCode_t removeCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
shellmatta_printf(handle, "removing command: %s\r\n", doSomeCmd.cmd);
|
||||
|
||||
shellmatta_removeCmd(handle, &doSomeCmd);
|
||||
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t removeCommand = {"remove", "r", "Function removes a command", "", removeCmdFct, NULL};
|
||||
|
||||
|
||||
static shellmatta_retCode_t quit(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
exitRequest = true;
|
||||
|
||||
(void)handle;
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t quitCommand = {"quit", "q", "Function quits the shell", "", quit, NULL};
|
||||
|
||||
static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
|
||||
shellmatta_printf(handle, "empty function called\r\n");
|
||||
shellmatta_configure(handle, SHELLMATTA_MODE_OVERWRITE, true, '\r');
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t emptyCommand = {"empty", NULL, NULL, NULL, empty, NULL};
|
||||
|
||||
static shellmatta_retCode_t reset(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
shellmatta_retCode_t ret;
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
char option;
|
||||
char *argument;
|
||||
uint32_t argLen;
|
||||
bool printPrompt = false;
|
||||
|
||||
static const shellmatta_opt_long_t options[] =
|
||||
{
|
||||
{"prompt", 'p', SHELLMATTA_OPT_ARG_REQUIRED},
|
||||
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE}
|
||||
};
|
||||
|
||||
ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen);
|
||||
while(SHELLMATTA_OK == ret)
|
||||
{
|
||||
switch(option)
|
||||
{
|
||||
case 'p':
|
||||
if(NULL != argument)
|
||||
{
|
||||
if(0 == strncmp("true", argument, 4u))
|
||||
{
|
||||
printPrompt = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
shellmatta_printf(handle, "Unknown option: %c\r\n", option);
|
||||
break;
|
||||
}
|
||||
ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen);
|
||||
}
|
||||
|
||||
shellmatta_resetShell(handle, printPrompt);
|
||||
shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, true, '\r');
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t resetCommand = {"reset", NULL, "resets the shellmatta instance", "reset [--prompt true/false]", reset, NULL};
|
||||
|
||||
static shellmatta_retCode_t continuous(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
|
||||
shellmatta_retCode_t ret = SHELLMATTA_CONTINUE;
|
||||
uint32_t stdinLength;
|
||||
char *stdinData;
|
||||
|
||||
shellmatta_read(handle, &stdinData, &stdinLength);
|
||||
if(NULL != stdinData)
|
||||
{
|
||||
if('x' == stdinData[0u])
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
stdinData[0u] ++;
|
||||
shellmatta_write(handle, stdinData, stdinLength);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
shellmatta_cmd_t continuousCommand = {"continuous", "cont", "prints continously all input bytes", "continuous", continuous, NULL};
|
||||
|
||||
static shellmatta_retCode_t busy(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void)arguments;
|
||||
(void)length;
|
||||
static uint32_t callCnt = 0u;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_BUSY;
|
||||
|
||||
if(callCnt < 10u)
|
||||
{
|
||||
callCnt ++;
|
||||
shellmatta_printf(handle, "%s - length %u - callCnt %u\r\n", arguments, length, callCnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
callCnt = 0u;
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
shellmatta_cmd_t busyCommand = {"busy", NULL, NULL, NULL, busy, NULL};
|
||||
|
||||
|
||||
shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write(f, data, length);
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static char buffer[1024];
|
||||
static char historyBuffer[4096];
|
||||
static shellmatta_instance_t instance;
|
||||
|
||||
if(2 != argc)
|
||||
{
|
||||
printf("%s <serial device>\n", argv[0u]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = open(argv[1u], O_RDWR | O_SYNC);
|
||||
|
||||
if (f < 0)
|
||||
{
|
||||
printf("failure opening device %s %d\n", argv[1u], errno);
|
||||
return f;
|
||||
}
|
||||
|
||||
shellmatta_doInit( &instance,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
shellmatta_addCmd(handle, &doSomeCmd);
|
||||
shellmatta_addCmd(handle, &quitCommand);
|
||||
shellmatta_addCmd(handle, &removeCommand);
|
||||
shellmatta_addCmd(handle, &emptyCommand);
|
||||
shellmatta_addCmd(handle, &resetCommand);
|
||||
shellmatta_addCmd(handle, &continuousCommand);
|
||||
shellmatta_addCmd(handle, &busyCommand);
|
||||
|
||||
while(exitRequest == false)
|
||||
{
|
||||
char c;
|
||||
shellmatta_retCode_t ret;
|
||||
int res = 0;
|
||||
res = read (f, &c, 1);
|
||||
|
||||
fprintf(stdout, "0x%02x \n", c);
|
||||
fflush(stdout);
|
||||
|
||||
do
|
||||
{
|
||||
ret = shellmatta_processData(handle, &c, res);
|
||||
if(SHELLMATTA_BUSY == ret)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
} while(SHELLMATTA_BUSY == ret);
|
||||
}
|
||||
|
||||
close(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
158
makefile
Normal file
158
makefile
Normal file
@@ -0,0 +1,158 @@
|
||||
#
|
||||
# Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
OBJ_DIR := output/
|
||||
|
||||
CC := gcc
|
||||
CPP := g++
|
||||
LN := ln
|
||||
|
||||
SOURCES := src/shellmatta.c \
|
||||
src/shellmatta_autocomplete.c \
|
||||
src/shellmatta_history.c \
|
||||
src/shellmatta_utils.c \
|
||||
src/shellmatta_escape.c \
|
||||
src/shellmatta_opt.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 \
|
||||
test/unittest/shellmatta_utils/test_utils_restoreCursorPos.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_eraseLine.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_rewindCursor.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_forwardCursor.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_clearInput.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_insertChars.cpp \
|
||||
test/unittest/shellmatta_utils/test_utils_terminateInput.cpp \
|
||||
test/unittest/shellmatta_autocomplete/test_autocomplete_run.cpp \
|
||||
test/unittest/shellmatta_escape/test_escape_processArrowKeys.cpp \
|
||||
test/unittest/shellmatta_history/test_appendHistoryByte.cpp \
|
||||
test/unittest/shellmatta/test_shellmatta_doInit.cpp
|
||||
|
||||
INTEGRATIONTEST_SOURCES := test/integrationtest/test_main.cpp \
|
||||
test/integrationtest/test_integration.cpp \
|
||||
test/integrationtest/test_integration_opt.cpp \
|
||||
test/integrationtest/test_integration_optLong.cpp \
|
||||
test/integrationtest/test_integration_continue.cpp \
|
||||
test/integrationtest/test_integration_busy.cpp
|
||||
|
||||
UNITTEST_CPPOBJ := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(UNITTEST_SOURCES))
|
||||
|
||||
INTEGRATIONTEST_CPPOBJ := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(INTEGRATIONTEST_SOURCES))
|
||||
|
||||
CFLAGS := $(INCLUDES:%=-I%) -g -Wall -Werror -Wextra -pedantic -DSHELLMATTA_HELP_ALIAS=\"?\"
|
||||
TESTFLAGS := $(INCLUDES:%=-I%) -g -Wall -Werror -Wextra -fprofile-arcs -ftest-coverage -pedantic
|
||||
TESTLFLAGS := -fprofile-arcs -Wl,--allow-multiple-definition
|
||||
|
||||
DEPEND = -MT $@ -MF "$(@:%.o=%.d)" -MG -MM
|
||||
|
||||
COBJ := $(patsubst %.c,$(OBJ_DIR)%.o,$(SOURCES))
|
||||
|
||||
EXAMPLE_SOURCES := example/main.c
|
||||
EXAMPLE_COBJ := $(patsubst %.c,$(OBJ_DIR)%.o,$(EXAMPLE_SOURCES))
|
||||
|
||||
EXAMPLE_TARGET := $(OBJ_DIR)example/example
|
||||
|
||||
UNITTEST_TARGET := $(OBJ_DIR)test/unittest/unittest
|
||||
|
||||
INTEGRATIONTEST_TARGET := $(OBJ_DIR)test/integrationtest/integrationtest
|
||||
|
||||
OBJ := $(COBJ) $(EXAMPLE_COBJ) $(UNITTEST_CPPOBJ) $(INTEGRATIONTEST_CPPOBJ)
|
||||
DEPS := $(OBJ:%.o=%.d)
|
||||
|
||||
export
|
||||
|
||||
help:
|
||||
@echo Shellmatta help
|
||||
@echo -----------------------------------------------
|
||||
@echo test - run all tests
|
||||
@echo cppcheck - run static code analysis (cppcheck)
|
||||
@echo example - build example
|
||||
@echo -----------------------------------------------
|
||||
|
||||
test: unittest integrationtest
|
||||
|
||||
cppcheck:
|
||||
- @mkdir -p output/cppcheck/html
|
||||
cppcheck --enable=all --template=gcc --cppcheck-build-dir=output/cppcheck $(SOURCES)
|
||||
cppcheck --enable=all --template=gcc --cppcheck-build-dir=output/cppcheck $(SOURCES) --xml 2>output/cppcheck/cppcheck.xml
|
||||
cppcheck-htmlreport --file=output/cppcheck/cppcheck.xml --title="Shellmatta" --report-dir=output/cppcheck/html
|
||||
|
||||
unittest: $(UNITTEST_TARGET)
|
||||
- @mkdir -p output/test/unittest/report
|
||||
@echo running test:
|
||||
@# remove coverage from former run
|
||||
@-find . -name "*.gcda" -type f -delete
|
||||
-$(UNITTEST_TARGET)
|
||||
@#gcov -o output/test/unittest $(UNITTEST_CPPOBJ) -r src
|
||||
|
||||
@# remove report from former run
|
||||
-rm -rf $(OBJ_DIR)test/unittest/report/*
|
||||
gcovr --html-details --output $(OBJ_DIR)test/unittest/report/report.html output/test/unittest -f src -f api
|
||||
@#-rm *.gcov
|
||||
|
||||
integrationtest: $(INTEGRATIONTEST_TARGET)
|
||||
- @mkdir -p output/test/integrationtest/report
|
||||
@echo running test:
|
||||
-$(INTEGRATIONTEST_TARGET)
|
||||
#gcov -o output/test $(TEST_CPPOBJ) -r
|
||||
gcovr --html-details --output $(OBJ_DIR)test/integrationtest/report/report.html output/src -f src -f api
|
||||
#-rm *.gcov
|
||||
|
||||
example: $(EXAMPLE_TARGET)
|
||||
@echo building example
|
||||
|
||||
doc:
|
||||
- @mkdir -p output/doc/html
|
||||
- @mkdir -p output/doc/latex
|
||||
doxygen cfg/doxygen/doxyfile
|
||||
|
||||
clean:
|
||||
- rm -rf $(OBJ_DIR)
|
||||
|
||||
$(EXAMPLE_TARGET): $(COBJ) $(EXAMPLE_COBJ)
|
||||
- @mkdir -p $(@D)
|
||||
$(CC) $(LFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
|
||||
|
||||
$(UNITTEST_TARGET): $(UNITTEST_CPPOBJ)
|
||||
- @mkdir -p $(@D)
|
||||
$(CPP) $(TESTLFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
|
||||
|
||||
$(INTEGRATIONTEST_TARGET): $(INTEGRATIONTEST_CPPOBJ) $(COBJ)
|
||||
- @mkdir -p $(@D)
|
||||
$(CPP) $(TESTLFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
- @mkdir -p $(@D)
|
||||
$(CC) $(LFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
|
||||
|
||||
$(COBJ):
|
||||
- @mkdir -p $(@D)
|
||||
@$(CC) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
|
||||
$(CC) -c $(CFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
|
||||
|
||||
$(EXAMPLE_COBJ):
|
||||
- @mkdir -p $(@D)
|
||||
@$(CC) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
|
||||
$(CC) -c $(CFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
|
||||
|
||||
$(UNITTEST_CPPOBJ) $(INTEGRATIONTEST_CPPOBJ):
|
||||
- @mkdir -p $(@D)
|
||||
@$(CPP) -c $(TESTFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.cpp))
|
||||
$(CPP) -c $(TESTFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.cpp))
|
||||
|
||||
%.o: %.cpp
|
||||
- @mkdir -p $(@D)
|
||||
@$(CPP) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
|
||||
$(CPP) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
-include $(DEPS)
|
||||
493
src/shellmatta.c
493
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>
|
||||
@@ -74,7 +75,11 @@ shellmatta_retCode_t shellmatta_doInit(
|
||||
inst->buffer = buffer;
|
||||
inst->bufferSize = bufferSize;
|
||||
inst->inputCount = 0u;
|
||||
inst->byteCounter = 0u;
|
||||
inst->lastNewlineIdx = 0u;
|
||||
inst->cursor = 0u;
|
||||
inst->stdinIdx = 0u;
|
||||
inst->stdinLength = 0u;
|
||||
inst->historyBuffer = historyBuffer;
|
||||
inst->historyBufferSize = historyBufferSize;
|
||||
inst->historyStart = 0u;
|
||||
@@ -87,13 +92,23 @@ shellmatta_retCode_t shellmatta_doInit(
|
||||
inst->dirty = false;
|
||||
inst->tabCounter = 0u;
|
||||
inst->escapeCounter = 0u;
|
||||
inst->hereStartIdx = 0u;
|
||||
inst->hereDelimiterIdx = 0u;
|
||||
inst->hereLength = 0u;
|
||||
inst->delimiter = '\r';
|
||||
inst->mode = SHELLMATTA_MODE_INSERT;
|
||||
inst->cmdList = &helpCmd;
|
||||
inst->cmdList = &(inst->helpCmd);
|
||||
inst->continuousCmd = NULL;
|
||||
inst->busyCmd = NULL;
|
||||
inst->cmdListIsConst = false;
|
||||
shellmatta_opt_init(inst, 0u);
|
||||
|
||||
/** -# copy the help command structure to this instance */
|
||||
memcpy(&(inst->helpCmd), &helpCmd, sizeof(shellmatta_cmd_t));
|
||||
|
||||
if(NULL != cmdList)
|
||||
{
|
||||
helpCmd.next = (shellmatta_cmd_t *) cmdList;
|
||||
inst->helpCmd.next = (shellmatta_cmd_t *) cmdList;
|
||||
inst->cmdListIsConst = true;
|
||||
}
|
||||
|
||||
@@ -107,6 +122,59 @@ shellmatta_retCode_t shellmatta_doInit(
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief resets the whole shellmatta instance
|
||||
* @param[in] handle shellmatta instance handle
|
||||
* @param[in] printPrompt print a new command prompt
|
||||
*
|
||||
* This function can be used e.g. when working with connection based interfaces (e.g. sockets) to clear
|
||||
* the shell from old content when a new connection is opened.
|
||||
* It resets all internal states - the buffers are left as they are - they will be overwritten.
|
||||
* The history buffer is deleted as well.
|
||||
*/
|
||||
shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle, bool printPrompt)
|
||||
{
|
||||
shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# check if the instance is plausible */
|
||||
if( (NULL != handle)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic))
|
||||
{
|
||||
inst->inputCount = 0u;
|
||||
inst->byteCounter = 0u;
|
||||
inst->continuousCmd = NULL;
|
||||
inst->busyCmd = NULL;
|
||||
inst->lastNewlineIdx = 0u;
|
||||
inst->cursor = 0u;
|
||||
inst->stdinIdx = 0u;
|
||||
inst->stdinLength = 0u;
|
||||
inst->historyStart = 0u;
|
||||
inst->historyEnd = 0u;
|
||||
inst->historyRead = 0u;
|
||||
inst->historyReadUp = true;
|
||||
inst->dirty = false;
|
||||
inst->tabCounter = 0u;
|
||||
inst->escapeCounter = 0u;
|
||||
inst->hereStartIdx = 0u;
|
||||
inst->hereDelimiterIdx = 0u;
|
||||
inst->hereLength = 0u;
|
||||
shellmatta_opt_init(inst, 0u);
|
||||
|
||||
if(true == printPrompt)
|
||||
{
|
||||
/** -# print a prompt if requested */
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief adds a command to the command list alphabetically ordered
|
||||
* @param[in] handle shellmatta instance handle
|
||||
@@ -114,6 +182,9 @@ shellmatta_retCode_t shellmatta_doInit(
|
||||
* @return errorcode #SHELLMATTA_OK
|
||||
* #SHELLMATTA_USE_FAULT (param err)
|
||||
* SHELLMATTA_DUPLICATE
|
||||
*
|
||||
* The cmd name is mandatory, the rest of the command parameters (alias, helpText and usageText) are optional
|
||||
* and can be set to NULL if not used.
|
||||
*/
|
||||
shellmatta_retCode_t shellmatta_addCmd(shellmatta_handle_t handle, shellmatta_cmd_t *cmd)
|
||||
{
|
||||
@@ -128,7 +199,9 @@ shellmatta_retCode_t shellmatta_addCmd(shellmatta_handle_t handle, shellmatta_cm
|
||||
/** -# check parameters for plausibility */
|
||||
if( (NULL != inst)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic)
|
||||
&& (false == inst->cmdListIsConst))
|
||||
&& (false == inst->cmdListIsConst)
|
||||
&& (NULL != cmd)
|
||||
&& (NULL != cmd->cmd))
|
||||
{
|
||||
tempCmd = inst->cmdList;
|
||||
prevCmd = &inst->cmdList;
|
||||
@@ -144,7 +217,16 @@ shellmatta_retCode_t shellmatta_addCmd(shellmatta_handle_t handle, shellmatta_cm
|
||||
while ((false == cmdPlaced) && (SHELLMATTA_OK == ret))
|
||||
{
|
||||
cmdDiff = strcmp(tempCmd->cmd, cmd->cmd);
|
||||
if( (NULL != cmd->cmdAlias)
|
||||
&& (NULL != tempCmd->cmdAlias))
|
||||
{
|
||||
aliasDiff = strcmp(tempCmd->cmdAlias, cmd->cmdAlias);
|
||||
}
|
||||
else
|
||||
{
|
||||
aliasDiff = 1;
|
||||
}
|
||||
|
||||
/** -# check for a duplicate command */
|
||||
if((0u == cmdDiff) || (0u == aliasDiff))
|
||||
{
|
||||
@@ -179,6 +261,103 @@ shellmatta_retCode_t shellmatta_addCmd(shellmatta_handle_t handle, shellmatta_cm
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief removes a command from the command list
|
||||
* @param[in] handle shellmatta instance handle
|
||||
* @param[in] cmd pointer to the command to remove type #shellmatta_cmd_t
|
||||
* @return errorcode #SHELLMATTA_OK
|
||||
* #SHELLMATTA_USE_FAULT (param err)
|
||||
*/
|
||||
shellmatta_retCode_t shellmatta_removeCmd(shellmatta_handle_t handle, shellmatta_cmd_t *cmd)
|
||||
{
|
||||
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
||||
shellmatta_cmd_t *prevCmd;
|
||||
shellmatta_cmd_t *tempCmd;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# check parameters for plausibility */
|
||||
if( (NULL != inst)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic)
|
||||
&& (false == inst->cmdListIsConst)
|
||||
&& (NULL != cmd)
|
||||
&& (NULL != cmd->cmd))
|
||||
{
|
||||
tempCmd = inst->cmdList;
|
||||
prevCmd = NULL;
|
||||
|
||||
/** -# loop through command list */
|
||||
while(NULL != tempCmd)
|
||||
{
|
||||
/** -# compare command strings to find the command to delete */
|
||||
if (0 == strcmp( tempCmd->cmd,
|
||||
cmd->cmd)
|
||||
&& (strlen(tempCmd->cmd) == strlen(cmd->cmd)))
|
||||
{
|
||||
/** -# first command removed */
|
||||
if(NULL == prevCmd)
|
||||
{
|
||||
inst->cmdList = tempCmd->next;
|
||||
}
|
||||
/** -# last command removed */
|
||||
else if(NULL == tempCmd->next)
|
||||
{
|
||||
prevCmd->next = NULL;
|
||||
}
|
||||
/** -# command removed from the middle of the list */
|
||||
else
|
||||
{
|
||||
prevCmd->next = tempCmd->next;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prevCmd = tempCmd;
|
||||
tempCmd = tempCmd->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief changes configuration of a shellmatta instance
|
||||
* @param[in] handle shellmatta instance handle
|
||||
* @param[in] mode insert mode of the shellmatta type #shellmatta_mode_t
|
||||
* @param[in] echoEnabled true: echo received chars to the output
|
||||
* @param[in] delimiter delimiter used to detect the end of a cmd (default "\r")
|
||||
* @return errorcode #SHELLMATTA_OK
|
||||
* #SHELLMATTA_USE_FAULT (param err)
|
||||
*/
|
||||
shellmatta_retCode_t shellmatta_configure( shellmatta_handle_t handle,
|
||||
shellmatta_mode_t mode,
|
||||
bool echoEnabled,
|
||||
char delimiter)
|
||||
{
|
||||
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# check parameters for plausibility */
|
||||
if( (NULL != inst)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic)
|
||||
&& ((mode == SHELLMATTA_MODE_INSERT) || (mode == SHELLMATTA_MODE_OVERWRITE)))
|
||||
{
|
||||
inst->mode = mode;
|
||||
inst->echoEnabled = echoEnabled;
|
||||
inst->delimiter = delimiter;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief processes the passed amount of data
|
||||
* @param[in] handle shellmatta instance handle
|
||||
@@ -194,42 +373,221 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
||||
shellmatta_cmd_t *cmd;
|
||||
uint8_t cmdExecuted = 0u;
|
||||
uint32_t cmdLen;
|
||||
char *tempString;
|
||||
|
||||
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
||||
shellmatta_retCode_t cmdRet;
|
||||
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
||||
|
||||
/** -# check parameters for plausibility */
|
||||
if( (NULL != inst)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic))
|
||||
{
|
||||
/** -# in busy mode - keep calling this command */
|
||||
if(NULL != inst->busyCmd)
|
||||
{
|
||||
/** -# just call the function until it is not busy anymore */
|
||||
(void)shellmatta_opt_reInit(inst);
|
||||
ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
||||
|
||||
if(SHELLMATTA_BUSY == ret)
|
||||
{
|
||||
/** -# do nothing - still busy */
|
||||
}
|
||||
else if(SHELLMATTA_CONTINUE == ret)
|
||||
{
|
||||
inst->continuousCmd = inst->busyCmd;
|
||||
inst->busyCmd = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
}
|
||||
/** -# call continuous function even if there is no data */
|
||||
else if((0u == size) && (NULL != inst->continuousCmd))
|
||||
{
|
||||
/** -# just call the function without any new data */
|
||||
inst->stdinLength = 0u;
|
||||
inst->buffer[inst->stdinIdx] = '\0';
|
||||
(void)shellmatta_opt_reInit(inst);
|
||||
ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
||||
|
||||
if(SHELLMATTA_CONTINUE == ret)
|
||||
{
|
||||
/** -# do nothing just continue */
|
||||
}
|
||||
else if(SHELLMATTA_BUSY == ret)
|
||||
{
|
||||
inst->busyCmd = inst->continuousCmd;
|
||||
inst->continuousCmd = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
}
|
||||
|
||||
/** -# process byte wise */
|
||||
for (uint32_t i = 0u; i < size; i++)
|
||||
for (; (inst->byteCounter < size) && (NULL == inst->busyCmd); inst->byteCounter++)
|
||||
{
|
||||
/** -# in continuous mode - pass data directly to the command */
|
||||
if(NULL != inst->continuousCmd)
|
||||
{
|
||||
/** -# copy data and call command function */
|
||||
inst->buffer[inst->stdinIdx] = data[inst->byteCounter];
|
||||
inst->buffer[inst->stdinIdx + 1u] = '\0';
|
||||
inst->stdinLength = 1u;
|
||||
(void)shellmatta_opt_reInit(inst);
|
||||
ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
||||
|
||||
/** -# check if continuous mode is canceled or interrupted by busy mode */
|
||||
if(SHELLMATTA_BUSY == ret)
|
||||
{
|
||||
inst->busyCmd = inst->continuousCmd;
|
||||
inst->continuousCmd = NULL;
|
||||
}
|
||||
else if(('\x03' == data[inst->byteCounter]))
|
||||
{
|
||||
/** -# cancel continue session */
|
||||
utils_terminateInput(inst);
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
else if(SHELLMATTA_CONTINUE == ret)
|
||||
{
|
||||
/** -# do nothing - continue */
|
||||
}
|
||||
else
|
||||
{
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
}
|
||||
/** -# handle escape sequences */
|
||||
if(inst->escapeCounter != 0u)
|
||||
else if(inst->escapeCounter != 0u)
|
||||
{
|
||||
escape_handleSequence(inst, *data);
|
||||
escape_handleSequence(inst, data[inst->byteCounter]);
|
||||
}
|
||||
/** -# ignore newline as first character (to be compatible to
|
||||
* terminals sending newline after return */
|
||||
else if((0u == inst->inputCount) && ('\n' == *data))
|
||||
/** -# handle delimiter as start of processing the command */
|
||||
else if (inst->delimiter == data[inst->byteCounter])
|
||||
{
|
||||
/* do nothing */
|
||||
if(0u == inst->hereLength)
|
||||
{
|
||||
/**
|
||||
* @dot
|
||||
* digraph heredocParser {
|
||||
* start -> wait [ label="<< in first line - store delimiter" ];
|
||||
* wait -> wait [ label="delimiter not detected" ];
|
||||
* wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
|
||||
* }
|
||||
* @enddot */
|
||||
|
||||
/** -# check for heredoc - add string delimiter to stop strstr from searching too far */
|
||||
inst->buffer[inst->inputCount] = '\0';
|
||||
tempString = strstr(inst->buffer, "<<");
|
||||
if(NULL != tempString)
|
||||
{
|
||||
/*' -# check if length of heredoc delimiter is valid */
|
||||
if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
|
||||
{
|
||||
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->hereDelimiterIdx ++;
|
||||
}
|
||||
/** -# handle return as start of processing the command */
|
||||
else if ('\r' == *data)
|
||||
|
||||
inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
|
||||
|
||||
inst->dirty = true;
|
||||
utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
||||
inst->lastNewlineIdx = inst->inputCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = inst->cmdList;
|
||||
inst->buffer[inst->inputCount] = 0u;
|
||||
inst->hereLength = 0u;
|
||||
|
||||
/** -# store the current command and reset the history buffer */
|
||||
inst->dirty = true;
|
||||
history_storeCmd(inst);
|
||||
history_reset(inst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/** -# store the current command and reset the history buffer */
|
||||
inst->dirty = true;
|
||||
history_storeCmd(inst);
|
||||
history_reset(inst);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempString = &inst->buffer[inst->lastNewlineIdx];
|
||||
cmdLen = inst->inputCount - inst->lastNewlineIdx;
|
||||
|
||||
/** -# skip newline characters before comparison */
|
||||
while(('\n' == *tempString) || ('\r' == *tempString))
|
||||
{
|
||||
tempString ++;
|
||||
cmdLen --;
|
||||
}
|
||||
|
||||
if( (inst->hereLength == cmdLen)
|
||||
&& (0 == strncmp( &inst->buffer[inst->hereDelimiterIdx],
|
||||
tempString,
|
||||
inst->hereLength)))
|
||||
{
|
||||
/** -# store the current command and reset the history buffer */
|
||||
inst->dirty = true;
|
||||
history_storeCmd(inst);
|
||||
history_reset(inst);
|
||||
|
||||
/** -# 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->stdinIdx ++;
|
||||
}
|
||||
/** -# calculate length and terminate stdin string */
|
||||
if(inst->stdinIdx < inst->lastNewlineIdx)
|
||||
{
|
||||
inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
|
||||
inst->buffer[inst->lastNewlineIdx] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
inst->stdinLength = 0u;
|
||||
}
|
||||
|
||||
/** -# calculate length and terminate argument string */
|
||||
inst->inputCount = inst->hereStartIdx;
|
||||
inst->buffer[inst->hereStartIdx] = '\0';
|
||||
|
||||
/** -# terminate heredoc session */
|
||||
inst->hereLength = 0u;
|
||||
}
|
||||
else
|
||||
{
|
||||
/** -# the party goes on - just print the delimiter and store the position */
|
||||
inst->lastNewlineIdx = inst->inputCount;
|
||||
utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
||||
}
|
||||
}
|
||||
|
||||
if(0u == inst->hereLength)
|
||||
{
|
||||
cmd = inst->cmdList;
|
||||
|
||||
/** -# determine the cmd len (chars until first space or \0 is found */
|
||||
cmdLen = 0u;
|
||||
while( (cmdLen < inst->inputCount)
|
||||
&& (' ' != inst->buffer[cmdLen])
|
||||
&& ('\r' != inst->buffer[cmdLen])
|
||||
&& ('\n' != inst->buffer[cmdLen])
|
||||
&& ('\0' != inst->buffer[cmdLen]))
|
||||
{
|
||||
cmdLen ++;
|
||||
@@ -238,20 +596,41 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
||||
/** -# search for a matching command */
|
||||
while (NULL != cmd)
|
||||
{
|
||||
/** -# compare command string and length */
|
||||
/** -# compare command and alias string and length */
|
||||
if ( ((0 == strncmp( inst->buffer,
|
||||
cmd->cmd,
|
||||
cmdLen))
|
||||
&& (cmdLen == strlen(cmd->cmd)))
|
||||
|| ((0 == strncmp( inst->buffer,
|
||||
|| ((NULL != cmd->cmdAlias)
|
||||
&& ((0 == strncmp( inst->buffer,
|
||||
cmd->cmdAlias,
|
||||
cmdLen))
|
||||
&& (cmdLen == strlen(cmd->cmdAlias))))
|
||||
&& (cmdLen == strlen(cmd->cmdAlias)))))
|
||||
{
|
||||
inst->write("\r\n", 2u);
|
||||
|
||||
utils_writeEcho(inst, "\r\n", 2u);
|
||||
shellmatta_opt_init(inst, cmdLen + 1u);
|
||||
cmdExecuted = 1u;
|
||||
cmd->cmdFct(inst, inst->buffer, inst->inputCount);
|
||||
cmdRet = cmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
||||
|
||||
switch(cmdRet)
|
||||
{
|
||||
case SHELLMATTA_CONTINUE:
|
||||
/** -# initialize stdin buffer and continuous cmd */
|
||||
inst->stdinIdx = inst->inputCount + 1u;
|
||||
inst->stdinLength = 0u;
|
||||
inst->continuousCmd = cmd;
|
||||
ret = cmdRet;
|
||||
break;
|
||||
|
||||
case SHELLMATTA_BUSY:
|
||||
inst->busyCmd = cmd;
|
||||
ret = cmdRet;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* nothing to do - everything ok */
|
||||
break;
|
||||
}
|
||||
cmd = NULL;
|
||||
}
|
||||
else
|
||||
@@ -262,57 +641,68 @@ 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(" not found", 10u);
|
||||
}
|
||||
|
||||
/** -# terminate this session if no continuous mode is requested */
|
||||
if( (NULL == inst->continuousCmd)
|
||||
&& (NULL == inst->busyCmd))
|
||||
{
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
/** -# ignore newline as first character (to be compatible to
|
||||
* terminals sending newline after return */
|
||||
else if((0u == inst->inputCount) && ('\n' == data[inst->byteCounter]))
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
/** -# check for tabulator key - auto complete */
|
||||
else if('\t' == *data)
|
||||
else if('\t' == data[inst->byteCounter])
|
||||
{
|
||||
inst->dirty = true;
|
||||
autocomplete_run(inst);
|
||||
}
|
||||
/** -# check for cancel -
|
||||
* terminate current input and print prompt again */
|
||||
else if(3 == *data)
|
||||
else if('\x03' == data[inst->byteCounter])
|
||||
{
|
||||
inst->dirty = false;
|
||||
history_reset(inst);
|
||||
utils_terminateInput(inst);
|
||||
}
|
||||
/** -# check for backspace */
|
||||
else if('\b' == *data)
|
||||
else if( ('\b' == data[inst->byteCounter])
|
||||
|| ('\x7f' == data[inst->byteCounter]))
|
||||
{
|
||||
inst->dirty = true;
|
||||
utils_removeChars(inst, 1u, true);
|
||||
}
|
||||
/** -# check for delete key */
|
||||
else if(0x7eu == *data)
|
||||
{
|
||||
inst->dirty = true;
|
||||
utils_removeChars(inst, 1u, false);
|
||||
}
|
||||
/** -# check for start of escape sequence */
|
||||
else if('\e' == *data)
|
||||
else if('\x1b' == data[inst->byteCounter])
|
||||
{
|
||||
inst->escapeCounter = 1u;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst->dirty = true;
|
||||
utils_insertChars(inst, data, 1);
|
||||
utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
||||
}
|
||||
|
||||
/** -# reset tab counter on not a tab */
|
||||
if ('\t' != *data)
|
||||
if ('\t' != data[inst->byteCounter])
|
||||
{
|
||||
inst->tabCounter = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
data ++;
|
||||
/** -# initialize the byte buffer if processing of the input is finished */
|
||||
if(ret != SHELLMATTA_BUSY)
|
||||
{
|
||||
inst->byteCounter = 0u;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -347,6 +737,41 @@ 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 stdin data or NULL
|
||||
* @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 or NULL */
|
||||
if(0u == inst->stdinLength)
|
||||
{
|
||||
*data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*data = &(inst->buffer[inst->stdinIdx]);
|
||||
}
|
||||
*length = inst->stdinLength;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef SHELLMATTA_STRIP_PRINTF
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,8 @@ void autocomplete_run(shellmatta_instance_t *inst)
|
||||
printedLen += 4u;
|
||||
}
|
||||
/** -# check if command alias matches the input */
|
||||
if( (strlen(cmd->cmdAlias) >= inst->cursor)
|
||||
if( (NULL != cmd->cmdAlias)
|
||||
&& (strlen(cmd->cmdAlias) >= inst->cursor)
|
||||
&& (0u == memcmp(cmd->cmdAlias, inst->buffer, inst->cursor)))
|
||||
{
|
||||
/** -# add newline on first find */
|
||||
@@ -123,7 +124,8 @@ void autocomplete_run(shellmatta_instance_t *inst)
|
||||
}
|
||||
|
||||
/** -# check if command Alias matches the input */
|
||||
if( (strlen(cmd->cmdAlias) >= inst->cursor)
|
||||
if( (NULL != cmd->cmdAlias)
|
||||
&& (strlen(cmd->cmdAlias) >= inst->cursor)
|
||||
&& (0u == memcmp(cmd->cmdAlias, inst->buffer, inst->cursor)))
|
||||
{
|
||||
/** -# store first match */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief processes the excape character stream of the instance and chacks
|
||||
* @brief processes the excape character stream of the instance and checks
|
||||
* if an arrow key was pressed
|
||||
* @param[in] inst pointer to a shellmatta instance
|
||||
* @return #SHELLMATTA_OK if an arrow key was pressed
|
||||
@@ -44,12 +44,11 @@ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst)
|
||||
history_storeCmd(inst);
|
||||
if(false == inst->historyReadUp)
|
||||
{
|
||||
history_navigate(inst, -1);
|
||||
(void)history_navigate(inst, -1);
|
||||
}
|
||||
inst->historyReadUp = true;
|
||||
utils_clearInput(inst);
|
||||
history_restoreCmd(inst);
|
||||
history_navigate(inst, -1);
|
||||
(void)history_navigate(inst, -1);
|
||||
|
||||
break;
|
||||
case 'B': /* arrow down */
|
||||
@@ -59,11 +58,10 @@ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst)
|
||||
history_storeCmd(inst);
|
||||
if(true == inst->historyReadUp)
|
||||
{
|
||||
history_navigate(inst, 1);
|
||||
(void)history_navigate(inst, 1);
|
||||
}
|
||||
inst->historyReadUp = false;
|
||||
history_navigate(inst, 1);
|
||||
utils_clearInput(inst);
|
||||
(void)history_navigate(inst, 1);
|
||||
history_restoreCmd(inst);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -59,7 +59,7 @@ static void appendHistoryByte(shellmatta_instance_t *inst, char byte)
|
||||
* @brief reads a byte from the history buffer and decreases the read index
|
||||
* @param[in] inst pointer to a shellmatta instance
|
||||
* @param[out] byte pointer to a char where the read out byte will be stored
|
||||
* @return
|
||||
* @return false: no new byte to read
|
||||
*/
|
||||
static bool getHistoryByte(shellmatta_instance_t *inst, char *byte)
|
||||
{
|
||||
@@ -84,6 +84,12 @@ static bool getHistoryByte(shellmatta_instance_t *inst, char *byte)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief navigates in the history buffer by the given number of commands
|
||||
* @param[in, out] inst pointer to a shellmatta instance
|
||||
* @param[in] cnt direction and count to navigate
|
||||
* @return false: end of buffer reached
|
||||
*/
|
||||
bool history_navigate(shellmatta_instance_t *inst, int32_t cnt)
|
||||
{
|
||||
bool ret = true;
|
||||
@@ -185,13 +191,6 @@ void history_storeCmd(shellmatta_instance_t *inst)
|
||||
inst->dirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief navigates in the history buffer by the given number of commands
|
||||
* @param[in] inst pointer to a shellmatta instance
|
||||
* @param[in] cnt direction and count to navigate
|
||||
* @return
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief restores the command from the history buffer where the read
|
||||
* index points on
|
||||
@@ -201,8 +200,16 @@ void history_restoreCmd(shellmatta_instance_t *inst)
|
||||
{
|
||||
char byte;
|
||||
bool ret = true;
|
||||
bool anythingToRestore = false;
|
||||
|
||||
ret = getHistoryByte(inst, &byte);
|
||||
|
||||
/** -# delete the input if there is data in the history buffer */
|
||||
if(true == ret)
|
||||
{
|
||||
utils_clearInput(inst);
|
||||
anythingToRestore = true;
|
||||
}
|
||||
while((ret == true) && (byte != 0u))
|
||||
{
|
||||
inst->buffer[inst->inputCount] = byte;
|
||||
@@ -211,10 +218,13 @@ void history_restoreCmd(shellmatta_instance_t *inst)
|
||||
ret = getHistoryByte(inst, &byte);
|
||||
}
|
||||
|
||||
if(true == anythingToRestore)
|
||||
{
|
||||
utils_writeEcho(inst, inst->buffer, inst->inputCount);
|
||||
history_navigate(inst, 1);
|
||||
inst->dirty = false;
|
||||
}
|
||||
(void)history_navigate(inst, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief resets the history buffer pointers to show to the most recent
|
||||
|
||||
432
src/shellmatta_opt.c
Normal file
432
src/shellmatta_opt.c
Normal file
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file shellmatta_opt.c
|
||||
* @brief option parser implementation of the shellmatta
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup shellmatta_opt
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "shellmatta_opt.h"
|
||||
#include "shellmatta_utils.h"
|
||||
#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] inst pointer to shellmatta instance
|
||||
* @param[in] optionString option string e.g. "cd:e::"
|
||||
* @param[out] option pointer to store the detected option to
|
||||
* @param[out] argtype pointer to var of type #shellmatta_opt_argtype_t != 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,
|
||||
const 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]))
|
||||
{
|
||||
*option = '\0';
|
||||
|
||||
/** -# search for option character in option string */
|
||||
for(i = 0u; ('\0' != optionString[i]) && ('\0' == *option); i ++)
|
||||
{
|
||||
if(buffer[1u] == optionString[i])
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# return found option character */
|
||||
*option = buffer[1u];
|
||||
|
||||
/** -# 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** -# skip "--" */
|
||||
else if((2u == inst->optionParser.len) && ('-' == buffer[0u]) && ('-' == buffer[1u]))
|
||||
{
|
||||
ret = SHELLMATTA_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*option = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief tries to parse the current input hunk and check if this is a configured option
|
||||
* @param[in] inst pointer to shellmatta instance
|
||||
* @param[in] longOptions option structure - pointer to array of type #shellmatta_opt_long_t
|
||||
* @param[out] option pointer to store the detected option to
|
||||
* @param[out] argtype pointer to var of type #shellmatta_opt_argtype_t != NULL
|
||||
* @return errorcode #SHELLMATTA_OK - option parsable and found in option String
|
||||
* #SHELLMATTA_ERROR - format error or option unknown
|
||||
*/
|
||||
static shellmatta_retCode_t parseLongOpt( shellmatta_instance_t *inst,
|
||||
const shellmatta_opt_long_t *longOptions,
|
||||
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 for short options */
|
||||
if((2u == inst->optionParser.len) && ('-' == buffer[0u]) && ('-' != buffer[1u]) && ('\0' != buffer[1u]))
|
||||
{
|
||||
/** -# search for option character in option list */
|
||||
for(i = 0u; ('\0' != longOptions[i].paramShort) && ('\0' == *option); i ++)
|
||||
{
|
||||
if(buffer[1u] == longOptions[i].paramShort)
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# return found option character */
|
||||
*option = longOptions[i].paramShort;
|
||||
*argtype = longOptions[i].argtype;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** -# check for correct syntax for long options */
|
||||
else if((3u <= inst->optionParser.len) && ('-' == buffer[0u]) && ('-' == buffer[1u]))
|
||||
{
|
||||
/** -# search for long option in option list */
|
||||
for(i = 0u; ('\0' != longOptions[i].paramShort) && ('\0' == *option); i ++)
|
||||
{
|
||||
if(0 == strcmp(&buffer[2u], longOptions[i].paramLong))
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
|
||||
/** -# return found option character */
|
||||
*option = longOptions[i].paramShort;
|
||||
*argtype = longOptions[i].argtype;
|
||||
}
|
||||
}
|
||||
}
|
||||
/** -# ignore "--" */
|
||||
else if((2u == inst->optionParser.len) && ('-' == buffer[0u]) && ('-' == buffer[1u]))
|
||||
{
|
||||
*option = '\0';
|
||||
ret = SHELLMATTA_CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*option = '\0';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scans the current input and parses options in getopt style - pass either optionString or longOptions
|
||||
* This is an internal funtion to handle both getopt styles and remove duplicated code...
|
||||
* The standard functions are just wrapper around this one.
|
||||
* @param[in] handle shellmatta handle
|
||||
* @param[in] optionString option string e.g. "cd:e::"
|
||||
* @param[in] longOptions option structure - pointer to array of type #shellmatta_opt_long_t
|
||||
* @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
|
||||
*/
|
||||
static shellmatta_retCode_t shellmatta_opt_int( shellmatta_handle_t handle,
|
||||
const char *optionString,
|
||||
const shellmatta_opt_long_t *longOptions,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen)
|
||||
{
|
||||
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)
|
||||
&& (SHELLMATTA_MAGIC == inst->magic)
|
||||
&& (NULL != option))
|
||||
{
|
||||
*option = '\0';
|
||||
if(NULL != argument)
|
||||
{
|
||||
*argument = NULL;
|
||||
}
|
||||
if(NULL != argLen)
|
||||
{
|
||||
*argLen = 0u;
|
||||
}
|
||||
|
||||
/** -# do this until we find a not skipable argument */
|
||||
do
|
||||
{
|
||||
ret = findNextHunk(inst);
|
||||
if(SHELLMATTA_OK == ret)
|
||||
{
|
||||
/** -# call the matching parse function */
|
||||
if(NULL != optionString)
|
||||
{
|
||||
ret = parseShortOpt(inst, optionString, option, &argtype);
|
||||
}
|
||||
else if(NULL != longOptions)
|
||||
{
|
||||
ret = parseLongOpt(inst, longOptions, option, &argtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
|
||||
/** -# when no option is found return this as raw argument */
|
||||
if(SHELLMATTA_ERROR == ret)
|
||||
{
|
||||
if(NULL != argument)
|
||||
{
|
||||
*argument = &(inst->buffer[inst->optionParser.offset]);
|
||||
}
|
||||
if(NULL != argLen)
|
||||
{
|
||||
*argLen = inst->optionParser.len;
|
||||
}
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
else if(SHELLMATTA_USE_FAULT == ret)
|
||||
{
|
||||
/** -# nothing to do - just return errorcode */
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(argtype)
|
||||
{
|
||||
case SHELLMATTA_OPT_ARG_REQUIRED:
|
||||
ret = findNextHunk(inst);
|
||||
if((NULL == argument) || (NULL == argLen))
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
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((NULL == argument) || (NULL == argLen))
|
||||
{
|
||||
ret = SHELLMATTA_USE_FAULT;
|
||||
}
|
||||
if(SHELLMATTA_OK == ret)
|
||||
{
|
||||
*argument = &(inst->buffer[inst->optionParser.offset]);
|
||||
*argLen = inst->optionParser.len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* nothing to do */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(SHELLMATTA_CONTINUE == ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief scans the current input and parses options in getopt style
|
||||
* @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] 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,
|
||||
const char *optionString,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen)
|
||||
{
|
||||
return shellmatta_opt_int( handle,
|
||||
optionString,
|
||||
NULL,
|
||||
option,
|
||||
argument,
|
||||
argLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief scans the current input and parses options in getopt_long style
|
||||
* @param[in] handle shellmatta handle
|
||||
* @param[in] longOptions option structure - pointer to array of type #shellmatta_opt_long_t
|
||||
* @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)
|
||||
*/
|
||||
shellmatta_retCode_t shellmatta_opt_long( shellmatta_handle_t handle,
|
||||
const shellmatta_opt_long_t *longOptions,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen)
|
||||
{
|
||||
return shellmatta_opt_int( handle,
|
||||
NULL,
|
||||
longOptions,
|
||||
option,
|
||||
argument,
|
||||
argLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initializes the option parser instance
|
||||
* @param[in, out] inst pointer to a shellmatta instance
|
||||
* @param[in] argStart start offset of the arguments (after command name/alias)
|
||||
*/
|
||||
void shellmatta_opt_init(shellmatta_instance_t *inst, uint32_t argStart)
|
||||
{
|
||||
/** -# initialize all relevant option parser variables */
|
||||
inst->optionParser.argStart = argStart;
|
||||
inst->optionParser.nextOffset = argStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief re-initializes the option parser instance using the data from the last init
|
||||
* @param[in, out] inst pointer to a shellmatta instance
|
||||
*/
|
||||
void shellmatta_opt_reInit(shellmatta_instance_t *inst)
|
||||
{
|
||||
/** -# initialize all relevant option parser variables */
|
||||
inst->optionParser.nextOffset = inst->optionParser.argStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
45
src/shellmatta_opt.h
Normal file
45
src/shellmatta_opt.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file shellmatta_opt.h
|
||||
* @brief option parser implementation of the shellmatta
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup shellmatta_opt
|
||||
* @{
|
||||
*/
|
||||
#ifndef _SHELLMATTA_OPT_H_
|
||||
#define _SHELLMATTA_OPT_H_
|
||||
|
||||
#include "shellmatta.h"
|
||||
#include <stdint.h>
|
||||
|
||||
shellmatta_retCode_t shellmatta_opt( shellmatta_handle_t handle,
|
||||
const char *optionString,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen);
|
||||
|
||||
shellmatta_retCode_t shellmatta_opt_long( shellmatta_handle_t handle,
|
||||
const shellmatta_opt_long_t *longOptions,
|
||||
char *option,
|
||||
char **argument,
|
||||
uint32_t *argLen);
|
||||
|
||||
void shellmatta_opt_init( shellmatta_instance_t *inst,
|
||||
uint32_t argStart);
|
||||
|
||||
void shellmatta_opt_reInit( shellmatta_instance_t *inst);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -69,7 +69,7 @@ uint32_t utils_shellItoa(int32_t value, char *buffer, uint32_t base)
|
||||
do
|
||||
{
|
||||
digitValue = (char) (value % base);
|
||||
tempBuffer[i] = (digitValue < 10u) ? ('0' + digitValue) : (('A' - 10) + digitValue);
|
||||
tempBuffer[i] = (digitValue < 10) ? ('0' + digitValue) : (('A' - 10) + digitValue);
|
||||
value /= base;
|
||||
i ++;
|
||||
}while(value > 0);
|
||||
@@ -91,7 +91,7 @@ uint32_t utils_shellItoa(int32_t value, char *buffer, uint32_t base)
|
||||
*/
|
||||
void utils_saveCursorPos(shellmatta_instance_t *inst)
|
||||
{
|
||||
utils_writeEcho(inst, "\e[s", 3u);
|
||||
utils_writeEcho(inst, "\x1b[s", 3u);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,7 @@ void utils_saveCursorPos(shellmatta_instance_t *inst)
|
||||
*/
|
||||
void utils_restoreCursorPos(shellmatta_instance_t *inst)
|
||||
{
|
||||
utils_writeEcho(inst, "\e[u", 3u);
|
||||
utils_writeEcho(inst, "\x1b[u", 3u);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +110,7 @@ void utils_restoreCursorPos(shellmatta_instance_t *inst)
|
||||
*/
|
||||
void utils_eraseLine(shellmatta_instance_t *inst)
|
||||
{
|
||||
utils_writeEcho(inst, "\e[K", 3u);
|
||||
utils_writeEcho(inst, "\x1b[K", 3u);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,7 +126,7 @@ void utils_rewindCursor(shellmatta_instance_t *inst, uint32_t length)
|
||||
length = SHELLMATTA_MIN (length, inst->cursor);
|
||||
if(length > 0u)
|
||||
{
|
||||
terminalCmd[0] = '\e';
|
||||
terminalCmd[0] = '\x1b';
|
||||
terminalCmd[1] = '[';
|
||||
size = 2u + utils_shellItoa(length, &terminalCmd[2], 10);
|
||||
terminalCmd[size] = 'D';
|
||||
@@ -148,7 +148,7 @@ void utils_forwardCursor(shellmatta_instance_t *inst, uint32_t length)
|
||||
length = SHELLMATTA_MIN (length, (inst->inputCount - inst->cursor));
|
||||
if (length > 0u)
|
||||
{
|
||||
terminalCmd[0] = '\e';
|
||||
terminalCmd[0] = '\x1b';
|
||||
terminalCmd[1] = '[';
|
||||
size = 2u + utils_shellItoa(length, &terminalCmd[2], 10);
|
||||
terminalCmd[size] = 'C';
|
||||
@@ -162,6 +162,7 @@ void utils_forwardCursor(shellmatta_instance_t *inst, uint32_t length)
|
||||
* @param[in] inst pointer to shellmatta instance
|
||||
* @param[in] data pointer to the data to be inserted
|
||||
* @param[in] length length of the data to be inserted
|
||||
* @todo this function shall check buffer overflows
|
||||
*/
|
||||
void utils_insertChars( shellmatta_instance_t *inst,
|
||||
char *data,
|
||||
@@ -192,16 +193,20 @@ void utils_insertChars( shellmatta_instance_t *inst,
|
||||
&(inst->buffer[inst->cursor + length]),
|
||||
inst->inputCount - inst->cursor);
|
||||
utils_restoreCursorPos(inst);
|
||||
inst->cursor += length;
|
||||
inst->inputCount += length;
|
||||
}
|
||||
/** -# just overwrite/append the chars */
|
||||
/** -# overwrite - if the cursor reaches the end of the input it is pushed further */
|
||||
else
|
||||
{
|
||||
memcpy(&(inst->buffer[inst->cursor]), data, length);
|
||||
utils_writeEcho(inst, data, length);
|
||||
}
|
||||
|
||||
inst->inputCount += length;
|
||||
inst->cursor += length;
|
||||
if(inst->cursor > inst->inputCount)
|
||||
{
|
||||
inst->inputCount = inst->cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,8 +295,14 @@ static shellmatta_retCode_t helpCmdFct(shellmatta_handle_t handle, const char *a
|
||||
while(NULL != cmd)
|
||||
{
|
||||
maxCmdLen = SHELLMATTA_MAX(maxCmdLen, strlen(cmd->cmd));
|
||||
if(NULL != cmd->cmdAlias)
|
||||
{
|
||||
maxCmdAliasLen = SHELLMATTA_MAX(maxCmdAliasLen, strlen(cmd->cmdAlias));
|
||||
}
|
||||
if(NULL != cmd->helpText)
|
||||
{
|
||||
maxCmdHelpLen = SHELLMATTA_MAX(maxCmdHelpLen, strlen(cmd->helpText));
|
||||
}
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
@@ -301,22 +312,31 @@ static shellmatta_retCode_t helpCmdFct(shellmatta_handle_t handle, const char *a
|
||||
{
|
||||
/** -# determine the length of each field to add padding */
|
||||
cmdLen = strlen(cmd->cmd);
|
||||
cmdAliasLen = strlen(cmd->cmdAlias);
|
||||
cmdHelpLen = strlen(cmd->helpText);
|
||||
cmdAliasLen = (NULL != cmd->cmdAlias) ? strlen(cmd->cmdAlias) : 0u;
|
||||
cmdHelpLen = (NULL != cmd->helpText) ? strlen(cmd->helpText) : 0u;
|
||||
|
||||
inst->write(cmd->cmd, strlen(cmd->cmd));
|
||||
tabCnt = (maxCmdLen - cmdLen) + 2u;
|
||||
SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
|
||||
|
||||
inst->write(cmd->cmdAlias, strlen(cmd->cmdAlias));
|
||||
if(NULL != cmd->cmdAlias)
|
||||
{
|
||||
inst->write(cmd->cmdAlias, cmdAliasLen);
|
||||
}
|
||||
tabCnt = (maxCmdAliasLen - cmdAliasLen) + 2u;
|
||||
SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
|
||||
|
||||
inst->write(cmd->helpText, strlen(cmd->helpText));
|
||||
if(NULL != cmd->helpText)
|
||||
{
|
||||
inst->write(cmd->helpText, cmdHelpLen);
|
||||
}
|
||||
tabCnt = (maxCmdHelpLen - cmdHelpLen) + 2u;
|
||||
SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
|
||||
|
||||
if(NULL != cmd->usageText)
|
||||
{
|
||||
inst->write(cmd->usageText, strlen(cmd->usageText));
|
||||
}
|
||||
inst->write("\r\n", 2u);
|
||||
|
||||
cmd = cmd->next;
|
||||
@@ -327,7 +347,12 @@ static shellmatta_retCode_t helpCmdFct(shellmatta_handle_t handle, const char *a
|
||||
|
||||
return ret;
|
||||
}
|
||||
shellmatta_cmd_t helpCmd = {"help", "h", "Print this help text", "help", helpCmdFct, NULL};
|
||||
const shellmatta_cmd_t helpCmd = {SHELLMATTA_HELP_COMMAND
|
||||
, SHELLMATTA_HELP_ALIAS
|
||||
, SHELLMATTA_HELP_HELP_TEXT
|
||||
, SHELLMATTA_HELP_USAGE_TEXT
|
||||
, helpCmdFct
|
||||
, NULL};
|
||||
|
||||
/**
|
||||
* @brief terminates an input and prints the prompt again
|
||||
@@ -336,7 +361,13 @@ shellmatta_cmd_t helpCmd = {"help", "h", "Print this help text", "help", helpCmd
|
||||
void utils_terminateInput(shellmatta_instance_t *inst)
|
||||
{
|
||||
inst->inputCount = 0u;
|
||||
inst->lastNewlineIdx = 0u;
|
||||
inst->hereLength = 0u;
|
||||
inst->cursor = 0u;
|
||||
inst->stdinIdx = 0u;
|
||||
inst->stdinLength = 0u;
|
||||
inst->continuousCmd = NULL;
|
||||
inst->busyCmd = NULL;
|
||||
inst->write("\r\n", 2u);
|
||||
inst->write(inst->prompt, strlen(inst->prompt));
|
||||
}
|
||||
|
||||
@@ -22,9 +22,26 @@
|
||||
#include "shellmatta.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief returns the minimum of a and b
|
||||
* @param[in] a parameter a
|
||||
* @param[in] b parameter b
|
||||
*/
|
||||
#define SHELLMATTA_MIN(a,b) (((a) > (b)) ? (b) : (a))
|
||||
|
||||
/**
|
||||
* @brief returns the maximum of a and b
|
||||
* @param[in] a parameter a
|
||||
* @param[in] b parameter b
|
||||
*/
|
||||
#define SHELLMATTA_MAX(a,b) (((a) < (b)) ? (b) : (a))
|
||||
|
||||
/**
|
||||
* @brief calls fct with cnt bytes from buffer (to print cnt same bytes)
|
||||
* @param[in] buffer buffer to send (shall contain the same char)
|
||||
* @param[in] cnt count of bytes to send
|
||||
* @param[in] fct write function
|
||||
*/
|
||||
#define SHELLMATTA_PRINT_BUFFER(buffer,cnt,fct) \
|
||||
while((cnt) > sizeof((buffer))) \
|
||||
{ \
|
||||
@@ -36,14 +53,44 @@
|
||||
(fct)((buffer), (cnt)); \
|
||||
}
|
||||
|
||||
extern shellmatta_cmd_t helpCmd;
|
||||
/** @brief help command which prints all shellmatta commands as table */
|
||||
extern const shellmatta_cmd_t helpCmd;
|
||||
|
||||
/** @brief magic used to check if a shellmatta instance is initiated */
|
||||
#define SHELLMATTA_MAGIC 0x5101E110u
|
||||
|
||||
/** @brief overwritable output buffer size */
|
||||
#ifndef SHELLMATTA_OUTPUT_BUFFER_SIZE
|
||||
#define SHELLMATTA_OUTPUT_BUFFER_SIZE 128u
|
||||
#endif
|
||||
|
||||
/** @defgroup Shellmatta Help command overwrites
|
||||
* @{
|
||||
* overwritable help command parameters - the help command is built in and cannot be removed, but you can change
|
||||
* the command, alias and help texts by defining them in your build process
|
||||
* To change the settings set one of these defines:
|
||||
* #SHELLMATTA_HELP_COMMAND to overwrite the help command
|
||||
* #SHELLMATTA_HELP_ALIAS to overwrite the help alias
|
||||
* #SHELLMATTA_HELP_HELP_TEXT to overwrite the help text
|
||||
* #SHELLMATTA_HELP_USAGE_TEXT to overwrite the usage text
|
||||
* e.g. use _-DSHELLMATTA_HELP_ALIAS=\"?\"_ as compile option to change the alias to ?
|
||||
*/
|
||||
#ifndef SHELLMATTA_HELP_COMMAND
|
||||
#define SHELLMATTA_HELP_COMMAND (char*)"help" /**< help command */
|
||||
#endif
|
||||
#ifndef SHELLMATTA_HELP_ALIAS
|
||||
#define SHELLMATTA_HELP_ALIAS (char*)"h" /**< help command alias */
|
||||
#endif
|
||||
#ifndef SHELLMATTA_HELP_HELP_TEXT
|
||||
#define SHELLMATTA_HELP_HELP_TEXT (char*)"Print this help text" /**< help command help text */
|
||||
#endif
|
||||
#ifndef SHELLMATTA_HELP_USAGE_TEXT
|
||||
#define SHELLMATTA_HELP_USAGE_TEXT (char*)"help" /**< help command usage text */
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
void utils_writeEcho( shellmatta_instance_t *inst,
|
||||
const char *data,
|
||||
uint32_t length);
|
||||
|
||||
16865
test/framework/catch.hpp
Normal file
16865
test/framework/catch.hpp
Normal file
File diff suppressed because it is too large
Load Diff
565
test/integrationtest/test_integration.cpp
Normal file
565
test/integrationtest/test_integration.cpp
Normal file
@@ -0,0 +1,565 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
extern "C" {
|
||||
#include "shellmatta.h"
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
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)
|
||||
{
|
||||
write_callCnt ++;
|
||||
while((length > 0) && (write_length < sizeof(write_data)))
|
||||
{
|
||||
write_data[write_length] = *data;
|
||||
data ++;
|
||||
length --;
|
||||
write_length ++;
|
||||
}
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
doSomethingArguments = arguments;
|
||||
doSomethingLength = length;
|
||||
|
||||
shellmatta_read(handle, &doSomethingStdin, &doSomethingStdinLength);
|
||||
|
||||
shellmatta_printf(handle, "%s - length: %u", arguments, length);
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t doSomethingCmd = {(char*)"doSomething", (char*)"do", (char*)"Function does something", (char*)"use me, please", doSomething, NULL};
|
||||
|
||||
static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
shellmatta_printf(handle, "empty - %s - length: %u", arguments, length);
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t emptyCmd = {(char*)"empty", NULL, NULL, NULL, empty, NULL};
|
||||
|
||||
TEST_CASE( "shellmatta empty function" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"\r", 1);
|
||||
|
||||
CHECK( write_length == 14u);
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta help function" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"empty \r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &emptyCmd);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
dummyData = (char*)"? 564 321 56 465 46\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"empty \r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
dummyData = (char*)"?r\r\n"
|
||||
"Command: ?r not found"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_processData(handle, (char*)"?r\r", 3);
|
||||
|
||||
CHECK( write_length == 39u);
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta heredoc test" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"do this ";
|
||||
char *dummyStdin = (char*)"asdf\r\n"
|
||||
"1234";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
doSomethingArguments = NULL;
|
||||
doSomethingLength = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"do this << EOF\r\n"
|
||||
"asdf\r\n"
|
||||
"1234\r\n"
|
||||
"EOF\r\n"
|
||||
, 33);
|
||||
|
||||
CHECK( doSomethingStdinLength == 10u);
|
||||
CHECK( strcmp(dummyStdin, doSomethingStdin) == 0);
|
||||
CHECK( doSomethingLength == 8u);
|
||||
REQUIRE( strcmp(dummyData, doSomethingArguments) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta heredoc test empty" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"do this ";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
doSomethingArguments = NULL;
|
||||
doSomethingLength = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"do this << EOF\r\n"
|
||||
"EOF\r\n"
|
||||
, 21);
|
||||
|
||||
CHECK( doSomethingStdinLength == 0u);
|
||||
CHECK( NULL == doSomethingStdin );
|
||||
CHECK( doSomethingLength == 8u);
|
||||
REQUIRE( strcmp(dummyData, doSomethingArguments) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta remove function" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == 123u);
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
dummyData = (char*)"? 564 321 56 465 46\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
|
||||
|
||||
CHECK( write_length == 141u);
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_removeCmd(handle, &doSomethingCmd);
|
||||
shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
|
||||
|
||||
dummyData = (char*)"? 564 321 56 465 46\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
CHECK( write_length == 72u);
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta reset no prompt" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd", 35);
|
||||
shellmatta_resetShell(handle, false);
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta reset with prompt" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd"
|
||||
"\r\nshellmatta->?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd", 35);
|
||||
shellmatta_resetShell(handle, true);
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta reset no prompt history buffer" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_resetShell(handle, false);
|
||||
|
||||
/* process arrow key up - if reset worked this should deliver nothing */
|
||||
shellmatta_processData(handle, (char*)"\033[A", 3u);
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta reset no prompt heredoc" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"?\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"dummy cmd << EOF\r\n", 18u);
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
|
||||
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* end the heredoc session by resetting the shell */
|
||||
shellmatta_resetShell(handle, false);
|
||||
|
||||
/* now the new command should be processed */
|
||||
shellmatta_processData(handle, (char*)"?\r", 2);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta configure disable echo" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
shellmatta_retCode_t ret;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"help this is some dummy Text\r\n"
|
||||
"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
char *dummyData2 = (char*)"doSomething do Function does something use me, please\r\n"
|
||||
"help ? Print this help text help\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* check with echo enabled */
|
||||
shellmatta_processData(handle, (char*)"help this is some dummy Text\r\n", 30u);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* turn off echo now */
|
||||
ret = shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
|
||||
CHECK( ret == SHELLMATTA_OK );
|
||||
|
||||
/* check with echo disabled */
|
||||
shellmatta_processData(handle, (char*)"help this is some dummy Text\r\n", 30u);
|
||||
|
||||
CHECK( write_length == strlen(dummyData2));
|
||||
REQUIRE( strcmp(dummyData2, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta configure mode" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
shellmatta_retCode_t ret;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"\r\nCommand: meow this is some dum123456my Text not found\r\nshellmatta->";
|
||||
|
||||
char *dummyData2 = (char*)"\r\nCommand: meow this is some dum123456t not found\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
ret = shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* check with insert mode */
|
||||
shellmatta_processData(handle, (char*)"meow this is some dummy Text\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D123456\r\n", 57u);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
CHECK( strcmp(dummyData, write_data) == 0);
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* check with overwrite mode */
|
||||
ret = shellmatta_configure(handle, SHELLMATTA_MODE_OVERWRITE, false, '\r');
|
||||
CHECK( ret == SHELLMATTA_OK );
|
||||
|
||||
/* check with echo disabled */
|
||||
shellmatta_processData(handle, (char*)"meow this is some dummy Text\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D123456\r\n", 57u);
|
||||
|
||||
CHECK( write_length == strlen(dummyData2));
|
||||
REQUIRE( strcmp(dummyData2, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta configure delimiter" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
shellmatta_retCode_t ret;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"doSomething argument - length: 20\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
shellmatta_addCmd(handle, &doSomethingCmd);
|
||||
ret = shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* check with insert mode */
|
||||
shellmatta_processData(handle, (char*)"doSomething argument\n", 21u);
|
||||
|
||||
CHECK( write_length == 0u);
|
||||
|
||||
shellmatta_resetShell(handle, false);
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
/* check with changed delimiter mode */
|
||||
ret = shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\n');
|
||||
CHECK( ret == SHELLMATTA_OK );
|
||||
|
||||
/* check with echo disabled */
|
||||
shellmatta_processData(handle, (char*)"doSomething argument\n", 21u);
|
||||
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
183
test/integrationtest/test_integration_busy.cpp
Normal file
183
test/integrationtest/test_integration_busy.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_integration_busy.cpp
|
||||
* @brief integration test implementation for the cmd busy function
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
extern "C" {
|
||||
#include "shellmatta.h"
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[1024];
|
||||
static uint32_t write_length;
|
||||
static uint32_t busyCallCnt;
|
||||
static uint32_t notBusyCallCnt;
|
||||
static bool suspendBusy;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
while((length > 0) && (write_length < sizeof(write_data)))
|
||||
{
|
||||
write_data[write_length] = *data;
|
||||
data ++;
|
||||
length --;
|
||||
write_length ++;
|
||||
}
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
static shellmatta_retCode_t busyCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void) handle;
|
||||
(void) arguments;
|
||||
(void) length;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_BUSY;
|
||||
static const char *callArgs = NULL;
|
||||
static uint32_t callLength = 0u;;
|
||||
|
||||
if(busyCallCnt < 10u)
|
||||
{
|
||||
if(NULL == callArgs)
|
||||
{
|
||||
callArgs = arguments;
|
||||
callLength = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(callArgs == arguments);
|
||||
CHECK(callLength == length);
|
||||
}
|
||||
|
||||
busyCallCnt ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
if(true == suspendBusy)
|
||||
{
|
||||
ret = SHELLMATTA_CONTINUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
shellmatta_cmd_t busyCmd = {(char*)"busy", (char*)"b", NULL, NULL, busyCmdFct, NULL};
|
||||
|
||||
|
||||
static shellmatta_retCode_t notBusyCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void) handle;
|
||||
(void) arguments;
|
||||
(void) length;
|
||||
|
||||
notBusyCallCnt ++;
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
shellmatta_cmd_t notBusyCmd = {(char*)"notBusy", (char*)"n", NULL, NULL, notBusyCmdFct, NULL};
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta busy 1" ) {
|
||||
|
||||
shellmatta_retCode_t ret;
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*) "busy and some arguments\r\n"
|
||||
"\r\nshellmatta->notBusy and some arguments\r\n"
|
||||
"\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
busyCallCnt = 0u;
|
||||
notBusyCallCnt = 0u;
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
suspendBusy = false;
|
||||
|
||||
shellmatta_addCmd(handle, &busyCmd);
|
||||
shellmatta_addCmd(handle, ¬BusyCmd);
|
||||
|
||||
do
|
||||
{
|
||||
ret = shellmatta_processData(handle, (char*)"busy and some arguments\r"
|
||||
"notBusy and some arguments\r", 51);
|
||||
|
||||
} while (SHELLMATTA_BUSY == ret);
|
||||
|
||||
|
||||
CHECK( 10u == busyCallCnt);
|
||||
CHECK( 1u == notBusyCallCnt );
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta busy suspend with continuous mode" ) {
|
||||
|
||||
shellmatta_retCode_t ret;
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*) "busy and some arguments\r\n";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
busyCallCnt = 0u;
|
||||
notBusyCallCnt = 0u;
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
suspendBusy = false;
|
||||
|
||||
shellmatta_addCmd(handle, &busyCmd);
|
||||
shellmatta_addCmd(handle, ¬BusyCmd);
|
||||
|
||||
do
|
||||
{
|
||||
ret = shellmatta_processData(handle, (char*)"busy and some arguments\r123", 27u);
|
||||
|
||||
suspendBusy = true;
|
||||
|
||||
} while (SHELLMATTA_BUSY == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"", 0u);
|
||||
|
||||
CHECK( SHELLMATTA_CONTINUE == ret);
|
||||
CHECK( 6u == busyCallCnt);
|
||||
CHECK( 0u == notBusyCallCnt );
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
284
test/integrationtest/test_integration_continue.cpp
Normal file
284
test/integrationtest/test_integration_continue.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_integration_busy.cpp
|
||||
* @brief integration test implementation for the cmd busy function
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
extern "C" {
|
||||
#include "shellmatta.h"
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[1024];
|
||||
static uint32_t write_length;
|
||||
static uint32_t contCallCnt;
|
||||
static uint32_t busyCallCnt;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
while((length > 0) && (write_length < sizeof(write_data)))
|
||||
{
|
||||
write_data[write_length] = *data;
|
||||
data ++;
|
||||
length --;
|
||||
write_length ++;
|
||||
}
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
static shellmatta_retCode_t continueCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void) handle;
|
||||
(void) arguments;
|
||||
(void) length;
|
||||
shellmatta_retCode_t ret = SHELLMATTA_CONTINUE;
|
||||
char *stdinData;
|
||||
uint32_t stdinLength = 0u;
|
||||
|
||||
shellmatta_read(handle, &stdinData, &stdinLength);
|
||||
if(NULL == stdinData)
|
||||
{
|
||||
stdinData = (char *)"";
|
||||
}
|
||||
|
||||
shellmatta_printf(handle, "arguments: %s length: %u\r\n", stdinData, stdinLength);
|
||||
|
||||
/** change to busy mode when k is pressed */
|
||||
if('k' == stdinData[0])
|
||||
{
|
||||
ret = SHELLMATTA_BUSY;
|
||||
busyCallCnt ++;
|
||||
}
|
||||
|
||||
if(busyCallCnt > 1u)
|
||||
{
|
||||
ret = SHELLMATTA_CONTINUE;
|
||||
}
|
||||
|
||||
if(contCallCnt >= 9u)
|
||||
{
|
||||
ret = SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
/* -# the arguments shall stay the same on every call - data is transferred per stdin */
|
||||
CHECK(length == 28u);
|
||||
CHECK(strcmp(arguments, "continue some arguments meow") == 0);
|
||||
|
||||
contCallCnt ++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
shellmatta_cmd_t continueCmd = {(char*)"continue", (char*)"c", NULL, NULL, continueCmdFct, NULL};
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta continue 1" ) {
|
||||
|
||||
shellmatta_retCode_t ret;
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*) "continue some arguments meow\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: a length: 1\r\n"
|
||||
"arguments: b length: 1\r\n"
|
||||
"arguments: c length: 1\r\n"
|
||||
"arguments: 8 length: 1\r\n"
|
||||
"arguments: 7 length: 1\r\n"
|
||||
"arguments: 6 length: 1\r\n"
|
||||
"arguments: 5 length: 1\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"\r\n"
|
||||
"shellmatta->\r\n"
|
||||
"shellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
contCallCnt = 0u;
|
||||
busyCallCnt = 0u;
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &continueCmd);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# call without any argument */
|
||||
ret = shellmatta_processData(handle, NULL, 0);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# pass some argument */
|
||||
ret = shellmatta_processData(handle, (char*)"abc", 3);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"8765", 4);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# call without any argument */
|
||||
ret = shellmatta_processData(handle, NULL, 0);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
/** -# continue session should be over */
|
||||
ret = shellmatta_processData(handle, (char*)"\r", 1);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
CHECK( 0u == busyCallCnt);
|
||||
CHECK( 10u == contCallCnt);
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta continue cancel" ) {
|
||||
|
||||
shellmatta_retCode_t ret;
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*) "continue some arguments meow\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: a length: 1\r\n"
|
||||
"arguments: b length: 1\r\n"
|
||||
"arguments: \x03 length: 1\r\n"
|
||||
"\r\n"
|
||||
"shellmatta->\r\n"
|
||||
"shellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
contCallCnt = 0u;
|
||||
busyCallCnt = 0u;
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &continueCmd);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# call without any argument */
|
||||
ret = shellmatta_processData(handle, NULL, 0);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# pass some argument */
|
||||
ret = shellmatta_processData(handle, (char*)"ab", 2);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"\x03", 1);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
/** -# continue session should be over */
|
||||
ret = shellmatta_processData(handle, (char*)"\r", 1);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
CHECK( 0u == busyCallCnt);
|
||||
CHECK( 5u == contCallCnt);
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta continue suspend with busy mode" ) {
|
||||
|
||||
shellmatta_retCode_t ret;
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*) "continue some arguments meow\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: a length: 1\r\n"
|
||||
"arguments: b length: 1\r\n"
|
||||
"arguments: k length: 1\r\n"
|
||||
"arguments: k length: 1\r\n"
|
||||
"arguments: length: 0\r\n"
|
||||
"arguments: a length: 1\r\n"
|
||||
"arguments: b length: 1\r\n"
|
||||
"arguments: c length: 1\r\n"
|
||||
"\r\n"
|
||||
"shellmatta->\r\n"
|
||||
"shellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
contCallCnt = 0u;
|
||||
busyCallCnt = 0u;
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &continueCmd);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# call without any argument */
|
||||
ret = shellmatta_processData(handle, NULL, 0);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
/** -# pass some argument */
|
||||
ret = shellmatta_processData(handle, (char*)"ab", 2);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"k", 1);
|
||||
CHECK(SHELLMATTA_BUSY == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"k", 1);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"", 0);
|
||||
CHECK(SHELLMATTA_CONTINUE == ret);
|
||||
|
||||
ret = shellmatta_processData(handle, (char*)"abc", 3);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
/** -# continue session should be over */
|
||||
ret = shellmatta_processData(handle, (char*)"\r", 1);
|
||||
CHECK(SHELLMATTA_OK == ret);
|
||||
|
||||
CHECK( 10u == contCallCnt);
|
||||
CHECK( 2u == busyCallCnt);
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
218
test/integrationtest/test_integration_opt.cpp
Normal file
218
test/integrationtest/test_integration_opt.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_integration_opt.cpp
|
||||
* @brief integration test implementation for the option parser of the shellmatta
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
extern "C" {
|
||||
#include "shellmatta.h"
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
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)
|
||||
{
|
||||
write_callCnt ++;
|
||||
while((length > 0) && (write_length < sizeof(write_data)))
|
||||
{
|
||||
write_data[write_length] = *data;
|
||||
data ++;
|
||||
length --;
|
||||
write_length ++;
|
||||
}
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
static shellmatta_retCode_t parseOpts(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void) arguments;
|
||||
(void) length;
|
||||
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};
|
||||
|
||||
TEST_CASE( "shellmatta option parser 1" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"parseOpts -a -e meow\r\nparseOpts - cnt: 2\r\n\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
initTestcase();
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &parseOptsCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"parseOpts -a -e meow\r", 21);
|
||||
|
||||
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 == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta option parser 2 - ignore \"--\"" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"parseOpts -a -e meow --\r\nparseOpts - cnt: 2\r\n\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
initTestcase();
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &parseOptsCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"parseOpts -a -e meow --\r", 24);
|
||||
|
||||
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 == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
229
test/integrationtest/test_integration_optLong.cpp
Normal file
229
test/integrationtest/test_integration_optLong.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_integration_optLong.cpp
|
||||
* @brief integration test implementation for the long option parser of the shellmatta
|
||||
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
||||
*/
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
extern "C" {
|
||||
#include "shellmatta.h"
|
||||
}
|
||||
#include <string.h>
|
||||
|
||||
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)
|
||||
{
|
||||
write_callCnt ++;
|
||||
while((length > 0) && (write_length < sizeof(write_data)))
|
||||
{
|
||||
write_data[write_length] = *data;
|
||||
data ++;
|
||||
length --;
|
||||
write_length ++;
|
||||
}
|
||||
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
static shellmatta_retCode_t parseOptsLong(shellmatta_handle_t handle, const char *arguments, uint32_t length)
|
||||
{
|
||||
(void) arguments;
|
||||
(void) length;
|
||||
char option;
|
||||
char *argumentString;
|
||||
uint32_t argumentLength;
|
||||
uint32_t optionCount = 0u;
|
||||
|
||||
shellmatta_opt_long_t longOptions[] = {
|
||||
{"auto", 'a', SHELLMATTA_OPT_ARG_NONE},
|
||||
{"build", 'b', SHELLMATTA_OPT_ARG_NONE},
|
||||
{"cat", 'c', SHELLMATTA_OPT_ARG_NONE},
|
||||
{"doom", 'd', SHELLMATTA_OPT_ARG_NONE},
|
||||
{"erase", 'e', SHELLMATTA_OPT_ARG_REQUIRED},
|
||||
{"fuck", 'f', SHELLMATTA_OPT_ARG_OPTIONAL},
|
||||
{NULL, '\0', SHELLMATTA_OPT_ARG_NONE}
|
||||
};
|
||||
|
||||
while(SHELLMATTA_OK == shellmatta_opt_long(handle, longOptions, &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 parseOptsLongCmd = {(char*)"parseOpts", (char*)"opt", NULL, NULL, parseOptsLong, NULL};
|
||||
|
||||
TEST_CASE( "shellmatta long option parser 1" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"parseOpts -a -e meow\r\nparseOpts - cnt: 2\r\n\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
initTestcase();
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &parseOptsLongCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"parseOpts -a -e meow\r", 21);
|
||||
|
||||
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 == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta long option parser 2" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
shellmatta_handle_t handle;
|
||||
char buffer[1024];
|
||||
char historyBuffer[1024];
|
||||
char *dummyData = (char*)"parseOpts --auto --erase meow -- --lalelu -u\r\nparseOpts - cnt: 4\r\n\r\nshellmatta->";
|
||||
|
||||
shellmatta_doInit( &inst,
|
||||
&handle,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
historyBuffer,
|
||||
sizeof(historyBuffer),
|
||||
"shellmatta->",
|
||||
NULL,
|
||||
writeFct);
|
||||
|
||||
initTestcase();
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
shellmatta_addCmd(handle, &parseOptsLongCmd);
|
||||
|
||||
shellmatta_processData(handle, (char*)"parseOpts --auto --erase meow -- --lalelu -u\r", 45);
|
||||
|
||||
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) );
|
||||
CHECK( cntDef == 2u );
|
||||
CHECK( lenDef == 2u );
|
||||
CHECK( write_length == strlen(dummyData));
|
||||
REQUIRE( strcmp(dummyData, write_data) == 0);
|
||||
}
|
||||
7
test/integrationtest/test_main.cpp
Normal file
7
test/integrationtest/test_main.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// 010-TestCase.cpp
|
||||
|
||||
// Let Catch provide main():
|
||||
#define CATCH_CONFIG_MAIN
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
|
||||
14
test/unittest/shellmatta/test_shellmatta_doInit.cpp
Normal file
14
test/unittest/shellmatta/test_shellmatta_doInit.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_CASE( "shellmatta dummy" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
//shellmatta_handle_t handle;
|
||||
inst.inputCount = 0u;
|
||||
|
||||
//shellmatta_doInit(&inst, &handle, )
|
||||
|
||||
REQUIRE( inst.inputCount == 0u);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_autocomplete.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_CASE( "shellmatta_autocomplete_run dummy" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
inst.inputCount = 0u;
|
||||
|
||||
autocomplete_run(&inst);
|
||||
|
||||
REQUIRE( inst.inputCount == 0u);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_escape.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_CASE( "shellmatta_escape dummy" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
inst.inputCount = 0u;
|
||||
|
||||
escape_processArrowKeys(&inst);
|
||||
|
||||
REQUIRE( inst.inputCount == 0u);
|
||||
}
|
||||
13
test/unittest/shellmatta_history/test_appendHistoryByte.cpp
Normal file
13
test/unittest/shellmatta_history/test_appendHistoryByte.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_history.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_CASE( "shellmatta_history dummy" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
inst.inputCount = 0u;
|
||||
|
||||
//appendHistoryByte(&inst, 'a');
|
||||
|
||||
REQUIRE( inst.inputCount == 0u);
|
||||
}
|
||||
162
test/unittest/shellmatta_opt/test_opt_findNextHunk.cpp
Normal file
162
test/unittest/shellmatta_opt/test_opt_findNextHunk.cpp
Normal file
@@ -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 );
|
||||
}
|
||||
28
test/unittest/shellmatta_utils/test_utils_clearInput.cpp
Normal file
28
test/unittest/shellmatta_utils/test_utils_clearInput.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
(void)data;
|
||||
(void)length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_clearInput normal call" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
utils_clearInput(&inst);
|
||||
|
||||
CHECK( inst.cursor == 0);
|
||||
REQUIRE( inst.inputCount == 0);
|
||||
}
|
||||
40
test/unittest/shellmatta_utils/test_utils_eraseLine.cpp
Normal file
40
test/unittest/shellmatta_utils/test_utils_eraseLine.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10];
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
memcpy(write_data, data, length);
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_eraseLine" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_eraseLine(&inst);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 3u);
|
||||
REQUIRE( strncmp("\x1b[K", write_data, 3u) == 0);
|
||||
}
|
||||
113
test/unittest/shellmatta_utils/test_utils_forwardCursor.cpp
Normal file
113
test/unittest/shellmatta_utils/test_utils_forwardCursor.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10];
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
strncpy(write_data, data, length);
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_forwardCursor normal" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 20;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_forwardCursor(&inst, 5u);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 4u);
|
||||
REQUIRE( strncmp("\x1b[5C", write_data, 4u) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils_forwardCursor normal echo off" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 20;
|
||||
inst.echoEnabled = false;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_forwardCursor(&inst, 5u);
|
||||
|
||||
CHECK( write_callCnt == 0u);
|
||||
CHECK( write_length == 0u);
|
||||
REQUIRE( strncmp("\0\0\0\0", write_data, 4u) == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_forwardCursor forward by 12 with cursor at 5 and input count at 10" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 5;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_forwardCursor(&inst, 12u);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 4u);
|
||||
REQUIRE( strncmp("\x1b[5C", write_data, 4u) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils_forwardCursor forward by 0" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_forwardCursor(&inst, 0u);
|
||||
|
||||
CHECK( write_callCnt == 0u);
|
||||
CHECK( write_length == 0u);
|
||||
REQUIRE( strncmp("\0\0\0\0\0", write_data, 4u) == 0);
|
||||
}
|
||||
125
test/unittest/shellmatta_utils/test_utils_insertChars.cpp
Normal file
125
test/unittest/shellmatta_utils/test_utils_insertChars.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[20];
|
||||
static uint32_t write_idx;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
strncpy(&write_data[write_idx], data, length);
|
||||
write_idx += length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_idx = 0u;
|
||||
|
||||
utils_insertChars(&inst, (char*)"blksdflsd kfjlk", 4u);
|
||||
|
||||
CHECK( inst.cursor == 12);
|
||||
CHECK( inst.inputCount == 14);
|
||||
CHECK( write_callCnt == 5u );
|
||||
CHECK( strncmp("blks\x1b[K\x1b[sij\x1b[u", write_data, 15u) == 0);
|
||||
REQUIRE( strncmp("abcdefghblksij\0\0\0\0\0\0\0", buffer, sizeof(buffer)) == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
inst.mode = SHELLMATTA_MODE_OVERWRITE;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_idx = 0u;
|
||||
|
||||
utils_insertChars(&inst, (char*)"blksdflsd kfjlk", 4u);
|
||||
|
||||
CHECK( inst.cursor == 12);
|
||||
CHECK( inst.inputCount == 12);
|
||||
CHECK( write_callCnt == 1u );
|
||||
CHECK( strncmp("blks", write_data, 5u) == 0);
|
||||
REQUIRE( strncmp("abcdefghblks\0\0\0\0\0\0\0\0\0", buffer, sizeof(buffer)) == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
inst.mode = SHELLMATTA_MODE_INSERT;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_idx = 0u;
|
||||
|
||||
utils_insertChars(&inst, (char*)"blksdflsd kfjlk", 4u);
|
||||
|
||||
CHECK( inst.cursor == 14);
|
||||
CHECK( inst.inputCount == 14);
|
||||
CHECK( write_callCnt == 1u );
|
||||
CHECK( strncmp("blks", write_data, 5u) == 0);
|
||||
REQUIRE( strncmp("abcdefghijblks\0\0\0\0\0\0\0", buffer, sizeof(buffer)) == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_idx = 0u;
|
||||
|
||||
utils_insertChars(&inst, (char*)"blksdflsd kfjlk", 0u);
|
||||
|
||||
CHECK( inst.cursor == 8u );
|
||||
CHECK( inst.inputCount == 10u );
|
||||
CHECK( write_callCnt == 0u );
|
||||
CHECK( memcmp("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", write_data, sizeof(write_data) ) == 0u );
|
||||
REQUIRE( memcmp("abcdefghij\0\0\0\0\0\0\0\0\0", buffer, sizeof(buffer)) == 0);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10];
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
memcpy(write_data, data, length);
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_restoreCursorPos" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_restoreCursorPos(&inst);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 3u);
|
||||
REQUIRE( strncmp("\x1b[u", write_data, 3u) == 0);
|
||||
}
|
||||
89
test/unittest/shellmatta_utils/test_utils_rewindCursor.cpp
Normal file
89
test/unittest/shellmatta_utils/test_utils_rewindCursor.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10];
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
strncpy(write_data, data, length);
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_rewindCursor normal" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_rewindCursor(&inst, 5u);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 4u);
|
||||
REQUIRE( strncmp("\x1b[5D", write_data, 4u) == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_rewindCursor rewind by 12 with cursor at 10" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_rewindCursor(&inst, 12u);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 5u);
|
||||
REQUIRE( strncmp("\x1b[10D", write_data, 5u) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils_rewindCursor rewind by 0" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_rewindCursor(&inst, 0u);
|
||||
|
||||
CHECK( write_callCnt == 0u);
|
||||
CHECK( write_length == 0u);
|
||||
REQUIRE( strncmp("\0\0\0\0\0", write_data, 4u) == 0);
|
||||
}
|
||||
40
test/unittest/shellmatta_utils/test_utils_saveCursorPos.cpp
Normal file
40
test/unittest/shellmatta_utils/test_utils_saveCursorPos.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10u];
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
memcpy(write_data, data, length);
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_saveCursorPos" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_length = 0u;
|
||||
|
||||
utils_saveCursorPos(&inst);
|
||||
|
||||
CHECK( write_callCnt == 1u);
|
||||
CHECK( write_length == 3u);
|
||||
REQUIRE( strncmp("\x1b[s", write_data, 3u) == 0);
|
||||
}
|
||||
52
test/unittest/shellmatta_utils/test_utils_shellItoa.cpp
Normal file
52
test/unittest/shellmatta_utils/test_utils_shellItoa.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 123456 base 10" ) {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(123456, buffer, 10) == 6 );
|
||||
REQUIRE( strcmp(buffer, "123456") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 0x0ABBCCDD base 16") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(0x0ABBCCDD, buffer, 16) == 7 );
|
||||
REQUIRE( strcmp(buffer, "ABBCCDD") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - -574236 base 10") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(-574236, buffer, 10) == 7 );
|
||||
REQUIRE( strcmp(buffer, "-574236") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 0x80000000 base 2") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(0x80000000, buffer, 2) == 33 );
|
||||
REQUIRE( strcmp(buffer, "-10000000000000000000000000000000") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 2") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 2) == 31 );
|
||||
REQUIRE( strcmp(buffer, "1111111111111111111111111111111") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 1 - wrong base") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 1) == 0 );
|
||||
REQUIRE( strcmp(buffer, "\0") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 17 - wrong base") {
|
||||
char buffer[64];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 17) == 0 );
|
||||
REQUIRE( strcmp(buffer, "\0") == 0);
|
||||
}
|
||||
43
test/unittest/shellmatta_utils/test_utils_terminateInput.cpp
Normal file
43
test/unittest/shellmatta_utils/test_utils_terminateInput.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static char write_data[10];
|
||||
static uint32_t write_idx;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
memcpy(&write_data[write_idx], data, length);
|
||||
write_idx += length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "shellmatta_utils_terminateInput" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
inst.prompt = "->";
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
memset(write_data, 0, sizeof(write_data));
|
||||
write_idx = 0u;
|
||||
|
||||
utils_terminateInput(&inst);
|
||||
|
||||
CHECK( inst.cursor == 0u );
|
||||
CHECK( inst.inputCount == 0u );
|
||||
CHECK( write_callCnt == 2u );
|
||||
CHECK( write_idx == 4u );
|
||||
REQUIRE( strncmp("\r\n->", write_data, 4u) == 0);
|
||||
}
|
||||
65
test/unittest/shellmatta_utils/test_utils_writeEcho.cpp
Normal file
65
test/unittest/shellmatta_utils/test_utils_writeEcho.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "test/framework/catch.hpp"
|
||||
#include "src/shellmatta_utils.c"
|
||||
#include <string.h>
|
||||
|
||||
static uint32_t write_callCnt = 0u;
|
||||
static const char *write_data;
|
||||
static uint32_t write_length;
|
||||
|
||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
|
||||
{
|
||||
write_callCnt ++;
|
||||
write_data = data;
|
||||
write_length = length;
|
||||
return SHELLMATTA_OK;
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_writeEcho echo enabled" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
char dummyData[29];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = true;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
write_data = 0u;
|
||||
write_length = 0u;
|
||||
|
||||
utils_writeEcho(&inst, (char*)&dummyData, sizeof(dummyData));
|
||||
|
||||
CHECK( write_callCnt == 1u );
|
||||
CHECK( write_data == (char*)&dummyData );
|
||||
REQUIRE( write_length == sizeof(dummyData));
|
||||
}
|
||||
|
||||
TEST_CASE( "shellmatta_writeEcho echo disabled" ) {
|
||||
|
||||
shellmatta_instance_t inst;
|
||||
char buffer[20];
|
||||
char dummyData[29];
|
||||
|
||||
inst.buffer = buffer;
|
||||
inst.bufferSize = 20;
|
||||
inst.cursor = 10;
|
||||
inst.inputCount = 10;
|
||||
inst.echoEnabled = false;
|
||||
|
||||
inst.write = writeFct;
|
||||
|
||||
write_callCnt = 0u;
|
||||
write_data = 0u;
|
||||
write_length = 0u;
|
||||
|
||||
utils_writeEcho(&inst, (char*)&dummyData, sizeof(dummyData));
|
||||
|
||||
CHECK( write_callCnt == 0u );
|
||||
CHECK( write_data == (char*)0u );
|
||||
REQUIRE( write_length == 0u );
|
||||
}
|
||||
7
test/unittest/test_main.cpp
Normal file
7
test/unittest/test_main.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// 010-TestCase.cpp
|
||||
|
||||
// Let Catch provide main():
|
||||
#define CATCH_CONFIG_MAIN
|
||||
|
||||
#include "test/framework/catch.hpp"
|
||||
|
||||
Reference in New Issue
Block a user