Compare commits
	
		
			19 Commits
		
	
	
		
			48fcf05b7d
			...
			continue
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b17dd06733 | |||
| 
						 | 
					ebf65d7448 | ||
| 
						 | 
					0fa2e5d1f8 | ||
| 
						 | 
					3f54a989f3 | ||
| 
						 | 
					6c76dfc7ae | ||
| 
						 | 
					785d73306d | ||
| 
						 | 
					96cf0c8d65 | ||
| 
						 | 
					d7962a54dc | ||
| 
						 | 
					3b99ad2a56 | ||
| 
						 | 
					c2e4324236 | ||
| 
						 | 
					5e84f1b022 | ||
| 
						 | 
					17bb88d292 | ||
| 
						 | 
					5a00f22e31 | ||
| 
						 | 
					2d130e2ee1 | ||
| 
						 | 
					ecc43307af | ||
| 
						 | 
					60c4c7dadd | ||
| 
						 | 
					2921f9791b | ||
| 
						 | 
					e970b6c941 | ||
| 
						 | 
					bf1d91eca7 | 
							
								
								
									
										21
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							@@ -4,6 +4,27 @@
 | 
			
		||||
    // 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",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
    // See https://go.microsoft.com/fwlink/?LinkId=733558
 | 
			
		||||
    // for the documentation about the tasks.json format
 | 
			
		||||
    "version": "2.0.0",
 | 
			
		||||
    "tasks": [
 | 
			
		||||
        {
 | 
			
		||||
@@ -51,6 +49,20 @@
 | 
			
		||||
                "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,36 @@ 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    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,8 +122,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     */
 | 
			
		||||
@@ -108,11 +142,16 @@ typedef struct
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -126,23 +165,48 @@ shellmatta_retCode_t shellmatta_doInit( shellmatta_instance_t   *inst,
 | 
			
		||||
                                        const shellmatta_cmd_t  *cmdList,
 | 
			
		||||
                                        shellmatta_write_t      writeFct);
 | 
			
		||||
 | 
			
		||||
shellmatta_retCode_t shellmatta_addCmd( shellmatta_handle_t     handle,
 | 
			
		||||
                                        shellmatta_cmd_t        *cmd);
 | 
			
		||||
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_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,
 | 
			
		||||
                                        ...);
 | 
			
		||||
shellmatta_retCode_t shellmatta_printf(     shellmatta_handle_t handle,
 | 
			
		||||
                                            const char          *fmt,
 | 
			
		||||
                                            ...);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
# Doxyfile 1.8.15
 | 
			
		||||
# Doxyfile 1.8.17
 | 
			
		||||
 | 
			
		||||
# This file describes the settings to be used by the documentation system
 | 
			
		||||
# doxygen (www.doxygen.org) for a project.
 | 
			
		||||
@@ -197,6 +197,16 @@ SHORT_NAMES            = NO
 | 
			
		||||
 | 
			
		||||
JAVADOC_AUTOBRIEF      = NO
 | 
			
		||||
 | 
			
		||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
 | 
			
		||||
# such as
 | 
			
		||||
# /***************
 | 
			
		||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
 | 
			
		||||
# Javadoc-style will behave just like regular comments and it will not be
 | 
			
		||||
# interpreted by doxygen.
 | 
			
		||||
# The default value is: NO.
 | 
			
		||||
 | 
			
		||||
JAVADOC_BANNER         = NO
 | 
			
		||||
 | 
			
		||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
 | 
			
		||||
# line (until the first dot) of a Qt-style comment as the brief description. If
 | 
			
		||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
 | 
			
		||||
@@ -299,7 +309,7 @@ OPTIMIZE_OUTPUT_SLICE  = NO
 | 
			
		||||
# parses. With this tag you can assign which parser to use for a given
 | 
			
		||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
 | 
			
		||||
# using this tag. The format is ext=language, where ext is a file extension, and
 | 
			
		||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
 | 
			
		||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
 | 
			
		||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
 | 
			
		||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
 | 
			
		||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
 | 
			
		||||
@@ -329,7 +339,7 @@ MARKDOWN_SUPPORT       = YES
 | 
			
		||||
# to that level are automatically included in the table of contents, even if
 | 
			
		||||
# they do not have an id attribute.
 | 
			
		||||
# Note: This feature currently applies only to Markdown headings.
 | 
			
		||||
# Minimum value: 0, maximum value: 99, default value: 0.
 | 
			
		||||
# Minimum value: 0, maximum value: 99, default value: 5.
 | 
			
		||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
 | 
			
		||||
 | 
			
		||||
TOC_INCLUDE_HEADINGS   = 0
 | 
			
		||||
@@ -465,6 +475,12 @@ EXTRACT_ALL            = NO
 | 
			
		||||
 | 
			
		||||
EXTRACT_PRIVATE        = NO
 | 
			
		||||
 | 
			
		||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
 | 
			
		||||
# methods of a class will be included in the documentation.
 | 
			
		||||
# The default value is: NO.
 | 
			
		||||
 | 
			
		||||
EXTRACT_PRIV_VIRTUAL   = NO
 | 
			
		||||
 | 
			
		||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
 | 
			
		||||
# scope will be included in the documentation.
 | 
			
		||||
# The default value is: NO.
 | 
			
		||||
@@ -519,8 +535,8 @@ HIDE_UNDOC_MEMBERS     = NO
 | 
			
		||||
HIDE_UNDOC_CLASSES     = NO
 | 
			
		||||
 | 
			
		||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
 | 
			
		||||
# (class|struct|union) declarations. If set to NO, these declarations will be
 | 
			
		||||
# included in the documentation.
 | 
			
		||||
# declarations. If set to NO, these declarations will be included in the
 | 
			
		||||
# documentation.
 | 
			
		||||
# The default value is: NO.
 | 
			
		||||
 | 
			
		||||
HIDE_FRIEND_COMPOUNDS  = NO
 | 
			
		||||
@@ -543,7 +559,7 @@ INTERNAL_DOCS          = NO
 | 
			
		||||
# names in lower-case letters. If set to YES, upper-case letters are also
 | 
			
		||||
# allowed. This is useful if you have classes or files whose names only differ
 | 
			
		||||
# in case and if your file system supports case sensitive file names. Windows
 | 
			
		||||
# and Mac users are advised to set this option to NO.
 | 
			
		||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
 | 
			
		||||
# The default value is: system dependent.
 | 
			
		||||
 | 
			
		||||
CASE_SENSE_NAMES       = YES
 | 
			
		||||
@@ -813,7 +829,8 @@ WARN_LOGFILE           =
 | 
			
		||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 | 
			
		||||
# Note: If this tag is empty the current directory is searched.
 | 
			
		||||
 | 
			
		||||
INPUT                  = src api
 | 
			
		||||
INPUT                  = src \
 | 
			
		||||
                         api
 | 
			
		||||
 | 
			
		||||
# This tag can be used to specify the character encoding of the source files
 | 
			
		||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 | 
			
		||||
@@ -835,8 +852,10 @@ INPUT_ENCODING         = UTF-8
 | 
			
		||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
 | 
			
		||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
 | 
			
		||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
 | 
			
		||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
 | 
			
		||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
 | 
			
		||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
 | 
			
		||||
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
 | 
			
		||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
 | 
			
		||||
# *.vhdl, *.ucf, *.qsf and *.ice.
 | 
			
		||||
 | 
			
		||||
FILE_PATTERNS          = *.c \
 | 
			
		||||
                         *.cc \
 | 
			
		||||
@@ -1250,9 +1269,9 @@ HTML_TIMESTAMP         = NO
 | 
			
		||||
 | 
			
		||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
 | 
			
		||||
# documentation will contain a main index with vertical navigation menus that
 | 
			
		||||
# are dynamically created via Javascript. If disabled, the navigation index will
 | 
			
		||||
# are dynamically created via JavaScript. If disabled, the navigation index will
 | 
			
		||||
# consists of multiple levels of tabs that are statically embedded in every HTML
 | 
			
		||||
# page. Disable this option to support browsers that do not have Javascript,
 | 
			
		||||
# page. Disable this option to support browsers that do not have JavaScript,
 | 
			
		||||
# like the Qt help browser.
 | 
			
		||||
# The default value is: YES.
 | 
			
		||||
# This tag requires that the tag GENERATE_HTML is set to YES.
 | 
			
		||||
@@ -1403,7 +1422,7 @@ QCH_FILE               =
 | 
			
		||||
 | 
			
		||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
 | 
			
		||||
# Project output. For more information please see Qt Help Project / Namespace
 | 
			
		||||
# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
 | 
			
		||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
 | 
			
		||||
# The default value is: org.doxygen.Project.
 | 
			
		||||
# This tag requires that the tag GENERATE_QHP is set to YES.
 | 
			
		||||
 | 
			
		||||
@@ -1411,7 +1430,7 @@ QHP_NAMESPACE          = org.doxygen.Project
 | 
			
		||||
 | 
			
		||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
 | 
			
		||||
# Help Project output. For more information please see Qt Help Project / Virtual
 | 
			
		||||
# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
 | 
			
		||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
 | 
			
		||||
# folders).
 | 
			
		||||
# The default value is: doc.
 | 
			
		||||
# This tag requires that the tag GENERATE_QHP is set to YES.
 | 
			
		||||
@@ -1420,7 +1439,7 @@ QHP_VIRTUAL_FOLDER     = doc
 | 
			
		||||
 | 
			
		||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
 | 
			
		||||
# filter to add. For more information please see Qt Help Project / Custom
 | 
			
		||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
 | 
			
		||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
 | 
			
		||||
# filters).
 | 
			
		||||
# This tag requires that the tag GENERATE_QHP is set to YES.
 | 
			
		||||
 | 
			
		||||
@@ -1428,7 +1447,7 @@ QHP_CUST_FILTER_NAME   =
 | 
			
		||||
 | 
			
		||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
 | 
			
		||||
# custom filter to add. For more information please see Qt Help Project / Custom
 | 
			
		||||
# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
 | 
			
		||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
 | 
			
		||||
# filters).
 | 
			
		||||
# This tag requires that the tag GENERATE_QHP is set to YES.
 | 
			
		||||
 | 
			
		||||
@@ -1436,7 +1455,7 @@ QHP_CUST_FILTER_ATTRS  =
 | 
			
		||||
 | 
			
		||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
 | 
			
		||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
 | 
			
		||||
# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
 | 
			
		||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
 | 
			
		||||
# This tag requires that the tag GENERATE_QHP is set to YES.
 | 
			
		||||
 | 
			
		||||
QHP_SECT_FILTER_ATTRS  =
 | 
			
		||||
@@ -1540,8 +1559,14 @@ FORMULA_FONTSIZE       = 10
 | 
			
		||||
 | 
			
		||||
FORMULA_TRANSPARENT    = YES
 | 
			
		||||
 | 
			
		||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
 | 
			
		||||
# to create new LaTeX commands to be used in formulas as building blocks. See
 | 
			
		||||
# the section "Including formulas" for details.
 | 
			
		||||
 | 
			
		||||
FORMULA_MACROFILE      =
 | 
			
		||||
 | 
			
		||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
 | 
			
		||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
 | 
			
		||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
 | 
			
		||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
 | 
			
		||||
# installed or if you want to formulas look prettier in the HTML output. When
 | 
			
		||||
# enabled you may also need to install MathJax separately and configure the path
 | 
			
		||||
@@ -1611,7 +1636,7 @@ MATHJAX_CODEFILE       =
 | 
			
		||||
SEARCHENGINE           = YES
 | 
			
		||||
 | 
			
		||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
 | 
			
		||||
# implemented using a web server instead of a web client using Javascript. There
 | 
			
		||||
# implemented using a web server instead of a web client using JavaScript. There
 | 
			
		||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
 | 
			
		||||
# setting. When disabled, doxygen will generate a PHP script for searching and
 | 
			
		||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
 | 
			
		||||
@@ -1715,10 +1740,11 @@ LATEX_CMD_NAME         =
 | 
			
		||||
MAKEINDEX_CMD_NAME     = makeindex
 | 
			
		||||
 | 
			
		||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
 | 
			
		||||
# generate index for LaTeX.
 | 
			
		||||
# generate index for LaTeX. In case there is no backslash (\) as first character
 | 
			
		||||
# it will be automatically added in the LaTeX code.
 | 
			
		||||
# Note: This tag is used in the generated output file (.tex).
 | 
			
		||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
 | 
			
		||||
# The default value is: \makeindex.
 | 
			
		||||
# The default value is: makeindex.
 | 
			
		||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
 | 
			
		||||
 | 
			
		||||
LATEX_MAKEINDEX_CMD    = \makeindex
 | 
			
		||||
@@ -2210,12 +2236,6 @@ EXTERNAL_GROUPS        = YES
 | 
			
		||||
 | 
			
		||||
EXTERNAL_PAGES         = YES
 | 
			
		||||
 | 
			
		||||
# The PERL_PATH should be the absolute path and name of the perl script
 | 
			
		||||
# interpreter (i.e. the result of 'which perl').
 | 
			
		||||
# The default file (with absolute path) is: /usr/bin/perl.
 | 
			
		||||
 | 
			
		||||
PERL_PATH              = /usr/bin/perl
 | 
			
		||||
 | 
			
		||||
#---------------------------------------------------------------------------
 | 
			
		||||
# Configuration options related to the dot tool
 | 
			
		||||
#---------------------------------------------------------------------------
 | 
			
		||||
@@ -2229,15 +2249,6 @@ PERL_PATH              = /usr/bin/perl
 | 
			
		||||
 | 
			
		||||
CLASS_DIAGRAMS         = YES
 | 
			
		||||
 | 
			
		||||
# You can define message sequence charts within doxygen comments using the \msc
 | 
			
		||||
# command. Doxygen will then run the mscgen tool (see:
 | 
			
		||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
 | 
			
		||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
 | 
			
		||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
 | 
			
		||||
# default search path.
 | 
			
		||||
 | 
			
		||||
MSCGEN_PATH            =
 | 
			
		||||
 | 
			
		||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
 | 
			
		||||
# then run dia to produce the diagram and insert it in the documentation. The
 | 
			
		||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										141
									
								
								example/main.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								example/main.c
									
									
									
									
									
								
							@@ -1,19 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * main.c
 | 
			
		||||
 * Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
 | 
			
		||||
 *
 | 
			
		||||
 *  Created on: Jun 10, 2019
 | 
			
		||||
 *      Author: stefan
 | 
			
		||||
 * 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 <ncurses.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <termios.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
@@ -22,24 +26,6 @@ static bool exitRequest = false;
 | 
			
		||||
int f;
 | 
			
		||||
shellmatta_handle_t handle;
 | 
			
		||||
 | 
			
		||||
void set_blocking (int fd, int should_block)
 | 
			
		||||
{
 | 
			
		||||
        struct termios tty;
 | 
			
		||||
        memset (&tty, 0, sizeof tty);
 | 
			
		||||
        if (tcgetattr (fd, &tty) != 0)
 | 
			
		||||
        {
 | 
			
		||||
                printf ("error %d from tggetattr", errno);
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tty.c_cc[VMIN]  = should_block ? 1 : 0;
 | 
			
		||||
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout
 | 
			
		||||
 | 
			
		||||
        if (tcsetattr (fd, TCSANOW, &tty) != 0)
 | 
			
		||||
            printf ("error %d setting term attributes", errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
 | 
			
		||||
{
 | 
			
		||||
    shellmatta_printf(handle, "%s - length: %u", arguments, length);
 | 
			
		||||
@@ -52,6 +38,8 @@ static shellmatta_retCode_t doSome(shellmatta_handle_t handle, const char *argum
 | 
			
		||||
 | 
			
		||||
    shellmatta_write(handle, "blubb\r\n", 7u);
 | 
			
		||||
 | 
			
		||||
    shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
 | 
			
		||||
 | 
			
		||||
    (void)arguments;
 | 
			
		||||
    (void)length;
 | 
			
		||||
 | 
			
		||||
@@ -91,11 +79,102 @@ static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *argume
 | 
			
		||||
    (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)
 | 
			
		||||
{
 | 
			
		||||
@@ -124,8 +203,6 @@ int main(int argc, char **argv)
 | 
			
		||||
        return f;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set_blocking (f, 1);
 | 
			
		||||
 | 
			
		||||
    shellmatta_doInit(  &instance,
 | 
			
		||||
                        &handle,
 | 
			
		||||
                        buffer,
 | 
			
		||||
@@ -140,18 +217,28 @@ int main(int argc, char **argv)
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
        shellmatta_processData(handle, &c, res);
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            ret = shellmatta_processData(handle, &c, res);
 | 
			
		||||
            if(SHELLMATTA_BUSY == ret)
 | 
			
		||||
            {
 | 
			
		||||
                sleep(1);
 | 
			
		||||
            }
 | 
			
		||||
        } while(SHELLMATTA_BUSY == ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(f);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								makefile
									
									
									
									
									
								
							@@ -16,11 +16,13 @@ SOURCES :=  src/shellmatta.c                \
 | 
			
		||||
            src/shellmatta_autocomplete.c   \
 | 
			
		||||
            src/shellmatta_history.c        \
 | 
			
		||||
            src/shellmatta_utils.c          \
 | 
			
		||||
            src/shellmatta_escape.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         \
 | 
			
		||||
@@ -36,8 +38,11 @@ UNITTEST_SOURCES := test/unittest/test_main.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
 | 
			
		||||
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_busy.cpp
 | 
			
		||||
 | 
			
		||||
UNITTEST_CPPOBJ  := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(UNITTEST_SOURCES))
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +53,7 @@ TESTFLAGS   := $(INCLUDES:%=-I%) -g -Wall -Werror -Wextra -fprofile-arcs -ftest-
 | 
			
		||||
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
 | 
			
		||||
@@ -67,17 +72,18 @@ export
 | 
			
		||||
 | 
			
		||||
help:
 | 
			
		||||
	@echo Shellmatta help
 | 
			
		||||
	@echo -------------------------
 | 
			
		||||
	@echo -----------------------------------------------
 | 
			
		||||
	@echo test      - run all tests
 | 
			
		||||
	@echo cppcheck  - run static code analysis (cppcheck)
 | 
			
		||||
	@echo example   - build example
 | 
			
		||||
	@echo -------------------------
 | 
			
		||||
	@echo -----------------------------------------------
 | 
			
		||||
 | 
			
		||||
test: unittest integrationtest
 | 
			
		||||
 | 
			
		||||
cppcheck:
 | 
			
		||||
	- @mkdir -p output/cppcheck/html
 | 
			
		||||
	cppcheck --addon=/usr/bin/misra.py --enable=all --template=gcc --cppcheck-build-dir=output/cppcheck $(SOURCES)
 | 
			
		||||
	cppcheck --addon=/usr/bin/misra.py --enable=all --template=gcc --cppcheck-build-dir=output/cppcheck $(SOURCES) --xml 2>output/cppcheck/cppcheck.xml
 | 
			
		||||
	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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										383
									
								
								src/shellmatta.c
									
									
									
									
									
								
							
							
						
						
									
										383
									
								
								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,8 +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;
 | 
			
		||||
@@ -91,13 +95,19 @@ shellmatta_retCode_t shellmatta_doInit(
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
        /** -# 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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -111,6 +121,58 @@ 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;
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
@@ -153,7 +215,8 @@ 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)
 | 
			
		||||
                if(     (NULL != cmd->cmdAlias)
 | 
			
		||||
                    &&  (NULL != tempCmd->cmdAlias))
 | 
			
		||||
                {
 | 
			
		||||
                    aliasDiff = strcmp(tempCmd->cmdAlias, cmd->cmdAlias);
 | 
			
		||||
                }
 | 
			
		||||
@@ -220,25 +283,25 @@ shellmatta_retCode_t shellmatta_removeCmd(shellmatta_handle_t handle, shellmatta
 | 
			
		||||
        tempCmd     = inst->cmdList;
 | 
			
		||||
        prevCmd     = NULL;
 | 
			
		||||
 | 
			
		||||
        /*! -# loop through command list */
 | 
			
		||||
        /** -# loop through command list */
 | 
			
		||||
        while(NULL != tempCmd)
 | 
			
		||||
        {
 | 
			
		||||
            /*! -# compare command strings to find the command to delete */
 | 
			
		||||
            /** -# 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 */
 | 
			
		||||
                /** -# first command removed */
 | 
			
		||||
                if(NULL == prevCmd)
 | 
			
		||||
                {
 | 
			
		||||
                    inst->cmdList = tempCmd->next;
 | 
			
		||||
                }
 | 
			
		||||
                /*! -# last command removed */
 | 
			
		||||
                /** -# last command removed */
 | 
			
		||||
                else if(NULL == tempCmd->next)
 | 
			
		||||
                {
 | 
			
		||||
                    prevCmd->next = NULL;
 | 
			
		||||
                }
 | 
			
		||||
                /*! -# command removed from the middle of the list */
 | 
			
		||||
                /** -# command removed from the middle of the list */
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    prevCmd->next = tempCmd->next;
 | 
			
		||||
@@ -259,6 +322,40 @@ shellmatta_retCode_t shellmatta_removeCmd(shellmatta_handle_t handle, shellmatta
 | 
			
		||||
    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
 | 
			
		||||
@@ -275,47 +372,107 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
    uint8_t                 cmdExecuted = 0u;
 | 
			
		||||
    uint32_t                cmdLen;
 | 
			
		||||
    char                    *tempString;
 | 
			
		||||
    char                    *argumentString = NULL;
 | 
			
		||||
    uint32_t                argumentLength = 0u;
 | 
			
		||||
    uint32_t                byteCounter;
 | 
			
		||||
    uint32_t                idx;
 | 
			
		||||
 | 
			
		||||
    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))
 | 
			
		||||
    {
 | 
			
		||||
        /** -# process byte wise */
 | 
			
		||||
        for (byteCounter = 0u; byteCounter < size; byteCounter++)
 | 
			
		||||
        /** -# in busy mode - keep calling this command */
 | 
			
		||||
        if(NULL != inst->busyCmd)
 | 
			
		||||
        {
 | 
			
		||||
            /** -# just call the function until it is not busy anymore */
 | 
			
		||||
            cmdRet = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
 | 
			
		||||
 | 
			
		||||
            if(SHELLMATTA_BUSY != cmdRet)
 | 
			
		||||
            {
 | 
			
		||||
                utils_terminateInput(inst);
 | 
			
		||||
            }
 | 
			
		||||
            else if(SHELLMATTA_CONTINUE == cmdRet)
 | 
			
		||||
            {
 | 
			
		||||
                inst->continuousCmd = inst->busyCmd;
 | 
			
		||||
                inst->busyCmd       = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                ret = cmdRet;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /** -# call continuous function even if there is no data */
 | 
			
		||||
        else if((0u != size) && (NULL != inst->continuousCmd))
 | 
			
		||||
        {
 | 
			
		||||
            /** -# just call the function until it is not busy anymore */
 | 
			
		||||
            cmdRet = inst->continuousCmd->cmdFct(handle, inst->buffer, size);
 | 
			
		||||
 | 
			
		||||
            if(SHELLMATTA_CONTINUE == cmdRet)
 | 
			
		||||
            {
 | 
			
		||||
                ret = cmdRet;
 | 
			
		||||
            }
 | 
			
		||||
            else if(SHELLMATTA_BUSY == cmdRet)
 | 
			
		||||
            {
 | 
			
		||||
                inst->busyCmd       = inst->continuousCmd;
 | 
			
		||||
                inst->continuousCmd = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                utils_terminateInput(inst);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** -# process byte wise */
 | 
			
		||||
        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->stdinLength               = 1u;
 | 
			
		||||
                cmdRet = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
 | 
			
		||||
                
 | 
			
		||||
                /** -# check if continuous mode is canceled or interrupted by busy mode */
 | 
			
		||||
                if(SHELLMATTA_BUSY == cmdRet)
 | 
			
		||||
                {
 | 
			
		||||
                    inst->busyCmd 	= inst->continuousCmd;
 | 
			
		||||
                    inst->continuousCmd = NULL;
 | 
			
		||||
                }
 | 
			
		||||
                else if(('\x03' == data[inst->byteCounter]))
 | 
			
		||||
                {
 | 
			
		||||
                    utils_terminateInput(inst);
 | 
			
		||||
                }
 | 
			
		||||
                else if(SHELLMATTA_CONTINUE == cmdRet)
 | 
			
		||||
                {
 | 
			
		||||
                    /** -# 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))
 | 
			
		||||
            {
 | 
			
		||||
                /* do nothing */
 | 
			
		||||
            }
 | 
			
		||||
            /** -# handle return as start of processing the command */
 | 
			
		||||
            else if ('\r' == *data)
 | 
			
		||||
            /** -# handle delimiter as start of processing the command */
 | 
			
		||||
            else if (inst->delimiter == data[inst->byteCounter])
 | 
			
		||||
            {
 | 
			
		||||
                if(0u == inst->hereLength)
 | 
			
		||||
                {
 | 
			
		||||
                    /**
 | 
			
		||||
                      *  \dot
 | 
			
		||||
                      *  @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 */
 | 
			
		||||
                      *  @enddot */
 | 
			
		||||
 | 
			
		||||
                    /** -# check for heredoc */
 | 
			
		||||
                    /** -# 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)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -334,7 +491,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
                            inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
 | 
			
		||||
 | 
			
		||||
                            inst->dirty = true;
 | 
			
		||||
                            utils_insertChars(inst, data, 1);
 | 
			
		||||
                            utils_insertChars(inst, &data[inst->byteCounter], 1u);
 | 
			
		||||
                            inst->lastNewlineIdx = inst->inputCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
@@ -349,9 +506,6 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        argumentString = inst->buffer;
 | 
			
		||||
                        argumentLength = inst->inputCount;
 | 
			
		||||
 | 
			
		||||
                        /** -# store the current command and reset the history buffer */
 | 
			
		||||
                        inst->dirty = true;
 | 
			
		||||
                        history_storeCmd(inst);
 | 
			
		||||
@@ -375,44 +529,56 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
                                            tempString,
 | 
			
		||||
                                            inst->hereLength)))
 | 
			
		||||
                    {
 | 
			
		||||
                        argumentLength = inst->lastNewlineIdx;
 | 
			
		||||
 | 
			
		||||
                        /** -# store the current command and reset the history buffer */
 | 
			
		||||
                        inst->dirty = true;
 | 
			
		||||
                        history_storeCmd(inst);
 | 
			
		||||
                        history_reset(inst);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        /* TODO it is difficult to store the complete command in the history buffer if it is restructured before...
 | 
			
		||||
                         * So this should be an extra function that can be called after parsing the command and before calling the command function */
 | 
			
		||||
                        for(idx = 1u; idx <= inst->hereStartIdx; idx++)
 | 
			
		||||
                        /** -# process heredoc as stdin like input  */
 | 
			
		||||
                        /** -# find start of heredoc data           */
 | 
			
		||||
                        inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
 | 
			
		||||
                        while(      ('\n' == inst->buffer[inst->stdinIdx])
 | 
			
		||||
                                ||  ('\r' == inst->buffer[inst->stdinIdx]))
 | 
			
		||||
                        {
 | 
			
		||||
                            inst->buffer[inst->hereDelimiterIdx + inst->hereLength - idx] = inst->buffer[inst->hereStartIdx - idx];
 | 
			
		||||
                            inst->stdinIdx ++;
 | 
			
		||||
                        }
 | 
			
		||||
                        /** -# 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;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        argumentString = &(inst->buffer[inst->hereDelimiterIdx + inst->hereLength - inst->hereStartIdx]);
 | 
			
		||||
                        argumentLength = inst->lastNewlineIdx - ((inst->hereDelimiterIdx + inst->hereLength) - inst->hereStartIdx);
 | 
			
		||||
                        /** -# 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, 1);
 | 
			
		||||
                        utils_insertChars(inst, &data[inst->byteCounter], 1u);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if(0u == inst->hereLength)
 | 
			
		||||
                {
 | 
			
		||||
                    cmd                             = inst->cmdList;
 | 
			
		||||
                    argumentString[argumentLength]  = 0u;
 | 
			
		||||
                    cmd = inst->cmdList;
 | 
			
		||||
 | 
			
		||||
                    /** -# determine the cmd len (chars until first space or \0 is found */
 | 
			
		||||
                    cmdLen = 0u;
 | 
			
		||||
                    while(      (cmdLen <   argumentLength)
 | 
			
		||||
                            &&  (' '    !=  argumentString[cmdLen])
 | 
			
		||||
                            &&  ('\r'   !=  argumentString[cmdLen])
 | 
			
		||||
                            &&  ('\n'   !=  argumentString[cmdLen])
 | 
			
		||||
                            &&  ('\0'   !=  argumentString[cmdLen]))
 | 
			
		||||
                    while(      (cmdLen <   inst->inputCount)
 | 
			
		||||
                            &&  (' '    !=  inst->buffer[cmdLen])
 | 
			
		||||
                            &&  ('\r'   !=  inst->buffer[cmdLen])
 | 
			
		||||
                            &&  ('\n'   !=  inst->buffer[cmdLen])
 | 
			
		||||
                            &&  ('\0'   !=  inst->buffer[cmdLen]))
 | 
			
		||||
                    {
 | 
			
		||||
                        cmdLen ++;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -420,29 +586,40 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
                    /** -# search for a matching command */
 | 
			
		||||
                    while (NULL != cmd)
 | 
			
		||||
                    {
 | 
			
		||||
                        /** -# compare command string and length */
 | 
			
		||||
                        if ((0 == strncmp(  argumentString,
 | 
			
		||||
                                            cmd->cmd,
 | 
			
		||||
                                            cmdLen))
 | 
			
		||||
                            && (cmdLen == strlen(cmd->cmd)))
 | 
			
		||||
                        {
 | 
			
		||||
                            inst->write("\r\n", 2u);
 | 
			
		||||
 | 
			
		||||
                            cmdExecuted = 1u;
 | 
			
		||||
                            cmd->cmdFct(inst, argumentString, argumentLength);
 | 
			
		||||
                            cmd = NULL;
 | 
			
		||||
                        }
 | 
			
		||||
                        /** -# compare command alias if any and length */
 | 
			
		||||
                        else if((NULL != cmd->cmdAlias)
 | 
			
		||||
                                && ((0 == strncmp(  argumentString,
 | 
			
		||||
                        /** -# compare command and alias string and length */
 | 
			
		||||
                        if (    ((0 == strncmp( inst->buffer,
 | 
			
		||||
                                                cmd->cmd,
 | 
			
		||||
                                                cmdLen))
 | 
			
		||||
                                && (cmdLen == strlen(cmd->cmd)))
 | 
			
		||||
                            || ((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, argumentString, argumentLength);
 | 
			
		||||
                            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;
 | 
			
		||||
                                    break;
 | 
			
		||||
                                
 | 
			
		||||
                                case SHELLMATTA_BUSY:
 | 
			
		||||
                                    inst->busyCmd   = cmd;
 | 
			
		||||
                                    ret             = cmdRet;
 | 
			
		||||
                                    break;
 | 
			
		||||
 | 
			
		||||
                                default:
 | 
			
		||||
                                    /* nothing to do - everything ok */
 | 
			
		||||
                                    break;
 | 
			
		||||
                            }
 | 
			
		||||
                            cmd = NULL;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
@@ -454,52 +631,67 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
 | 
			
		||||
                    if ((cmdExecuted == 0u) && (inst->inputCount > 0))
 | 
			
		||||
                    {
 | 
			
		||||
                        inst->write("\r\nCommand: ", 11u);
 | 
			
		||||
                        inst->write(argumentString, argumentLength);
 | 
			
		||||
                        inst->write(inst->buffer, inst->inputCount);
 | 
			
		||||
                        inst->write(" not found", 10u);
 | 
			
		||||
                    }
 | 
			
		||||
                    utils_terminateInput(inst);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                    /** -# 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)
 | 
			
		||||
                    ||  ('\x7f' == *data))
 | 
			
		||||
            else if(    ('\b'   == data[inst->byteCounter])
 | 
			
		||||
                    ||  ('\x7f' == data[inst->byteCounter]))
 | 
			
		||||
            {
 | 
			
		||||
                inst->dirty = true;
 | 
			
		||||
                utils_removeChars(inst, 1u, true);
 | 
			
		||||
            }
 | 
			
		||||
            /** -# check for start of escape sequence */
 | 
			
		||||
            else if('\x1b' == *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
 | 
			
		||||
@@ -534,6 +726,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
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -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,9 +218,12 @@ void history_restoreCmd(shellmatta_instance_t *inst)
 | 
			
		||||
        ret = getHistoryByte(inst, &byte);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    utils_writeEcho(inst, inst->buffer, inst->inputCount);
 | 
			
		||||
    history_navigate(inst, 1);
 | 
			
		||||
    inst->dirty = false;
 | 
			
		||||
    if(true == anythingToRestore)
 | 
			
		||||
    {
 | 
			
		||||
        utils_writeEcho(inst, inst->buffer, inst->inputCount);
 | 
			
		||||
        inst->dirty = false;
 | 
			
		||||
    }
 | 
			
		||||
    (void)history_navigate(inst, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										423
									
								
								src/shellmatta_opt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								src/shellmatta_opt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,423 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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)
 | 
			
		||||
 */
 | 
			
		||||
shellmatta_retCode_t shellmatta_opt_init(shellmatta_instance_t *inst, uint32_t argStart)
 | 
			
		||||
{
 | 
			
		||||
    /** -# initialize all relevant option parser variables */
 | 
			
		||||
    inst->optionParser.nextOffset = argStart;
 | 
			
		||||
 | 
			
		||||
    return SHELLMATTA_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @}
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										43
									
								
								src/shellmatta_opt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/shellmatta_opt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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);
 | 
			
		||||
 | 
			
		||||
shellmatta_retCode_t shellmatta_opt_init(   shellmatta_instance_t   *inst,
 | 
			
		||||
                                            uint32_t argStart);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
@@ -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->cursor        += length;
 | 
			
		||||
            if(inst->cursor > inst->inputCount)
 | 
			
		||||
            {
 | 
			
		||||
                inst->inputCount    =  inst->cursor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        inst->inputCount    += length;
 | 
			
		||||
        inst->cursor        += length;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -289,7 +294,7 @@ static shellmatta_retCode_t helpCmdFct(shellmatta_handle_t handle, const char *a
 | 
			
		||||
    /** -# loop through all commands to determine the lengths of each cmd */
 | 
			
		||||
    while(NULL != cmd)
 | 
			
		||||
    {
 | 
			
		||||
        maxCmdLen       = SHELLMATTA_MAX(maxCmdLen,         strlen(cmd->cmd));
 | 
			
		||||
        maxCmdLen           = SHELLMATTA_MAX(maxCmdLen,         strlen(cmd->cmd));
 | 
			
		||||
        if(NULL != cmd->cmdAlias)
 | 
			
		||||
        {
 | 
			
		||||
            maxCmdAliasLen  = SHELLMATTA_MAX(maxCmdAliasLen,    strlen(cmd->cmdAlias));
 | 
			
		||||
@@ -342,12 +347,12 @@ static shellmatta_retCode_t helpCmdFct(shellmatta_handle_t handle, const char *a
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
shellmatta_cmd_t helpCmd = {  SHELLMATTA_HELP_COMMAND
 | 
			
		||||
                            , SHELLMATTA_HELP_ALIAS
 | 
			
		||||
                            , SHELLMATTA_HELP_HELP_TEXT
 | 
			
		||||
                            , SHELLMATTA_HELP_USAGE_TEXT
 | 
			
		||||
                            , 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
 | 
			
		||||
@@ -359,6 +364,10 @@ void utils_terminateInput(shellmatta_instance_t *inst)
 | 
			
		||||
    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>
 | 
			
		||||
 | 
			
		||||
/* some helper macros */
 | 
			
		||||
/**
 | 
			
		||||
 * @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,16 +53,18 @@
 | 
			
		||||
        (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 */
 | 
			
		||||
/** @brief overwritable output buffer size */
 | 
			
		||||
#ifndef SHELLMATTA_OUTPUT_BUFFER_SIZE
 | 
			
		||||
#define SHELLMATTA_OUTPUT_BUFFER_SIZE   128u
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*! @defgroup Shellmatta Help command overwrites
 | 
			
		||||
/** @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  
 | 
			
		||||
@@ -57,18 +76,18 @@ extern shellmatta_cmd_t helpCmd;
 | 
			
		||||
 *  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               */
 | 
			
		||||
#define SHELLMATTA_HELP_COMMAND     (char*)"help"                   /**< help command               */
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef SHELLMATTA_HELP_ALIAS
 | 
			
		||||
#define SHELLMATTA_HELP_ALIAS       (char*)"h"                      /*!< help command 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     */
 | 
			
		||||
#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    */
 | 
			
		||||
#define SHELLMATTA_HELP_USAGE_TEXT  (char*)"help"                   /**< help command usage text    */
 | 
			
		||||
#endif
 | 
			
		||||
/*!
 | 
			
		||||
/**
 | 
			
		||||
 *  @}
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,8 @@ static char write_data[1024];
 | 
			
		||||
static uint32_t write_length;
 | 
			
		||||
static const char *doSomethingArguments;
 | 
			
		||||
static uint32_t doSomethingLength;
 | 
			
		||||
static char *doSomethingStdin;
 | 
			
		||||
static uint32_t doSomethingStdinLength;
 | 
			
		||||
 | 
			
		||||
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
 | 
			
		||||
{
 | 
			
		||||
@@ -28,6 +30,9 @@ static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *
 | 
			
		||||
{
 | 
			
		||||
    doSomethingArguments = arguments;
 | 
			
		||||
    doSomethingLength = length;
 | 
			
		||||
 | 
			
		||||
    shellmatta_read(handle, &doSomethingStdin, &doSomethingStdinLength);
 | 
			
		||||
 | 
			
		||||
    shellmatta_printf(handle, "%s - length: %u", arguments, length);
 | 
			
		||||
    return SHELLMATTA_OK;
 | 
			
		||||
}
 | 
			
		||||
@@ -77,6 +82,7 @@ TEST_CASE( "shellmatta help function" ) {
 | 
			
		||||
    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->";
 | 
			
		||||
 | 
			
		||||
@@ -89,6 +95,7 @@ TEST_CASE( "shellmatta help function" ) {
 | 
			
		||||
                        "shellmatta->",
 | 
			
		||||
                        NULL,
 | 
			
		||||
                        writeFct);
 | 
			
		||||
    shellmatta_addCmd(handle, &emptyCmd);
 | 
			
		||||
    shellmatta_addCmd(handle, &doSomethingCmd);
 | 
			
		||||
 | 
			
		||||
    write_callCnt = 0u;
 | 
			
		||||
@@ -97,11 +104,9 @@ TEST_CASE( "shellmatta help function" ) {
 | 
			
		||||
 | 
			
		||||
    shellmatta_processData(handle, (char*)"?\r", 2);
 | 
			
		||||
 | 
			
		||||
    CHECK( write_length == 123u);
 | 
			
		||||
    CHECK( write_length == strlen(dummyData));
 | 
			
		||||
    CHECK( strcmp(dummyData, write_data) == 0);
 | 
			
		||||
 | 
			
		||||
    shellmatta_addCmd(handle, &emptyCmd);
 | 
			
		||||
 | 
			
		||||
    write_callCnt = 0u;
 | 
			
		||||
    memset(write_data, 0, sizeof(write_data));
 | 
			
		||||
    write_length = 0u;
 | 
			
		||||
@@ -140,8 +145,8 @@ TEST_CASE( "shellmatta heredoc test" ) {
 | 
			
		||||
    shellmatta_handle_t handle;
 | 
			
		||||
    char buffer[1024];
 | 
			
		||||
    char historyBuffer[1024];
 | 
			
		||||
    char *dummyData =   (char*)"do this \r\n"
 | 
			
		||||
                        "asdf\r\n"
 | 
			
		||||
    char *dummyData =   (char*)"do this ";
 | 
			
		||||
    char *dummyStdin =  (char*)"asdf\r\n"
 | 
			
		||||
                        "1234";
 | 
			
		||||
 | 
			
		||||
    shellmatta_doInit(  &inst,
 | 
			
		||||
@@ -162,14 +167,45 @@ TEST_CASE( "shellmatta heredoc test" ) {
 | 
			
		||||
                                    "asdf\r\n"
 | 
			
		||||
                                    "1234\r\n"
 | 
			
		||||
                                    "EOF\r\n"
 | 
			
		||||
                                , 34);
 | 
			
		||||
                                , 33);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    CHECK( doSomethingLength == 20u);
 | 
			
		||||
    CHECK( doSomethingStdinLength == 10u);
 | 
			
		||||
    CHECK( strcmp(dummyStdin, doSomethingStdin) == 0);
 | 
			
		||||
    CHECK( doSomethingLength == 8u);
 | 
			
		||||
    REQUIRE( strcmp(dummyData, doSomethingArguments) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "shellmatta 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" ) {
 | 
			
		||||
 | 
			
		||||
@@ -228,9 +264,302 @@ TEST_CASE( "shellmatta remove function" ) {
 | 
			
		||||
                    "help  ?  Print this help text  help\r\n"
 | 
			
		||||
                    "\r\nshellmatta->";
 | 
			
		||||
 | 
			
		||||
    printf("sdfsd sdf sdf sdf sdf sd fds\n%s", write_data);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										130
									
								
								test/integrationtest/test_integration_busy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								test/integrationtest/test_integration_busy.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,130 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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 );
 | 
			
		||||
}
 | 
			
		||||
@@ -19,6 +19,7 @@ TEST_CASE( "shellmatta_insertChars normal call" ) {
 | 
			
		||||
    shellmatta_instance_t inst;
 | 
			
		||||
    char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 | 
			
		||||
 | 
			
		||||
    memset(&inst, 0, sizeof(inst));
 | 
			
		||||
    inst.buffer = buffer;
 | 
			
		||||
    inst.bufferSize = 20;
 | 
			
		||||
    inst.cursor = 8;
 | 
			
		||||
@@ -45,6 +46,7 @@ TEST_CASE( "shellmatta_insertChars overwrite" ) {
 | 
			
		||||
    shellmatta_instance_t inst;
 | 
			
		||||
    char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 | 
			
		||||
 | 
			
		||||
    memset(&inst, 0, sizeof(inst));
 | 
			
		||||
    inst.buffer = buffer;
 | 
			
		||||
    inst.bufferSize = 20;
 | 
			
		||||
    inst.cursor = 8;
 | 
			
		||||
@@ -61,7 +63,7 @@ TEST_CASE( "shellmatta_insertChars overwrite" ) {
 | 
			
		||||
    utils_insertChars(&inst, (char*)"blksdflsd kfjlk", 4u);
 | 
			
		||||
 | 
			
		||||
    CHECK( inst.cursor == 12);
 | 
			
		||||
    CHECK( inst.inputCount == 14);
 | 
			
		||||
    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);
 | 
			
		||||
@@ -72,6 +74,7 @@ TEST_CASE( "shellmatta_insertChars append" ) {
 | 
			
		||||
    shellmatta_instance_t inst;
 | 
			
		||||
    char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 | 
			
		||||
 | 
			
		||||
    memset(&inst, 0, sizeof(inst));
 | 
			
		||||
    inst.buffer = buffer;
 | 
			
		||||
    inst.bufferSize = 20;
 | 
			
		||||
    inst.cursor = 10;
 | 
			
		||||
@@ -99,6 +102,7 @@ TEST_CASE( "shellmatta_insertChars 0 length" ) {
 | 
			
		||||
    shellmatta_instance_t inst;
 | 
			
		||||
    char buffer[20] = "abcdefghij\0\0\0\0\0\0\0\0\0";
 | 
			
		||||
 | 
			
		||||
    memset(&inst, 0, sizeof(inst));
 | 
			
		||||
    inst.buffer = buffer;
 | 
			
		||||
    inst.bufferSize = 20;
 | 
			
		||||
    inst.cursor = 8;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user