mirror of
https://github.com/MaJerle/lwshell.git
synced 2025-02-06 13:08:22 +08:00
Merge branch 'develop'
This commit is contained in:
commit
45b1d75d20
27
.github/workflows/release.yml
vendored
Normal file
27
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
# Sequence of patterns matched against refs/tags
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
name: Create Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Create Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Release ${{ github.ref }}
|
||||||
|
body: |
|
||||||
|
See the CHANGELOG.md
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v1.0.0
|
||||||
|
|
||||||
|
|
@ -7,11 +7,13 @@ It targets communication with embedded systems from remote terminal to quickly s
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Lightweight commands shell for embedded systems
|
* Lightweight commands shell for embedded systems
|
||||||
* Platform independent and very easy to port
|
* Platform independent and very easy to port
|
||||||
* Development of library under Win32 platform
|
* Development of library under Win32 platform
|
||||||
* Written in C language (C99)
|
* Written in C language (C99)
|
||||||
* No dynamic allocation, maximum number of commands assigned at compile time
|
* No dynamic allocation, maximum number of commands assigned at compile time
|
||||||
|
* Highly configurable
|
||||||
|
* Simple help-text with `cmd -v` option
|
||||||
* User friendly MIT license
|
* User friendly MIT license
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
31
dev/VisualStudio/lwshell_dev.sln
Normal file
31
dev/VisualStudio/lwshell_dev.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.28922.388
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwshell_dev", "lwshell_dev.vcxproj", "{C095C533-523E-4604-B3EF-B5025E4D96C0}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{C095C533-523E-4604-B3EF-B5025E4D96C0}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0D5E996C-005B-40C8-95F9-90D0632471E5}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
153
dev/VisualStudio/lwshell_dev.vcxproj
Normal file
153
dev/VisualStudio/lwshell_dev.vcxproj
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{C095C533-523E-4604-B3EF-B5025E4D96C0}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>dynamic_memory</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>lwshell_dev</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>..\..\lwshell\src\include;.;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>..\..\lwmem\src\include;.;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level1</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;LWMEM_DEV;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;LWMEM_DEV;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\examples\example_minimal.c" />
|
||||||
|
<ClCompile Include="..\..\lwshell\src\lwshell\lwshell.c" />
|
||||||
|
<ClCompile Include="main.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
26
dev/VisualStudio/lwshell_dev.vcxproj.filters
Normal file
26
dev/VisualStudio/lwshell_dev.vcxproj.filters
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Tests">
|
||||||
|
<UniqueIdentifier>{87f67bb1-45c3-4724-b7de-f1e8551453e3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\LWSHELL">
|
||||||
|
<UniqueIdentifier>{a9bad49b-d114-4596-8fe8-162c60f482ee}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\lwshell\src\lwshell\lwshell.c">
|
||||||
|
<Filter>Source Files\LWSHELL</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\examples\example_minimal.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
43
dev/VisualStudio/lwshell_opts.h
Normal file
43
dev/VisualStudio/lwshell_opts.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* \file lwshell_opts.h
|
||||||
|
* \brief LwSHELL application options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Tilen MAJERLE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of Lightweight shell library.
|
||||||
|
*
|
||||||
|
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||||
|
* Version: v0.1.0
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_HDR_OPTS_H
|
||||||
|
#define LWSHELL_HDR_OPTS_H
|
||||||
|
|
||||||
|
/* Rename this file to "lwshell_opts.h" for your application */
|
||||||
|
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
#define LWSHELL_CFG_USE_OUTPUT 1
|
||||||
|
|
||||||
|
#endif /* LWSHELL_HDR_OPTS_H */
|
97
dev/VisualStudio/main.c
Normal file
97
dev/VisualStudio/main.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "lwshell/lwshell.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void example_minimal(void);
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
addint_cmd(int32_t argc, char** argv) {
|
||||||
|
long long i1, i2;
|
||||||
|
if (argc < 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i1 = lwshell_parse_long_long(argv[1]);
|
||||||
|
i2 = lwshell_parse_long_long(argv[2]);
|
||||||
|
|
||||||
|
printf("%lld\r\n", i1 + i2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
subint_cmd(int32_t argc, char** argv) {
|
||||||
|
long long i1, i2;
|
||||||
|
if (argc < 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i1 = lwshell_parse_long_long(argv[1]);
|
||||||
|
i2 = lwshell_parse_long_long(argv[2]);
|
||||||
|
|
||||||
|
printf("%lld\r\n", i1 - i2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
adddbl_cmd(int32_t argc, char** argv) {
|
||||||
|
double i1, i2;
|
||||||
|
if (argc < 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i1 = lwshell_parse_double(argv[1]);
|
||||||
|
i2 = lwshell_parse_double(argv[2]);
|
||||||
|
|
||||||
|
printf("%f\r\n", (i1 + i2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
subdbl_cmd(int32_t argc, char** argv) {
|
||||||
|
double i1, i2;
|
||||||
|
if (argc < 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i1 = lwshell_parse_double(argv[1]);
|
||||||
|
i2 = lwshell_parse_double(argv[2]);
|
||||||
|
|
||||||
|
printf("%f\r\n", (i1 - i2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Application output function
|
||||||
|
* \param[in] str: String to print, null-terminated
|
||||||
|
* \param[in] lw: LwSHELL instance
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shell_output(const char* str, lwshell_t* lw) {
|
||||||
|
printf("%s", str);
|
||||||
|
if (*str == '\r') {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program entry point */
|
||||||
|
int
|
||||||
|
main(void) {
|
||||||
|
/* Init library */
|
||||||
|
lwshell_init();
|
||||||
|
|
||||||
|
/* Add optional output function for the purpose of the feedback */
|
||||||
|
lwshell_set_output_fn(shell_output);
|
||||||
|
|
||||||
|
/* Define shell commands */
|
||||||
|
lwshell_register_cmd("addint", addint_cmd, "Adds 2 integer numbers and prints them");
|
||||||
|
lwshell_register_cmd("subint", subint_cmd, "Substitute 2 integer numbers and prints them");
|
||||||
|
lwshell_register_cmd("adddbl", adddbl_cmd, "Adds 2 double numbers and prints them");
|
||||||
|
lwshell_register_cmd("subdbl", subdbl_cmd, "Substitute 2 double numbers and prints them");
|
||||||
|
|
||||||
|
/* User input to process every character */
|
||||||
|
printf("Start entering your command and press enter...\r\n");
|
||||||
|
while (1) {
|
||||||
|
char c = getch();
|
||||||
|
|
||||||
|
/* Insert input to library */
|
||||||
|
lwshell_input(&c, 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = .
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Put it first so that "make" without argument is like "make help".
|
||||||
|
help:
|
||||||
|
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||||
|
|
||||||
|
.PHONY: help Makefile
|
||||||
|
|
||||||
|
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||||
|
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||||
|
%: Makefile
|
||||||
|
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
12
docs/api-reference/index.rst
Normal file
12
docs/api-reference/index.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.. _api_reference:
|
||||||
|
|
||||||
|
API reference
|
||||||
|
=============
|
||||||
|
|
||||||
|
List of all the modules:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
lwshell
|
||||||
|
lwshell_opt
|
6
docs/api-reference/lwshell.rst
Normal file
6
docs/api-reference/lwshell.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.. _api_lwshell:
|
||||||
|
|
||||||
|
LwSHELL
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. doxygengroup:: LWSHELL
|
12
docs/api-reference/lwshell_opt.rst
Normal file
12
docs/api-reference/lwshell_opt.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.. _api_lwshell_opt:
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
This is the default configuration of the middleware.
|
||||||
|
When any of the settings shall be modified, it shall be done in dedicated application config ``lwshell_opts.h`` file.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Check :ref:`getting_started` for guidelines on how to create and use configuration file.
|
||||||
|
|
||||||
|
.. doxygengroup:: LWSHELL_OPT
|
134
docs/conf.py
Normal file
134
docs/conf.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
# import sys
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||||
|
import subprocess, os
|
||||||
|
|
||||||
|
# Run doxygen first
|
||||||
|
# read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True'
|
||||||
|
# if read_the_docs_build:
|
||||||
|
subprocess.call('doxygen doxyfile.doxy', shell=True)
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'LwSHELL'
|
||||||
|
copyright = '2020, Tilen MAJERLE'
|
||||||
|
author = 'Tilen MAJERLE'
|
||||||
|
|
||||||
|
# Try to get branch at which this is running
|
||||||
|
# and try to determine which version to display in sphinx
|
||||||
|
# Version is using git tag if on master or "latest-develop" if on develop branch
|
||||||
|
version = ''
|
||||||
|
git_branch = ''
|
||||||
|
|
||||||
|
# Get current branch
|
||||||
|
res = os.popen('git branch').read().strip()
|
||||||
|
for line in res.split("\n"):
|
||||||
|
if line[0] == '*':
|
||||||
|
git_branch = line[1:].strip()
|
||||||
|
|
||||||
|
# Decision for display version
|
||||||
|
git_branch = git_branch.replace('(HEAD detached at ', '').replace(')', '')
|
||||||
|
if git_branch.find('master') >= 0 or git_branch.find('main') >= 0:
|
||||||
|
version = os.popen('git describe --tags --abbrev=0').read().strip()
|
||||||
|
if version == '':
|
||||||
|
version = 'v0.0.0'
|
||||||
|
elif git_branch.find('develop') != -1 and not (git_branch.find('develop-') >= 0 or git_branch.find('develop/') >= 0):
|
||||||
|
version = 'latest-develop'
|
||||||
|
else:
|
||||||
|
version = 'branch-' + git_branch
|
||||||
|
|
||||||
|
# For debugging purpose only
|
||||||
|
print("GIT BRANCH: " + git_branch)
|
||||||
|
print("GIT VERSION: " + version)
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
'sphinx.ext.autosectionlabel',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.coverage',
|
||||||
|
'sphinx.ext.mathjax',
|
||||||
|
'sphinx.ext.ifconfig',
|
||||||
|
'sphinx.ext.viewcode',
|
||||||
|
'sphinx_sitemap',
|
||||||
|
|
||||||
|
'breathe',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
highlight_language = 'c'
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
html_theme_options = {
|
||||||
|
'canonical_url': '',
|
||||||
|
'analytics_id': '', # Provided by Google in your dashboard
|
||||||
|
'display_version': True,
|
||||||
|
'prev_next_buttons_location': 'bottom',
|
||||||
|
'style_external_links': False,
|
||||||
|
|
||||||
|
'logo_only': False,
|
||||||
|
|
||||||
|
# Toc options
|
||||||
|
'collapse_navigation': True,
|
||||||
|
'sticky_navigation': True,
|
||||||
|
'navigation_depth': 4,
|
||||||
|
'includehidden': True,
|
||||||
|
'titles_only': False
|
||||||
|
}
|
||||||
|
html_logo = 'static/images/logo.svg'
|
||||||
|
github_url = 'https://github.com/MaJerle/lwshell'
|
||||||
|
html_baseurl = 'https://docs.majerle.eu/projects/lwshell/'
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['static']
|
||||||
|
html_css_files = [
|
||||||
|
'css/common.css',
|
||||||
|
'css/custom.css',
|
||||||
|
]
|
||||||
|
html_js_files = [
|
||||||
|
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css'
|
||||||
|
]
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
#
|
||||||
|
# Breathe configuration
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
breathe_projects = {
|
||||||
|
"lwshell": "_build/xml/"
|
||||||
|
}
|
||||||
|
breathe_default_project = "lwshell"
|
||||||
|
breathe_default_members = ('members', 'undoc-members')
|
2456
docs/doxyfile.doxy
Normal file
2456
docs/doxyfile.doxy
Normal file
File diff suppressed because it is too large
Load Diff
37
docs/examples/index.rst
Normal file
37
docs/examples/index.rst
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
.. _examples:
|
||||||
|
|
||||||
|
Examples and demos
|
||||||
|
==================
|
||||||
|
|
||||||
|
Various examples are provided for fast library evaluation on embedded systems. These are prepared and maintained for ``2`` platforms, but could be easily extended to more platforms:
|
||||||
|
|
||||||
|
* WIN32 examples, prepared as `Visual Studio Community <https://visualstudio.microsoft.com/vs/community/>`_ projects
|
||||||
|
* ARM Cortex-M examples for STM32, prepared as `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`_ GCC projects
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
Library is platform independent and can be used on any platform.
|
||||||
|
|
||||||
|
Example architectures
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
There are many platforms available today on a market, however supporting them all would be tough task for single person.
|
||||||
|
Therefore it has been decided to support (for purpose of examples) ``2`` platforms only, `WIN32` and `STM32`.
|
||||||
|
|
||||||
|
WIN32
|
||||||
|
*****
|
||||||
|
|
||||||
|
Examples for *WIN32* are prepared as `Visual Studio Community <https://visualstudio.microsoft.com/vs/community/>`_ projects.
|
||||||
|
You can directly open project in the IDE, compile & debug.
|
||||||
|
|
||||||
|
STM32
|
||||||
|
*****
|
||||||
|
|
||||||
|
Embedded market is supported by many vendors and STMicroelectronics is, with their `STM32 <https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html>`_ series of microcontrollers, one of the most important players.
|
||||||
|
There are numerous amount of examples and topics related to this architecture.
|
||||||
|
|
||||||
|
Examples for *STM32* are natively supported with `STM32CubeIDE <https://www.st.com/en/development-tools/stm32cubeide.html>`_, an official development IDE from STMicroelectronics.
|
||||||
|
|
||||||
|
You can run examples on one of official development boards, available in repository examples.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
103
docs/get-started/index.rst
Normal file
103
docs/get-started/index.rst
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
.. _getting_started:
|
||||||
|
|
||||||
|
Getting started
|
||||||
|
===============
|
||||||
|
|
||||||
|
Getting started may be the most challenging part of every new library.
|
||||||
|
This guide is describing how to start with the library quickly and effectively
|
||||||
|
|
||||||
|
.. _download_library:
|
||||||
|
|
||||||
|
Download library
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Library is primarly hosted on `Github <https://github.com/MaJerle/lwshell>`_.
|
||||||
|
|
||||||
|
You can get it with:
|
||||||
|
|
||||||
|
* Downloading latest release from `releases area <https://github.com/MaJerle/lwshell/releases>`_ on Github
|
||||||
|
* Cloning ``master`` branch for latest stable version
|
||||||
|
* Cloning ``develop`` branch for latest development
|
||||||
|
|
||||||
|
Download from releases
|
||||||
|
**********************
|
||||||
|
|
||||||
|
All releases are available on Github `releases area <https://github.com/MaJerle/lwshell/releases>`_.
|
||||||
|
|
||||||
|
Clone from Github
|
||||||
|
*****************
|
||||||
|
|
||||||
|
First-time clone
|
||||||
|
""""""""""""""""
|
||||||
|
|
||||||
|
This is used when you do not have yet local copy on your machine.
|
||||||
|
|
||||||
|
* Make sure ``git`` is installed.
|
||||||
|
* Open console and navigate to path in the system to clone repository to. Use command ``cd your_path``
|
||||||
|
* Clone repository with one of available ``3`` options
|
||||||
|
|
||||||
|
* Run ``git clone --recurse-submodules https://github.com/MaJerle/lwshell`` command to clone entire repository, including submodules
|
||||||
|
* Run ``git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwshell`` to clone `development` branch, including submodules
|
||||||
|
* Run ``git clone --recurse-submodules --branch master https://github.com/MaJerle/lwshell`` to clone `latest stable` branch, including submodules
|
||||||
|
|
||||||
|
* Navigate to ``examples`` directory and run favourite example
|
||||||
|
|
||||||
|
Update cloned to latest version
|
||||||
|
"""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path``
|
||||||
|
* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``master`` branch
|
||||||
|
* Run ``git pull origin develop --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules on ``develop`` branch
|
||||||
|
* Run ``git submodule foreach git pull origin master`` to update & merge all submodules
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This is preferred option to use when you want to evaluate library and run prepared examples.
|
||||||
|
Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository.
|
||||||
|
|
||||||
|
Add library to project
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
At this point it is assumed that you have successfully download library, either cloned it or from releases page.
|
||||||
|
Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path
|
||||||
|
|
||||||
|
* Copy ``lwshell`` folder to your project, it contains library files
|
||||||
|
* Add ``lwshell/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag
|
||||||
|
* Add source files from ``lwshell/src/`` folder to toolchain build. These files are built by `C/C++` compiler
|
||||||
|
* Copy ``lwshell/src/include/lwshell/lwshell_opts_template.h`` to project folder and rename it to ``lwshell_opts.h``
|
||||||
|
* Build the project
|
||||||
|
|
||||||
|
Configuration file
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Configuration file is used to overwrite default settings defined for the essential use case.
|
||||||
|
Library comes with template config file, which can be modified according to needs.
|
||||||
|
and it should be copied (or simply renamed in-place) and named ``lwshell_opts.h``
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Default configuration template file location: ``lwshell/src/include/lwshell/lwshell_opts_template.h``.
|
||||||
|
File must be renamed to ``lwshell_opts.h`` first and then copied to the project directory where compiler
|
||||||
|
include paths have access to it by using ``#include "lwshell_opts.h"``.
|
||||||
|
|
||||||
|
List of configuration options are available in the :ref:`api_lwshell_opt` section.
|
||||||
|
If any option is about to be modified, it should be done in configuration file
|
||||||
|
|
||||||
|
.. literalinclude:: ../../lwshell/src/include/lwshell/lwshell_opts_template.h
|
||||||
|
:language: c
|
||||||
|
:linenos:
|
||||||
|
:caption: Template configuration file
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
If you prefer to avoid using configuration file, application must define
|
||||||
|
a global symbol ``LWSHELL_IGNORE_USER_OPTS``, visible across entire application.
|
||||||
|
This can be achieved with ``-D`` compiler option.
|
||||||
|
|
||||||
|
Minimal example code
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
To verify proper library setup, minimal example has been prepared.
|
||||||
|
Run it in your main application file to verify its proper execution
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/example_minimal.c
|
||||||
|
:language: c
|
||||||
|
:linenos:
|
||||||
|
:caption: Absolute minimum example
|
64
docs/index.rst
Normal file
64
docs/index.rst
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
LwSHELL |version| documentation
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Welcome to the documentation for version |version|.
|
||||||
|
|
||||||
|
LwSHELL is lightweight dynamic memory manager optimized for embedded systems.
|
||||||
|
|
||||||
|
.. image:: static/images/logo.svg
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
.. rst-class:: center
|
||||||
|
.. rst-class:: index_links
|
||||||
|
|
||||||
|
:ref:`download_library` :ref:`getting_started` `Open Github <https://github.com/MaJerle/lwshell>`_ `Donate <https://paypal.me/tilz0R>`_
|
||||||
|
|
||||||
|
Features
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
* Lightweight commands shell for embedded systems
|
||||||
|
* Platform independent and very easy to port
|
||||||
|
|
||||||
|
* Development of library under Win32 platform
|
||||||
|
* Written in C language (C99)
|
||||||
|
* No dynamic allocation, maximum number of commands assigned at compile time
|
||||||
|
* Highly configurable
|
||||||
|
* Simple help-text with `cmd -v` option
|
||||||
|
* User friendly MIT license
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
* C compiler
|
||||||
|
* Less than ``5kB`` of non-volatile memory
|
||||||
|
|
||||||
|
Contribute
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
Fresh contributions are always welcome. Simple instructions to proceed:
|
||||||
|
|
||||||
|
#. Fork Github repository
|
||||||
|
#. Respect `C style & coding rules <https://github.com/MaJerle/c-code-style>`_ used by the library
|
||||||
|
#. Create a pull request to ``develop`` branch with new features or bug fixes
|
||||||
|
|
||||||
|
Alternatively you may:
|
||||||
|
|
||||||
|
#. Report a bug
|
||||||
|
#. Ask for a feature request
|
||||||
|
|
||||||
|
License
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
.. literalinclude:: ../LICENSE
|
||||||
|
|
||||||
|
Table of contents
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
self
|
||||||
|
get-started/index
|
||||||
|
user-manual/index
|
||||||
|
api-reference/index
|
||||||
|
examples/index
|
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=.
|
||||||
|
set BUILDDIR=_build
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.http://sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
8
docs/requirements.txt
Normal file
8
docs/requirements.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
breathe>=4.9.1
|
||||||
|
colorama
|
||||||
|
docutils==0.16
|
||||||
|
sphinx>=3.5.1
|
||||||
|
sphinx_rtd_theme
|
||||||
|
sphinx-tabs
|
||||||
|
sphinxcontrib-svg2pdfconverter
|
||||||
|
sphinx-sitemap
|
64
docs/static/css/common.css
vendored
Normal file
64
docs/static/css/common.css
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Center aligned text */
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paragraph with main links on index page */
|
||||||
|
.index-links {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.index-links a {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #0E4263;
|
||||||
|
padding: 5px 20px;
|
||||||
|
margin: 2px 5px;
|
||||||
|
background: #2980B9;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.index-links a:hover, .index-links a:active {
|
||||||
|
background: #0E4263;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table header p w/0 margin */
|
||||||
|
.index-links a table thead th {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead th p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-nowrap td {
|
||||||
|
white-space: normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Breathe output changes */
|
||||||
|
.breathe-sectiondef.container {
|
||||||
|
background: #f9f9f9;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid #efefef;
|
||||||
|
}
|
||||||
|
.breathe-sectiondef.container .breathe-sectiondef-title {
|
||||||
|
background: #2980b9;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 4px;
|
||||||
|
margin: -10px -10px 0 -10px;
|
||||||
|
}
|
||||||
|
.breathe-sectiondef.container .function,
|
||||||
|
.breathe-sectiondef.container .member,
|
||||||
|
.breathe-sectiondef.container .class,
|
||||||
|
.breathe-sectiondef.container .type {
|
||||||
|
border-bottom: 1px solid #efefef;
|
||||||
|
}
|
||||||
|
.breathe-sectiondef.container .function:last-child,
|
||||||
|
.breathe-sectiondef.container .member:last-child,
|
||||||
|
.breathe-sectiondef.container .class:last-child,
|
||||||
|
.breathe-sectiondef.container .type:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=common.css.map */
|
0
docs/static/css/custom.css
vendored
Normal file
0
docs/static/css/custom.css
vendored
Normal file
1
docs/static/images/logo.drawio
vendored
Normal file
1
docs/static/images/logo.drawio
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="Electron" modified="2021-04-07T22:03:45.135Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.3.2 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36" etag="W7BecXTfw0RkIekNUFhW" version="12.3.2" type="device" pages="1"><diagram id="Wsjaadh77UIxB9X1bxos" name="Page-1">jZJNb4MwDIZ/DcdKQGBqr+26VhrrhUPPEXFJtISgNCx0v35hOHyomrRT4scfsV8nIgfVnwxt+YdmIKM0Zn1EXqM0TeI088dAHiPJt2QEtREMg2ZQim8ImUg7weC+CrRaSyvaNax000BlV4wao9067Kbl+tWW1vAEyorKZ3oVzPKRbvN45mcQNQ8vJzF6FA3BCO6cMu0WiBwjcjBa2/Gm+gPIQbygy5j39od3asxAY/+TcNmwDHbKFRfV7bPd+01ekw1W+aKyw4ELV56PRYE920cQwuiuYTDUSiKyd1xYKFtaDV7nV+8Zt0qi+26N/pwEe/HkphuL2yWDPakRe+N5lNAXGAv9AuFoJ9AKrHn4EPSSLB9T8J+lwXbz1pItMr7YWNgkxY9ST6VnLf0F5QzmvLZf3+Lzk+MP</diagram></mxfile>
|
3
docs/static/images/logo.svg
vendored
Normal file
3
docs/static/images/logo.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="191px" height="56px" viewBox="-0.5 -0.5 191 56" content="<mxfile host="Electron" modified="2021-04-07T22:03:50.459Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.3.2 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36" etag="Y1WfZ64eFs34UZLLlP_w" version="12.3.2" type="device" pages="1"><diagram id="Wsjaadh77UIxB9X1bxos" name="Page-1">jZJNb4MwDIZ/DcdKQGBqr+26VhrrhUPPEXFJtISgNCx0v35hOHyomrRT4scfsV8nIgfVnwxt+YdmIKM0Zn1EXqM0TeI088dAHiPJt2QEtREMg2ZQim8ImUg7weC+CrRaSyvaNax000BlV4wao9067Kbl+tWW1vAEyorKZ3oVzPKRbvN45mcQNQ8vJzF6FA3BCO6cMu0WiBwjcjBa2/Gm+gPIQbygy5j39od3asxAY/+TcNmwDHbKFRfV7bPd+01ekw1W+aKyw4ELV56PRYE920cQwuiuYTDUSiKyd1xYKFtaDV7nV+8Zt0qi+26N/pwEe/HkphuL2yWDPakRe+N5lNAXGAv9AuFoJ9AKrHn4EPSSLB9T8J+lwXbz1pItMr7YWNgkxY9ST6VnLf0F5QzmvLZf3+Lzk+MP</diagram></mxfile>"><defs/><g><rect x="3" y="3" width="185" height="50" rx="7.5" ry="7.5" fill="#ffffff" stroke="#000000" stroke-width="6" pointer-events="all"/><g transform="translate(15.5,7.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="160" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 36px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 161px; white-space: nowrap; overflow-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;white-space:normal;">LwSHELL</div></div></foreignObject><text x="80" y="39" fill="#000000" text-anchor="middle" font-size="36px" font-family="Helvetica">LwSHELL</text></switch></g></g></svg>
|
After Width: | Height: | Size: 2.0 KiB |
BIN
docs/static/images/logo_tm.png
vendored
Normal file
BIN
docs/static/images/logo_tm.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
docs/static/images/logo_tm_full.png
vendored
Normal file
BIN
docs/static/images/logo_tm_full.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
61
docs/user-manual/how-it-works.rst
Normal file
61
docs/user-manual/how-it-works.rst
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
.. _how_it_works:
|
||||||
|
|
||||||
|
How it works
|
||||||
|
============
|
||||||
|
|
||||||
|
This section describes how library works from the basic perspective.
|
||||||
|
|
||||||
|
LwSHELL is designed to accept *computer-command-like* input, in format of ``cmdname param1 "param 2 with space"``,
|
||||||
|
parse it properly and search for function callback that is assigned for specific ``cmdname``.
|
||||||
|
|
||||||
|
Library starts processing input line on *line-feed* or *carriage-return* characters.
|
||||||
|
It splits tokens by space character:
|
||||||
|
|
||||||
|
* Tokens must not include ``space`` character or it will be considered as multi-token input
|
||||||
|
* To use *space* character as token input, encapsulate character in *double-quotes*
|
||||||
|
|
||||||
|
Command structure
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Every command has assigned dedicated name and must start with it.
|
||||||
|
Application must take care to input exact command name since commands are case-sensitive, ``mycmd`` is a different command than ``Mycmd``.
|
||||||
|
|
||||||
|
Command structure looks like:
|
||||||
|
|
||||||
|
* It must start with command name and has at least one (``1``) parameter, eg. ``mycommand``. Command name is counted as first parameter
|
||||||
|
* It may have additional parameters split with *space* character
|
||||||
|
* Every input is parsed as string, even if parameter is string
|
||||||
|
|
||||||
|
.. tip::
|
||||||
|
To use space as an input, encapsulate it with *double quotes*, eg. ``mycmd param1 "param 1 has spaces"``
|
||||||
|
|
||||||
|
Register command
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Application must register command(s) to be used by the system.
|
||||||
|
This can be done using :cpp:func:`lwshell_register_cmd` function which accepts
|
||||||
|
*command name*, *command function* and optional *command description*
|
||||||
|
|
||||||
|
Command description
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Every command can have assigned its very simple description text, know as *help text*.
|
||||||
|
Description is later accessible with special command input that has ``2`` parameters in total and second is ``-h``, ``cmdname -h``.
|
||||||
|
|
||||||
|
Data output
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
To properly work with the library, application must input data to process by using :cpp:func:`lwshell_input` function.
|
||||||
|
Thanks to the library implementation, it is possible to get data feedback and be able to implement OS-like console.
|
||||||
|
|
||||||
|
To enable data-output feature, define your output callback function and assign it with :cpp:func:`lwshell_set_output_fn` function.
|
||||||
|
|
||||||
|
Data outputs works on:
|
||||||
|
|
||||||
|
* Special characters for *carriage return* and *line-feed*
|
||||||
|
* Special character *backspace* that returns set of characters to implement backspace-like event on your output
|
||||||
|
* Actual input character printed back for user feedback
|
||||||
|
* ``cmdname -h`` feature works to print simple help text
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
9
docs/user-manual/index.rst
Normal file
9
docs/user-manual/index.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.. _um:
|
||||||
|
|
||||||
|
User manual
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
how-it-works
|
31
examples/example_minimal.c
Normal file
31
examples/example_minimal.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "lwshell/lwshell.h"
|
||||||
|
|
||||||
|
/* Command to get called */
|
||||||
|
int32_t
|
||||||
|
mycmd_fn(int32_t argc, char** argv) {
|
||||||
|
printf("mycmd_fn called. Number of argv: %d\r\n", (int)argc);
|
||||||
|
for (int32_t i = 0; i < argc; ++i) {
|
||||||
|
printf("ARG[%d]: %s\r\n", (int)argc, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Successful execution */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Example code */
|
||||||
|
void
|
||||||
|
example_minimal(void) {
|
||||||
|
const char* input_str = "mycmd param1 \"param 2 with space\"";
|
||||||
|
|
||||||
|
/* Init library */
|
||||||
|
lwshell_init();
|
||||||
|
|
||||||
|
/* Define shell commands */
|
||||||
|
lwshell_register_cmd("mycmd", mycmd_fn, "Adds 2 integer numbers and prints them");
|
||||||
|
|
||||||
|
/* User input to process every character */
|
||||||
|
|
||||||
|
/* Now insert input */
|
||||||
|
lwshell_input(input_str, strlen(input_str));
|
||||||
|
}
|
137
lwshell/src/include/lwshell/lwshell.h
Normal file
137
lwshell/src/include/lwshell/lwshell.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/**
|
||||||
|
* \file lwshell.h
|
||||||
|
* \brief Lightweight shell
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Tilen MAJERLE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of LwSHELL - Lightweight shell library.
|
||||||
|
*
|
||||||
|
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||||
|
* Version: v0.1.0
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_HDR_H
|
||||||
|
#define LWSHELL_HDR_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "lwshell/lwshell_opt.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup LWSHELL Lightweight shell
|
||||||
|
* \brief Lightweight shell
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get size of statically allocated array
|
||||||
|
* \param[in] x: Object to get array size of
|
||||||
|
* \return Number of elements in array
|
||||||
|
*/
|
||||||
|
#define LWSHELL_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief LwSHELL result enumeration
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
lwshellOK = 0x00, /*!< Everything OK */
|
||||||
|
lwshellERRPAR, /*!< Parameter error */
|
||||||
|
lwshellERRMEM, /*!< Memory error */
|
||||||
|
} lwshellr_t;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
struct lwshell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Command function prototype
|
||||||
|
* \param[in] argc: Number of arguments
|
||||||
|
* \param[in] argv: Pointer to arguments
|
||||||
|
* \return `0` on success, `-1` otherwise
|
||||||
|
*/
|
||||||
|
typedef int32_t (*lwshell_cmd_fn)(int32_t argc, char** argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Callback function for character output
|
||||||
|
* \param[in] str: String to output
|
||||||
|
* \param[in] lw: LwSHELL instance
|
||||||
|
*/
|
||||||
|
typedef void (*lwshell_output_fn)(const char* str, struct lwshell* lw);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief LwSHELL main structure
|
||||||
|
*/
|
||||||
|
typedef struct lwshell {
|
||||||
|
lwshell_output_fn out_fn; /*!< Optional output function */
|
||||||
|
char buff[LWSHELL_CFG_MAX_INPUT_LEN + 1]; /*!< Shell command input buffer */
|
||||||
|
size_t buff_ptr; /*!< Buffer pointer for input */
|
||||||
|
int32_t argc; /*!< Number of arguments parsed in command */
|
||||||
|
char* argv[LWSHELL_CFG_MAX_CMD_ARGS]; /*!< Array of all arguments */
|
||||||
|
} lwshell_t;
|
||||||
|
|
||||||
|
lwshellr_t lwshell_init(void);
|
||||||
|
lwshellr_t lwshell_set_output_fn(lwshell_output_fn out_fn);
|
||||||
|
lwshellr_t lwshell_register_cmd(const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc);
|
||||||
|
lwshellr_t lwshell_input(const void* in_data, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Parse input string as `integer`
|
||||||
|
* \param[in] str: String to parse
|
||||||
|
* \return String parsed as integer
|
||||||
|
*/
|
||||||
|
#define lwshell_parse_int(str) atoi(str)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Parse input string as `double`
|
||||||
|
* \param[in] str: String to parse
|
||||||
|
* \return String parsed as `double`
|
||||||
|
*/
|
||||||
|
#define lwshell_parse_double(str) atof(str)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Parse input string as `long`
|
||||||
|
* \param[in] str: String to parse
|
||||||
|
* \return String parsed as `long`
|
||||||
|
*/
|
||||||
|
#define lwshell_parse_long(str) atol(str)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Parse input string as `long long`
|
||||||
|
* \param[in] str: String to parse
|
||||||
|
* \return String parsed as `long long`
|
||||||
|
*/
|
||||||
|
#define lwshell_parse_long_long(str) atoll(str)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* LWSHELL_HDR_H */
|
108
lwshell/src/include/lwshell/lwshell_opt.h
Normal file
108
lwshell/src/include/lwshell/lwshell_opt.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* \file lwshell_opt.h
|
||||||
|
* \brief LwSHELL options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Tilen MAJERLE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of LwSHELL - Lightweight shell library.
|
||||||
|
*
|
||||||
|
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||||
|
* Version: v0.1.0
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_HDR_OPT_H
|
||||||
|
#define LWSHELL_HDR_OPT_H
|
||||||
|
|
||||||
|
/* Uncomment to ignore user options (or set macro in compiler flags) */
|
||||||
|
/* #define LWSHELL_IGNORE_USER_OPTS */
|
||||||
|
|
||||||
|
/* Include application options */
|
||||||
|
#ifndef LWSHELL_IGNORE_USER_OPTS
|
||||||
|
#include "lwshell_opts.h"
|
||||||
|
#endif /* LWSHELL_IGNORE_USER_OPTS */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup LWSHELL_OPT Configuration
|
||||||
|
* \brief LwSHELL options
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Maximum number of different commands to be registered
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_CFG_MAX_CMDS
|
||||||
|
#define LWSHELL_CFG_MAX_CMDS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Maximum characters for command line input
|
||||||
|
*
|
||||||
|
* This includes new line character and trailing zero.
|
||||||
|
* Commands longer than this are automatically discarded
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_CFG_MAX_INPUT_LEN
|
||||||
|
#define LWSHELL_CFG_MAX_INPUT_LEN 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Maximum characters for command name
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_CFG_MAX_CMD_NAME_LEN
|
||||||
|
#define LWSHELL_CFG_MAX_CMD_NAME_LEN 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Maximum number of parameters accepted by command.
|
||||||
|
*
|
||||||
|
* Number includes command name itself
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_CFG_MAX_CMD_ARGS
|
||||||
|
#define LWSHELL_CFG_MAX_CMD_ARGS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enables `1` or disables `0` output function to
|
||||||
|
* print data from library to application.
|
||||||
|
*
|
||||||
|
* This is useful to give library feedback to user
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_CFG_USE_OUTPUT
|
||||||
|
#define LWSHELL_CFG_USE_OUTPUT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* LWSHELL_HDR_OPT_H */
|
44
lwshell/src/include/lwshell/lwshell_opts_template.h
Normal file
44
lwshell/src/include/lwshell/lwshell_opts_template.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* \file lwshell_opts_template.h
|
||||||
|
* \brief Template config file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Tilen MAJERLE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of LwSHELL - Lightweight shell library.
|
||||||
|
*
|
||||||
|
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||||
|
* Version: v0.1.0
|
||||||
|
*/
|
||||||
|
#ifndef LWSHELL_HDR_OPTS_H
|
||||||
|
#define LWSHELL_HDR_OPTS_H
|
||||||
|
|
||||||
|
/* Rename this file to "lwshell_opts.h" for your application */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open "include/lwshell/lwshell_opt.h" and
|
||||||
|
* copy & replace here settings you want to change values
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* LWSHELL_HDR_OPTS_H */
|
288
lwshell/src/lwshell/lwshell.c
Normal file
288
lwshell/src/lwshell/lwshell.c
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
/**
|
||||||
|
* \file lwshell.c
|
||||||
|
* \brief Lightweight shell
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Tilen MAJERLE
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge,
|
||||||
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* This file is part of LwSHELL - Lightweight shell library.
|
||||||
|
*
|
||||||
|
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||||
|
* Version: v0.1.0
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include "lwshell/lwshell.h"
|
||||||
|
|
||||||
|
/* Default characters */
|
||||||
|
#define LWSHELL_ASCII_NULL 0x00 /*!< Null character */
|
||||||
|
#define LWSHELL_ASCII_BACKSPACE 0x08 /*!< Backspace */
|
||||||
|
#define LWSHELL_ASCII_LF 0x0A /*!< Line feed */
|
||||||
|
#define LWSHELL_ASCII_CR 0x0D /*!< Carriage return */
|
||||||
|
#define LWSHELL_ASCII_DEL 0x7F /*!< Delete character */
|
||||||
|
#define LWSHELL_ASCII_SPACE 0x20 /*!< Space character */
|
||||||
|
|
||||||
|
#if LWSHELL_CFG_USE_OUTPUT
|
||||||
|
#define LW_OUTPUT(lw, str) do { if ((lw)->out_fn != NULL && (str) != NULL) { (lw)->out_fn((str), (lw)); }} while (0)
|
||||||
|
#else
|
||||||
|
#define LW_OUTPUT(lw, str)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Shell command structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
lwshell_cmd_fn fn; /*!< Command function to call on match */
|
||||||
|
const char* name; /*!< Command name to search for match */
|
||||||
|
const char* desc; /*!< Command description for help */
|
||||||
|
} lwshell_cmd_t;
|
||||||
|
|
||||||
|
/* Array of all commands */
|
||||||
|
static lwshell_cmd_t cmds[LWSHELL_CFG_MAX_CMDS];
|
||||||
|
static size_t cmds_cnt;
|
||||||
|
static lwshell_t shell;
|
||||||
|
|
||||||
|
/* Get shell instance from input */
|
||||||
|
#define LWSHELL_GET_LW(lw) ((lw) != NULL ? (lw) : (&shell))
|
||||||
|
|
||||||
|
/* Add character to instance */
|
||||||
|
#define LWSHELL_ADD_CH(lw, ch) do { \
|
||||||
|
if ((lw)->buff_ptr < (LWSHELL_ARRAYSIZE(lw->buff) - 1)) { \
|
||||||
|
(lw)->buff[(lw)->buff_ptr] = ch; \
|
||||||
|
(lw)->buff[++(lw)->buff_ptr] = '\0'; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Reset buffers */
|
||||||
|
#define LWSHELL_RESET_BUFF(lw) do { \
|
||||||
|
memset((lw)->buff, 0x00, sizeof((lw)->buff)); \
|
||||||
|
memset((lw)->argv, 0x00, sizeof((lw)->argv)); \
|
||||||
|
(lw)->buff_ptr = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Parse input string
|
||||||
|
* \param[in] lw: LwSHELL instance
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
prv_parse_input(lwshell_t* lw) {
|
||||||
|
size_t s_len;
|
||||||
|
char ch, prev_ch;
|
||||||
|
char* str;
|
||||||
|
|
||||||
|
lw = LWSHELL_GET_LW(lw);
|
||||||
|
|
||||||
|
/* Check string length and compare */
|
||||||
|
s_len = strlen(lw->buff);
|
||||||
|
if (lw->buff_ptr != s_len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be more than `1` character since we have to include end of line */
|
||||||
|
if (lw->buff_ptr > 0) {
|
||||||
|
uint8_t in_quote = 0;
|
||||||
|
|
||||||
|
/* Set default values */
|
||||||
|
lw->argc = 0;
|
||||||
|
lw->argv[0] = lw->buff;
|
||||||
|
|
||||||
|
/* Process complete input */
|
||||||
|
prev_ch = '\0';
|
||||||
|
str = lw->buff;
|
||||||
|
|
||||||
|
/* Process complete string */
|
||||||
|
lw->argc = 0;
|
||||||
|
while (*str != '\0') {
|
||||||
|
while (*str == ' ' && ++str) {} /* Remove leading spaces */
|
||||||
|
if (*str == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if it starts with quote to handle escapes */
|
||||||
|
if (*str == '"') {
|
||||||
|
++str;
|
||||||
|
lw->argv[lw->argc++] = str; /* Set start of argument after quotes */
|
||||||
|
|
||||||
|
/* Process until end of quote */
|
||||||
|
while (*str != '\0') {
|
||||||
|
if (*str == '\\') {
|
||||||
|
++str;
|
||||||
|
if (*str == '"') {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
} else if (*str == '"') {
|
||||||
|
*str = '\0';
|
||||||
|
++str;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lw->argv[lw->argc++] = str; /* Set start of argument directly on character */
|
||||||
|
while ((*str != ' ' && *str != '\0')) {
|
||||||
|
if (*str == '"') { /* Quote should not be here... */
|
||||||
|
*str = '\0'; /* ...add NULL termination to end token */
|
||||||
|
}
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for number of arguments */
|
||||||
|
if (lw->argc == LWSHELL_ARRAYSIZE(lw->argv)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for command */
|
||||||
|
if (lw->argc > 0 && cmds_cnt > 0) {
|
||||||
|
lwshell_cmd_t* c = NULL;
|
||||||
|
/* Process all commands */
|
||||||
|
for (size_t i = 0; i < cmds_cnt; ++i) {
|
||||||
|
if (strncmp(cmds[i].name, lw->argv[0], strlen(lw->argv[0])) == 0) {
|
||||||
|
c = &cmds[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Valid command ready? */
|
||||||
|
if (c != NULL) {
|
||||||
|
if (lw->argc == 2
|
||||||
|
&& lw->argv[1][0] == '-' && lw->argv[1][1] == 'h' && lw->argv[1][2] == '\0') {
|
||||||
|
/* Here we can print version */
|
||||||
|
LW_OUTPUT(lw, c->desc);
|
||||||
|
LW_OUTPUT(lw, "\r\n");
|
||||||
|
} else {
|
||||||
|
c->fn(lw->argc, lw->argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize shell interface
|
||||||
|
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||||
|
*/
|
||||||
|
lwshellr_t
|
||||||
|
lwshell_init(void) {
|
||||||
|
lwshell_t* lw = LWSHELL_GET_LW(NULL);
|
||||||
|
memset(lw, 0x00, sizeof(*lw));
|
||||||
|
return lwshellOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWSHELL_CFG_USE_OUTPUT || __DOXYGEN__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set output function to use to print data from library to user
|
||||||
|
* \param[in] out_fn: Output function to print library data.
|
||||||
|
* Set to `NULL` to disable the feature
|
||||||
|
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||||
|
*/
|
||||||
|
lwshellr_t
|
||||||
|
lwshell_set_output_fn(lwshell_output_fn out_fn) {
|
||||||
|
lwshell_t* lw = LWSHELL_GET_LW(NULL);
|
||||||
|
lw->out_fn = out_fn;
|
||||||
|
return lwshellOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWSHELL_CFG_USE_OUTPUT || __DOXYGEN__ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Register new command to shell
|
||||||
|
* \param[in] cmd_name: Command name. This one is used when entering shell command
|
||||||
|
* \param[in] cmd_fn: Function to call on command match
|
||||||
|
* \param[in] desc: Custom command description
|
||||||
|
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||||
|
*/
|
||||||
|
lwshellr_t
|
||||||
|
lwshell_register_cmd(const char* cmd_name, lwshell_cmd_fn cmd_fn, const char* desc) {
|
||||||
|
if (cmd_name == NULL || cmd_fn == NULL
|
||||||
|
|| strlen(cmd_name) == 0) {
|
||||||
|
return lwshellERRPAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for memory available */
|
||||||
|
if (cmds_cnt < LWSHELL_ARRAYSIZE(cmds)) {
|
||||||
|
cmds[cmds_cnt].name = cmd_name;
|
||||||
|
cmds[cmds_cnt].fn = cmd_fn;
|
||||||
|
cmds[cmds_cnt].desc = desc;
|
||||||
|
|
||||||
|
++cmds_cnt;
|
||||||
|
return lwshellOK;
|
||||||
|
}
|
||||||
|
return lwshellERRMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Input data to shell processing
|
||||||
|
* \param[in] in_data: Input data to process
|
||||||
|
* \param[in] len: Length of data for input
|
||||||
|
* \return \ref lwshellOK on success, member of \ref lwshellr_t otherwise
|
||||||
|
*/
|
||||||
|
lwshellr_t
|
||||||
|
lwshell_input(const void* in_data, size_t len) {
|
||||||
|
const char* d = in_data;
|
||||||
|
lwshell_t* lw = LWSHELL_GET_LW(NULL);
|
||||||
|
|
||||||
|
if (in_data == NULL || len == 0) {
|
||||||
|
return lwshellERRPAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process all bytes */
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
switch (d[i]) {
|
||||||
|
case LWSHELL_ASCII_CR: {
|
||||||
|
LW_OUTPUT(lw, "\r");
|
||||||
|
prv_parse_input(lw);
|
||||||
|
LWSHELL_RESET_BUFF(lw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LWSHELL_ASCII_LF: {
|
||||||
|
LW_OUTPUT(lw, "\n");
|
||||||
|
prv_parse_input(lw);
|
||||||
|
LWSHELL_RESET_BUFF(lw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LWSHELL_ASCII_BACKSPACE: {
|
||||||
|
/* Try to delete character from buffer */
|
||||||
|
if (lw->buff_ptr > 0) {
|
||||||
|
lw->buff[lw->buff_ptr] = '\0';
|
||||||
|
--lw->buff_ptr;
|
||||||
|
LW_OUTPUT(lw, "\b \b");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
char str[2] = { d[i] };
|
||||||
|
LW_OUTPUT(lw, str);
|
||||||
|
if (d[i] >= 0x20 && d[i] < 0x7F) {
|
||||||
|
LWSHELL_ADD_CH(lw, d[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lwshellOK;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user