mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-16 19:54:38 +01:00
commit
856a046e61
33
FSM/FSM_vs120.sln
Normal file
33
FSM/FSM_vs120.sln
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Express 2013 for Windows Desktop
|
||||||
|
VisualStudioVersion = 12.0.40629.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FMSc", "FSMc_vs120.vcxproj", "{E12E5C71-79A4-495A-848F-F1710111E610}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
debug_shared|Win32 = debug_shared|Win32
|
||||||
|
debug_static_md|Win32 = debug_static_md|Win32
|
||||||
|
debug_static_mt|Win32 = debug_static_mt|Win32
|
||||||
|
release_shared|Win32 = release_shared|Win32
|
||||||
|
release_static_md|Win32 = release_static_md|Win32
|
||||||
|
release_static_mt|Win32 = release_static_mt|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_shared|Win32.Build.0 = debug_shared|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_static_md|Win32.Build.0 = debug_static_md|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_shared|Win32.ActiveCfg = release_shared|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_shared|Win32.Build.0 = release_shared|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_static_md|Win32.ActiveCfg = release_static_md|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_static_md|Win32.Build.0 = release_static_md|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32
|
||||||
|
{E12E5C71-79A4-495A-848F-F1710111E610}.release_static_mt|Win32.Build.0 = release_static_mt|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
367
FSM/FSMc_vs120.vcxproj
Normal file
367
FSM/FSMc_vs120.vcxproj
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="debug_shared|Win32">
|
||||||
|
<Configuration>debug_shared</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="debug_static_md|Win32">
|
||||||
|
<Configuration>debug_static_md</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="debug_static_mt|Win32">
|
||||||
|
<Configuration>debug_static_mt</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="release_shared|Win32">
|
||||||
|
<Configuration>release_shared</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="release_static_md|Win32">
|
||||||
|
<Configuration>release_static_md</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="release_static_mt|Win32">
|
||||||
|
<Configuration>release_static_mt</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="src\parser\BNF.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Action.cpp" />
|
||||||
|
<ClCompile Include="src\ActionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Actions.cpp" />
|
||||||
|
<ClCompile Include="src\Argument.cpp" />
|
||||||
|
<ClCompile Include="src\ArgumentForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\BinaryOperation.cpp" />
|
||||||
|
<ClCompile Include="src\BinaryOperationForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Character.cpp" />
|
||||||
|
<ClCompile Include="src\Comment.cpp" />
|
||||||
|
<ClCompile Include="src\CompilableForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Dumper.cpp" />
|
||||||
|
<ClCompile Include="src\Element.cpp" />
|
||||||
|
<ClCompile Include="src\ElementForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Entry.cpp" />
|
||||||
|
<ClCompile Include="src\EntryForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Exit.cpp" />
|
||||||
|
<ClCompile Include="src\ExitForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Expression.cpp" />
|
||||||
|
<ClCompile Include="src\ExpressionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\FactoryForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\FSM.cpp" />
|
||||||
|
<ClCompile Include="src\fsmc.cpp" />
|
||||||
|
<ClCompile Include="src\FSMForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Function.cpp" />
|
||||||
|
<ClCompile Include="src\FunctionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Guard.cpp" />
|
||||||
|
<ClCompile Include="src\GuardForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Identifier.cpp" />
|
||||||
|
<ClCompile Include="src\IndentStream.cpp" />
|
||||||
|
<ClCompile Include="src\Keyword.cpp" />
|
||||||
|
<ClCompile Include="src\Literal.cpp" />
|
||||||
|
<ClCompile Include="src\LiteralForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Map.cpp" />
|
||||||
|
<ClCompile Include="src\MapForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Number.cpp" />
|
||||||
|
<ClCompile Include="src\Operation.cpp" />
|
||||||
|
<ClCompile Include="src\Operator.cpp" />
|
||||||
|
<ClCompile Include="src\Parameter.cpp" />
|
||||||
|
<ClCompile Include="src\ParameterForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Parser.cpp" />
|
||||||
|
<ClCompile Include="src\Print.cpp" />
|
||||||
|
<ClCompile Include="src\Reference.cpp" />
|
||||||
|
<ClCompile Include="src\ReferenceForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\State.cpp" />
|
||||||
|
<ClCompile Include="src\StateForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\String.cpp" />
|
||||||
|
<ClCompile Include="src\Token.cpp" />
|
||||||
|
<ClCompile Include="src\Tokenizer.cpp" />
|
||||||
|
<ClCompile Include="src\Transition.cpp" />
|
||||||
|
<ClCompile Include="src\TransitionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\UnaryOperation.cpp" />
|
||||||
|
<ClCompile Include="src\UnaryOperationForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Variable.cpp" />
|
||||||
|
<ClCompile Include="src\VariableForCpp.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectName>FSMc</ProjectName>
|
||||||
|
<ProjectGuid>{E12E5C71-79A4-495A-848F-F1710111E610}</ProjectGuid>
|
||||||
|
<RootNamespace>FSMc</RootNamespace>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings" />
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="PropertySheets">
|
||||||
|
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>12.0.30501.0</_ProjectFileVersion>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">$(ProjectName)d</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">$(ProjectName)d</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">$(ProjectName)d</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">$(ProjectName)</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">$(ProjectName)</TargetName>
|
||||||
|
<TargetName Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">$(ProjectName)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">
|
||||||
|
<OutDir>bin\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">
|
||||||
|
<OutDir>bin\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">
|
||||||
|
<OutDir>bin\static_mt\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">
|
||||||
|
<OutDir>bin\static_mt\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">
|
||||||
|
<OutDir>bin\static_md\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">
|
||||||
|
<OutDir>bin\static_md\</OutDir>
|
||||||
|
<IntDir>obj\$(ProjectName)\$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>bin\$(TargetName).pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat />
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\static_mt\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>bin\static_mt\$(TargetName).pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat />
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\static_mt\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\static_md\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<ProgramDatabaseFile>bin\static_md\$(TargetName).pdb</ProgramDatabaseFile>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
|
<OmitFramePointers>true</OmitFramePointers>
|
||||||
|
<AdditionalIncludeDirectories>src;.\include;..\Foundation\include;..\XML\include;..\Util\include;..\Net\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||||
|
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||||
|
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||||
|
<PrecompiledHeader />
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat />
|
||||||
|
<CompileAs>Default</CompileAs>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>iphlpapi.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<OutputFile>bin\static_md\$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
<AdditionalLibraryDirectories>..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
|
</Project>
|
75
FSM/FSMc_vs120.vcxproj.filters
Normal file
75
FSM/FSMc_vs120.vcxproj.filters
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="model">
|
||||||
|
<UniqueIdentifier>{60fd8794-fb4f-47a7-822e-b7eeaedaa5bc}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="parser">
|
||||||
|
<UniqueIdentifier>{718e55ba-57a5-460a-b9d6-2cc3e8e17da9}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="cpp">
|
||||||
|
<UniqueIdentifier>{a8451f20-ad5b-42c6-8137-7d9f5f4dc222}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="src\parser\BNF.txt">
|
||||||
|
<Filter>parser</Filter>
|
||||||
|
</Text>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Action.cpp" />
|
||||||
|
<ClCompile Include="src\ActionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Actions.cpp" />
|
||||||
|
<ClCompile Include="src\Argument.cpp" />
|
||||||
|
<ClCompile Include="src\ArgumentForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\BinaryOperation.cpp" />
|
||||||
|
<ClCompile Include="src\BinaryOperationForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Character.cpp" />
|
||||||
|
<ClCompile Include="src\Comment.cpp" />
|
||||||
|
<ClCompile Include="src\CompilableForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Dumper.cpp" />
|
||||||
|
<ClCompile Include="src\Element.cpp" />
|
||||||
|
<ClCompile Include="src\ElementForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Entry.cpp" />
|
||||||
|
<ClCompile Include="src\EntryForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Exit.cpp" />
|
||||||
|
<ClCompile Include="src\ExitForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Expression.cpp" />
|
||||||
|
<ClCompile Include="src\ExpressionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\FactoryForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\FSM.cpp" />
|
||||||
|
<ClCompile Include="src\fsmc.cpp" />
|
||||||
|
<ClCompile Include="src\FSMForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Function.cpp" />
|
||||||
|
<ClCompile Include="src\FunctionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Guard.cpp" />
|
||||||
|
<ClCompile Include="src\GuardForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Identifier.cpp" />
|
||||||
|
<ClCompile Include="src\IndentStream.cpp" />
|
||||||
|
<ClCompile Include="src\Keyword.cpp" />
|
||||||
|
<ClCompile Include="src\Literal.cpp" />
|
||||||
|
<ClCompile Include="src\LiteralForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Map.cpp" />
|
||||||
|
<ClCompile Include="src\MapForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Number.cpp" />
|
||||||
|
<ClCompile Include="src\Operation.cpp" />
|
||||||
|
<ClCompile Include="src\Operator.cpp" />
|
||||||
|
<ClCompile Include="src\Parameter.cpp" />
|
||||||
|
<ClCompile Include="src\ParameterForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Parser.cpp" />
|
||||||
|
<ClCompile Include="src\Print.cpp" />
|
||||||
|
<ClCompile Include="src\Reference.cpp" />
|
||||||
|
<ClCompile Include="src\ReferenceForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\State.cpp" />
|
||||||
|
<ClCompile Include="src\StateForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\String.cpp" />
|
||||||
|
<ClCompile Include="src\Token.cpp" />
|
||||||
|
<ClCompile Include="src\Tokenizer.cpp" />
|
||||||
|
<ClCompile Include="src\Transition.cpp" />
|
||||||
|
<ClCompile Include="src\TransitionForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\UnaryOperation.cpp" />
|
||||||
|
<ClCompile Include="src\UnaryOperationForCpp.cpp" />
|
||||||
|
<ClCompile Include="src\Variable.cpp" />
|
||||||
|
<ClCompile Include="src\VariableForCpp.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
77
FSM/Makefile
Normal file
77
FSM/Makefile
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# $Id: //poco/1.4/FSM/Makefile#1 $
|
||||||
|
#
|
||||||
|
# Makefile for Poco C++ Finite State Machine Compiler
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/rules/global
|
||||||
|
INCLUDE += -Isrc
|
||||||
|
CXXFLAGS += -std=c++11 -fno-operator-names
|
||||||
|
|
||||||
|
objects = \
|
||||||
|
Action \
|
||||||
|
ActionForCpp \
|
||||||
|
Actions \
|
||||||
|
Argument \
|
||||||
|
ArgumentForCpp \
|
||||||
|
BinaryOperation \
|
||||||
|
BinaryOperationForCpp \
|
||||||
|
Character \
|
||||||
|
Comment \
|
||||||
|
CompilableForCpp \
|
||||||
|
Dumper \
|
||||||
|
Element \
|
||||||
|
ElementForCpp \
|
||||||
|
Entry \
|
||||||
|
EntryForCpp \
|
||||||
|
Exit \
|
||||||
|
ExitForCpp \
|
||||||
|
Expression \
|
||||||
|
ExpressionForCpp \
|
||||||
|
FactoryForCpp \
|
||||||
|
FSM \
|
||||||
|
fsmc \
|
||||||
|
FSMForCpp \
|
||||||
|
Function \
|
||||||
|
FunctionForCpp \
|
||||||
|
Guard \
|
||||||
|
GuardForCpp \
|
||||||
|
Identifier \
|
||||||
|
IndentStream \
|
||||||
|
Keyword \
|
||||||
|
Literal \
|
||||||
|
LiteralForCpp \
|
||||||
|
Map \
|
||||||
|
MapForCpp \
|
||||||
|
Number \
|
||||||
|
Operation \
|
||||||
|
Operator \
|
||||||
|
Parameter \
|
||||||
|
ParameterForCpp \
|
||||||
|
Parser \
|
||||||
|
Print \
|
||||||
|
Reference \
|
||||||
|
ReferenceForCpp \
|
||||||
|
State \
|
||||||
|
StateForCpp \
|
||||||
|
String \
|
||||||
|
Token \
|
||||||
|
Tokenizer \
|
||||||
|
Transition \
|
||||||
|
TransitionForCpp \
|
||||||
|
UnaryOperation \
|
||||||
|
UnaryOperationForCpp \
|
||||||
|
Variable \
|
||||||
|
VariableForCpp
|
||||||
|
|
||||||
|
ifdef POCO_UNBUNDLED
|
||||||
|
SYSLIBS += -lz -lpcre -lexpat
|
||||||
|
endif
|
||||||
|
|
||||||
|
target = fsmc
|
||||||
|
target_version = 1
|
||||||
|
target_libs = PocoUtil PocoXML PocoJSON PocoFoundation
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/rules/exec
|
BIN
FSM/SMC Manual_6_6_0.pdf
Normal file
BIN
FSM/SMC Manual_6_6_0.pdf
Normal file
Binary file not shown.
BIN
FSM/SmcMan_6_6_0.tgz
Normal file
BIN
FSM/SmcMan_6_6_0.tgz
Normal file
Binary file not shown.
19
FSM/fsmc.properties
Normal file
19
FSM/fsmc.properties
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
logging.loggers.root.channel.class = ConsoleChannel
|
||||||
|
|
||||||
|
logging.formatters.full.class = PatternFormatter
|
||||||
|
logging.formatters.full.pattern = %Y-%m-%d %H:%M:%S %s: [%q] %t
|
||||||
|
|
||||||
|
logging.channels.console.class = ConsoleChannel
|
||||||
|
logging.channels.console.formatter = full
|
||||||
|
|
||||||
|
logging.channels.fsmc.class = FileChannel
|
||||||
|
logging.channels.fsmc.path = fsmc.log
|
||||||
|
logging.channels.fsmc.formatter = full
|
||||||
|
|
||||||
|
logging.channels.log.class = SplitterChannel
|
||||||
|
logging.channels.log.channels = console,fsmc
|
||||||
|
|
||||||
|
logging.loggers.fsmc.name = fsmc
|
||||||
|
logging.loggers.fsmc.channel = fsmc
|
||||||
|
logging.loggers.fsmc.level = debug
|
||||||
|
|
712
FSM/include/Poco/FSM/statemap.h
Normal file
712
FSM/include/Poco/FSM/statemap.h
Normal file
@ -0,0 +1,712 @@
|
|||||||
|
#ifndef _H_STATEMAP
|
||||||
|
#define _H_STATEMAP
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Namespace
|
||||||
|
// statemap
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// This namespace contains the finite state machine context
|
||||||
|
// class. The user can derive FSM contexts from this class and
|
||||||
|
// interface to them with the methods of this class.
|
||||||
|
//
|
||||||
|
// Notes
|
||||||
|
// The finite state machine needs to be initialized to the
|
||||||
|
// starting state of the FSM. This must be done manually in
|
||||||
|
// the constructor of the derived class.
|
||||||
|
//
|
||||||
|
// Author
|
||||||
|
// C. W. Rapp
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// Id: statemap.h,v 1.19 2014/09/06 19:31:28 fperrad Exp
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// (See bottom of file)
|
||||||
|
//
|
||||||
|
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
#if defined(SMC_USES_IOSTREAMS)
|
||||||
|
#include <iostream>
|
||||||
|
#endif // SMC_USES_IOSTREAMS
|
||||||
|
#if defined(SMC_NO_EXCEPTIONS)
|
||||||
|
#include <cassert>
|
||||||
|
#endif // SMC_NO_EXCEPTIONS
|
||||||
|
#include <cstdio>
|
||||||
|
#elif defined(WIN32)
|
||||||
|
#if defined(SMC_NO_EXCEPTIONS)
|
||||||
|
#include <cassert>
|
||||||
|
#endif // SMC_NO_EXCEPTIONS
|
||||||
|
#else
|
||||||
|
#if defined(SMC_NO_EXCEPTIONS)
|
||||||
|
#include <assert.h>
|
||||||
|
#endif // SMC_NO_EXCEPTIONS
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
#if ! defined(SMC_NO_EXCEPTIONS)
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <cstring>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_NAME_LEN 32
|
||||||
|
|
||||||
|
namespace statemap {
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Routines.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
// When static memory is used, a string has only one copy.
|
||||||
|
inline char* copyString(const char *s) {
|
||||||
|
// Cast your const upon the waters and see what blows up.
|
||||||
|
return (const_cast<char *>(s));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline char* copyString(const char *s) {
|
||||||
|
char *retval = nullptr;
|
||||||
|
|
||||||
|
if (s != nullptr) {
|
||||||
|
retval = new char[MAX_NAME_LEN + 1];
|
||||||
|
retval[MAX_NAME_LEN] = '\0';
|
||||||
|
(void) std::strncpy(retval, s, MAX_NAME_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Exception Classes.
|
||||||
|
//
|
||||||
|
|
||||||
|
//#define SMC_NO_EXCEPTIONS
|
||||||
|
#ifndef SMC_NO_EXCEPTIONS
|
||||||
|
// Base class for all SMC exceptions.
|
||||||
|
class SmcException : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~SmcException() throw() {
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SmcException(const std::string& reason)
|
||||||
|
: std::runtime_error(reason) {
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
SmcException();
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
class PushOnFullStateStackException :
|
||||||
|
public SmcException {
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
// Member methods.
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
PushOnFullStateStackException()
|
||||||
|
: SmcException("cannot push on full state stack") {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~PushOnFullStateStackException() throw() {
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
// Member data.
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This class is thrown when a pop is issued on an empty
|
||||||
|
// state stack.
|
||||||
|
class PopOnEmptyStateStackException :
|
||||||
|
public SmcException {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
PopOnEmptyStateStackException()
|
||||||
|
: SmcException("no state to pop from state stack") {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~PopOnEmptyStateStackException() throw() {
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class is thrown when a transition is issued
|
||||||
|
// but there is no current state. This happens when
|
||||||
|
// a transition is issued from within a transition
|
||||||
|
// action.
|
||||||
|
class StateUndefinedException :
|
||||||
|
public SmcException {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
StateUndefinedException()
|
||||||
|
: SmcException("transition invoked while in transition") {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~StateUndefinedException() throw() {
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class is thrown when a transition is issued
|
||||||
|
// but there is no code to handle it.
|
||||||
|
class TransitionUndefinedException :
|
||||||
|
public SmcException {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
TransitionUndefinedException()
|
||||||
|
: SmcException("no such transition in current state"),
|
||||||
|
_state(nullptr),
|
||||||
|
_transition(nullptr) {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct an exception using the specified state
|
||||||
|
// and transition.
|
||||||
|
TransitionUndefinedException(const char *state,
|
||||||
|
const char *transition)
|
||||||
|
: SmcException("no such transition in current state"),
|
||||||
|
_state(copyString(state)),
|
||||||
|
_transition(copyString(transition)) {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy constructor.
|
||||||
|
TransitionUndefinedException(
|
||||||
|
const TransitionUndefinedException& ex)
|
||||||
|
: SmcException("no such transition in current state"),
|
||||||
|
_state(copyString(ex._state)),
|
||||||
|
_transition(copyString(ex._transition)) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~TransitionUndefinedException() throw() {
|
||||||
|
if (_state != nullptr) {
|
||||||
|
delete[] _state;
|
||||||
|
_state = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_transition != nullptr) {
|
||||||
|
delete[] _transition;
|
||||||
|
_transition = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const TransitionUndefinedException&
|
||||||
|
operator=(const TransitionUndefinedException& ex) {
|
||||||
|
// Don't do self assignment.
|
||||||
|
if (this != &ex) {
|
||||||
|
if (_state != nullptr) {
|
||||||
|
delete[] _state;
|
||||||
|
_state = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_transition != nullptr) {
|
||||||
|
delete[] _transition;
|
||||||
|
_transition = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
_state = copyString(ex._state);
|
||||||
|
_transition = copyString(ex._transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the state. May be nullptr.
|
||||||
|
const char* getState() const {
|
||||||
|
return(_state);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the transition. May be nullptr.
|
||||||
|
const char* getTransition() const {
|
||||||
|
return (_transition);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *_state;
|
||||||
|
char *_transition;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class is thrown when a state ID is either less than
|
||||||
|
// the minimal value or greater than the maximal value.
|
||||||
|
class IndexOutOfBoundsException :
|
||||||
|
public SmcException {
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexOutOfBoundsException()
|
||||||
|
: SmcException("index out of bounds"),
|
||||||
|
_index(0),
|
||||||
|
_minIndex(0),
|
||||||
|
_maxIndex(0) {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Constructs an exception using the specified index,
|
||||||
|
// minimum index and maximum index.
|
||||||
|
IndexOutOfBoundsException(const int index,
|
||||||
|
const int minIndex,
|
||||||
|
const int maxIndex)
|
||||||
|
: SmcException("index out of bounds"),
|
||||||
|
_index(index),
|
||||||
|
_minIndex(minIndex),
|
||||||
|
_maxIndex(maxIndex) {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy constructor.
|
||||||
|
IndexOutOfBoundsException(
|
||||||
|
const IndexOutOfBoundsException& ex)
|
||||||
|
: SmcException("index out of bounds"),
|
||||||
|
_index(ex._index),
|
||||||
|
_minIndex(ex._minIndex),
|
||||||
|
_maxIndex(ex._maxIndex) {
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~IndexOutOfBoundsException() throw() {
|
||||||
|
};
|
||||||
|
|
||||||
|
const IndexOutOfBoundsException&
|
||||||
|
operator=(const IndexOutOfBoundsException& ex) {
|
||||||
|
// Don't do self assignment.
|
||||||
|
if (this != &ex) {
|
||||||
|
_index = ex._index;
|
||||||
|
_minIndex = ex._minIndex;
|
||||||
|
_maxIndex = ex._maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the out-of-bounds index.
|
||||||
|
int getIndex() const {
|
||||||
|
return(_index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the minimum allowed index value.
|
||||||
|
int getMinIndex() const {
|
||||||
|
return (_minIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the maximum allowed index value.
|
||||||
|
int getMaxIndex() const {
|
||||||
|
return (_maxIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _index;
|
||||||
|
int _minIndex;
|
||||||
|
int _maxIndex;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// end of Exception Classes.
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
class State {
|
||||||
|
public:
|
||||||
|
const char* getName() const {
|
||||||
|
return (_name);
|
||||||
|
};
|
||||||
|
|
||||||
|
int getId() const {
|
||||||
|
return (_stateId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
State() = delete;
|
||||||
|
State(const State&) = delete;
|
||||||
|
|
||||||
|
State(const char *name, int stateId)
|
||||||
|
: _name(nullptr),
|
||||||
|
_stateId(stateId) {
|
||||||
|
if (name != nullptr) {
|
||||||
|
_name = copyString(name);
|
||||||
|
} else {
|
||||||
|
_name = copyString("NAME NOT SET");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~State() {
|
||||||
|
#ifndef SMC_FIXED_STACK
|
||||||
|
if (_name != nullptr) {
|
||||||
|
delete[] _name;
|
||||||
|
_name = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
char *_name; // This state's printable name.
|
||||||
|
int _stateId; // This state's unique identifier.
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Event {
|
||||||
|
Enter,
|
||||||
|
Leave,
|
||||||
|
Switch,
|
||||||
|
Transition,
|
||||||
|
Push,
|
||||||
|
Pop
|
||||||
|
};
|
||||||
|
|
||||||
|
class Notifier {
|
||||||
|
public:
|
||||||
|
virtual void operator()(const Event& event, const char* s) = 0;
|
||||||
|
virtual void operator()(const Event& event, const State* state) = 0;
|
||||||
|
virtual void operator()(const Event& event, const State* previous, const State* next) = 0;
|
||||||
|
};
|
||||||
|
class FSMContext {
|
||||||
|
private:
|
||||||
|
class StateEntry {
|
||||||
|
public:
|
||||||
|
StateEntry(State *state, StateEntry *next)
|
||||||
|
: _state(state),
|
||||||
|
_next(next) {
|
||||||
|
};
|
||||||
|
|
||||||
|
~StateEntry() {
|
||||||
|
_state = nullptr;
|
||||||
|
_next = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
State* getState() {
|
||||||
|
return(_state);
|
||||||
|
};
|
||||||
|
|
||||||
|
const State* getState() const {
|
||||||
|
return(_state);
|
||||||
|
};
|
||||||
|
|
||||||
|
StateEntry* getNext() {
|
||||||
|
return(_next);
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
State *_state;
|
||||||
|
StateEntry *_next;
|
||||||
|
|
||||||
|
friend class FSMContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~FSMContext() {
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
_transition = nullptr;
|
||||||
|
#else // ! SMC_FIXED_STACK
|
||||||
|
StateEntry *state;
|
||||||
|
|
||||||
|
if (_transition != nullptr) {
|
||||||
|
delete[] _transition;
|
||||||
|
_transition = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// But we did allocate the state stack.
|
||||||
|
while (_state_stack != nullptr) {
|
||||||
|
state = _state_stack;
|
||||||
|
_state_stack = _state_stack->_next;
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
#endif // ! SMC_FIXED_STACK
|
||||||
|
};
|
||||||
|
|
||||||
|
FSMContext& operator=(const FSMContext& fsm) {
|
||||||
|
// Don't do the assignment if the left and right
|
||||||
|
// hand sides are the same object.
|
||||||
|
if (this != &fsm) {
|
||||||
|
_state = fsm._state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(*this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Starts the finite state machine running by executing
|
||||||
|
// the initial state's entry actions.
|
||||||
|
virtual void enterStartState()=0;
|
||||||
|
|
||||||
|
// Exact same object (is it me?)
|
||||||
|
int same(const FSMContext& fsm) const {
|
||||||
|
return(this == &fsm);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool getDebugFlag() {
|
||||||
|
return(_debug_flag);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setDebugFlag(bool flag) {
|
||||||
|
_debug_flag = flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is this state machine already inside a transition?
|
||||||
|
// Yes if state is null.
|
||||||
|
bool isInTransition() const {
|
||||||
|
return(_state == nullptr ? true : false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the current transition's name.
|
||||||
|
// Used only for debugging purposes.
|
||||||
|
char* getTransition() const {
|
||||||
|
return (_transition);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Saves away the transition name only if debugging
|
||||||
|
// is turned on.
|
||||||
|
void setTransition(const char *transition) {
|
||||||
|
#ifndef SMC_FIXED_STACK
|
||||||
|
if (_transition != nullptr) {
|
||||||
|
delete[] _transition;
|
||||||
|
_transition = nullptr;
|
||||||
|
}
|
||||||
|
#endif // ! SMC_FIXED_STACK
|
||||||
|
|
||||||
|
_transition = copyString(transition);
|
||||||
|
if (getDebugFlag() && transition)
|
||||||
|
_notify(Event::Transition, transition);
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clears the current state.
|
||||||
|
void clearState() {
|
||||||
|
_previous_state = _state;
|
||||||
|
_state = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the state which a transition left.
|
||||||
|
// May be nullptr.
|
||||||
|
State* getPreviousState() {
|
||||||
|
return (_previous_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the current state to the specified state.
|
||||||
|
void setState(const State& state) {
|
||||||
|
// clearState() is not called when a transition has
|
||||||
|
// no actions, so set _previous_state to _state in
|
||||||
|
// that situation. We know clearState() was not
|
||||||
|
// called when _state is not null.
|
||||||
|
if (_state != nullptr) {
|
||||||
|
if (_debug_flag) {
|
||||||
|
_notify(Event::Leave, _state);
|
||||||
|
}
|
||||||
|
_previous_state = _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
_state = const_cast<State *>(&state);
|
||||||
|
|
||||||
|
if (_debug_flag) {
|
||||||
|
_notify(Event::Switch, _previous_state, _state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
// Returns true if the state stack is empty and false
|
||||||
|
// otherwise.
|
||||||
|
bool isStateStackEmpty() const {
|
||||||
|
return (_state_stack_depth == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the state stack's depth.
|
||||||
|
int getStateStackDepth() const {
|
||||||
|
return (_state_stack_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the current state on top of the state stack
|
||||||
|
// and make the specified state the current state.
|
||||||
|
void pushState(const State& state) {
|
||||||
|
#ifdef SMC_NO_EXCEPTIONS
|
||||||
|
assert (_state_stack_depth < SMC_STATE_STACK_SIZE);
|
||||||
|
#else
|
||||||
|
if (_state_stack_depth == SMC_STATE_STACK_SIZE) {
|
||||||
|
throw PushOnFullStateStackException();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Do the push only if there is a state to be pushed
|
||||||
|
// on the stack.
|
||||||
|
if (_state != nullptr) {
|
||||||
|
_state_stack[_state_stack_depth] = _state;
|
||||||
|
++_state_stack_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
_previous_state = _state;
|
||||||
|
_state = const_cast<State *>(&state);
|
||||||
|
|
||||||
|
if (_debug_flag == true) {
|
||||||
|
_notify(Event::PUSH_STATE, _state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make the state on top of the state stack the
|
||||||
|
// current state.
|
||||||
|
void popState() {
|
||||||
|
// Popping when there was no previous push is an error.
|
||||||
|
#ifdef SMC_NO_EXCEPTIONS
|
||||||
|
poco_assert(_state_stack_depth > 0);
|
||||||
|
#else
|
||||||
|
if (_state_stack_depth == 0) {
|
||||||
|
throw PopOnEmptyStateStackException();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_previous_state = _state;
|
||||||
|
--_state_stack_depth;
|
||||||
|
_state = _state_stack[_state_stack_depth];
|
||||||
|
|
||||||
|
if (_debug_flag == true) {
|
||||||
|
_notify(Event::POP, _state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove all states from the state stack.
|
||||||
|
void emptyStateStack() {
|
||||||
|
_state_stack_depth = 0;
|
||||||
|
};
|
||||||
|
#else // ! SMC_FIXED_STACK
|
||||||
|
// Returns true if the state stack is empty and false
|
||||||
|
// otherwise.
|
||||||
|
bool isStateStackEmpty() const {
|
||||||
|
return (_state_stack == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the state stack's depth.
|
||||||
|
int getStateStackDepth() const {
|
||||||
|
StateEntry *state_ptr;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
for (state_ptr = _state_stack, retval = 0;
|
||||||
|
state_ptr != nullptr;
|
||||||
|
state_ptr = state_ptr->getNext(), ++retval)
|
||||||
|
;
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the current state on top of the state stack
|
||||||
|
// and make the specified state the current state.
|
||||||
|
void pushState(const State& state) {
|
||||||
|
StateEntry *new_entry;
|
||||||
|
|
||||||
|
// Do the push only if there is a state to be pushed
|
||||||
|
// on the stack.
|
||||||
|
if (_state != nullptr) {
|
||||||
|
new_entry = new StateEntry(_state, _state_stack);
|
||||||
|
_state_stack = new_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
_previous_state = _state;
|
||||||
|
_state = const_cast<State *>(&state);
|
||||||
|
|
||||||
|
if (_debug_flag == true) {
|
||||||
|
_notify(Event::Push, _state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make the state on top of the state stack the
|
||||||
|
// current state.
|
||||||
|
void popState() {
|
||||||
|
StateEntry *entry;
|
||||||
|
|
||||||
|
// Popping when there was no previous push is an error.
|
||||||
|
#ifdef SMC_NO_EXCEPTIONS
|
||||||
|
poco_assert(_state_stack != nullptr);
|
||||||
|
#else
|
||||||
|
if (_state_stack == nullptr) {
|
||||||
|
throw PopOnEmptyStateStackException();
|
||||||
|
}
|
||||||
|
#endif // SMC_NO_EXCEPTIONS
|
||||||
|
|
||||||
|
_previous_state = _state;
|
||||||
|
_state = _state_stack->getState();
|
||||||
|
entry = _state_stack;
|
||||||
|
_state_stack = _state_stack->getNext();
|
||||||
|
delete entry;
|
||||||
|
|
||||||
|
if (_debug_flag == true) {
|
||||||
|
_notify(Event::Pop, _state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove all states from the state stack.
|
||||||
|
void emptyStateStack() {
|
||||||
|
StateEntry *state_ptr, *next_ptr;
|
||||||
|
|
||||||
|
for (state_ptr = _state_stack; state_ptr != nullptr; state_ptr = next_ptr) {
|
||||||
|
next_ptr = state_ptr->getNext();
|
||||||
|
delete state_ptr;
|
||||||
|
}
|
||||||
|
_state_stack = nullptr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FSMContext(const FSMContext&) = delete;
|
||||||
|
// Default constructor.
|
||||||
|
FSMContext(Notifier& notifier, const State& state)
|
||||||
|
: _state(const_cast<State *>(&state)),
|
||||||
|
_previous_state(nullptr),
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
_state_stack_depth(0),
|
||||||
|
#else
|
||||||
|
_state_stack(nullptr),
|
||||||
|
#endif
|
||||||
|
_transition(nullptr),
|
||||||
|
_debug_flag(false),
|
||||||
|
_notify(notifier)
|
||||||
|
{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// The current state of the finite state machine.
|
||||||
|
State *_state;
|
||||||
|
|
||||||
|
// Remember which state a transition left.
|
||||||
|
State *_previous_state;
|
||||||
|
|
||||||
|
// The stack of pushed states.
|
||||||
|
#ifdef SMC_FIXED_STACK
|
||||||
|
State* _state_stack[SMC_STATE_STACK_SIZE];
|
||||||
|
int _state_stack_depth;
|
||||||
|
#else
|
||||||
|
StateEntry *_state_stack;
|
||||||
|
#endif
|
||||||
|
char *_transition;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _debug_flag;
|
||||||
|
Notifier& _notify;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
12
FSM/samples/Makefile
Normal file
12
FSM/samples/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# $Id: //poco/1.4/PageCompiler/samples/Makefile#1 $
|
||||||
|
#
|
||||||
|
# Makefile for Poco PageCompiler Samples
|
||||||
|
#
|
||||||
|
|
||||||
|
.PHONY: projects
|
||||||
|
clean all: projects
|
||||||
|
projects:
|
||||||
|
$(MAKE) -C TrafficLight $(MAKECMDGOALS)
|
377
FSM/samples/TCP/AppClient.cpp
Normal file
377
FSM/samples/TCP/AppClient.cpp
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// AppClient.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TcpClient listener object.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: AppClient.cpp,v 1.6 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: AppClient.cpp,v $
|
||||||
|
// Revision 1.6 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:34:34 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AppClient.h"
|
||||||
|
#include "AppServer.h"
|
||||||
|
#include "Eventloop.h"
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Externally defined global variables.
|
||||||
|
extern Eventloop *Gevent_loop;
|
||||||
|
|
||||||
|
// Class variables.
|
||||||
|
int AppClient::_initFlag = 0;
|
||||||
|
const long AppClient::MIN_SLEEP_TIME = 100;
|
||||||
|
const long AppClient::MAX_SLEEP_TIME = 30000;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// AppClient() (Public)
|
||||||
|
// Default constructor.
|
||||||
|
//
|
||||||
|
AppClient::AppClient()
|
||||||
|
: _client_socket(NULL),
|
||||||
|
_owner(NULL),
|
||||||
|
_host(),
|
||||||
|
_messageCount(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// AppClient(const char*, TcpClient&, AppServer&) (Public)
|
||||||
|
// An "accept" construct.
|
||||||
|
//
|
||||||
|
AppClient::AppClient(const string& host,
|
||||||
|
TcpClient& tcp_client,
|
||||||
|
AppServer& owner)
|
||||||
|
: _client_socket(&tcp_client),
|
||||||
|
_owner(&owner),
|
||||||
|
_host(host),
|
||||||
|
_messageCount(0)
|
||||||
|
{
|
||||||
|
// Tell the client that this object is now listening to it.
|
||||||
|
tcp_client.setListener(*this);
|
||||||
|
|
||||||
|
// Since this client is already connected, set the
|
||||||
|
// random transmit timer.
|
||||||
|
setTransmitTimer();
|
||||||
|
return;
|
||||||
|
} // end of AppClient::AppClient(TcpClient&, AppServer&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~AppClient() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
AppClient::~AppClient()
|
||||||
|
{
|
||||||
|
if (_client_socket != NULL)
|
||||||
|
{
|
||||||
|
delete _client_socket;
|
||||||
|
_client_socket = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::~AppClient()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getHost() const (Public)
|
||||||
|
// Return the host name.
|
||||||
|
//
|
||||||
|
const string& AppClient::getHost() const
|
||||||
|
{
|
||||||
|
return(_host);
|
||||||
|
} // end of AppClient::getHost() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// open(const string&, const sockaddr_in&) (Public)
|
||||||
|
// Open a connection to the named TCP service.
|
||||||
|
//
|
||||||
|
void AppClient::open(const string& host,
|
||||||
|
const sockaddr_in& address)
|
||||||
|
{
|
||||||
|
if (_client_socket == NULL)
|
||||||
|
{
|
||||||
|
// Store away the host name.
|
||||||
|
_host = host;
|
||||||
|
|
||||||
|
cout << "Opening connection to "
|
||||||
|
<< host
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< " ... ";
|
||||||
|
|
||||||
|
// Create the client object and open it.
|
||||||
|
_client_socket = new TcpClient(*this);
|
||||||
|
_client_socket->open(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::open(const string&, const sockaddr_in&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// close() (Public)
|
||||||
|
// Close the client connection.
|
||||||
|
//
|
||||||
|
void AppClient::close()
|
||||||
|
{
|
||||||
|
if (_client_socket != NULL)
|
||||||
|
{
|
||||||
|
cout << "Closing connection to "
|
||||||
|
<< _host
|
||||||
|
<< ":"
|
||||||
|
<< ntohs((_client_socket->getServerAddress()).sin_port)
|
||||||
|
<< " ... ";
|
||||||
|
|
||||||
|
_client_socket->doClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::close()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// opened(TcpConnection&) (Public)
|
||||||
|
// TCP client connection successful.
|
||||||
|
//
|
||||||
|
void AppClient::opened(TcpConnection&)
|
||||||
|
{
|
||||||
|
cout << "open successful." << endl;
|
||||||
|
|
||||||
|
// Set the transmit timer.
|
||||||
|
setTransmitTimer();
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::opened(TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// openFailed(const char*, TcpConnection&) (Public)
|
||||||
|
// TCP client connection failed.
|
||||||
|
//
|
||||||
|
void AppClient::openFailed(const char *reason, TcpConnection&)
|
||||||
|
{
|
||||||
|
void socketClosed();
|
||||||
|
|
||||||
|
cout << "open failed";
|
||||||
|
if (reason == NULL)
|
||||||
|
{
|
||||||
|
cout << "." << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << " - "
|
||||||
|
<< reason
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the application know that the socket is closed.
|
||||||
|
socketClosed();
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::openFailed(const char*, TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// transmitted(TcpConnection&) (Public)
|
||||||
|
// Data successfully transmitted.
|
||||||
|
//
|
||||||
|
void AppClient::transmitted(TcpConnection&)
|
||||||
|
{
|
||||||
|
// Set the timer for the next transmission.
|
||||||
|
setTransmitTimer();
|
||||||
|
|
||||||
|
cout << "transmit successful." << endl;
|
||||||
|
return;
|
||||||
|
} // end of AppClient::transmitted(TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// transmitFailed(const char*, TcpConnection&) (Public)
|
||||||
|
// Failed to send data to far-end.
|
||||||
|
//
|
||||||
|
void AppClient::transmitFailed(const char *reason, TcpConnection&)
|
||||||
|
{
|
||||||
|
cout << "transmit failed - " << reason << "." << endl;
|
||||||
|
return;
|
||||||
|
} // end of AppClient::transmitFailed(const char*, TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// receive(const char*, int, TcpConnection&) (Public)
|
||||||
|
// Received data from far end.
|
||||||
|
//
|
||||||
|
void AppClient::receive(const char *data,
|
||||||
|
int size,
|
||||||
|
TcpConnection&)
|
||||||
|
{
|
||||||
|
const sockaddr_in& address = _client_socket->getServerAddress();
|
||||||
|
char *string = new char[size + 1];
|
||||||
|
|
||||||
|
// Turn the data into a string.
|
||||||
|
(void) memcpy(string, data, size);
|
||||||
|
string[size] = '\0';
|
||||||
|
|
||||||
|
cout << "Received data from "
|
||||||
|
<< inet_ntoa(address.sin_addr)
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< ": \""
|
||||||
|
<< string
|
||||||
|
<< "\""
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
delete[] string;
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::receive(const char*, int, TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// halfClosed(TcpConnection&) (Public)
|
||||||
|
// This far end has closed its connection. Close down this side.
|
||||||
|
//
|
||||||
|
void AppClient::halfClosed(TcpConnection&)
|
||||||
|
{
|
||||||
|
const sockaddr_in& address = _client_socket->getServerAddress();
|
||||||
|
|
||||||
|
cout << "Connection from "
|
||||||
|
<< _host
|
||||||
|
<< ":"
|
||||||
|
<< address.sin_port
|
||||||
|
<< " has closed its side."
|
||||||
|
<< endl
|
||||||
|
<< "Closing connection to "
|
||||||
|
<< _host
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< " ... ";
|
||||||
|
|
||||||
|
// Stop the transmit timer if running.
|
||||||
|
Gevent_loop->stopTimer("TRANSMIT_TIMER", *this);
|
||||||
|
|
||||||
|
// When this timer expires, close this end of the connection,
|
||||||
|
// after waiting one millisecond.
|
||||||
|
Gevent_loop->startTimer("CLOSE_TIMER", 1, *this);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::halfClosed(TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// closed(const char*, TcpConnection&) (Public)
|
||||||
|
// This client connection is closed.
|
||||||
|
//
|
||||||
|
void AppClient::closed(const char*, TcpConnection&)
|
||||||
|
{
|
||||||
|
void socketClosed();
|
||||||
|
|
||||||
|
cout << "closed." << endl;
|
||||||
|
|
||||||
|
// Stop the transmit timer if running.
|
||||||
|
Gevent_loop->stopTimer("TRANSMIT_TIMER", *this);
|
||||||
|
|
||||||
|
// If this is an accepted connection, tell the service owner
|
||||||
|
// that this connection is gone.
|
||||||
|
if (_owner != NULL)
|
||||||
|
{
|
||||||
|
_owner->clientClosed(*this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Tell the client application that this connection is
|
||||||
|
// closed.
|
||||||
|
socketClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::closed(const char*, TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// handleTimeout(const char*) (Public)
|
||||||
|
// Time to send another message.
|
||||||
|
//
|
||||||
|
void AppClient::handleTimeout(const char *name)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "TRANSMIT_TIMER") == 0)
|
||||||
|
{
|
||||||
|
char message[30];
|
||||||
|
const sockaddr_in& address = _client_socket->getServerAddress();
|
||||||
|
|
||||||
|
(void) sprintf(message,
|
||||||
|
"This is message #%d.",
|
||||||
|
++_messageCount);
|
||||||
|
|
||||||
|
cout << "Transmitting to "
|
||||||
|
<< _host
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< ": \""
|
||||||
|
<< message
|
||||||
|
<< "\" ... ";
|
||||||
|
|
||||||
|
_client_socket->transmit(message, 0, strlen(message));
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "CLOSE_TIMER") == 0)
|
||||||
|
{
|
||||||
|
_client_socket->doClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::handleTimeout(const char*)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// setTransmitTimer() (Private)
|
||||||
|
// Set the transmit timer to expire some random time in the
|
||||||
|
// future.
|
||||||
|
//
|
||||||
|
void AppClient::setTransmitTimer()
|
||||||
|
{
|
||||||
|
long duration;
|
||||||
|
|
||||||
|
// Initialize the random number generator, if necessary.
|
||||||
|
if (_initFlag == 0)
|
||||||
|
{
|
||||||
|
srand(time(NULL));
|
||||||
|
_initFlag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the next tranmission to some random time.
|
||||||
|
duration = ((long) rand()) % MAX_SLEEP_TIME;
|
||||||
|
if (duration < MIN_SLEEP_TIME)
|
||||||
|
{
|
||||||
|
duration = MIN_SLEEP_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gevent_loop->startTimer("TRANSMIT_TIMER", duration, *this);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppClient::setTransmitTimer()
|
135
FSM/samples/TCP/AppClient.h
Normal file
135
FSM/samples/TCP/AppClient.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#ifndef _H_APPCLIENT
|
||||||
|
#define _H_APPCLIENT
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// AppClient.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates a TcpClient object.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: AppClient.h,v 1.6 2009/03/01 18:20:38 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: AppClient.h,v $
|
||||||
|
// Revision 1.6 2009/03/01 18:20:38 cwrapp
|
||||||
|
// Preliminary v. 6.0.0 commit.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:34:49 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpClient.h"
|
||||||
|
#include "TcpServer.h"
|
||||||
|
#include "TcpConnectionListener.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Foward declarations.
|
||||||
|
class AppServer;
|
||||||
|
|
||||||
|
class AppClient :
|
||||||
|
/* implements */ public TcpConnectionListener,
|
||||||
|
/* implements */ public TimerListener
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
AppClient();
|
||||||
|
|
||||||
|
// Create a client around an accepted connection.
|
||||||
|
AppClient(const std::string& host,
|
||||||
|
TcpClient& client,
|
||||||
|
AppServer& owner);
|
||||||
|
|
||||||
|
virtual ~AppClient();
|
||||||
|
|
||||||
|
const std::string& getHost() const;
|
||||||
|
|
||||||
|
// Create a TCP client object and open a connection to the
|
||||||
|
// specified service.
|
||||||
|
void open(const std::string& host,
|
||||||
|
const sockaddr_in& address);
|
||||||
|
|
||||||
|
// Close the TCP service.
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// TCP connection listener callback methods.
|
||||||
|
void opened(TcpConnection& connection);
|
||||||
|
void openFailed(const char *reason,
|
||||||
|
TcpConnection& connection);
|
||||||
|
void transmitted(TcpConnection& connection);
|
||||||
|
void transmitFailed(const char *reason,
|
||||||
|
TcpConnection& connection);
|
||||||
|
void receive(const char *data,
|
||||||
|
int size,
|
||||||
|
TcpConnection& connection);
|
||||||
|
void halfClosed(TcpConnection& connection);
|
||||||
|
void closed(const char *reason,
|
||||||
|
TcpConnection& connection);
|
||||||
|
|
||||||
|
// Clients never receive this event.
|
||||||
|
void accepted(TcpClient&, TcpServer&) {};
|
||||||
|
|
||||||
|
// Timer listener callback method.
|
||||||
|
void handleTimeout(const char *name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Randomly set the transmit time.
|
||||||
|
void setTransmitTimer();
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// The TCP service itself.
|
||||||
|
TcpClient *_client_socket;
|
||||||
|
|
||||||
|
// If this was an accepted client connection, _owner points
|
||||||
|
// to the parent TCP service. This will be NULL otherwise.
|
||||||
|
AppServer *_owner;
|
||||||
|
|
||||||
|
// The host to which we are connected.
|
||||||
|
std::string _host;
|
||||||
|
|
||||||
|
// Every time a message is sent, increment this counter.
|
||||||
|
int _messageCount;
|
||||||
|
|
||||||
|
// Initialize the random number generator once per process.
|
||||||
|
static int _initFlag;
|
||||||
|
|
||||||
|
// Class constants. Minimum and Maximum transmit timeout.
|
||||||
|
const static long MIN_SLEEP_TIME;
|
||||||
|
const static long MAX_SLEEP_TIME;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
285
FSM/samples/TCP/AppServer.cpp
Normal file
285
FSM/samples/TCP/AppServer.cpp
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// AppServer.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates a TcpServer object.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: AppServer.cpp,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: AppServer.cpp,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:35:08 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AppServer.h"
|
||||||
|
#include "AppClient.h"
|
||||||
|
#include "Eventloop.h"
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Externally defined global variables.
|
||||||
|
extern Eventloop *Gevent_loop;
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
const static char *DELETE_TIMER = "DeleteTimer";
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// AppServer() (Public)
|
||||||
|
// Default constructor.
|
||||||
|
//
|
||||||
|
AppServer::AppServer()
|
||||||
|
: _server(NULL),
|
||||||
|
_clientList(NULL),
|
||||||
|
_deleteList(NULL)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~AppServer() (Public)
|
||||||
|
// Destructor. Close and delete all accepted client connections.
|
||||||
|
//
|
||||||
|
AppServer::~AppServer()
|
||||||
|
{
|
||||||
|
ClientEntry *client,
|
||||||
|
*nextClient;
|
||||||
|
|
||||||
|
// Close and delete the server if necessary.
|
||||||
|
if (_server != NULL)
|
||||||
|
{
|
||||||
|
_server->doClose();
|
||||||
|
delete _server;
|
||||||
|
_server = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (client = _clientList;
|
||||||
|
client != NULL;
|
||||||
|
client = nextClient)
|
||||||
|
{
|
||||||
|
nextClient = client->getNext();
|
||||||
|
(client->getClient())->close();
|
||||||
|
delete client;
|
||||||
|
}
|
||||||
|
_clientList = NULL;
|
||||||
|
|
||||||
|
for (client = _deleteList;
|
||||||
|
client != NULL;
|
||||||
|
client = nextClient)
|
||||||
|
{
|
||||||
|
nextClient = client->getNext();
|
||||||
|
delete client;
|
||||||
|
}
|
||||||
|
_deleteList = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::~AppServer()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// open(unsigned short) (Public)
|
||||||
|
// Create a TCP service object and have it start opening.
|
||||||
|
//
|
||||||
|
void AppServer::open(unsigned short port)
|
||||||
|
{
|
||||||
|
if (_server == NULL)
|
||||||
|
{
|
||||||
|
_server = new TcpServer(*this);
|
||||||
|
_server->open(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::open(unsigned short)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// close() (Public)
|
||||||
|
// Have the TCP service start the close process.
|
||||||
|
//
|
||||||
|
void AppServer::close()
|
||||||
|
{
|
||||||
|
if (_server != NULL)
|
||||||
|
{
|
||||||
|
_server->doClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::close()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// clientClosed(const AppClient&) (Public)
|
||||||
|
// One of the accepted client connections is now closed. Remove
|
||||||
|
// it from the client list.
|
||||||
|
//
|
||||||
|
void AppServer::clientClosed(const AppClient& client)
|
||||||
|
{
|
||||||
|
ClientEntry **entry,
|
||||||
|
*remove_entry;
|
||||||
|
|
||||||
|
for (entry = &_clientList;
|
||||||
|
*entry != NULL;
|
||||||
|
entry = &((*entry)->_next))
|
||||||
|
{
|
||||||
|
if ((*entry)->getClient() == &client)
|
||||||
|
{
|
||||||
|
remove_entry = *entry;
|
||||||
|
*entry = (*entry)->getNext();
|
||||||
|
|
||||||
|
// Now put the client on the delete list and
|
||||||
|
// start the delete timer.
|
||||||
|
remove_entry->setNext(_deleteList);
|
||||||
|
_deleteList = remove_entry;
|
||||||
|
|
||||||
|
if (Gevent_loop->doesTimerExist(DELETE_TIMER) == true)
|
||||||
|
{
|
||||||
|
Gevent_loop->startTimer(DELETE_TIMER, 1, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::clientClosed(const AppClient&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// opened(TcpConnection&) (Public)
|
||||||
|
// TCP service successfully opened.
|
||||||
|
//
|
||||||
|
void AppServer::opened(TcpConnection&)
|
||||||
|
{
|
||||||
|
sockaddr_in address;
|
||||||
|
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_port = _server->getPort();
|
||||||
|
address.sin_addr.s_addr = _server->getAddress();
|
||||||
|
|
||||||
|
cout << "Service opened on "
|
||||||
|
<< inet_ntoa(address.sin_addr)
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< "."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::opened(TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// openFailed(const char*, TcpConnection&) (Public)
|
||||||
|
// TCP service failed to open.
|
||||||
|
//
|
||||||
|
void AppServer::openFailed(const char *reason, TcpConnection&)
|
||||||
|
{
|
||||||
|
void socketClosed();
|
||||||
|
|
||||||
|
cout << "Service failed to open on port "
|
||||||
|
<< _server->getPort()
|
||||||
|
<< ", reason: "
|
||||||
|
<< reason
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Tell the application that the TCP service is closed.
|
||||||
|
socketClosed();
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::openFailed(const char*, TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// closed(const char*, TcpConnection&) (Public)
|
||||||
|
// TCP service is now closed.
|
||||||
|
//
|
||||||
|
void AppServer::closed(const char *reason, TcpConnection&)
|
||||||
|
{
|
||||||
|
void socketClosed();
|
||||||
|
|
||||||
|
cout << "Service closed: "
|
||||||
|
<< reason
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Tell the application that the TCP service is closed.
|
||||||
|
socketClosed();
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::closed(TcpConnection&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// accepteded(TcpClient&, TcpServer&) (Public)
|
||||||
|
// TCP service has accepted a new connection.
|
||||||
|
//
|
||||||
|
void AppServer::accepted(TcpClient& client, TcpServer&)
|
||||||
|
{
|
||||||
|
AppClient *new_client;
|
||||||
|
ClientEntry *new_entry;
|
||||||
|
const sockaddr_in& address = client.getServerAddress();
|
||||||
|
string host;
|
||||||
|
|
||||||
|
host = inet_ntoa(address.sin_addr);
|
||||||
|
|
||||||
|
cout << "Accepted new connection from "
|
||||||
|
<< host
|
||||||
|
<< ":"
|
||||||
|
<< ntohs(address.sin_port)
|
||||||
|
<< "."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Create a new client handler and put in the client list.
|
||||||
|
new_client = new AppClient(host, client, *this);
|
||||||
|
new_entry = new ClientEntry(*new_client);
|
||||||
|
new_entry->setNext(_clientList);
|
||||||
|
_clientList = new_entry;
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::accepted(TcpClient&, TcpServer&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// handleTimeout(const char*) (Public)
|
||||||
|
// Time to delete the zombie clients.
|
||||||
|
//
|
||||||
|
void AppServer::handleTimeout(const char *name)
|
||||||
|
{
|
||||||
|
if (strcmp(name, DELETE_TIMER) == 0)
|
||||||
|
{
|
||||||
|
ClientEntry *it;
|
||||||
|
ClientEntry *next;
|
||||||
|
|
||||||
|
for (it = _deleteList; it != NULL; it = next)
|
||||||
|
{
|
||||||
|
next = it->getNext();
|
||||||
|
it->setNext(NULL);
|
||||||
|
delete it;
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteList = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of AppServer::handleTimeout(const char*)
|
147
FSM/samples/TCP/AppServer.h
Normal file
147
FSM/samples/TCP/AppServer.h
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#ifndef _H_APPSERVER
|
||||||
|
#define _H_APPSERVER
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2003 Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// AppServer.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates a TcpServer object.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: AppServer.h,v 1.6 2009/03/01 18:20:38 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: AppServer.h,v $
|
||||||
|
// Revision 1.6 2009/03/01 18:20:38 cwrapp
|
||||||
|
// Preliminary v. 6.0.0 commit.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:35:24 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpServer.h"
|
||||||
|
#include "TcpClient.h"
|
||||||
|
#include "TcpConnectionListener.h"
|
||||||
|
#include "TimerListener.h"
|
||||||
|
|
||||||
|
// Foward declarations.
|
||||||
|
class AppClient;
|
||||||
|
|
||||||
|
class AppServer :
|
||||||
|
/* implements */ public TcpConnectionListener,
|
||||||
|
/* implements */ public TimerListener
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
AppServer();
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~AppServer();
|
||||||
|
|
||||||
|
// Create a TCP server object and open it.
|
||||||
|
void open(unsigned short port);
|
||||||
|
|
||||||
|
// Close the TCP service.
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// Accepted client socket closed.
|
||||||
|
void clientClosed(const AppClient& client);
|
||||||
|
|
||||||
|
// TCP connection listener callback methods.
|
||||||
|
void opened(TcpConnection& connection);
|
||||||
|
void openFailed(const char *reason,
|
||||||
|
TcpConnection& connection);
|
||||||
|
inline void halfClosed(TcpConnection&)
|
||||||
|
{};
|
||||||
|
void closed(const char *reason,
|
||||||
|
TcpConnection& connection);
|
||||||
|
void accepted(TcpClient& client, TcpServer& server);
|
||||||
|
|
||||||
|
// These callbacks are never generated by a TCP server.
|
||||||
|
void transmitted(TcpConnection&) {};
|
||||||
|
void transmitFailed(const char*, TcpConnection&) {};
|
||||||
|
void receive(const char*, int, TcpConnection&) {};
|
||||||
|
|
||||||
|
// The "delete clients" timer has expired.
|
||||||
|
void handleTimeout(const char *name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Nested classes.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
class ClientEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClientEntry(AppClient& client)
|
||||||
|
: _client(&client),
|
||||||
|
_next(NULL)
|
||||||
|
{};
|
||||||
|
|
||||||
|
~ClientEntry() {};
|
||||||
|
|
||||||
|
AppClient* getClient() const
|
||||||
|
{ return(_client);};
|
||||||
|
|
||||||
|
ClientEntry* getNext() const
|
||||||
|
{ return(_next);};
|
||||||
|
|
||||||
|
void setNext(ClientEntry *entry)
|
||||||
|
{ _next = entry; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppClient *_client;
|
||||||
|
ClientEntry *_next;
|
||||||
|
|
||||||
|
friend class AppServer;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// The TCP service itself.
|
||||||
|
TcpServer *_server;
|
||||||
|
|
||||||
|
// Keep track of all the accepted client connections.
|
||||||
|
// When this application terminates, they will all be
|
||||||
|
// closed and deleted.
|
||||||
|
ClientEntry *_clientList;
|
||||||
|
|
||||||
|
// Delete these clients when the timer expires.
|
||||||
|
ClientEntry *_deleteList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
621
FSM/samples/TCP/Eventloop.cpp
Normal file
621
FSM/samples/TCP/Eventloop.cpp
Normal file
@ -0,0 +1,621 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// Eventloop.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates the select-based event loop and timer table.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: Eventloop.cpp,v 1.6 2008/02/04 12:45:07 fperrad Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: Eventloop.cpp,v $
|
||||||
|
// Revision 1.6 2008/02/04 12:45:07 fperrad
|
||||||
|
// fix build on linux (gcc 4.1.3)
|
||||||
|
//
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:35:40 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Eventloop.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#if !defined(WIN32)
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const static long USECS_PER_SEC = 1000000;
|
||||||
|
const static long USECS_PER_MSEC = 1000;
|
||||||
|
const static int WIN32_MAX_SOCKET = 1024;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Eventloop() (Public)
|
||||||
|
// Default constructor.
|
||||||
|
//
|
||||||
|
Eventloop::Eventloop()
|
||||||
|
: _continueRunning(1),
|
||||||
|
_maxFD(-1),
|
||||||
|
_fdCount(0),
|
||||||
|
_timerTable(NULL)
|
||||||
|
{
|
||||||
|
#if !defined(WIN32)
|
||||||
|
rlimit limit;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FD_ZERO(&_fdSet);
|
||||||
|
|
||||||
|
// Allocate the file descriptor callback table. First, find
|
||||||
|
// out the max file descriptor value.
|
||||||
|
#if defined(WIN32)
|
||||||
|
_fdTable = new InputListener*[WIN32_MAX_SOCKET];
|
||||||
|
(void) memset(_fdTable,
|
||||||
|
0,
|
||||||
|
(FD_SETSIZE * sizeof(InputListener*)));
|
||||||
|
#else
|
||||||
|
(void) getrlimit(RLIMIT_NOFILE, &limit);
|
||||||
|
_fdTable = new InputListener*[limit.rlim_cur];
|
||||||
|
(void) memset(_fdTable,
|
||||||
|
0,
|
||||||
|
(limit.rlim_cur * sizeof(InputListener*)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::Eventloop()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~Eventloop() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
Eventloop::~Eventloop()
|
||||||
|
{
|
||||||
|
Eventloop::Timer *timerIt,
|
||||||
|
*nextTimer;
|
||||||
|
|
||||||
|
// Just in case the event loop is still running.
|
||||||
|
_continueRunning = 0;
|
||||||
|
|
||||||
|
if (_fdTable != NULL)
|
||||||
|
{
|
||||||
|
delete[] _fdTable;
|
||||||
|
_fdTable = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (timerIt = _timerTable;
|
||||||
|
timerIt != NULL;
|
||||||
|
timerIt = nextTimer)
|
||||||
|
{
|
||||||
|
nextTimer = timerIt->getNext();
|
||||||
|
timerIt->setNext(NULL);
|
||||||
|
delete timerIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::~Eventloop()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// start() (Public)
|
||||||
|
// Start the event loop running.
|
||||||
|
//
|
||||||
|
int Eventloop::start()
|
||||||
|
{
|
||||||
|
timeval timeout,
|
||||||
|
currTime,
|
||||||
|
*timeoutPtr;
|
||||||
|
Timer *timer;
|
||||||
|
fd_set readSet;
|
||||||
|
int i,
|
||||||
|
fdCount,
|
||||||
|
retcode;
|
||||||
|
TimerListener *listener;
|
||||||
|
char *timerName;
|
||||||
|
|
||||||
|
_continueRunning = 1;
|
||||||
|
retcode = 0;
|
||||||
|
while (_continueRunning == 1)
|
||||||
|
{
|
||||||
|
// Figure out how long to wait. If there are no timers,
|
||||||
|
// then set timeoutPtr to NULL and wait forever.
|
||||||
|
// Otherwise, put the timeout in the timeval struct and
|
||||||
|
// point timeoutPtr to it.
|
||||||
|
if (_timerTable == NULL)
|
||||||
|
{
|
||||||
|
timeoutPtr = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the current time and figure out how long until
|
||||||
|
// the next timeout.
|
||||||
|
gettime(currTime);
|
||||||
|
|
||||||
|
// If we have passed the current timeout value, then
|
||||||
|
// don't sleep at all.
|
||||||
|
if (*_timerTable < currTime)
|
||||||
|
{
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout.tv_sec =
|
||||||
|
(_timerTable->getExpiration()).tv_sec - currTime.tv_sec;
|
||||||
|
timeout.tv_usec =
|
||||||
|
(_timerTable->getExpiration()).tv_usec - currTime.tv_usec;
|
||||||
|
|
||||||
|
// If the microseconds are less than 0, then subtract
|
||||||
|
// a second and add 1,000,000 microseconds.
|
||||||
|
if (timeout.tv_usec < 0)
|
||||||
|
{
|
||||||
|
--(timeout.tv_sec);
|
||||||
|
timeout.tv_usec += USECS_PER_SEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutPtr = &timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since select modifies the FD sets, pass in a copy.
|
||||||
|
FD_ZERO(&readSet);
|
||||||
|
for (i = 0; i < _maxFD; ++i)
|
||||||
|
{
|
||||||
|
if (FD_ISSET(i, &_fdSet))
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
FD_SET((u_int) i, &readSet);
|
||||||
|
#else
|
||||||
|
FD_SET(i, &readSet);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fdCount = select(_maxFD, &readSet, NULL, NULL, timeoutPtr)) < 0)
|
||||||
|
{
|
||||||
|
// If select() was interrupted, ignore the error.
|
||||||
|
if (errno != EINTR)
|
||||||
|
{
|
||||||
|
_continueRunning = 0;
|
||||||
|
retcode = errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Issue read events first.
|
||||||
|
for (i = 0; i < _maxFD && fdCount > 0; ++i)
|
||||||
|
{
|
||||||
|
if (FD_ISSET(i, &readSet))
|
||||||
|
{
|
||||||
|
--fdCount;
|
||||||
|
|
||||||
|
if (_fdTable[i] != NULL)
|
||||||
|
{
|
||||||
|
_fdTable[i]->handleReceive(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue timeouts.
|
||||||
|
gettime(currTime);
|
||||||
|
while (_timerTable != NULL &&
|
||||||
|
*_timerTable <= currTime)
|
||||||
|
{
|
||||||
|
// Remove the timer from the timer table *before*
|
||||||
|
// issuing the callback 'cause the callback may
|
||||||
|
// set this same timer again before returning
|
||||||
|
// (and the set will fail if the timer is already
|
||||||
|
// in the table).
|
||||||
|
timer = _timerTable;
|
||||||
|
_timerTable = timer->getNext();
|
||||||
|
timer->setNext(NULL);
|
||||||
|
|
||||||
|
// Save away the necessary timer info.
|
||||||
|
listener = &(timer->getListener());
|
||||||
|
timerName = new char[strlen(timer->getName()) + 1];
|
||||||
|
strcpy(timerName, timer->getName());
|
||||||
|
|
||||||
|
// Now delete the defunct timer.
|
||||||
|
delete timer;
|
||||||
|
|
||||||
|
listener->handleTimeout(timerName);
|
||||||
|
delete[] timerName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(retcode);
|
||||||
|
} // end of Eventloop::start()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// stop() (Public)
|
||||||
|
// Stop the event loop.
|
||||||
|
//
|
||||||
|
void Eventloop::stop()
|
||||||
|
{
|
||||||
|
_continueRunning = 0;
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::stop()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// addFD(int, InputListener&) (Public)
|
||||||
|
// Start watching a file descriptor and route the callback to the
|
||||||
|
// given connection.
|
||||||
|
//
|
||||||
|
void Eventloop::addFD(int fd, InputListener& listener)
|
||||||
|
{
|
||||||
|
if (!FD_ISSET(fd, &_fdSet))
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
FD_SET((u_int) fd, &_fdSet);
|
||||||
|
#else
|
||||||
|
FD_SET(fd, &_fdSet);
|
||||||
|
#endif
|
||||||
|
++_fdCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fdTable[fd] = &listener;
|
||||||
|
|
||||||
|
if (fd >= _maxFD)
|
||||||
|
{
|
||||||
|
_maxFD = fd + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::addFD(int, InputListener&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// removeFD(int) (Public)
|
||||||
|
// Stop watching a file descriptor.
|
||||||
|
//
|
||||||
|
void Eventloop::removeFD(int fd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
FD_CLR((u_int) fd, &_fdSet);
|
||||||
|
#else
|
||||||
|
FD_CLR(fd, &_fdSet);
|
||||||
|
#endif
|
||||||
|
_fdTable[fd] = NULL;
|
||||||
|
--_fdCount;
|
||||||
|
|
||||||
|
// Are we watching any file descriptors?
|
||||||
|
if (_fdCount == 0)
|
||||||
|
{
|
||||||
|
_maxFD = -1;
|
||||||
|
}
|
||||||
|
// Are we removing the max fd?
|
||||||
|
else if (fd == (_maxFD - 1))
|
||||||
|
{
|
||||||
|
// Yes. Then look for the next max fd.
|
||||||
|
for (i = (fd -1); i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (FD_ISSET(i, &_fdSet))
|
||||||
|
{
|
||||||
|
_maxFD = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::removeFD(int)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// startTimer(const char*, unsigned long, TimerListener&) (Public)
|
||||||
|
// Start the named timer.
|
||||||
|
//
|
||||||
|
void Eventloop::startTimer(const char *name,
|
||||||
|
long duration,
|
||||||
|
TimerListener& listener)
|
||||||
|
{
|
||||||
|
timeval expiration;
|
||||||
|
Eventloop::Timer *timer,
|
||||||
|
**timerIt;
|
||||||
|
|
||||||
|
// Get the current time and add the duration to it.
|
||||||
|
gettime(expiration);
|
||||||
|
expiration.tv_usec += duration * USECS_PER_MSEC;
|
||||||
|
if (expiration.tv_usec >= USECS_PER_SEC)
|
||||||
|
{
|
||||||
|
expiration.tv_sec += (expiration.tv_usec / USECS_PER_SEC);
|
||||||
|
expiration.tv_usec = (expiration.tv_usec % USECS_PER_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this timer already exists. If yes, then remove the
|
||||||
|
// timer from the list and update its duration and expiration.
|
||||||
|
timer = NULL;
|
||||||
|
for (timerIt = &_timerTable;
|
||||||
|
*timerIt != NULL;
|
||||||
|
timerIt = &((*timerIt)->_next))
|
||||||
|
{
|
||||||
|
if (strcmp((*timerIt)->getName(), name) == 0 &&
|
||||||
|
&((*timerIt)->getListener()) == &listener)
|
||||||
|
{
|
||||||
|
timer = *timerIt;
|
||||||
|
*timerIt = timer->getNext();
|
||||||
|
timer->setNext(NULL);
|
||||||
|
|
||||||
|
timer->setDuration(duration);
|
||||||
|
timer->setExpiration(expiration);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer == NULL)
|
||||||
|
{
|
||||||
|
timer = new Timer(name, duration, expiration, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out where to put this timer in the list.
|
||||||
|
for (timerIt = &_timerTable;
|
||||||
|
*timerIt != NULL && **timerIt <= expiration;
|
||||||
|
timerIt = &((*timerIt)->_next))
|
||||||
|
;
|
||||||
|
|
||||||
|
timer->setNext(*timerIt);
|
||||||
|
*timerIt = timer;
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::startTimer(const char*, long, TimerListener&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// stopTimer(const char*, const TimerListener&) (Public)
|
||||||
|
// Stop the named timer.
|
||||||
|
//
|
||||||
|
void Eventloop::stopTimer(const char *name,
|
||||||
|
const TimerListener& listener)
|
||||||
|
{
|
||||||
|
Eventloop::Timer **timerIt,
|
||||||
|
*timer;
|
||||||
|
|
||||||
|
for (timerIt = &_timerTable;
|
||||||
|
*timerIt != NULL;
|
||||||
|
timerIt = &((*timerIt)->_next))
|
||||||
|
{
|
||||||
|
if (strcmp((*timerIt)->getName(), name) == 0 &&
|
||||||
|
&((*timerIt)->getListener()) == &listener)
|
||||||
|
{
|
||||||
|
timer = *timerIt;
|
||||||
|
*timerIt = timer->getNext();
|
||||||
|
timer->setNext(NULL);
|
||||||
|
delete timer;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::stopTimer(const char*, const TimerListener&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// doesTimerExist(const char*) const (Public)
|
||||||
|
// Return true if the named timer exists.
|
||||||
|
//
|
||||||
|
bool Eventloop::doesTimerExist(const char *name) const
|
||||||
|
{
|
||||||
|
Eventloop::Timer **timerIt;
|
||||||
|
bool retval;
|
||||||
|
|
||||||
|
for (timerIt = const_cast<Eventloop::Timer**>(&_timerTable),
|
||||||
|
retval = false;
|
||||||
|
*timerIt != NULL && retval == false;
|
||||||
|
timerIt = &((*timerIt)->_next))
|
||||||
|
{
|
||||||
|
if (strcmp((*timerIt)->getName(), name) == 0)
|
||||||
|
{
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
} // end of Eventloop::doesTimerExist(const char*) const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Timer(const char*, long, const timeval&, TimerListener&)
|
||||||
|
// (Public)
|
||||||
|
// Constructor.
|
||||||
|
//
|
||||||
|
Eventloop::Timer::Timer(const char *name,
|
||||||
|
long duration,
|
||||||
|
const timeval& expiration,
|
||||||
|
TimerListener& listener)
|
||||||
|
: _name(NULL),
|
||||||
|
_duration(duration),
|
||||||
|
_listener(listener),
|
||||||
|
_next(NULL)
|
||||||
|
{
|
||||||
|
_name = new char[strlen(name) + 1];
|
||||||
|
(void) strcpy(_name, name);
|
||||||
|
(void) memcpy(&_expiration, &expiration, sizeof(_expiration));
|
||||||
|
} // end of Eventloop::Timer::Timer(...)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~Timer() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
Eventloop::Timer::~Timer()
|
||||||
|
{
|
||||||
|
if (_name != NULL)
|
||||||
|
{
|
||||||
|
delete[] _name;
|
||||||
|
_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::Timer::~Timer()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator<(const timeval&) (Public)
|
||||||
|
// Is the expiration time less than the given time?
|
||||||
|
//
|
||||||
|
int Eventloop::Timer::operator<(const timeval& time)
|
||||||
|
{
|
||||||
|
return(_expiration.tv_sec < time.tv_sec ||
|
||||||
|
(_expiration.tv_sec == time.tv_sec &&
|
||||||
|
_expiration.tv_usec < time.tv_usec));
|
||||||
|
} // end of Eventloop::Timer::operator<(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator<=(const timeval&) (Public)
|
||||||
|
// Is the expiration time less than or equal to the given time?
|
||||||
|
//
|
||||||
|
int Eventloop::Timer::operator<=(const timeval& time)
|
||||||
|
{
|
||||||
|
return(_expiration.tv_sec < time.tv_sec ||
|
||||||
|
(_expiration.tv_sec == time.tv_sec &&
|
||||||
|
_expiration.tv_usec <= time.tv_usec));
|
||||||
|
} // end of Eventloop::Timer::operator<=(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator==(const timeval&) (Public)
|
||||||
|
// Is the expiration time equal to the given time?
|
||||||
|
//
|
||||||
|
int Eventloop::Timer::operator==(const timeval& time)
|
||||||
|
{
|
||||||
|
return(_expiration.tv_sec == time.tv_sec &&
|
||||||
|
_expiration.tv_usec == time.tv_usec);
|
||||||
|
} // end of Eventloop::Timer::operator==(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator>=(const timeval&) (Public)
|
||||||
|
// Is the expiration time greater than or equal to the given
|
||||||
|
// time?
|
||||||
|
//
|
||||||
|
int Eventloop::Timer::operator>=(const timeval& time)
|
||||||
|
{
|
||||||
|
return(_expiration.tv_sec > time.tv_sec ||
|
||||||
|
(_expiration.tv_sec == time.tv_sec &&
|
||||||
|
_expiration.tv_usec >= time.tv_usec));
|
||||||
|
} // end of Eventloop::Timer::operator>=(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator>(const timeval&) (Public)
|
||||||
|
// Is the expiration time greater than the given time?
|
||||||
|
//
|
||||||
|
int Eventloop::Timer::operator>(const timeval& time)
|
||||||
|
{
|
||||||
|
return(_expiration.tv_sec > time.tv_sec ||
|
||||||
|
(_expiration.tv_sec == time.tv_sec &&
|
||||||
|
_expiration.tv_usec > time.tv_usec));
|
||||||
|
} // end of Eventloop::Timer::operator>(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getName() const (Public)
|
||||||
|
// Return the timer's name.
|
||||||
|
//
|
||||||
|
const char* Eventloop::Timer::getName() const
|
||||||
|
{
|
||||||
|
return(_name);
|
||||||
|
} // end of Eventloop::Timer::getName() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getDuration() const (Public)
|
||||||
|
// Return the timer's duration in milliseconds.
|
||||||
|
//
|
||||||
|
long Eventloop::Timer::getDuration() const
|
||||||
|
{
|
||||||
|
return(_duration);
|
||||||
|
} // end of Eventloop::Timer::getDuration() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// setDuration(long) (Public)
|
||||||
|
// Set the timer's duration.
|
||||||
|
//
|
||||||
|
void Eventloop::Timer::setDuration(long duration)
|
||||||
|
{
|
||||||
|
_duration = duration;
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::Timer::setDuration(long)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getExpiration() const (Public)
|
||||||
|
// Return the timer's expiration.
|
||||||
|
//
|
||||||
|
const timeval& Eventloop::Timer::getExpiration() const
|
||||||
|
{
|
||||||
|
return(_expiration);
|
||||||
|
} // end of Eventloop::Timer::getExpiration() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// setExpiration(const timeval&) (Public)
|
||||||
|
// Set the timer's expiration.
|
||||||
|
//
|
||||||
|
void Eventloop::Timer::setExpiration(const timeval& expiration)
|
||||||
|
{
|
||||||
|
(void) memcpy(&_expiration, &expiration, sizeof(_expiration));
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::Timer::setExpiration(const timeval&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getListener() const (Public)
|
||||||
|
// Return timer's callback connection object.
|
||||||
|
//
|
||||||
|
TimerListener& Eventloop::Timer::getListener() const
|
||||||
|
{
|
||||||
|
return(_listener);
|
||||||
|
} // end of Eventloop::Timer::getListener() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getNext() const (Public)
|
||||||
|
// Return the next pointer.
|
||||||
|
//
|
||||||
|
Eventloop::Timer* Eventloop::Timer::getNext() const
|
||||||
|
{
|
||||||
|
return(_next);
|
||||||
|
} // end of Eventloop::Timer::getNext() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// setNext(Timer*) (Public)
|
||||||
|
// Set the next pointer.
|
||||||
|
//
|
||||||
|
void Eventloop::Timer::setNext(Eventloop::Timer *timer)
|
||||||
|
{
|
||||||
|
_next = timer;
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::Timer::setNext(Eventloop::Timer*)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// gettime(timeval&) const (Private)
|
||||||
|
// Get the current time.
|
||||||
|
//
|
||||||
|
void Eventloop::gettime(timeval& timeval) const
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
_timeb currTime;
|
||||||
|
|
||||||
|
_ftime(&currTime);
|
||||||
|
timeval.tv_sec = currTime.time;
|
||||||
|
timeval.tv_usec = currTime.millitm * USECS_PER_MSEC;
|
||||||
|
#else
|
||||||
|
(void) gettimeofday(&timeval, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of Eventloop::gettime(timeval&) const
|
163
FSM/samples/TCP/Eventloop.h
Normal file
163
FSM/samples/TCP/Eventloop.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#ifndef _EVENTLOOP_H
|
||||||
|
#define _EVENTLOOP_H
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// Eventloop.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates the select-based event loop and timer table.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: Eventloop.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: Eventloop.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:35:56 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "InputListener.h"
|
||||||
|
#include "TimerListener.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Eventloop
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
Eventloop();
|
||||||
|
~Eventloop();
|
||||||
|
|
||||||
|
// Enter the event loop and continue running until told to
|
||||||
|
// stop. If the event loop terminated normally, 0 is
|
||||||
|
// returned; otherwise a return value greater than 0 is
|
||||||
|
// returned.
|
||||||
|
int start();
|
||||||
|
|
||||||
|
// Stop the event loop.
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
// Methods for adding and removing file descriptors.
|
||||||
|
void addFD(int fd, InputListener& listener);
|
||||||
|
void removeFD(int fd);
|
||||||
|
|
||||||
|
// Methods for starting and stopping timers.
|
||||||
|
void startTimer(const char *name,
|
||||||
|
long duration,
|
||||||
|
TimerListener& listener);
|
||||||
|
void stopTimer(const char *name, const TimerListener& listener);
|
||||||
|
bool doesTimerExist(const char *name) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
void gettime(timeval& timeval) const;
|
||||||
|
|
||||||
|
// Inner classes.
|
||||||
|
|
||||||
|
class Timer
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
Timer(const char *name,
|
||||||
|
long duration,
|
||||||
|
const timeval& expiration,
|
||||||
|
TimerListener& listener);
|
||||||
|
|
||||||
|
~Timer();
|
||||||
|
|
||||||
|
int operator<(const timeval& time);
|
||||||
|
int operator<=(const timeval& time);
|
||||||
|
int operator==(const timeval& time);
|
||||||
|
int operator>=(const timeval& time);
|
||||||
|
int operator>(const timeval& time);
|
||||||
|
|
||||||
|
const char* getName() const;
|
||||||
|
long getDuration() const;
|
||||||
|
void setDuration(long duration);
|
||||||
|
const timeval& getExpiration() const;
|
||||||
|
void setExpiration(const timeval& expiration);
|
||||||
|
TimerListener& getListener() const;
|
||||||
|
Timer* getNext() const;
|
||||||
|
void setNext(Timer *timer);
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
private:
|
||||||
|
|
||||||
|
char *_name;
|
||||||
|
|
||||||
|
// Duration is in milliseconds.
|
||||||
|
long _duration;
|
||||||
|
|
||||||
|
// When the timer is expected to expire.
|
||||||
|
timeval _expiration;
|
||||||
|
|
||||||
|
// The TcpConnection receiving this callback.
|
||||||
|
TimerListener& _listener;
|
||||||
|
|
||||||
|
Timer *_next;
|
||||||
|
|
||||||
|
// Friends.
|
||||||
|
friend class Eventloop;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Set to true while event loop is running and false when
|
||||||
|
// event loop is to stop.
|
||||||
|
int _continueRunning;
|
||||||
|
|
||||||
|
// The file descriptors to watch.
|
||||||
|
fd_set _fdSet;
|
||||||
|
|
||||||
|
// Keep track of the maximum file descriptor.
|
||||||
|
int _maxFD;
|
||||||
|
|
||||||
|
// Keep track of the number of file descriptors being
|
||||||
|
// watched.
|
||||||
|
int _fdCount;
|
||||||
|
|
||||||
|
// The TCP connection associated with each file descriptor.
|
||||||
|
InputListener **_fdTable;
|
||||||
|
|
||||||
|
// This table is sorted by expiration time - from earliest
|
||||||
|
// to latest.
|
||||||
|
Timer *_timerTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
68
FSM/samples/TCP/InputListener.h
Normal file
68
FSM/samples/TCP/InputListener.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef _H_INPUTLISTENER
|
||||||
|
#define _H_INPUTLISTENER
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// InputListener.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Input event handler.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: InputListener.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: InputListener.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:38:51 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
class InputListener
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
InputListener() {};
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~InputListener() {};
|
||||||
|
|
||||||
|
// Input callback method.
|
||||||
|
virtual void handleReceive(int fd)=0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
630
FSM/samples/TCP/TCP.sm
Normal file
630
FSM/samples/TCP/TCP.sm
Normal file
@ -0,0 +1,630 @@
|
|||||||
|
// -*- tab-width: 4; -*-
|
||||||
|
|
||||||
|
%{
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TCP.sm
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// The TCP/IP state transition diagram.
|
||||||
|
//
|
||||||
|
%}
|
||||||
|
|
||||||
|
%class TcpConnection
|
||||||
|
%header TcpConnection.h
|
||||||
|
%include "TcpSegment.h"
|
||||||
|
%start TCP::CLOSED
|
||||||
|
|
||||||
|
%map TCP
|
||||||
|
%%
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
PassiveOpen(port: unsigned short) ServiceOpening { openServerSocket(port); }
|
||||||
|
ActiveOpen(address: const sockaddr_in*) ClientOpening { openClientSocket(address); }
|
||||||
|
AcceptOpen(segment: const TcpSegment&) SYN_RCVD { sendSynAck(segment);setNearAddress(); }
|
||||||
|
// Ignore close requests when closed.
|
||||||
|
Close nil {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait here until service open has either succeeded or failed.
|
||||||
|
ServiceOpening
|
||||||
|
{
|
||||||
|
ServerOpened LISTEN { openSuccess(); }
|
||||||
|
OpenFailed(reason: const char*) CLOSED { closeSocket(); openFailed(reason); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait here until client open has either succeeded or failed.
|
||||||
|
ClientOpening
|
||||||
|
{
|
||||||
|
ClientOpened(address: const sockaddr_in*)SYN_SENT { sendOpenSyn(address); }
|
||||||
|
|
||||||
|
OpenFailed(reason: const char*) CLOSED { closeSocket();openFailed(reason); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server sockets just sit here, creating new client sockets when
|
||||||
|
// a SYN is received.
|
||||||
|
LISTEN
|
||||||
|
{
|
||||||
|
// Create a new client socket and send its port number in
|
||||||
|
// the SYN/ACK response.
|
||||||
|
SYN(segment: const TcpSegment&) nil { accept(segment);deleteSegment(segment); }
|
||||||
|
Close CLOSED { closeSocket();closed(""); }
|
||||||
|
|
||||||
|
// But don't reset a reset message because there is no
|
||||||
|
// connection to reset.
|
||||||
|
RST(segment: const TcpSegment&) nil { deleteSegment(segment); }
|
||||||
|
|
||||||
|
// Don't die on an undefined segment either.
|
||||||
|
UNDEF(segment: const TcpSegment&) nil { doSend(TcpSegment::RST, NULL, 0, 0, &segment);deleteSegment(segment); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// An "accepted" client socket starts life in this state.
|
||||||
|
SYN_RCVD
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("ACK_TIMER", TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// The connection was reset before it was established.
|
||||||
|
// Close the datagram socket but don't tell anybody.
|
||||||
|
RST(segment: const TcpSegment&) CLOSED { closeSocket();clearListener(); deleteSegment(segment); }
|
||||||
|
|
||||||
|
// The TCP state transition diagram shows the server socket
|
||||||
|
// taking an ACK transtion to the ESTABLISHED state but that
|
||||||
|
// is not quite true. The accepted client socket goes to
|
||||||
|
// the ESTABLISHED state while the server socket goes back to
|
||||||
|
// LISTEN.
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
ESTABLISHED { accepted();deleteSegment(segment); }
|
||||||
|
Close FIN_WAIT_1 { doSend(TcpSegment::FIN, NULL, 0, 0, NULL); }
|
||||||
|
AckTimeout CLOSED { doSend(TcpSegment::RST, NULL, 0, 0, NULL);closeSocket(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// A application-created client starts life in this state.
|
||||||
|
SYN_SENT
|
||||||
|
Entry
|
||||||
|
{ startTimer("CONN_ACK_TIMER", TcpConnection::ACK_TIMEOUT); }
|
||||||
|
Exit
|
||||||
|
{ stopTimer("CONN_ACK_TIMER"); }
|
||||||
|
{
|
||||||
|
// When a TCP service accepts a new connection, it creates
|
||||||
|
// a new client to handle this connection.
|
||||||
|
SYN_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
ESTABLISHED { setFarAddress(segment);sendSynAckAck(segment);openSuccess();deleteSegment(segment); }
|
||||||
|
|
||||||
|
Close CLOSED { closeSocket();closed(""); }
|
||||||
|
ConnAckTimeout CLOSED { closeSocket();openFailed("acknowledge timeout"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
ESTABLISHED
|
||||||
|
{
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
CLOSE_WAIT { doSend(TcpSegment::ACK, NULL, 0, 0, &segment);halfClosed();deleteSegment(segment); }
|
||||||
|
|
||||||
|
PSH(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
nil { doSend(TcpSegment::ACK, NULL, 0, 0, &segment);receive(segment);deleteSegment(segment); }
|
||||||
|
|
||||||
|
Transmit(data: const char*, offset: int, size: int)
|
||||||
|
Transmitting
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::PSH, data, offset, size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Close
|
||||||
|
FIN_WAIT_1
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::FIN, NULL, 0, 0, NULL); }
|
||||||
|
}
|
||||||
|
|
||||||
|
Transmitting
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("TRANS_ACK_TIMER",
|
||||||
|
TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("TRANS_ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
ESTABLISHED
|
||||||
|
{
|
||||||
|
transmitted();
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSH_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
ESTABLISHED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
transmitted();
|
||||||
|
receive(segment);
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a push is received now, that means the far end sent
|
||||||
|
// data at exactly the same time as we sent it. Send an ack
|
||||||
|
// but don't go anywhere.
|
||||||
|
PSH(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
receive(segment);
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
CLOSE_WAIT
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
halfClosed();
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
Close
|
||||||
|
FIN_WAIT_1
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::FIN, NULL, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransAckTimeout
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
transmitFailed("peer did not acknowledge");
|
||||||
|
closed("connection lost");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOSE_WAIT
|
||||||
|
{
|
||||||
|
Close
|
||||||
|
LAST_ACK
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::FIN, NULL, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LAST_ACK
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("CLOSE_ACK_TIMER", TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("CLOSE_ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::FIN, NULL, 0, 0, &segment);
|
||||||
|
closeSocket();
|
||||||
|
closed("");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseAckTimeout
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
closed("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN_WAIT_1
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("CLOSE_ACK_TIMER", TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("CLOSE_ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
FIN_WAIT_2
|
||||||
|
{
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
CLOSING
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
TIME_WAIT
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseAckTimeout
|
||||||
|
FIN_WAIT_2
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
closed("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN_WAIT_2
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("CLOSE_ACK_TIMER", TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("CLOSE_ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort()]
|
||||||
|
TIME_WAIT
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::ACK, NULL, 0, 0, &segment);
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseAckTimeout
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore undefined transitions.
|
||||||
|
UNDEF(segment: const TcpSegment&)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOSING
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("CLOSE_ACK_TIMER", TcpConnection::ACK_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("CLOSE_ACK_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
TIME_WAIT
|
||||||
|
{
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseAckTimeout
|
||||||
|
TIME_WAIT
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
closed("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore undefined transitions.
|
||||||
|
UNDEF(segment: const TcpSegment&)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TIME_WAIT
|
||||||
|
Entry
|
||||||
|
{
|
||||||
|
startTimer("CLOSE_TIMER", TcpConnection::CLOSE_TIMEOUT);
|
||||||
|
}
|
||||||
|
Exit
|
||||||
|
{
|
||||||
|
stopTimer("CLOSE_TIMER");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FIN_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() == ctxt.getFarAddress() &&
|
||||||
|
segment.getSrcPort() == ctxt.getFarPort() &&
|
||||||
|
segment.getAcknowledgeNumber() == ctxt.getSequenceNumber()]
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseTimeout
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closeSocket();
|
||||||
|
closed("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore undefined transitions.
|
||||||
|
UNDEF(segment: const TcpSegment&)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
PassiveOpen(port : unsigned short)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
openFailed("already open");
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveOpen(address: const sockaddr_in*)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
openFailed("already open");
|
||||||
|
}
|
||||||
|
|
||||||
|
Transmit(data: const char*, offset: int, size: int)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
transmitFailed("connection not established");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default action when an unknown client sends us a
|
||||||
|
// segment is to reset the unknown client but remain in
|
||||||
|
// the current state for a segment from the real client.
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYN(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSH(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
URG(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYN_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSH_ACK(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNDEF(segment: const TcpSegment&)
|
||||||
|
[segment.getSrcAddress() != ctxt.getFarAddress() ||
|
||||||
|
segment.getSrcPort() != ctxt.getFarPort()]
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not reset a reset. Just go to closed.
|
||||||
|
RST(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closed("connection reset by peer");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
RST_ACK(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
closed("connection reset by peer");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The remain transitions represent segments received
|
||||||
|
// when they were not expected from the peer. The
|
||||||
|
// connection is reset.
|
||||||
|
FIN(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYN(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSH(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACK(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
URG(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIN_ACK(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYN_ACK(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSH_ACK(segment: const TcpSegment&)
|
||||||
|
CLOSED
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNDEF(segment: const TcpSegment&)
|
||||||
|
nil
|
||||||
|
{
|
||||||
|
doSend(TcpSegment::RST, NULL, 0, 0, &segment);
|
||||||
|
closed("connection reset");
|
||||||
|
deleteSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore timeouts which occur when not expected.
|
||||||
|
ConnAckTimeout
|
||||||
|
nil
|
||||||
|
{}
|
||||||
|
|
||||||
|
TransAckTimeout
|
||||||
|
nil
|
||||||
|
{}
|
||||||
|
|
||||||
|
CloseAckTimeout
|
||||||
|
nil
|
||||||
|
{}
|
||||||
|
|
||||||
|
CloseTimeout
|
||||||
|
nil
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
%%
|
127
FSM/samples/TCP/TCP_vs120.vcxproj
Normal file
127
FSM/samples/TCP/TCP_vs120.vcxproj
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.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>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="AppClient.cpp" />
|
||||||
|
<ClCompile Include="AppServer.cpp" />
|
||||||
|
<ClCompile Include="client.cpp" />
|
||||||
|
<ClCompile Include="Eventloop.cpp" />
|
||||||
|
<ClCompile Include="server.cpp" />
|
||||||
|
<ClCompile Include="stdafx.cpp" />
|
||||||
|
<ClCompile Include="TcpClient.cpp" />
|
||||||
|
<ClCompile Include="TcpConnection.cpp" />
|
||||||
|
<ClCompile Include="TcpSegment.cpp" />
|
||||||
|
<ClCompile Include="TcpServer.cpp" />
|
||||||
|
<ClCompile Include="winsock_strerror.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="AppClient.h" />
|
||||||
|
<ClInclude Include="AppServer.h" />
|
||||||
|
<ClInclude Include="Eventloop.h" />
|
||||||
|
<ClInclude Include="InputListener.h" />
|
||||||
|
<ClInclude Include="stdafx.h" />
|
||||||
|
<ClInclude Include="targetver.h" />
|
||||||
|
<ClInclude Include="TcpClient.h" />
|
||||||
|
<ClInclude Include="TcpConnection.h" />
|
||||||
|
<ClInclude Include="TcpConnectionListener.h" />
|
||||||
|
<ClInclude Include="TcpSegment.h" />
|
||||||
|
<ClInclude Include="TcpServer.h" />
|
||||||
|
<ClInclude Include="TimerListener.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TCP.sm" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{11E01C5F-683C-4290-B520-D3D248327DE1}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>TrafficLight</RootNamespace>
|
||||||
|
<ProjectName>TCP</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</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>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>$(IncludePath)</IncludePath>
|
||||||
|
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\FSM\include;..\..\..\Util\include;..\..\..\Foundation\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>set PATH=..\..\..\bin;%PATH% && ..\..\bin\fsmc TCP.sm</Command>
|
||||||
|
<Outputs>SpotLight_sm.h;SpotLight_sm.cpp</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</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;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\FSM\include;..\..\..\Util\include;..\..\..\Foundation\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>set PATH=..\..\..\bin;%PATH% && ..\..\bin\fsmc TCP.sm</Command>
|
||||||
|
<Outputs>SpotLight_sm.h;SpotLight_sm.cpp</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
157
FSM/samples/TCP/TcpClient.cpp
Normal file
157
FSM/samples/TCP/TcpClient.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2003 Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpClient.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP client connection class implementation.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpClient.cpp,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpClient.cpp,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:39:43 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpClient.h"
|
||||||
|
#if defined (WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
# if defined(__sun)
|
||||||
|
#include <sys/systeminfo.h>
|
||||||
|
# else
|
||||||
|
#include <unistd.h>
|
||||||
|
# endif
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Const declarations.
|
||||||
|
const static long MAX_HOSTNAME_LEN = 257;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// TcpClient(TcpConnectionListener&) (Public)
|
||||||
|
// Create an unconnected TCP client.
|
||||||
|
//
|
||||||
|
TcpClient::TcpClient(TcpConnectionListener& listener)
|
||||||
|
: TcpConnection(listener)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~TcpClient() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
TcpClient::~TcpClient()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getServerAddress() const (Public)
|
||||||
|
// This client is connected to this TCP service.
|
||||||
|
//
|
||||||
|
const sockaddr_in& TcpClient::getServerAddress() const
|
||||||
|
{
|
||||||
|
return(_farAddress);
|
||||||
|
} // end of TcpClient::getServerAddress() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getClientPort() const (Public)
|
||||||
|
// This client's TCP port.
|
||||||
|
//
|
||||||
|
unsigned short TcpClient::getClientPort() const
|
||||||
|
{
|
||||||
|
return(_nearAddress.sin_port);
|
||||||
|
} // end of TcpClient::getClientPort() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// open(unsigned short) (Public)
|
||||||
|
// Open a client connection to a local TCP service.
|
||||||
|
//
|
||||||
|
void TcpClient::open(unsigned short port)
|
||||||
|
{
|
||||||
|
sockaddr_in address;
|
||||||
|
char hostname[MAX_HOSTNAME_LEN];
|
||||||
|
hostent *hostentry;
|
||||||
|
|
||||||
|
// Get the local address.
|
||||||
|
#if defined(__sun)
|
||||||
|
(void) sysinfo(SI_HOSTNAME, hostname, MAX_HOSTNAME_LEN);
|
||||||
|
#else
|
||||||
|
(void) gethostname(hostname, MAX_HOSTNAME_LEN);
|
||||||
|
#endif
|
||||||
|
hostentry = gethostbyname(hostname);
|
||||||
|
|
||||||
|
// Fill in the destination address.
|
||||||
|
address.sin_port = port;
|
||||||
|
(void) memcpy(&(address.sin_addr.s_addr),
|
||||||
|
hostentry->h_addr_list[0],
|
||||||
|
4);
|
||||||
|
|
||||||
|
activeOpen(address);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of TcpClient::open(unsigned short)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// open(const sockaddr_in&) (Public)
|
||||||
|
// Open a client connection to a remove TCP service.
|
||||||
|
//
|
||||||
|
void TcpClient::open(const sockaddr_in& address)
|
||||||
|
{
|
||||||
|
activeOpen(address);
|
||||||
|
return;
|
||||||
|
} // end of TcpClient::open(const sockaddr_in&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// TcpClient(const sockaddr_in&, ...) (Private)
|
||||||
|
// Create an "accepted" client connection.
|
||||||
|
//
|
||||||
|
TcpClient::TcpClient(const sockaddr_in& far_address,
|
||||||
|
const sockaddr_in& near_address,
|
||||||
|
#if defined(WIN32)
|
||||||
|
unsigned short actual_port,
|
||||||
|
SOCKET udp_socket,
|
||||||
|
HANDLE udp_handle,
|
||||||
|
#else
|
||||||
|
int udp_socket,
|
||||||
|
#endif
|
||||||
|
unsigned long sequence_number,
|
||||||
|
TcpServer& server,
|
||||||
|
TcpConnectionListener& listener)
|
||||||
|
: TcpConnection(far_address,
|
||||||
|
near_address,
|
||||||
|
#if defined(WIN32)
|
||||||
|
actual_port,
|
||||||
|
udp_socket,
|
||||||
|
udp_handle,
|
||||||
|
#else
|
||||||
|
udp_socket,
|
||||||
|
#endif
|
||||||
|
sequence_number,
|
||||||
|
server,
|
||||||
|
listener)
|
||||||
|
{}
|
104
FSM/samples/TCP/TcpClient.h
Normal file
104
FSM/samples/TCP/TcpClient.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#ifndef _H_TCPCLIENT
|
||||||
|
#define _H_TCPCLIENT
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpClient.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP client connection class header.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpClient.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpClient.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:40:04 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpConnection.h"
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
class TcpServer;
|
||||||
|
|
||||||
|
class TcpClient: public TcpConnection
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Create an unconnected client.
|
||||||
|
TcpClient(TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
~TcpClient();
|
||||||
|
|
||||||
|
// This client is connected to this TCP service.
|
||||||
|
const sockaddr_in& getServerAddress() const;
|
||||||
|
|
||||||
|
// This client's TCP port.
|
||||||
|
unsigned short getClientPort() const;
|
||||||
|
|
||||||
|
// Open a client connection to a local TCP service.
|
||||||
|
void open(unsigned short port);
|
||||||
|
|
||||||
|
// Open a client connection to a remote TCP service.
|
||||||
|
void open(const sockaddr_in& address);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Create an "accepted" client connection. This constructor
|
||||||
|
// may only be called by TcpConnection.
|
||||||
|
TcpClient(const sockaddr_in& far_address,
|
||||||
|
const sockaddr_in& near_address,
|
||||||
|
#if defined(WIN32)
|
||||||
|
unsigned short actual_port,
|
||||||
|
SOCKET udp_socket,
|
||||||
|
HANDLE udp_handle,
|
||||||
|
#else
|
||||||
|
int udp_socket,
|
||||||
|
#endif
|
||||||
|
unsigned long sequence_number,
|
||||||
|
TcpServer& server,
|
||||||
|
TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// Don't allow default or copy constructors.
|
||||||
|
TcpClient();
|
||||||
|
TcpClient(const TcpClient&);
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Friends.
|
||||||
|
friend class TcpConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
1428
FSM/samples/TCP/TcpConnection.cpp
Normal file
1428
FSM/samples/TCP/TcpConnection.cpp
Normal file
File diff suppressed because it is too large
Load Diff
237
FSM/samples/TCP/TcpConnection.h
Normal file
237
FSM/samples/TCP/TcpConnection.h
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#ifndef _H_TCPCONNECTION
|
||||||
|
#define _H_TCPCONNECTION
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpConnection.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP connection class header.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpConnection.h,v 1.6 2015/08/02 19:44:35 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpConnection.h,v $
|
||||||
|
// Revision 1.6 2015/08/02 19:44:35 cwrapp
|
||||||
|
// Release 6.6.0 commit.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:40:45 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#include "TcpSegment.h"
|
||||||
|
#include "TcpConnection_sm.h"
|
||||||
|
#include "TcpConnectionListener.h"
|
||||||
|
#include "InputListener.h"
|
||||||
|
#include "TimerListener.h"
|
||||||
|
|
||||||
|
class TcpConnection :
|
||||||
|
/* implements */ public InputListener,
|
||||||
|
/* implements */ public TimerListener
|
||||||
|
#ifdef CRTP
|
||||||
|
/* extends */ , public TcpConnectionContext<TcpConnection>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~TcpConnection();
|
||||||
|
|
||||||
|
// Return the far-end's 4-byte IP address.
|
||||||
|
unsigned long getFarAddress() const;
|
||||||
|
|
||||||
|
// Return the far-end's TCP port.
|
||||||
|
unsigned short getFarPort() const;
|
||||||
|
|
||||||
|
// Return the current sequence number.
|
||||||
|
unsigned long getSequenceNumber() const;
|
||||||
|
|
||||||
|
// Send the raw bytes to the far end client socket.
|
||||||
|
void transmit(const char *data,
|
||||||
|
int offset,
|
||||||
|
int size);
|
||||||
|
|
||||||
|
// Start closing this connection.
|
||||||
|
void doClose();
|
||||||
|
|
||||||
|
// Set an accepted client socket's listener.
|
||||||
|
void setListener(TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// Socket event handling methods.
|
||||||
|
void handleReceive(int fd);
|
||||||
|
void handleTimeout(const char *name);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
// State Machine Actions
|
||||||
|
//
|
||||||
|
void openServerSocket(unsigned short port);
|
||||||
|
void openClientSocket(const sockaddr_in *address);
|
||||||
|
void openSuccess();
|
||||||
|
void openFailed(const char *reason);
|
||||||
|
void closeSocket();
|
||||||
|
void halfClosed();
|
||||||
|
void closed(const char *reason);
|
||||||
|
void clearListener();
|
||||||
|
void transmitted();
|
||||||
|
void transmitFailed(const char *reason);
|
||||||
|
void receive(const TcpSegment& segment);
|
||||||
|
void sendOpenSyn(const sockaddr_in *address);
|
||||||
|
void accept(const TcpSegment& segment);
|
||||||
|
void accepted();
|
||||||
|
void sendSynAck(const TcpSegment& segment);
|
||||||
|
void sendSynAckAck(const TcpSegment& segment);
|
||||||
|
void doSend(unsigned short flags,
|
||||||
|
const char *data,
|
||||||
|
int offset,
|
||||||
|
int size,
|
||||||
|
const TcpSegment *recv_segment);
|
||||||
|
void startTimer(const char *name, time_t time);
|
||||||
|
void stopTimer(const char *name);
|
||||||
|
void setNearAddress();
|
||||||
|
void setFarAddress(const TcpSegment& segment);
|
||||||
|
void deleteSegment(const TcpSegment& segment);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Server and active client socket constructor.
|
||||||
|
TcpConnection(TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// "Accepted" socket constructor.
|
||||||
|
TcpConnection(const sockaddr_in& near_address,
|
||||||
|
const sockaddr_in& far_address,
|
||||||
|
#if defined(WIN32)
|
||||||
|
unsigned short actual_port,
|
||||||
|
SOCKET udp_socket,
|
||||||
|
HANDLE udp_handle,
|
||||||
|
#else
|
||||||
|
int udp_socket,
|
||||||
|
#endif
|
||||||
|
int sequence_number,
|
||||||
|
TcpServer& server,
|
||||||
|
TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// Open a server socket.
|
||||||
|
void passiveOpen(unsigned short port);
|
||||||
|
|
||||||
|
// Open a client socket.
|
||||||
|
void activeOpen(const sockaddr_in& address);
|
||||||
|
|
||||||
|
// An accepted client socket.
|
||||||
|
void acceptOpen(const TcpSegment& segment);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Copy construction and assignment not allowed.
|
||||||
|
TcpConnection(const TcpConnection&);
|
||||||
|
const TcpConnection& operator=(const TcpConnection&);
|
||||||
|
|
||||||
|
// Increase the buffer's size.
|
||||||
|
void expandBuffer();
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// Windows doesn't bind UDP sockets to random ports
|
||||||
|
// correctly. So this app has to do it itself.
|
||||||
|
int doBind(int handle) const;
|
||||||
|
#else
|
||||||
|
// Return the UDP socket's port.
|
||||||
|
unsigned short getLocalPort(int fd) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Return this machine's address.
|
||||||
|
unsigned long getLocalAddress() const;
|
||||||
|
|
||||||
|
// Return the expected ack number for the given segment.
|
||||||
|
int getAck(const TcpSegment& segment);
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
// Initial Sequence Number.
|
||||||
|
const static unsigned long ISN;
|
||||||
|
|
||||||
|
// Minimum timeout is 1 millisecond.
|
||||||
|
const static int MIN_TIMEOUT;
|
||||||
|
|
||||||
|
// Wait only so long for an ACK (in milliseconds).
|
||||||
|
const static int ACK_TIMEOUT;
|
||||||
|
|
||||||
|
// Wait a while before reusing this port (in milliseconds).
|
||||||
|
const static int CLOSE_TIMEOUT;
|
||||||
|
|
||||||
|
// Allocate the input buffer using this block size.
|
||||||
|
const static int BUFFER_BLOCK_SIZE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Send TCP events to this listener.
|
||||||
|
TcpConnectionListener *_listener;
|
||||||
|
|
||||||
|
// Connected to this address.
|
||||||
|
sockaddr_in _farAddress;
|
||||||
|
|
||||||
|
// This socket's address.
|
||||||
|
sockaddr_in _nearAddress;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// This socket's actual port number.
|
||||||
|
unsigned short _actualPort;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
SOCKET _udp_win_socket;
|
||||||
|
#endif
|
||||||
|
int _udp_socket;
|
||||||
|
unsigned long _sequence_number;
|
||||||
|
|
||||||
|
// Read data into the following buffer.
|
||||||
|
char *_buffer;
|
||||||
|
int _bufferSize;
|
||||||
|
|
||||||
|
// The server which accepted this connection. Will only be
|
||||||
|
// set if this is an "accepted" client connection.
|
||||||
|
TcpServer *_server;
|
||||||
|
|
||||||
|
// Store failure messages here.
|
||||||
|
char *_errorMessage;
|
||||||
|
|
||||||
|
#ifndef CRTP
|
||||||
|
TcpConnectionContext _fsm;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
81
FSM/samples/TCP/TcpConnectionListener.h
Normal file
81
FSM/samples/TCP/TcpConnectionListener.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef _H_TCPCONNECTIONLISTENER
|
||||||
|
#define _H_TCPCONNECTIONLISTENER
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpConnectionListener.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP connection connection callback handler.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpConnectionListener.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpConnectionListener.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:41:24 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
class TcpConnection;
|
||||||
|
class TcpClient;
|
||||||
|
class TcpServer;
|
||||||
|
|
||||||
|
class TcpConnectionListener
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~TcpConnectionListener()
|
||||||
|
{};
|
||||||
|
|
||||||
|
virtual void opened(TcpConnection& connection)=0;
|
||||||
|
virtual void openFailed(const char *reason,
|
||||||
|
TcpConnection& connection)=0;
|
||||||
|
virtual void halfClosed(TcpConnection& connection)=0;
|
||||||
|
virtual void closed(const char *reason,
|
||||||
|
TcpConnection& connection)=0;
|
||||||
|
virtual void transmitted(TcpConnection& connection)=0;
|
||||||
|
virtual void transmitFailed(const char *reason,
|
||||||
|
TcpConnection& connection)=0;
|
||||||
|
virtual void receive(const char *data,
|
||||||
|
int size,
|
||||||
|
TcpConnection& connection)=0;
|
||||||
|
virtual void accepted(TcpClient& client, TcpServer& server)=0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
471
FSM/samples/TCP/TcpSegment.cpp
Normal file
471
FSM/samples/TCP/TcpSegment.cpp
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpSegment.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Converts between raw bytes and segment objects.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpSegment.cpp,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpSegment.cpp,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:41:38 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpSegment.h"
|
||||||
|
#include <memory.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#if !defined(WIN32)
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Static member data declarations.
|
||||||
|
const int TcpSegment::TCP_HEADER_SIZE = 16;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// TcpSegment(const sockaddr_in&, ...) (Public)
|
||||||
|
// Create an outbound segment.
|
||||||
|
//
|
||||||
|
TcpSegment::TcpSegment(const sockaddr_in& source_address,
|
||||||
|
const sockaddr_in& destination_address,
|
||||||
|
unsigned long sequence_number,
|
||||||
|
unsigned long ack_number,
|
||||||
|
unsigned short flags,
|
||||||
|
const char *data,
|
||||||
|
int offset,
|
||||||
|
int size)
|
||||||
|
{
|
||||||
|
(void) memcpy(&_src_address,
|
||||||
|
&source_address,
|
||||||
|
sizeof(source_address));
|
||||||
|
(void) memcpy(&_dest_address,
|
||||||
|
&destination_address,
|
||||||
|
sizeof(destination_address));
|
||||||
|
_sequence_number = sequence_number;
|
||||||
|
_ack_number = ack_number;
|
||||||
|
_flags = flags;
|
||||||
|
|
||||||
|
// Copy the data.
|
||||||
|
_data = new char[size];
|
||||||
|
_data_size = size;
|
||||||
|
(void) memcpy(_data, (data + offset), size);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of TcpSegment::TcpSegment(const sockaddr_in&, ...)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// TcpSegment(const sockaddr_in&, ...) (Public)
|
||||||
|
// Create an inbound segment.
|
||||||
|
//
|
||||||
|
TcpSegment::TcpSegment(const sockaddr_in& source_address,
|
||||||
|
const sockaddr_in& dest_address,
|
||||||
|
const char *data,
|
||||||
|
int)
|
||||||
|
{
|
||||||
|
unsigned short srcPort;
|
||||||
|
unsigned short destPort;
|
||||||
|
unsigned long sequence;
|
||||||
|
unsigned long ack;
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short data_size;
|
||||||
|
|
||||||
|
srcPort = ((((unsigned short) data[ 0]) & 0x00ff) << 8) |
|
||||||
|
(((unsigned short) data[ 1]) & 0x00ff);
|
||||||
|
destPort = ((((unsigned short) data[ 2]) & 0x00ff) << 8) |
|
||||||
|
(((unsigned short) data[ 3]) & 0x00ff);
|
||||||
|
sequence = ((((unsigned long) data[ 4]) & 0x000000ff) << 24) |
|
||||||
|
((((unsigned long) data[ 5]) & 0x000000ff) << 16) |
|
||||||
|
((((unsigned long) data[ 6]) & 0x000000ff) << 8) |
|
||||||
|
(((unsigned long) data[ 7]) & 0x000000ff);
|
||||||
|
ack = ((((unsigned long) data[ 8]) & 0x000000ff) << 24) |
|
||||||
|
((((unsigned long) data[ 9]) & 0x000000ff) << 16) |
|
||||||
|
((((unsigned long) data[10]) & 0x000000ff) << 8) |
|
||||||
|
(((unsigned long) data[11]) & 0x000000ff);
|
||||||
|
flags = ((((unsigned short) data[12]) & 0x00ff) << 8) |
|
||||||
|
(((unsigned short) data[13]) & 0x00ff);
|
||||||
|
data_size = ((((unsigned short) data[14]) & 0x00ff) << 8) |
|
||||||
|
(((unsigned short) data[15]) & 0x00ff);
|
||||||
|
|
||||||
|
// Set the source address.
|
||||||
|
_src_address.sin_family = AF_INET;
|
||||||
|
_src_address.sin_port = ntohs(srcPort);
|
||||||
|
_src_address.sin_addr.s_addr = source_address.sin_addr.s_addr;
|
||||||
|
|
||||||
|
// Set the destination address.
|
||||||
|
_dest_address.sin_family = AF_INET;
|
||||||
|
_dest_address.sin_port = ntohs(destPort);
|
||||||
|
_dest_address.sin_addr.s_addr = dest_address.sin_addr.s_addr;
|
||||||
|
|
||||||
|
_sequence_number = sequence;
|
||||||
|
_ack_number = ack;
|
||||||
|
_flags = flags;
|
||||||
|
_data_size = data_size;
|
||||||
|
|
||||||
|
|
||||||
|
if (_data_size == 0)
|
||||||
|
{
|
||||||
|
_data = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_data = new char[_data_size];
|
||||||
|
(void) memcpy(_data,
|
||||||
|
&(data[TCP_HEADER_SIZE]),
|
||||||
|
_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of TcpSegment::TcpSegment(const char*, int)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~TcpSegment() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
TcpSegment::~TcpSegment()
|
||||||
|
{
|
||||||
|
if (_data != NULL)
|
||||||
|
{
|
||||||
|
delete[] _data;
|
||||||
|
_data = NULL;
|
||||||
|
_data_size = 0;
|
||||||
|
}
|
||||||
|
} // end of TcpSegment::~TcpSegment()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getSource() const (Public)
|
||||||
|
// Return segment's source address.
|
||||||
|
//
|
||||||
|
const sockaddr_in& TcpSegment::getSource() const
|
||||||
|
{
|
||||||
|
return(_src_address);
|
||||||
|
} // end of TcpSegment::getSource() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getDestination() const (Public)
|
||||||
|
// Return segment's destination address.
|
||||||
|
//
|
||||||
|
const sockaddr_in& TcpSegment::getDestination() const
|
||||||
|
{
|
||||||
|
return(_dest_address);
|
||||||
|
} // end of TcpSegment::getDestination() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getSrcAddress() const (Public)
|
||||||
|
// Return the segment's source address.
|
||||||
|
//
|
||||||
|
unsigned long TcpSegment::getSrcAddress() const
|
||||||
|
{
|
||||||
|
return (_src_address.sin_addr.s_addr);
|
||||||
|
} // end of TcpSegment::getSrcAddress() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getSrcPort() const (Public)
|
||||||
|
// Return the segment's source port.
|
||||||
|
//
|
||||||
|
unsigned short TcpSegment::getSrcPort() const
|
||||||
|
{
|
||||||
|
return (_src_address.sin_port);
|
||||||
|
} // end of TcpSegment::getSrcPort() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getDestAddress() const (Public)
|
||||||
|
// Return the segment's destination address.
|
||||||
|
//
|
||||||
|
unsigned long TcpSegment::getDestAddress() const
|
||||||
|
{
|
||||||
|
return (_dest_address.sin_addr.s_addr);
|
||||||
|
} // end of TcpSegment::getDestAddress() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getDestPort() const (Public)
|
||||||
|
// Return the segment's destination port.
|
||||||
|
//
|
||||||
|
unsigned short TcpSegment::getDestPort() const
|
||||||
|
{
|
||||||
|
return (_dest_address.sin_port);
|
||||||
|
} // end of TcpSegment::getDestPort() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getSequenceNumber() const (Public)
|
||||||
|
// Return segment's sequence number.
|
||||||
|
//
|
||||||
|
unsigned long TcpSegment::getSequenceNumber() const
|
||||||
|
{
|
||||||
|
return(_sequence_number);
|
||||||
|
} // end of TcpSegment::getSequenceNumber() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getAcknowledgeNumber() const (Public)
|
||||||
|
// Return segment's acknowledge number.
|
||||||
|
//
|
||||||
|
unsigned long TcpSegment::getAcknowledgeNumber() const
|
||||||
|
{
|
||||||
|
return(_ack_number);
|
||||||
|
} // end of TcpSegment::getAcknowledgeNumber() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getFlags() const (Public)
|
||||||
|
// Return segment's flags.
|
||||||
|
//
|
||||||
|
unsigned short TcpSegment::getFlags() const
|
||||||
|
{
|
||||||
|
return(_flags);
|
||||||
|
} // end of TcpSegment::getFlags() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getDataSize() const (Public)
|
||||||
|
// Return segment's data size.
|
||||||
|
//
|
||||||
|
int TcpSegment::getDataSize() const
|
||||||
|
{
|
||||||
|
return(_data_size);
|
||||||
|
} // end of TcpSegment::getDataSize() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getData() const (Public)
|
||||||
|
// Return segment's data.
|
||||||
|
//
|
||||||
|
const char* TcpSegment::getData() const
|
||||||
|
{
|
||||||
|
return(_data);
|
||||||
|
} // end of TcpSegment::getData() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// packetize(char*&, int&) (Public)
|
||||||
|
// Convert this TCP segment into raw bytes.
|
||||||
|
//
|
||||||
|
void TcpSegment::packetize(char*& data, int& size)
|
||||||
|
{
|
||||||
|
unsigned short srcPort;
|
||||||
|
unsigned short destPort;
|
||||||
|
unsigned long sequence;
|
||||||
|
unsigned long ack;
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short data_size;
|
||||||
|
|
||||||
|
// The segment's size is the TCP header size + data size.
|
||||||
|
// (TCP options are *not* supported).
|
||||||
|
size = TCP_HEADER_SIZE + _data_size;
|
||||||
|
|
||||||
|
data = new char[size];
|
||||||
|
|
||||||
|
// Get data in network byte order.
|
||||||
|
srcPort = htons(_src_address.sin_port);
|
||||||
|
destPort = htons(_dest_address.sin_port);
|
||||||
|
sequence = _sequence_number;
|
||||||
|
ack = _ack_number;
|
||||||
|
flags = _flags;
|
||||||
|
data_size = _data_size;
|
||||||
|
|
||||||
|
// Fill in the TCP header.
|
||||||
|
data[ 0] = (char) (( srcPort & 0xff00) >> 8);
|
||||||
|
data[ 1] = (char) ( srcPort & 0x00ff);
|
||||||
|
data[ 2] = (char) (( destPort & 0xff00) >> 8);
|
||||||
|
data[ 3] = (char) ( destPort & 0x00ff);
|
||||||
|
data[ 4] = (char) (( sequence & 0xff000000) >> 24);
|
||||||
|
data[ 5] = (char) (( sequence & 0x00ff0000) >> 16);
|
||||||
|
data[ 6] = (char) (( sequence & 0x0000ff00) >> 8);
|
||||||
|
data[ 7] = (char) ( sequence & 0x000000ff);
|
||||||
|
data[ 8] = (char) (( ack & 0xff000000) >> 24);
|
||||||
|
data[ 9] = (char) (( ack & 0x00ff0000) >> 16);
|
||||||
|
data[10] = (char) (( ack & 0x0000ff00) >> 8);
|
||||||
|
data[11] = (char) ( ack & 0x000000ff);
|
||||||
|
data[12] = (char) (( flags & 0xff00) >> 8);
|
||||||
|
data[13] = (char) ( flags & 0x00ff);
|
||||||
|
data[14] = (char) ((data_size & 0xff00) >> 8);
|
||||||
|
data[15] = (char) (data_size & 0x00ff);
|
||||||
|
|
||||||
|
// Copy in the data.
|
||||||
|
if (_data_size > 0)
|
||||||
|
{
|
||||||
|
(void) memcpy((data + TCP_HEADER_SIZE),
|
||||||
|
_data,
|
||||||
|
_data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of TcpSegment::packetize(char&*, int&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// flagsToString(unsigned short) (Static Private)
|
||||||
|
// Make a string representation of the TCP header flags.
|
||||||
|
//
|
||||||
|
char* TcpSegment::flagsToString(unsigned short flags)
|
||||||
|
{
|
||||||
|
char separator[3] = "{";
|
||||||
|
char *retval;
|
||||||
|
char *cptr;
|
||||||
|
|
||||||
|
(void) strcpy(separator, "{");
|
||||||
|
retval = new char[31];
|
||||||
|
(void) memset(retval, 0, 31);
|
||||||
|
cptr = retval;
|
||||||
|
if ((flags & FIN) == FIN)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "FIN");
|
||||||
|
cptr += 3;
|
||||||
|
(void) strcpy(separator, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & SYN) == SYN)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "SYN");
|
||||||
|
cptr += 3;
|
||||||
|
(void) strcpy(separator, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & RST) == RST)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "RST");
|
||||||
|
cptr += 3;
|
||||||
|
(void) strcpy(separator, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & PSH) == PSH)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "PSH");
|
||||||
|
cptr += 3;
|
||||||
|
(void) strcpy(separator, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & ACK) == ACK)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "ACK");
|
||||||
|
cptr += 3;
|
||||||
|
(void) strcpy(separator, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & URG) == URG)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "URG");
|
||||||
|
cptr += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & FLAG_MASK) == 0)
|
||||||
|
{
|
||||||
|
(void) strcpy(cptr, separator);
|
||||||
|
cptr += strlen(separator);
|
||||||
|
(void) strcpy(cptr, "UNK");
|
||||||
|
cptr += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cptr = '}';
|
||||||
|
|
||||||
|
return(retval);
|
||||||
|
} // end of TcpSegment::flagsToString(unsigned short)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// addressToString(const sockaddr_in&) (Static Private)
|
||||||
|
// Generate a string representation of an IP address.
|
||||||
|
//
|
||||||
|
char* TcpSegment::addressToString(const sockaddr_in& address)
|
||||||
|
{
|
||||||
|
struct hostent *hostEntry;
|
||||||
|
char *dotted_addr;
|
||||||
|
char port[6];
|
||||||
|
char *retval;
|
||||||
|
char *cptr;
|
||||||
|
unsigned short udp_port;
|
||||||
|
|
||||||
|
retval = new char[512];
|
||||||
|
(void) memset(retval, 0, 512);
|
||||||
|
cptr = retval;
|
||||||
|
hostEntry = gethostbyaddr((char *) &(address.sin_addr),
|
||||||
|
sizeof(address.sin_addr),
|
||||||
|
AF_INET);
|
||||||
|
(void) strcpy(cptr,
|
||||||
|
(hostEntry == NULL ?
|
||||||
|
"<no hostname>" :
|
||||||
|
hostEntry->h_name));
|
||||||
|
cptr += strlen(cptr);
|
||||||
|
*cptr++ = '(';
|
||||||
|
dotted_addr = inet_ntoa(address.sin_addr);
|
||||||
|
(void) strcpy(cptr, dotted_addr);
|
||||||
|
cptr += strlen(dotted_addr);
|
||||||
|
(void) strcpy(cptr, "):");
|
||||||
|
cptr += 2;
|
||||||
|
udp_port = ntohs(address.sin_port);
|
||||||
|
sprintf(port, "%d", udp_port);
|
||||||
|
(void) strcpy(cptr, port);
|
||||||
|
|
||||||
|
return(retval);
|
||||||
|
} // end of TcpSegment::addressToString(const sockaddr_in&)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// operator<<(ostream&, const TcpSegment&) (Routine)
|
||||||
|
// Print this segment out to the stream.
|
||||||
|
//
|
||||||
|
ostream& operator<<(ostream& stream, const TcpSegment& segment)
|
||||||
|
{
|
||||||
|
char *srcAddrStr,
|
||||||
|
*destAddrStr,
|
||||||
|
*flagStr;
|
||||||
|
|
||||||
|
srcAddrStr = TcpSegment::addressToString(segment._src_address);
|
||||||
|
destAddrStr = TcpSegment::addressToString(segment._dest_address);
|
||||||
|
flagStr = TcpSegment::flagsToString(segment._flags);
|
||||||
|
|
||||||
|
stream << "\t Source: "
|
||||||
|
<< srcAddrStr
|
||||||
|
<< "\n\t Destination: "
|
||||||
|
<< destAddrStr
|
||||||
|
<< "\n\t Sequence #: "
|
||||||
|
<< segment._sequence_number
|
||||||
|
<< "\n\tAcknowledge #: "
|
||||||
|
<< segment._ack_number
|
||||||
|
<< "\n\t Flags: "
|
||||||
|
<< flagStr
|
||||||
|
<< " (0x"
|
||||||
|
<< ios::hex << segment._flags << ios::dec << ")"
|
||||||
|
<< "\n\t Data size: "
|
||||||
|
<< segment._data_size;
|
||||||
|
|
||||||
|
delete[] srcAddrStr;
|
||||||
|
delete[] destAddrStr;
|
||||||
|
delete[] flagStr;
|
||||||
|
|
||||||
|
return(stream);
|
||||||
|
} // end of operator<<(ostream&, const TcpSegment&)
|
145
FSM/samples/TCP/TcpSegment.h
Normal file
145
FSM/samples/TCP/TcpSegment.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#ifndef _H_TCPSEGMENT
|
||||||
|
#define _H_TCPSEGMENT
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpSegment.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// All TCP transmissions are put into a segment.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpSegment.h,v 1.6 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpSegment.h,v $
|
||||||
|
// Revision 1.6 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2005/06/08 11:09:12 cwrapp
|
||||||
|
// + Updated Python code generator to place "pass" in methods with empty
|
||||||
|
// bodies.
|
||||||
|
// + Corrected FSM errors in Python example 7.
|
||||||
|
// + Removed unnecessary includes from C++ examples.
|
||||||
|
// + Corrected errors in top-level makefile's distribution build.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:41:54 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#elif defined(WIN32)
|
||||||
|
#include <iostream>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <iostream.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class TcpSegment
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
TcpSegment(const sockaddr_in& source_address,
|
||||||
|
const sockaddr_in& destination_address,
|
||||||
|
unsigned long sequence_number,
|
||||||
|
unsigned long ack_number,
|
||||||
|
unsigned short flags,
|
||||||
|
const char *data,
|
||||||
|
int offset,
|
||||||
|
int size);
|
||||||
|
|
||||||
|
// Convert the raw bytes into a segment.
|
||||||
|
TcpSegment(const sockaddr_in& source_address,
|
||||||
|
const sockaddr_in& dest_address,
|
||||||
|
const char *data,
|
||||||
|
int size);
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
~TcpSegment();
|
||||||
|
|
||||||
|
const sockaddr_in& getSource() const;
|
||||||
|
const sockaddr_in& getDestination() const;
|
||||||
|
unsigned long getSrcAddress() const;
|
||||||
|
unsigned short getSrcPort() const;
|
||||||
|
unsigned long getDestAddress() const;
|
||||||
|
unsigned short getDestPort() const;
|
||||||
|
unsigned long getSequenceNumber() const;
|
||||||
|
unsigned long getAcknowledgeNumber() const;
|
||||||
|
unsigned short getFlags() const;
|
||||||
|
int getDataSize() const;
|
||||||
|
const char* getData() const;
|
||||||
|
|
||||||
|
// Convert this segment into raw bytes.
|
||||||
|
void packetize(char*& data, int& size);
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& stream,
|
||||||
|
const TcpSegment& segment);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
static char* flagsToString(unsigned short flags);
|
||||||
|
static char* addressToString(const sockaddr_in& address);
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum TcpHeaderFlags
|
||||||
|
{
|
||||||
|
NONE= 0x00,
|
||||||
|
FIN = 0x01,
|
||||||
|
SYN = 0x02,
|
||||||
|
RST = 0x04,
|
||||||
|
PSH = 0x08,
|
||||||
|
ACK = 0x10,
|
||||||
|
URG = 0x20,
|
||||||
|
FIN_ACK = 0x11,
|
||||||
|
SYN_ACK = 0x12,
|
||||||
|
RST_ACK = 0x14,
|
||||||
|
PSH_ACK = 0x18,
|
||||||
|
FLAG_MASK = 0x3f
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int TCP_HEADER_SIZE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
sockaddr_in _src_address;
|
||||||
|
sockaddr_in _dest_address;
|
||||||
|
unsigned long _sequence_number;
|
||||||
|
unsigned long _ack_number;
|
||||||
|
unsigned short _flags;
|
||||||
|
char *_data;
|
||||||
|
int _data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
85
FSM/samples/TCP/TcpServer.cpp
Normal file
85
FSM/samples/TCP/TcpServer.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpServer.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP server connection class implementation.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpServer.cpp,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpServer.cpp,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:43:00 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpServer.h"
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// TcpServer(TcpConnectionListener&) (Public)
|
||||||
|
// Create a TCP service object.
|
||||||
|
//
|
||||||
|
TcpServer::TcpServer(TcpConnectionListener& listener)
|
||||||
|
: TcpConnection(listener)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ~TcpServer() (Public)
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
TcpServer::~TcpServer()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getPort() const (Public)
|
||||||
|
// Return this service's TCP port.
|
||||||
|
//
|
||||||
|
unsigned short TcpServer::getPort() const
|
||||||
|
{
|
||||||
|
return(_nearAddress.sin_port);
|
||||||
|
} // end of TcpServer::getPort() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getAddress() const (Public)
|
||||||
|
// Return this service's IP address.
|
||||||
|
//
|
||||||
|
unsigned long TcpServer::getAddress() const
|
||||||
|
{
|
||||||
|
return(_nearAddress.sin_addr.s_addr);
|
||||||
|
} // end of TcpServer::getAddress() const
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// open(unsigned short) (Public)
|
||||||
|
// Open this TCP service.
|
||||||
|
//
|
||||||
|
void TcpServer::open(unsigned short port)
|
||||||
|
{
|
||||||
|
passiveOpen(port);
|
||||||
|
return;
|
||||||
|
} // end of TcpServer::open(unsigned short)
|
77
FSM/samples/TCP/TcpServer.h
Normal file
77
FSM/samples/TCP/TcpServer.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#ifndef _H_TCPSERVER
|
||||||
|
#define _H_TCPSERVER
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TcpServer.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// TCP server connection class header.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TcpServer.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TcpServer.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:43:20 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TcpConnection.h"
|
||||||
|
|
||||||
|
class TcpServer: public TcpConnection
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Create a TCP service.
|
||||||
|
TcpServer(TcpConnectionListener& listener);
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
~TcpServer();
|
||||||
|
|
||||||
|
// Return the TCP service's port.
|
||||||
|
unsigned short getPort() const;
|
||||||
|
|
||||||
|
// Return the TCP service's address.
|
||||||
|
unsigned long getAddress() const;
|
||||||
|
|
||||||
|
// Open the TCP service.
|
||||||
|
void open(unsigned short port);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
68
FSM/samples/TCP/TimerListener.h
Normal file
68
FSM/samples/TCP/TimerListener.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef _H_TIMERLISTENER
|
||||||
|
#define _H_TIMERLISTENER
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TimerListener.h
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Timer event handler.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: TimerListener.h,v 1.5 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: TimerListener.h,v $
|
||||||
|
// Revision 1.5 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:43:36 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
class TimerListener
|
||||||
|
{
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Default constructor.
|
||||||
|
TimerListener() {};
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~TimerListener() {};
|
||||||
|
|
||||||
|
// Input callback method.
|
||||||
|
virtual void handleTimeout(const char *name)=0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
277
FSM/samples/TCP/client.cpp
Normal file
277
FSM/samples/TCP/client.cpp
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// File
|
||||||
|
// client.cpp
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates "TCP" client connection.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: client.cpp,v 1.6 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: client.cpp,v $
|
||||||
|
// Revision 1.6 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2005/06/08 11:09:12 cwrapp
|
||||||
|
// + Updated Python code generator to place "pass" in methods with empty
|
||||||
|
// bodies.
|
||||||
|
// + Corrected FSM errors in Python example 7.
|
||||||
|
// + Removed unnecessary includes from C++ examples.
|
||||||
|
// + Corrected errors in top-level makefile's distribution build.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:43:52 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Eventloop.h"
|
||||||
|
#include "AppClient.h"
|
||||||
|
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
#include <string.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#elif defined(WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <string.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#ifndef SA_NOMASK
|
||||||
|
#define SA_NOMASK 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Global variable declarations.
|
||||||
|
Eventloop *Gevent_loop;
|
||||||
|
|
||||||
|
// Static variable declarations.
|
||||||
|
static AppClient *Sclient_socket;
|
||||||
|
|
||||||
|
// Constant declarations.
|
||||||
|
const static int STDIN_FD = 0;
|
||||||
|
#ifndef INADDR_NONE
|
||||||
|
const static unsigned long INADDR_NONE = 0xffffffff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
char* winsock_strerror(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// main(int, char**) (Routine)
|
||||||
|
// Process the command line arguments, open the TCP service and
|
||||||
|
// then sit in the event loop. Stop running when the Enter key
|
||||||
|
// is hit.
|
||||||
|
//
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int longPort;
|
||||||
|
unsigned long ip_address = INADDR_ANY;
|
||||||
|
sockaddr_in address;
|
||||||
|
int retcode;
|
||||||
|
#if defined(WIN32)
|
||||||
|
WORD winsockVersion;
|
||||||
|
WSADATA winsockData;
|
||||||
|
int errorCode;
|
||||||
|
#else
|
||||||
|
struct sigaction signalAction;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// External routine declarations.
|
||||||
|
unsigned long getIPAddress(const char*);
|
||||||
|
void sigintHandler(int);
|
||||||
|
#if defined(WIN32)
|
||||||
|
char* winsock_strerror(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows kinda supports signals.
|
||||||
|
(void) signal(SIGINT, sigintHandler);
|
||||||
|
#else
|
||||||
|
// Set up the SIGINT handler.
|
||||||
|
signalAction.sa_handler = sigintHandler;
|
||||||
|
#if defined(__hpux) || defined (__linux__)
|
||||||
|
sigemptyset(&signalAction.sa_mask);
|
||||||
|
#if defined(__linux__)
|
||||||
|
signalAction.sa_restorer = NULL;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
signalAction.sa_flags = SA_NOMASK;
|
||||||
|
if (sigaction(SIGINT,
|
||||||
|
&signalAction,
|
||||||
|
(struct sigaction *) NULL) != 0)
|
||||||
|
{
|
||||||
|
cerr << "Unable to set SIGINT handling function." << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// Initialize winsock.
|
||||||
|
winsockVersion = MAKEWORD(2, 0);
|
||||||
|
if ((errorCode = WSAStartup(winsockVersion, &winsockData)) != 0)
|
||||||
|
{
|
||||||
|
cout << "Unable to initialize Win32 sockets - "
|
||||||
|
<< winsock_strerror(errorCode)
|
||||||
|
<< "."
|
||||||
|
<< endl;
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
cerr << argv[0]
|
||||||
|
<< ": Wrong number of arguments."
|
||||||
|
<< endl;
|
||||||
|
cerr << "usage: client {hostname | IP address} port" << endl;
|
||||||
|
retcode = 1;
|
||||||
|
}
|
||||||
|
// Check the port's validity.
|
||||||
|
else if (sscanf(argv[2], "%d", &longPort) != 1 ||
|
||||||
|
longPort < 0 ||
|
||||||
|
longPort > 65535)
|
||||||
|
{
|
||||||
|
cerr << "Invalid port number - \""
|
||||||
|
<< argv[2]
|
||||||
|
<< "\"."
|
||||||
|
<< endl;
|
||||||
|
retcode = 2;
|
||||||
|
}
|
||||||
|
// Check the address' validity.
|
||||||
|
else if ((ip_address = getIPAddress(argv[1])) == INADDR_NONE)
|
||||||
|
{
|
||||||
|
cerr << "Invalid host - \""
|
||||||
|
<< argv[1]
|
||||||
|
<< "\"."
|
||||||
|
<< endl;
|
||||||
|
retcode = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string host(argv[1]);
|
||||||
|
unsigned short port;
|
||||||
|
|
||||||
|
// Set up the service address.
|
||||||
|
(void) memset(&address, 0, sizeof(address));
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
port = static_cast<unsigned short>(longPort);
|
||||||
|
address.sin_port = htons(port);
|
||||||
|
address.sin_addr.s_addr = ip_address;
|
||||||
|
|
||||||
|
cout << "(Starting execution. Hit \"Cntl-c\" to stop.)" << endl;
|
||||||
|
|
||||||
|
// 1. Create the event loop object.
|
||||||
|
Gevent_loop = new Eventloop();
|
||||||
|
|
||||||
|
// 2. Open server port.
|
||||||
|
Sclient_socket = new AppClient();
|
||||||
|
Sclient_socket->open(host, address);
|
||||||
|
|
||||||
|
// 3. Start connection process.
|
||||||
|
Gevent_loop->start();
|
||||||
|
|
||||||
|
cout << "(Stopping execution.)" << endl;
|
||||||
|
|
||||||
|
// 4. Close connection.
|
||||||
|
delete Sclient_socket;
|
||||||
|
Sclient_socket = NULL;
|
||||||
|
|
||||||
|
// Delete the event loop.
|
||||||
|
delete Gevent_loop;
|
||||||
|
Gevent_loop = NULL;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
retcode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(retcode);
|
||||||
|
} // end of main(int, char**)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// socketClosed() (Routine)
|
||||||
|
// The server socket is closed. Stop the application.
|
||||||
|
//
|
||||||
|
void socketClosed()
|
||||||
|
{
|
||||||
|
Gevent_loop->stop();
|
||||||
|
return;
|
||||||
|
} // end of socketClosed()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// getIPAddress(const char*) (Routine)
|
||||||
|
// Convert a host name or dotted-decimal notation address into
|
||||||
|
// an IP address.
|
||||||
|
//
|
||||||
|
unsigned long getIPAddress(const char *host)
|
||||||
|
{
|
||||||
|
hostent *host_entry = NULL;
|
||||||
|
unsigned long retcode;
|
||||||
|
|
||||||
|
// First try to convert host name as a dotted-decimal
|
||||||
|
// notation. If that fails, try gethostbyname().
|
||||||
|
if ((retcode = inet_addr(host)) == INADDR_NONE &&
|
||||||
|
(host_entry = gethostbyname(host)) == NULL)
|
||||||
|
{
|
||||||
|
// Failed to convert host name into IP address.
|
||||||
|
retcode = INADDR_NONE;
|
||||||
|
}
|
||||||
|
else if (host_entry != NULL)
|
||||||
|
{
|
||||||
|
(void) memcpy(&retcode,
|
||||||
|
host_entry->h_addr,
|
||||||
|
host_entry->h_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(retcode);
|
||||||
|
} // end of getIPAddress(const char*)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// sigintHandler(int) (Routine)
|
||||||
|
// When an interrupt is detected, start shutting down the
|
||||||
|
// connection.
|
||||||
|
//
|
||||||
|
void sigintHandler(int)
|
||||||
|
{
|
||||||
|
Sclient_socket->close();
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows removes the SIGINT callback. So put
|
||||||
|
// the callback back in place.
|
||||||
|
(void) signal(SIGINT, sigintHandler);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of sigintHandler(int)
|
209
FSM/samples/TCP/server.cpp
Normal file
209
FSM/samples/TCP/server.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2007. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Function
|
||||||
|
// Main
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates "TCP" server connection, accepting new client connections.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: server.cpp,v 1.6 2007/12/28 12:34:40 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: server.cpp,v $
|
||||||
|
// Revision 1.6 2007/12/28 12:34:40 cwrapp
|
||||||
|
// Version 5.0.1 check-in.
|
||||||
|
//
|
||||||
|
// Revision 1.5 2005/06/08 11:09:12 cwrapp
|
||||||
|
// + Updated Python code generator to place "pass" in methods with empty
|
||||||
|
// bodies.
|
||||||
|
// + Corrected FSM errors in Python example 7.
|
||||||
|
// + Removed unnecessary includes from C++ examples.
|
||||||
|
// + Corrected errors in top-level makefile's distribution build.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:44:25 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Eventloop.h"
|
||||||
|
#include "AppServer.h"
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#if !defined(SA_NOMASK)
|
||||||
|
#define SA_NOMASK 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Global variable declarations.
|
||||||
|
Eventloop *Gevent_loop;
|
||||||
|
|
||||||
|
// Static variable declarations.
|
||||||
|
static AppServer *Sserver_socket;
|
||||||
|
|
||||||
|
// Constant declarations.
|
||||||
|
const static int STDIN_FD = 0;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// main(int, char**) (Routine)
|
||||||
|
// Process the command line arguments, open the TCP service and
|
||||||
|
// then sit in the event loop. Stop running when the Enter key
|
||||||
|
// is hit.
|
||||||
|
//
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int longPort;
|
||||||
|
int retcode;
|
||||||
|
#if defined(WIN32)
|
||||||
|
WORD winsockVersion;
|
||||||
|
WSADATA winsockData;
|
||||||
|
int errorCode;
|
||||||
|
#else
|
||||||
|
struct sigaction signalAction;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// External routine declarations.
|
||||||
|
void sigintHandler(int);
|
||||||
|
#if defined(WIN32)
|
||||||
|
char* winsock_strerror(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows kinda supports signals.
|
||||||
|
(void) signal(SIGINT, sigintHandler);
|
||||||
|
#else
|
||||||
|
// Set up the SIGINT handler.
|
||||||
|
signalAction.sa_handler = sigintHandler;
|
||||||
|
#if defined(__hpux) || defined (__linux__)
|
||||||
|
sigemptyset(&signalAction.sa_mask);
|
||||||
|
#if defined(__linux__)
|
||||||
|
signalAction.sa_restorer = NULL;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
signalAction.sa_flags = SA_NOMASK;
|
||||||
|
if (sigaction(SIGINT,
|
||||||
|
&signalAction,
|
||||||
|
(struct sigaction *) NULL) != 0)
|
||||||
|
{
|
||||||
|
cerr << "Unable to set SIGINT handling function." << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// Initialize winsock.
|
||||||
|
winsockVersion = MAKEWORD(2, 0);
|
||||||
|
if ((errorCode = WSAStartup(winsockVersion, &winsockData)) != 0)
|
||||||
|
{
|
||||||
|
cout << "Unable to initialize Win32 sockets - "
|
||||||
|
<< winsock_strerror(errorCode)
|
||||||
|
<< "."
|
||||||
|
<< endl;
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
cerr << argv[0]
|
||||||
|
<< ": Wrong number of arguments."
|
||||||
|
<< endl;
|
||||||
|
cerr << "usage: server port" << endl;
|
||||||
|
retcode = 1;
|
||||||
|
}
|
||||||
|
else if (sscanf(argv[1], "%d", &longPort) != 1 ||
|
||||||
|
longPort < 0 ||
|
||||||
|
longPort > 65535)
|
||||||
|
{
|
||||||
|
cerr << "Invalid port number - \""
|
||||||
|
<< argv[1]
|
||||||
|
<< "\"."
|
||||||
|
<< endl;
|
||||||
|
retcode = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned short port;
|
||||||
|
|
||||||
|
cout << "(Starting execution. Hit \"Cntl-c\" to stop.)" << endl;
|
||||||
|
|
||||||
|
// 1. Create the event loop object.
|
||||||
|
Gevent_loop = new Eventloop();
|
||||||
|
|
||||||
|
// 2. Open server port.
|
||||||
|
Sserver_socket = new AppServer();
|
||||||
|
port = static_cast<unsigned short>(longPort);
|
||||||
|
Sserver_socket->open(htons(port));
|
||||||
|
|
||||||
|
// 3. Wait for accept messages.
|
||||||
|
Gevent_loop->start();
|
||||||
|
|
||||||
|
cout << "(Stopping execution.)" << endl;
|
||||||
|
|
||||||
|
// 4. Delete the TCP service.
|
||||||
|
delete Sserver_socket;
|
||||||
|
Sserver_socket = NULL;
|
||||||
|
|
||||||
|
// 5. Delete the event loop.
|
||||||
|
delete Gevent_loop;
|
||||||
|
Gevent_loop = NULL;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
retcode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(retcode);
|
||||||
|
} // end of main(int, char**)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// socketClosed() (Routine)
|
||||||
|
// The server socket is closed. Stop the application.
|
||||||
|
//
|
||||||
|
void socketClosed()
|
||||||
|
{
|
||||||
|
Gevent_loop->stop();
|
||||||
|
return;
|
||||||
|
} // end of socketClosed()
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// sigintHandler(int) (Routine)
|
||||||
|
// When an interrupt is detected, stop execution.
|
||||||
|
//
|
||||||
|
void sigintHandler(int)
|
||||||
|
{
|
||||||
|
Sserver_socket->close();
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows removes the SIGINT callback. So put
|
||||||
|
// the callback back in place.
|
||||||
|
(void) signal(SIGINT, sigintHandler);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
} // end of sigintHandler(int)
|
8
FSM/samples/TCP/stdafx.cpp
Normal file
8
FSM/samples/TCP/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// stdafx.cpp : fichier source incluant simplement les fichiers Include standard
|
||||||
|
// TCP.pch représente l'en-tête précompilé
|
||||||
|
// stdafx.obj contient les informations de type précompilées
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
// TODO: faites référence aux en-têtes supplémentaires nécessaires dans STDAFX.H
|
||||||
|
// absents de ce fichier
|
15
FSM/samples/TCP/stdafx.h
Normal file
15
FSM/samples/TCP/stdafx.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// stdafx.h : fichier Include pour les fichiers Include système standard,
|
||||||
|
// ou les fichiers Include spécifiques aux projets qui sont utilisés fréquemment,
|
||||||
|
// et sont rarement modifiés
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "targetver.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: faites référence ici aux en-têtes supplémentaires nécessaires au programme
|
8
FSM/samples/TCP/targetver.h
Normal file
8
FSM/samples/TCP/targetver.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Si vous incluez SDKDDKVer.h, cela définit la dernière plateforme Windows disponible.
|
||||||
|
|
||||||
|
// Si vous souhaitez générer votre application pour une plateforme Windows précédente, incluez WinSDKVer.h et
|
||||||
|
// définissez la macro _WIN32_WINNT à la plateforme que vous souhaitez prendre en charge avant d'inclure SDKDDKVer.h.
|
||||||
|
|
||||||
|
#include <SDKDDKVer.h>
|
199
FSM/samples/TCP/winsock_strerror.cpp
Normal file
199
FSM/samples/TCP/winsock_strerror.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2003 Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Function
|
||||||
|
// Main
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// Encapsulates "TCP" server connection, accepting new client connections.
|
||||||
|
//
|
||||||
|
// RCS ID
|
||||||
|
// $Id: winsock_strerror.cpp,v 1.5 2009/03/01 18:20:38 cwrapp Exp $
|
||||||
|
//
|
||||||
|
// CHANGE LOG
|
||||||
|
// $Log: winsock_strerror.cpp,v $
|
||||||
|
// Revision 1.5 2009/03/01 18:20:38 cwrapp
|
||||||
|
// Preliminary v. 6.0.0 commit.
|
||||||
|
//
|
||||||
|
// Revision 1.4 2005/05/28 13:31:18 cwrapp
|
||||||
|
// Updated C++ examples.
|
||||||
|
//
|
||||||
|
// Revision 1.0 2003/12/14 19:44:45 charlesr
|
||||||
|
// Initial revision
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// winsock_strerror(int) (Routine)
|
||||||
|
// Return a string equivalent for a winsock error.
|
||||||
|
//
|
||||||
|
char* winsock_strerror(int error)
|
||||||
|
{
|
||||||
|
char *retval;
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case WSANOTINITIALISED:
|
||||||
|
retval = "winsock library not initialized";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAENETDOWN:
|
||||||
|
retval = "network down";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEAFNOSUPPORT:
|
||||||
|
retval = "address family not supported";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEINPROGRESS:
|
||||||
|
retval = "blocking call in progress";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEMFILE:
|
||||||
|
retval = "no more socket descriptors available";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAENOBUFS:
|
||||||
|
retval = "buffer space exhausted";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEPROTONOSUPPORT:
|
||||||
|
retval = "specified protocol not supported";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEPROTOTYPE:
|
||||||
|
retval = "specified protocol incorrect type for socket";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAESOCKTNOSUPPORT:
|
||||||
|
retval = "socket family and type combination not supported";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEADDRINUSE:
|
||||||
|
retval = "address in use";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEADDRNOTAVAIL:
|
||||||
|
retval = "address not available";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEFAULT:
|
||||||
|
retval = "invalid address";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEINVAL:
|
||||||
|
retval = "invalid request";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAENOTSOCK:
|
||||||
|
retval = "invalid socket specified";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEISCONN:
|
||||||
|
retval = "socket is connected";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAENETRESET:
|
||||||
|
retval = "network reset";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEOPNOTSUPP:
|
||||||
|
retval = "operation not supported";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAESHUTDOWN:
|
||||||
|
retval = "socket was shutdown";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
retval = "socket would block";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEMSGSIZE:
|
||||||
|
retval = "message too large";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAETIMEDOUT:
|
||||||
|
retval = "timed out";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAECONNRESET:
|
||||||
|
retval = "connection reset";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEINTR:
|
||||||
|
retval = "call interrupted";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEHOSTUNREACH:
|
||||||
|
retval = "host unreachable";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAECONNABORTED:
|
||||||
|
retval = "connection aborted";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEDESTADDRREQ:
|
||||||
|
retval = "destination address required";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAENETUNREACH:
|
||||||
|
retval = "network unreachable";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSASYSNOTREADY:
|
||||||
|
retval = "network subsystem not ready";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAVERNOTSUPPORTED:
|
||||||
|
retval = "version not supported";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAEPROCLIM:
|
||||||
|
retval = "process limit reached";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSAHOST_NOT_FOUND:
|
||||||
|
retval = "host not found";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSATRY_AGAIN:
|
||||||
|
retval = "try again";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSANO_RECOVERY:
|
||||||
|
retval = "no recovery";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WSANO_DATA:
|
||||||
|
retval = "no data";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
retval = "unknown error code";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(retval);
|
||||||
|
} // end of TcpConnection::winsock_strerror(int)
|
||||||
|
|
||||||
|
#endif
|
36
FSM/samples/TrafficLight/Makefile
Normal file
36
FSM/samples/TrafficLight/Makefile
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# $Id: //poco/1.4/FSM/samples/TrafficLight/Makefile#1 $
|
||||||
|
#
|
||||||
|
# Makefile for Poco FSM TrafficLight
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/rules/global
|
||||||
|
INCLUDE += -I$(POCO_BASE)/FSM/include
|
||||||
|
CXXFLAGS += -std=c++11 -fno-operator-names
|
||||||
|
|
||||||
|
# Cygwin Poco*.dll should be on PATH
|
||||||
|
ifeq ($(OSNAME), Cygwin)
|
||||||
|
PATH :=$(LIBPATH):$(PATH)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Where to find the Finite State Machine Compiler executable
|
||||||
|
FSMc = $(POCO_BUILD)/FSM/bin/$(OSNAME)/$(OSARCH)/FSMc
|
||||||
|
|
||||||
|
objects = stoplight Stoplight_sm TrafficLight
|
||||||
|
|
||||||
|
target = TrafficLight
|
||||||
|
target_version = 1
|
||||||
|
target_libs = PocoUtil PocoJSON PocoNet PocoXML PocoFoundation
|
||||||
|
|
||||||
|
include $(POCO_BASE)/build/rules/exec
|
||||||
|
|
||||||
|
ifdef POCO_UNBUNDLED
|
||||||
|
SYSLIBS += -lz -lpcre -lexpat
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Rule for runnning Finite State Machine Compiler
|
||||||
|
src/%.cpp: src/%.sm
|
||||||
|
@echo "** Compiling FSM " $<
|
||||||
|
$(SET_LD_LIBRARY_PATH) $(FSMc) $<
|
84
FSM/samples/TrafficLight/Stoplight_sm.cpp
Normal file
84
FSM/samples/TrafficLight/Stoplight_sm.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "stoplightdefs.h"
|
||||||
|
#include "stoplight.h"
|
||||||
|
#include "Stoplight_sm.h"
|
||||||
|
using namespace statemap;
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
// FSM Map constructor.
|
||||||
|
StopMap::StopMap() :
|
||||||
|
EastWestGreen("EastWestGreen", 0),
|
||||||
|
EastWestYellow("EastWestYellow", 1),
|
||||||
|
NorthSouthGreen("NorthSouthGreen", 2),
|
||||||
|
NorthSouthYellow("NorthSouthYellow", 3)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Class state -----------------------------------
|
||||||
|
void StoplightState::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Default(context);
|
||||||
|
}
|
||||||
|
void StoplightState::Default(StoplightContext<Stoplight>& context) {
|
||||||
|
throw TransitionUndefinedException(context.getState().getName(), context.getTransition());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void StopMap_EastWestGreen::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(NSLIGHT, RED);
|
||||||
|
ctxt.TurnLight(EWLIGHT, GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_EastWestGreen::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.EastWestYellow);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::YellowTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_EastWestYellow::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(EWLIGHT, YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_EastWestYellow::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.NorthSouthGreen);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::NSGreenTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_NorthSouthGreen::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(EWLIGHT, RED);
|
||||||
|
ctxt.TurnLight(NSLIGHT, GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_NorthSouthGreen::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.NorthSouthYellow);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::YellowTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_NorthSouthYellow::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(NSLIGHT, YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_NorthSouthYellow::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.EastWestGreen);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::EWGreenTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
126
FSM/samples/TrafficLight/Stoplight_sm.h
Normal file
126
FSM/samples/TrafficLight/Stoplight_sm.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#ifndef cpp_ex4_Stoplight_sm_H
|
||||||
|
#define cpp_ex4_Stoplight_sm_H
|
||||||
|
#include "Poco/FSM/statemap.h"
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
// Forward declarations.--------------------------
|
||||||
|
class StopMap;
|
||||||
|
class StopMap_EastWestGreen;
|
||||||
|
class StopMap_EastWestYellow;
|
||||||
|
class StopMap_NorthSouthGreen;
|
||||||
|
class StopMap_NorthSouthYellow;
|
||||||
|
class StopMap_Default;
|
||||||
|
class StoplightState;
|
||||||
|
template<typename Derived> class StoplightContext;
|
||||||
|
class Stoplight;
|
||||||
|
|
||||||
|
|
||||||
|
// Class State.-----------------------------------
|
||||||
|
class StoplightState : public statemap::State {
|
||||||
|
public:
|
||||||
|
StoplightState(const char *name, int no) : statemap::State(name, no) {};
|
||||||
|
|
||||||
|
virtual void Entry(StoplightContext<Stoplight>&) {};
|
||||||
|
virtual void Exit(StoplightContext<Stoplight>&) {};
|
||||||
|
|
||||||
|
virtual void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
protected:
|
||||||
|
virtual void Default(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map default state class.-------------------
|
||||||
|
class StopMap_Default : public StoplightState {
|
||||||
|
public:
|
||||||
|
StopMap_Default (const char *name, int stateId) : StoplightState(name, stateId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map states class.--------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_EastWestGreen: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_EastWestGreen(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_EastWestYellow: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_EastWestYellow(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_NorthSouthGreen: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_NorthSouthGreen(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_NorthSouthYellow: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_NorthSouthYellow(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map class.---------------------------------
|
||||||
|
class StopMap {
|
||||||
|
public:
|
||||||
|
StopMap();
|
||||||
|
StopMap_EastWestGreen EastWestGreen;
|
||||||
|
StopMap_EastWestYellow EastWestYellow;
|
||||||
|
StopMap_NorthSouthGreen NorthSouthGreen;
|
||||||
|
StopMap_NorthSouthYellow NorthSouthYellow;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM context class -----------------------------
|
||||||
|
template<typename Derived>
|
||||||
|
class StoplightContext : public statemap::FSMContext, public StopMap {
|
||||||
|
public:
|
||||||
|
explicit
|
||||||
|
StoplightContext(statemap::Notifier& notifier) : FSMContext(notifier, StopMap::NorthSouthGreen) {};
|
||||||
|
StoplightContext(statemap::Notifier& notifier, const statemap::State& state) : FSMContext(notifier, state) {};
|
||||||
|
|
||||||
|
void setStartState(const statemap::State& state) {
|
||||||
|
setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void enterStartState() {
|
||||||
|
getState().Entry(*this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& getOwner() {
|
||||||
|
return (*static_cast<Derived*>(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
const Derived& getOwner() const {
|
||||||
|
return (*static_cast<const Derived*>(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
StoplightState& getState() const {
|
||||||
|
if (_state == nullptr) {
|
||||||
|
throw statemap::StateUndefinedException();
|
||||||
|
}
|
||||||
|
return (dynamic_cast<StoplightState&>(*_state));
|
||||||
|
};
|
||||||
|
|
||||||
|
void Timeout() {
|
||||||
|
setTransition("Timeout");
|
||||||
|
getState().Timeout(*this);
|
||||||
|
setTransition(nullptr);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
63
FSM/samples/TrafficLight/TrafficLight.sm
Normal file
63
FSM/samples/TrafficLight/TrafficLight.sm
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// -*- tab-width: 4; -*-
|
||||||
|
|
||||||
|
%{
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy of
|
||||||
|
// the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an "AS
|
||||||
|
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2003 Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// State Machine
|
||||||
|
// Stoplight
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// This state machine implements a US traffic light.
|
||||||
|
//
|
||||||
|
%}
|
||||||
|
%start StopMap::NorthSouthGreen
|
||||||
|
%class Stoplight
|
||||||
|
%fsmclass StoplightContext
|
||||||
|
%include "stoplightdefs.h"
|
||||||
|
%header stoplight.h
|
||||||
|
%package cpp_ex4
|
||||||
|
|
||||||
|
%map StopMap
|
||||||
|
%%
|
||||||
|
EastWestGreen
|
||||||
|
Entry { TurnLight(NSLIGHT, RED); TurnLight(EWLIGHT, GREEN); }
|
||||||
|
{
|
||||||
|
Timeout EastWestYellow { setTimer(Stoplight::YellowTimer); }
|
||||||
|
}
|
||||||
|
|
||||||
|
EastWestYellow
|
||||||
|
Entry { TurnLight(EWLIGHT, YELLOW); }
|
||||||
|
{
|
||||||
|
Timeout NorthSouthGreen { setTimer(Stoplight::NSGreenTimer); }
|
||||||
|
}
|
||||||
|
|
||||||
|
NorthSouthGreen
|
||||||
|
Entry { TurnLight(EWLIGHT, RED); TurnLight(NSLIGHT, GREEN); }
|
||||||
|
{
|
||||||
|
Timeout NorthSouthYellow { setTimer(Stoplight::YellowTimer); }
|
||||||
|
}
|
||||||
|
|
||||||
|
NorthSouthYellow
|
||||||
|
Entry { TurnLight(NSLIGHT, YELLOW); }
|
||||||
|
{
|
||||||
|
Timeout EastWestGreen { setTimer(Stoplight::EWGreenTimer); }
|
||||||
|
}
|
||||||
|
%%
|
114
FSM/samples/TrafficLight/TrafficLight_vs120.vcxproj
Normal file
114
FSM/samples/TrafficLight/TrafficLight_vs120.vcxproj
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.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>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{E3EE4584-8403-494A-B982-EFC4E5B04690}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>TrafficLight</RootNamespace>
|
||||||
|
<ProjectName>TrafficLight</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</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>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<IncludePath>$(IncludePath)</IncludePath>
|
||||||
|
<CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\FSM\include;..\..\..\Util\include;..\..\..\Foundation\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>set PATH=..\..\..\bin;%PATH% && ..\..\bin\fsmc TrafficLight.sm</Command>
|
||||||
|
<Outputs>SpotLight_sm.h;SpotLight_sm.cpp</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</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;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\FSM\include;..\..\..\Util\include;..\..\..\Foundation\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\lib</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
<CustomBuildStep>
|
||||||
|
<Command>set PATH=..\..\..\bin;%PATH% && ..\..\bin\fsmc TrafficLight.sm</Command>
|
||||||
|
<Outputs>SpotLight_sm.h;SpotLight_sm.cpp</Outputs>
|
||||||
|
</CustomBuildStep>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\..\fsmc.properties" />
|
||||||
|
<None Include="TrafficLight.sm" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\stdafx.cpp" />
|
||||||
|
<ClCompile Include="src\stoplight.cpp" />
|
||||||
|
<ClCompile Include="src\Stoplight_sm.cpp" />
|
||||||
|
<ClCompile Include="src\TrafficLight.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\stdafx.h" />
|
||||||
|
<ClInclude Include="src\stoplight.h" />
|
||||||
|
<ClInclude Include="src\stoplightdefs.h" />
|
||||||
|
<ClInclude Include="src\stoplight_sm.h" />
|
||||||
|
<ClInclude Include="src\targetver.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
52
FSM/samples/TrafficLight/TrafficLight_vs120.vcxproj.filters
Normal file
52
FSM/samples/TrafficLight/TrafficLight_vs120.vcxproj.filters
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Fichiers sources">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Fichiers d%27en-tête">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Fichiers de ressources">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="TrafficLight.sm" />
|
||||||
|
<None Include="..\..\fsmc.properties" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\stdafx.cpp">
|
||||||
|
<Filter>Fichiers sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\stoplight.cpp">
|
||||||
|
<Filter>Fichiers sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Stoplight_sm.cpp">
|
||||||
|
<Filter>Fichiers sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\TrafficLight.cpp">
|
||||||
|
<Filter>Fichiers sources</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\stdafx.h">
|
||||||
|
<Filter>Fichiers d%27en-tête</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\stoplight.h">
|
||||||
|
<Filter>Fichiers d%27en-tête</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\stoplight_sm.h">
|
||||||
|
<Filter>Fichiers d%27en-tête</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\stoplightdefs.h">
|
||||||
|
<Filter>Fichiers d%27en-tête</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\targetver.h">
|
||||||
|
<Filter>Fichiers d%27en-tête</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
84
FSM/samples/TrafficLight/src/Stoplight_sm.cpp
Normal file
84
FSM/samples/TrafficLight/src/Stoplight_sm.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "stoplightdefs.h"
|
||||||
|
#include "stoplight.h"
|
||||||
|
#include "Stoplight_sm.h"
|
||||||
|
using namespace statemap;
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
// FSM Map constructor.
|
||||||
|
StopMap::StopMap() :
|
||||||
|
EastWestGreen("EastWestGreen", 0),
|
||||||
|
EastWestYellow("EastWestYellow", 1),
|
||||||
|
NorthSouthGreen("NorthSouthGreen", 2),
|
||||||
|
NorthSouthYellow("NorthSouthYellow", 3)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Class state -----------------------------------
|
||||||
|
void StoplightState::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Default(context);
|
||||||
|
}
|
||||||
|
void StoplightState::Default(StoplightContext<Stoplight>& context) {
|
||||||
|
throw TransitionUndefinedException(context.getState().getName(), context.getTransition());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void StopMap_EastWestGreen::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(NSLIGHT, RED);
|
||||||
|
ctxt.TurnLight(EWLIGHT, GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_EastWestGreen::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.EastWestYellow);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::YellowTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_EastWestYellow::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(EWLIGHT, YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_EastWestYellow::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.NorthSouthGreen);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::NSGreenTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_NorthSouthGreen::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(EWLIGHT, RED);
|
||||||
|
ctxt.TurnLight(NSLIGHT, GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_NorthSouthGreen::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.NorthSouthYellow);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::YellowTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
void StopMap_NorthSouthYellow::Entry(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
ctxt.TurnLight(NSLIGHT, YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
void StopMap_NorthSouthYellow::Timeout(StoplightContext<Stoplight>& context) {
|
||||||
|
Stoplight& ctxt = context.getOwner();
|
||||||
|
|
||||||
|
(context.getState()).Exit(context);
|
||||||
|
context.setState(context.EastWestGreen);
|
||||||
|
(context.getState()).Entry(context);
|
||||||
|
ctxt.setTimer(Stoplight::EWGreenTimer);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
94
FSM/samples/TrafficLight/src/TrafficLight.cpp
Normal file
94
FSM/samples/TrafficLight/src/TrafficLight.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include "Poco/DateTime.h"
|
||||||
|
#include "Poco/DateTimeFormatter.h"
|
||||||
|
#include "Poco/Util/LoggingConfigurator.h"
|
||||||
|
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
|
#include "Poco/Util/Option.h"
|
||||||
|
#include "Poco/Util/OptionSet.h"
|
||||||
|
#include "Poco/Util/HelpFormatter.h"
|
||||||
|
#include "Poco/Util/Application.h"
|
||||||
|
#include "Poco/Timer.h"
|
||||||
|
#include "Poco/Thread.h"
|
||||||
|
#include "Poco/Stopwatch.h"
|
||||||
|
|
||||||
|
using Poco::Util::Application;
|
||||||
|
using Poco::Util::Option;
|
||||||
|
using Poco::Util::OptionSet;
|
||||||
|
using Poco::Util::HelpFormatter;
|
||||||
|
using Poco::Util::LoggingConfigurator;
|
||||||
|
using Poco::Util::PropertyFileConfiguration;
|
||||||
|
using Poco::AutoPtr;
|
||||||
|
using Poco::TimerCallback;
|
||||||
|
using Poco::Stopwatch;
|
||||||
|
using Poco::Thread;
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include "stoplight.h"
|
||||||
|
using namespace cpp_ex4;
|
||||||
|
|
||||||
|
|
||||||
|
class TrafficLight : public Application {
|
||||||
|
/// The main application class.
|
||||||
|
///
|
||||||
|
/// This class handles command-line arguments and configuration files.
|
||||||
|
/// Start the TrafficLight executable with the help
|
||||||
|
/// option (/help on Windows, --help on Unix) for
|
||||||
|
/// the available command line options.
|
||||||
|
///
|
||||||
|
protected:
|
||||||
|
void initialize(Application& self) {
|
||||||
|
loadConfiguration(); // load default configuration files, if present
|
||||||
|
Application::initialize(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninitialize() {
|
||||||
|
Application::uninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void defineOptions(OptionSet& options) {
|
||||||
|
Application::defineOptions(options);
|
||||||
|
|
||||||
|
options.addOption(
|
||||||
|
Option("help", "h", "display help information on command line arguments")
|
||||||
|
.required(false)
|
||||||
|
.repeatable(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleOption(const std::string& name, const std::string& value) {
|
||||||
|
Application::handleOption(name, value);
|
||||||
|
|
||||||
|
if (name == "help")
|
||||||
|
help = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayHelp() {
|
||||||
|
HelpFormatter helpFormatter(options());
|
||||||
|
helpFormatter.setCommand(commandName());
|
||||||
|
helpFormatter.setUsage("OPTIONS");
|
||||||
|
helpFormatter.setHeader("A US TrafficLight as a FSM.");
|
||||||
|
helpFormatter.format(std::cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(const std::vector<std::string>& args) {
|
||||||
|
if (help) {
|
||||||
|
displayHelp();
|
||||||
|
} else {
|
||||||
|
Stoplight stoplight(NORTH_SOUTH, NSGreenTimer, EWGreenTimer);
|
||||||
|
stoplight.start(YellowTimer);
|
||||||
|
}
|
||||||
|
return Application::EXIT_OK;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int KeepGoing = 1;
|
||||||
|
|
||||||
|
int YellowTimer = 2; // Yellow lights last 2 seconds.
|
||||||
|
int NSGreenTimer = 8; // North-south green lasts 8 seconds.
|
||||||
|
int EWGreenTimer = 5; // East-west green lasts 5 seconds.
|
||||||
|
bool help = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
POCO_APP_MAIN(TrafficLight)
|
8
FSM/samples/TrafficLight/src/stdafx.cpp
Normal file
8
FSM/samples/TrafficLight/src/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// stdafx.cpp : fichier source incluant simplement les fichiers Include standard
|
||||||
|
// TrafficLight.pch représente l'en-tête précompilé
|
||||||
|
// stdafx.obj contient les informations de type précompilées
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
// TODO: faites référence aux en-têtes supplémentaires nécessaires dans STDAFX.H
|
||||||
|
// absents de ce fichier
|
15
FSM/samples/TrafficLight/src/stdafx.h
Normal file
15
FSM/samples/TrafficLight/src/stdafx.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// stdafx.h : fichier Include pour les fichiers Include système standard,
|
||||||
|
// ou les fichiers Include spécifiques aux projets qui sont utilisés fréquemment,
|
||||||
|
// et sont rarement modifiés
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "targetver.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: faites référence ici aux en-têtes supplémentaires nécessaires au programme
|
154
FSM/samples/TrafficLight/src/stoplight.cpp
Normal file
154
FSM/samples/TrafficLight/src/stoplight.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2009. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Class
|
||||||
|
// Stoplight
|
||||||
|
//
|
||||||
|
// Member Functions
|
||||||
|
// Stoplight() - Default constructor.
|
||||||
|
// Stoplight(Directions) - Set initial direction.
|
||||||
|
// TurnLight(StopLights, LightColors) - Change directions.
|
||||||
|
// SetTimer(int) - Start a timer.
|
||||||
|
// Initialize(Directions) - Set start state and timer.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "Poco/Thread.h"
|
||||||
|
#include "Poco/Stopwatch.h"
|
||||||
|
#include "stoplight.h"
|
||||||
|
|
||||||
|
static const char tab = '\t';
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using Poco::TimerCallback;
|
||||||
|
using Poco::Stopwatch;
|
||||||
|
using Poco::Thread;
|
||||||
|
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
|
||||||
|
int Stoplight::YellowTimer;
|
||||||
|
int Stoplight::NSGreenTimer;
|
||||||
|
int Stoplight::EWGreenTimer;
|
||||||
|
|
||||||
|
const char* literal(const statemap::Event & event) {
|
||||||
|
switch (event) {
|
||||||
|
case statemap::Event::Enter: return "Enter ";
|
||||||
|
case statemap::Event::Leave: return "Leave ";
|
||||||
|
case statemap::Event::Switch: return "Switch ";
|
||||||
|
case statemap::Event::Transition: return "Transition";
|
||||||
|
case statemap::Event::Push: return "Push ";
|
||||||
|
case statemap::Event::Pop: return "Pop ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Print : public statemap::Notifier {
|
||||||
|
public:
|
||||||
|
void operator ()(const statemap::Event & event, const char * message) {
|
||||||
|
clog << tab << tab << literal(event) << ": " << message << endl;
|
||||||
|
}
|
||||||
|
void operator ()(const statemap::Event & event, const statemap::State * state) {
|
||||||
|
// clog << tab << tab << literal(event) << ": " << state->getName() << endl;
|
||||||
|
}
|
||||||
|
void operator ()(const statemap::Event & event, const statemap::State * fromState, const statemap::State *toState) {
|
||||||
|
clog << tab << tab << literal(event) << ": " << fromState->getName() << " => " << toState->getName() << endl << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static Print print;
|
||||||
|
|
||||||
|
Stoplight::Stoplight(Directions direction, int NSGreenTimer, int EWGreenTimer) :
|
||||||
|
StoplightContext(print),
|
||||||
|
callback(*this, &Stoplight::onTimer) {
|
||||||
|
|
||||||
|
#define FSM_DEBUG
|
||||||
|
#ifdef FSM_DEBUG
|
||||||
|
setDebugFlag(true);
|
||||||
|
#endif
|
||||||
|
switch(direction) {
|
||||||
|
case NORTH_SOUTH:
|
||||||
|
cout << "Turning the north-south lights green." << endl;
|
||||||
|
setStartState(NorthSouthGreen);
|
||||||
|
timer.setStartInterval(NSGreenTimer * 1000);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EAST_WEST:
|
||||||
|
cout << "Turning the east-west lights green." << endl;
|
||||||
|
setStartState(EastWestGreen);
|
||||||
|
timer.setStartInterval(EWGreenTimer * 1000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->NSGreenTimer = NSGreenTimer;
|
||||||
|
this->EWGreenTimer = EWGreenTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stoplight::start(int YellowTimer) {
|
||||||
|
this->YellowTimer = YellowTimer;
|
||||||
|
enterStartState();
|
||||||
|
timer.start(callback);
|
||||||
|
|
||||||
|
Stopwatch sw;
|
||||||
|
sw.start();
|
||||||
|
_event.wait();
|
||||||
|
sw.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stoplight::TurnLight(StopLights light, LightColors color) {
|
||||||
|
cout << "Turning the ";
|
||||||
|
|
||||||
|
switch(light) {
|
||||||
|
case EWLIGHT:
|
||||||
|
cout << "east-west lights ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSLIGHT:
|
||||||
|
cout << "north-south lights ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(color) {
|
||||||
|
case GREEN:
|
||||||
|
cout << "green." << endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case YELLOW:
|
||||||
|
cout << "yellow." << endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RED:
|
||||||
|
cout << "red." << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stoplight::onTimer(Timer& t) {
|
||||||
|
// clog << ">>> onTimer: " << endl;
|
||||||
|
Timeout();
|
||||||
|
// clog << "<<< onTimer: " << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stoplight::setTimer(int seconds) {
|
||||||
|
// clog << ">>> setTimer: " << seconds << endl;
|
||||||
|
timer.setPeriodicInterval(seconds * 1000);
|
||||||
|
timer.restart();
|
||||||
|
// clog << "<<< setTimer: " << seconds << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
80
FSM/samples/TrafficLight/src/stoplight.h
Normal file
80
FSM/samples/TrafficLight/src/stoplight.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef _H_STOPLIGHT
|
||||||
|
#define _H_STOPLIGHT
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy
|
||||||
|
// of the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an
|
||||||
|
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2009. Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TheContext
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// When a state map executes an action, it is really calling a
|
||||||
|
// member function in the context class.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Poco/Timer.h"
|
||||||
|
#include "Poco/Event.h"
|
||||||
|
using Poco::Timer;
|
||||||
|
using Poco::Event;
|
||||||
|
using Poco::TimerCallback;
|
||||||
|
|
||||||
|
#include "stoplightdefs.h"
|
||||||
|
#include "stoplight_sm.h"
|
||||||
|
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
class Stoplight : protected StoplightContext<Stoplight> {
|
||||||
|
// Member data.
|
||||||
|
public:
|
||||||
|
static int YellowTimer;
|
||||||
|
static int NSGreenTimer;
|
||||||
|
static int EWGreenTimer;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onTimer(Timer& t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Event _event;
|
||||||
|
Timer timer;
|
||||||
|
TimerCallback<Stoplight> callback;
|
||||||
|
|
||||||
|
// Member functions.
|
||||||
|
public:
|
||||||
|
// Specify the initial direction with the green light.
|
||||||
|
Stoplight(Directions direction, int NSGreenTimer, int EWGreenTimer);
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
virtual ~Stoplight() {};
|
||||||
|
|
||||||
|
void start(int YellowTimer);
|
||||||
|
|
||||||
|
// Change a stoplight's color.
|
||||||
|
void TurnLight(StopLights light, LightColors color);
|
||||||
|
|
||||||
|
// Set a timer for the specified number of seconds.
|
||||||
|
void setTimer(int time);
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the initial state of the state map and the initial timer.
|
||||||
|
//static Stoplight* Initialize(Directions direction);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
126
FSM/samples/TrafficLight/src/stoplight_sm.h
Normal file
126
FSM/samples/TrafficLight/src/stoplight_sm.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#ifndef cpp_ex4_Stoplight_sm_H
|
||||||
|
#define cpp_ex4_Stoplight_sm_H
|
||||||
|
#include "Poco/FSM/statemap.h"
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
// Forward declarations.--------------------------
|
||||||
|
class StopMap;
|
||||||
|
class StopMap_EastWestGreen;
|
||||||
|
class StopMap_EastWestYellow;
|
||||||
|
class StopMap_NorthSouthGreen;
|
||||||
|
class StopMap_NorthSouthYellow;
|
||||||
|
class StopMap_Default;
|
||||||
|
class StoplightState;
|
||||||
|
template<typename Derived> class StoplightContext;
|
||||||
|
class Stoplight;
|
||||||
|
|
||||||
|
|
||||||
|
// Class State.-----------------------------------
|
||||||
|
class StoplightState : public statemap::State {
|
||||||
|
public:
|
||||||
|
StoplightState(const char *name, int no) : statemap::State(name, no) {};
|
||||||
|
|
||||||
|
virtual void Entry(StoplightContext<Stoplight>&) {};
|
||||||
|
virtual void Exit(StoplightContext<Stoplight>&) {};
|
||||||
|
|
||||||
|
virtual void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
protected:
|
||||||
|
virtual void Default(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map default state class.-------------------
|
||||||
|
class StopMap_Default : public StoplightState {
|
||||||
|
public:
|
||||||
|
StopMap_Default (const char *name, int stateId) : StoplightState(name, stateId) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map states class.--------------------------
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_EastWestGreen: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_EastWestGreen(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_EastWestYellow: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_EastWestYellow(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_NorthSouthGreen: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_NorthSouthGreen(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
class StopMap_NorthSouthYellow: public StopMap_Default {
|
||||||
|
public:
|
||||||
|
StopMap_NorthSouthYellow(const char* name, int no) : StopMap_Default(name, no) {}
|
||||||
|
|
||||||
|
void Entry(StoplightContext<Stoplight>& context);
|
||||||
|
|
||||||
|
void Timeout(StoplightContext<Stoplight>& context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM map class.---------------------------------
|
||||||
|
class StopMap {
|
||||||
|
public:
|
||||||
|
StopMap();
|
||||||
|
StopMap_EastWestGreen EastWestGreen;
|
||||||
|
StopMap_EastWestYellow EastWestYellow;
|
||||||
|
StopMap_NorthSouthGreen NorthSouthGreen;
|
||||||
|
StopMap_NorthSouthYellow NorthSouthYellow;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FSM context class -----------------------------
|
||||||
|
template<typename Derived>
|
||||||
|
class StoplightContext : public statemap::FSMContext, public StopMap {
|
||||||
|
public:
|
||||||
|
explicit
|
||||||
|
StoplightContext(statemap::Notifier& notifier) : FSMContext(notifier, StopMap::NorthSouthGreen) {};
|
||||||
|
StoplightContext(statemap::Notifier& notifier, const statemap::State& state) : FSMContext(notifier, state) {};
|
||||||
|
|
||||||
|
void setStartState(const statemap::State& state) {
|
||||||
|
setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void enterStartState() {
|
||||||
|
getState().Entry(*this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Derived& getOwner() {
|
||||||
|
return (*static_cast<Derived*>(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
const Derived& getOwner() const {
|
||||||
|
return (*static_cast<const Derived*>(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
StoplightState& getState() const {
|
||||||
|
if (_state == nullptr) {
|
||||||
|
throw statemap::StateUndefinedException();
|
||||||
|
}
|
||||||
|
return (dynamic_cast<StoplightState&>(*_state));
|
||||||
|
};
|
||||||
|
|
||||||
|
void Timeout() {
|
||||||
|
setTransition("Timeout");
|
||||||
|
getState().Timeout(*this);
|
||||||
|
setTransition(nullptr);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
55
FSM/samples/TrafficLight/src/stoplightdefs.h
Normal file
55
FSM/samples/TrafficLight/src/stoplightdefs.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef _H_STOPLIGHTDEFS
|
||||||
|
#define _H_STOPLIGHTDEFS
|
||||||
|
|
||||||
|
//
|
||||||
|
// The contents of this file are subject to the Mozilla Public
|
||||||
|
// License Version 1.1 (the "License"); you may not use this file
|
||||||
|
// except in compliance with the License. You may obtain a copy of
|
||||||
|
// the License at http://www.mozilla.org/MPL/
|
||||||
|
//
|
||||||
|
// Software distributed under the License is distributed on an "AS
|
||||||
|
// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
// implied. See the License for the specific language governing
|
||||||
|
// rights and limitations under the License.
|
||||||
|
//
|
||||||
|
// The Original Code is State Machine Compiler (SMC).
|
||||||
|
//
|
||||||
|
// The Initial Developer of the Original Code is Charles W. Rapp.
|
||||||
|
// Portions created by Charles W. Rapp are
|
||||||
|
// Copyright (C) 2000 - 2003 Charles W. Rapp.
|
||||||
|
// All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Contributor(s):
|
||||||
|
//
|
||||||
|
// Name
|
||||||
|
// TheContext
|
||||||
|
//
|
||||||
|
// Description
|
||||||
|
// When a state machine executes an action, it is really calling a
|
||||||
|
// member function in the context class.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Use this value when setting the stoplight timer.
|
||||||
|
#define STOPLIGHT_TIMER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cpp_ex4 {
|
||||||
|
enum LightColors {
|
||||||
|
GREEN = 0,
|
||||||
|
YELLOW,
|
||||||
|
RED
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StopLights {
|
||||||
|
EWLIGHT = 1,
|
||||||
|
NSLIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Directions {
|
||||||
|
NORTH_SOUTH,
|
||||||
|
EAST_WEST
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
8
FSM/samples/TrafficLight/src/targetver.h
Normal file
8
FSM/samples/TrafficLight/src/targetver.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Si vous incluez SDKDDKVer.h, cela définit la dernière plateforme Windows disponible.
|
||||||
|
|
||||||
|
// Si vous souhaitez générer votre application pour une plateforme Windows précédente, incluez WinSDKVer.h et
|
||||||
|
// définissez la macro _WIN32_WINNT à la plateforme que vous souhaitez prendre en charge avant d'inclure SDKDDKVer.h.
|
||||||
|
|
||||||
|
#include <SDKDDKVer.h>
|
28
FSM/samples/samples_vs120.sln
Normal file
28
FSM/samples/samples_vs120.sln
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Express 2013 for Windows Desktop
|
||||||
|
VisualStudioVersion = 12.0.40629.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TrafficLight", "TrafficLight\TrafficLight_vs120.vcxproj", "{E3EE4584-8403-494A-B982-EFC4E5B04690}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TCP", "TCP\TCP_vs120.vcxproj", "{11E01C5F-683C-4290-B520-D3D248327DE1}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E3EE4584-8403-494A-B982-EFC4E5B04690}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{E3EE4584-8403-494A-B982-EFC4E5B04690}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{E3EE4584-8403-494A-B982-EFC4E5B04690}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{E3EE4584-8403-494A-B982-EFC4E5B04690}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{11E01C5F-683C-4290-B520-D3D248327DE1}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{11E01C5F-683C-4290-B520-D3D248327DE1}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{11E01C5F-683C-4290-B520-D3D248327DE1}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{11E01C5F-683C-4290-B520-D3D248327DE1}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
44
FSM/src/Action.cpp
Normal file
44
FSM/src/Action.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Action.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Action.h"
|
||||||
|
#include "model/Argument.h"
|
||||||
|
#include "model/Print.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Action::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += name();
|
||||||
|
oneline += '(';
|
||||||
|
string arguments;
|
||||||
|
|
||||||
|
for (int no = 0; no < _arguments.size(); ++no)
|
||||||
|
{
|
||||||
|
arguments += _arguments[no]->name();
|
||||||
|
if (no + 1 < _arguments.size())
|
||||||
|
arguments += ", ";
|
||||||
|
}
|
||||||
|
oneline += arguments;
|
||||||
|
oneline += ')';
|
||||||
|
oneline += ';';
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
void Action::print(Print& print) const
|
||||||
|
{
|
||||||
|
print(display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
FSM/src/ActionForCpp.cpp
Normal file
36
FSM/src/ActionForCpp.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* ActionForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
using std::replace;
|
||||||
|
|
||||||
|
#include "cpp/ActionForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
const string ActionForCpp::name() const
|
||||||
|
{
|
||||||
|
string cppname = Element::name();
|
||||||
|
replace(cppname.begin(), cppname.end(), '-', '_');
|
||||||
|
return cppname;
|
||||||
|
}
|
||||||
|
void ActionForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ActionForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
FSM/src/Actions.cpp
Normal file
19
FSM/src/Actions.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Actions.cpp
|
||||||
|
*
|
||||||
|
* Created on: 26 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Actions.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
FSM/src/Argument.cpp
Normal file
27
FSM/src/Argument.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Argument.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Argument.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Argument::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += name();
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
FSM/src/ArgumentForCpp.cpp
Normal file
28
FSM/src/ArgumentForCpp.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* ArgumentForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/ArgumentForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void ArgumentForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ArgumentForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
FSM/src/BinaryOperation.cpp
Normal file
48
FSM/src/BinaryOperation.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* BinaryOperation.cpp
|
||||||
|
*
|
||||||
|
* Created on: 20 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/BinaryOperation.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string BinaryOperation::display() const
|
||||||
|
{
|
||||||
|
if (_asstring.empty())
|
||||||
|
{
|
||||||
|
_asstring += _left->display();
|
||||||
|
switch (_operator)
|
||||||
|
{
|
||||||
|
case Operator::equal:
|
||||||
|
_asstring += "==";
|
||||||
|
break;
|
||||||
|
case Operator::notequal:
|
||||||
|
_asstring += "!=";
|
||||||
|
break;
|
||||||
|
case Operator::and:
|
||||||
|
_asstring += "&&";
|
||||||
|
break;
|
||||||
|
case Operator::or:
|
||||||
|
_asstring += "||";
|
||||||
|
break;
|
||||||
|
case Operator::xor:
|
||||||
|
_asstring += '^';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_asstring += "???";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_asstring += _right->display();
|
||||||
|
}
|
||||||
|
return _asstring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
FSM/src/BinaryOperationForCpp.cpp
Normal file
50
FSM/src/BinaryOperationForCpp.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* BinaryOperationForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 24 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/BinaryOperationForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
const string BinaryOperationForCpp::display(const string& prefix) const
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
value += dynamic_cast<ExpressionForCpp*>(left())->display(prefix);
|
||||||
|
switch (_operator)
|
||||||
|
{
|
||||||
|
case Poco::FSM::MODEL::Operator::equal:
|
||||||
|
value += "==";
|
||||||
|
break;
|
||||||
|
case Poco::FSM::MODEL::Operator::notequal:
|
||||||
|
value += "!=";
|
||||||
|
break;
|
||||||
|
case Poco::FSM::MODEL::Operator::and:
|
||||||
|
value += "&&";
|
||||||
|
break;
|
||||||
|
case Poco::FSM::MODEL::Operator::or:
|
||||||
|
value += "||";
|
||||||
|
break;
|
||||||
|
case Poco::FSM::MODEL::Operator::xor:
|
||||||
|
value += '^';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value += "???";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value += dynamic_cast<ExpressionForCpp*>(right())->display(prefix);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
FSM/src/Character.cpp
Normal file
89
FSM/src/Character.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Character.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
#include "parser/Character.h"
|
||||||
|
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::SyntaxException;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
|
||||||
|
Character::Character()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Character::~Character()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Token::Class Character::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::CHAR_LITERAL_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Character::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
return c == '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Character::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int next = istr.peek();
|
||||||
|
while (next != -1 && next != '\'' && next != '\n' && next != '\r')
|
||||||
|
{
|
||||||
|
if (next == '\\') _value += (char) istr.get();
|
||||||
|
_value += (char) istr.get();
|
||||||
|
next = istr.peek();
|
||||||
|
}
|
||||||
|
if (next == '\'')
|
||||||
|
{
|
||||||
|
next = istr.get();
|
||||||
|
_value += (char) next;
|
||||||
|
}
|
||||||
|
else throw SyntaxException("Unterminated character literal");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char Character::asChar() const
|
||||||
|
{
|
||||||
|
char result('\0');
|
||||||
|
std::string::const_iterator it = _value.begin();
|
||||||
|
std::string::const_iterator end = _value.end();
|
||||||
|
if (it != end)
|
||||||
|
{
|
||||||
|
if (*it == '\'') ++it;
|
||||||
|
while (it != end && *it != '\'')
|
||||||
|
{
|
||||||
|
if (*it == '\\') ++it;
|
||||||
|
if (it != end) result = *it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
FSM/src/Comment.cpp
Normal file
89
FSM/src/Comment.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Comment.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
#include "parser/Comment.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
|
||||||
|
Comment::Comment()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Comment::~Comment()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Token::Class Comment::tokenClass() const
|
||||||
|
{
|
||||||
|
return (_value.length() > 2 && _value[2] == '/') ? Token::SPECIAL_COMMENT_TOKEN : Token::COMMENT_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Comment::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
int next = istr.peek();
|
||||||
|
return c == '/' && (next == '*' || next == '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Comment::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int next = istr.peek();
|
||||||
|
if (next == '/')
|
||||||
|
{
|
||||||
|
while (next != -1 && next != '\r' && next != '\n')
|
||||||
|
{
|
||||||
|
_value += (char) istr.get();
|
||||||
|
next = istr.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_value += (char) istr.get(); // *
|
||||||
|
next = istr.peek();
|
||||||
|
while (next != -1)
|
||||||
|
{
|
||||||
|
next = istr.get();
|
||||||
|
_value += (char) next;
|
||||||
|
if (next == '*' && istr.peek() == '/')
|
||||||
|
{
|
||||||
|
_value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Comment::asString() const
|
||||||
|
{
|
||||||
|
if (_value.length() > 2 && _value[2] == '/')
|
||||||
|
return _value.substr(3);
|
||||||
|
else
|
||||||
|
return _value.substr(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FSM/src/CompilableForCpp.cpp
Normal file
22
FSM/src/CompilableForCpp.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* CompilableForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 24 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/CompilableForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
FSM/src/Dumper.cpp
Normal file
19
FSM/src/Dumper.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Dumper.cpp
|
||||||
|
*
|
||||||
|
* Created on: 8 févr. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Dumper.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
FSM/src/Element.cpp
Normal file
19
FSM/src/Element.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Element.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Element.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FSM/src/ElementForCpp.cpp
Normal file
22
FSM/src/ElementForCpp.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* ElementForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 2 févr. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/ElementForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
FSM/src/Entry.cpp
Normal file
39
FSM/src/Entry.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Entry.cpp
|
||||||
|
*
|
||||||
|
* Created on: 26 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Print.h"
|
||||||
|
#include "model/Entry.h"
|
||||||
|
#include "model/Action.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Entry::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += Element::name();
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
void Entry::print(Print& print) const
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
line += "Entry\t{";
|
||||||
|
|
||||||
|
for (const auto& action : actions())
|
||||||
|
line += action->display();
|
||||||
|
|
||||||
|
line += '}';
|
||||||
|
print(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
FSM/src/EntryForCpp.cpp
Normal file
27
FSM/src/EntryForCpp.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* EntryForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 26 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/EntryForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void EntryForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void EntryForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
FSM/src/Exit.cpp
Normal file
38
FSM/src/Exit.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Exit.cpp
|
||||||
|
*
|
||||||
|
* Created on: 26 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Exit.h"
|
||||||
|
#include "model/Action.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Exit::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += name();
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
void Exit::print(Print& print) const
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
line += "Exit\t{";
|
||||||
|
|
||||||
|
for (const auto& action : actions())
|
||||||
|
line += action->display();
|
||||||
|
|
||||||
|
line += '}';
|
||||||
|
print(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
FSM/src/ExitForCpp.cpp
Normal file
27
FSM/src/ExitForCpp.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* ExitForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 26 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/ExitForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void ExitForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ExitForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
FSM/src/Expression.cpp
Normal file
19
FSM/src/Expression.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Expression.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Expression.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FSM/src/ExpressionForCpp.cpp
Normal file
22
FSM/src/ExpressionForCpp.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* ExpressionForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 24 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/ExpressionForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
FSM/src/FSM.cpp
Normal file
62
FSM/src/FSM.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* FSM.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Format.h"
|
||||||
|
using Poco::format;
|
||||||
|
|
||||||
|
#include "parser/Keyword.h"
|
||||||
|
#include "model/FSM.h"
|
||||||
|
#include "model/Map.h"
|
||||||
|
using Poco::FSM::PARSER::Keyword;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
void FSM::add(MapPtr map)
|
||||||
|
{
|
||||||
|
_maps.push_back(map);
|
||||||
|
map->fsm() = this;
|
||||||
|
}
|
||||||
|
void FSM::addPackage(const string& package)
|
||||||
|
{
|
||||||
|
_packages.push_back(package);
|
||||||
|
}
|
||||||
|
void FSM::addImport(const string& import)
|
||||||
|
{
|
||||||
|
_imports.push_back(import);
|
||||||
|
}
|
||||||
|
void FSM::addInclude(const string& inc)
|
||||||
|
{
|
||||||
|
_includes.push_back(inc);
|
||||||
|
}
|
||||||
|
void FSM::addDeclare(const string& declare)
|
||||||
|
{
|
||||||
|
_declares.push_back(declare);
|
||||||
|
}
|
||||||
|
void FSM::print(Print& print) const
|
||||||
|
{
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::START)), startState()));
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::FSMFILE)), fsmfile()));
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::FFSMLASS)), fsmclass()));
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::CLASS)), klass()));
|
||||||
|
// print(format("%s\t%s", string(Keyword::asString(Keyword::DECLARE)), declare()));
|
||||||
|
// print(format("%s\t%s", string(Keyword::asString(Keyword::ACCESS)), access()));
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::HEADER)), header()));
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::PACKAGE)), packages()[0]));
|
||||||
|
|
||||||
|
for (const auto& map : maps())
|
||||||
|
{
|
||||||
|
print(format("%s\t%s", string(Keyword::asString(Keyword::MAP)), map->Element::name()));
|
||||||
|
map->print(print);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
FSM/src/FSMForCpp.cpp
Normal file
112
FSM/src/FSMForCpp.cpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* FSMForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "Poco/Timestamp.h"
|
||||||
|
#include "Poco/File.h"
|
||||||
|
#include "Poco/FileStream.h"
|
||||||
|
using Poco::FileInputStream;
|
||||||
|
using Poco::FileOutputStream;
|
||||||
|
using Poco::File;
|
||||||
|
using Poco::Timestamp;
|
||||||
|
|
||||||
|
#include "cpp/FSMForCpp.h"
|
||||||
|
#include "cpp/MapForCpp.h"
|
||||||
|
#include "parser/Parser.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void FSMForCpp::openNamespaces(IndentStream& os) const
|
||||||
|
{
|
||||||
|
for (const auto& package : packages())
|
||||||
|
if (!package.empty())
|
||||||
|
os << "namespace " << package << " {" << endl << tab;
|
||||||
|
}
|
||||||
|
void FSMForCpp::closeNamespaces(IndentStream& os) const
|
||||||
|
{
|
||||||
|
for (const auto& package : packages())
|
||||||
|
if (!package.empty())
|
||||||
|
os << back << '}' << endl;
|
||||||
|
}
|
||||||
|
void FSMForCpp::generate(const Path& out, bool debug) const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Path incPath(out, fsmfile() + ".h");
|
||||||
|
FileOutputStream incfos(incPath.toString());
|
||||||
|
IndentStream inc(incfos);
|
||||||
|
string define;
|
||||||
|
for (const auto& ns : packages())
|
||||||
|
{
|
||||||
|
define += ns;
|
||||||
|
define += "_";
|
||||||
|
}
|
||||||
|
define += fsmfile();
|
||||||
|
inc << "#ifndef " << define << "_H" << endl;
|
||||||
|
inc << "#define " << define << "_H" << endl;
|
||||||
|
|
||||||
|
inc << "#include \"Poco/FSM/statemap.h\"" << endl;
|
||||||
|
|
||||||
|
openNamespaces(inc);
|
||||||
|
|
||||||
|
for (auto map : _maps)
|
||||||
|
{
|
||||||
|
dynamic_cast<MapForCpp*>(map)->generateInclude(inc, debug);
|
||||||
|
}
|
||||||
|
closeNamespaces(inc);
|
||||||
|
inc << "#endif" << endl;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Path cppPath(out, fsmfile() + ".cpp");
|
||||||
|
FileOutputStream cppfos(cppPath.toString());
|
||||||
|
IndentStream cpp(cppfos);
|
||||||
|
|
||||||
|
for (const auto& include : includes())
|
||||||
|
if (!include.empty())
|
||||||
|
cpp << "#include \"" << include << "\"" << endl;
|
||||||
|
|
||||||
|
if (!header().empty())
|
||||||
|
cpp << "#include \"" << header() << "\"" << endl;
|
||||||
|
|
||||||
|
cpp << "#include \"" << fsmfile() << ".h\"" << endl;
|
||||||
|
|
||||||
|
cpp << "using namespace statemap;" << endl;
|
||||||
|
|
||||||
|
openNamespaces(cpp);
|
||||||
|
for (const auto& map : _maps)
|
||||||
|
{
|
||||||
|
dynamic_cast<MapForCpp*>(map)->generateCode(cpp, debug);
|
||||||
|
}
|
||||||
|
closeNamespaces(cpp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool FSMForCpp::updated(const Path& out)
|
||||||
|
{
|
||||||
|
Path incPath(out, fsmfile() + ".h");
|
||||||
|
File incFile(incPath);
|
||||||
|
if (incFile.exists())
|
||||||
|
{
|
||||||
|
Timestamp incFilets = incFile.getLastModified();
|
||||||
|
Timestamp fsmfilets = parser()->file().getLastModified();
|
||||||
|
if (incFilets > fsmfilets)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
FSM/src/FactoryForCpp.cpp
Normal file
111
FSM/src/FactoryForCpp.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* FactoryForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 20 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/FactoryForCpp.h"
|
||||||
|
#include "cpp/ActionForCpp.h"
|
||||||
|
#include "cpp/FSMForCpp.h"
|
||||||
|
#include "cpp/GuardForCpp.h"
|
||||||
|
#include "cpp/MapForCpp.h"
|
||||||
|
#include "cpp/ParameterForCpp.h"
|
||||||
|
#include "cpp/StateForCpp.h"
|
||||||
|
#include "cpp/EntryForCpp.h"
|
||||||
|
#include "cpp/ExitForCpp.h"
|
||||||
|
#include "cpp/TransitionForCpp.h"
|
||||||
|
#include "cpp/ReferenceForCpp.h"
|
||||||
|
#include "cpp/VariableForCpp.h"
|
||||||
|
#include "cpp/FunctionForCpp.h"
|
||||||
|
#include "cpp/LiteralForCpp.h"
|
||||||
|
#include "cpp/ArgumentForCpp.h"
|
||||||
|
#include "cpp/UnaryOperationForCpp.h"
|
||||||
|
#include "cpp/BinaryOperationForCpp.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
ActionPtr FactoryForCpp::newAction(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new ActionForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
FSMPtr FactoryForCpp::newFSM(Parser* parser) const
|
||||||
|
{
|
||||||
|
return new FSMForCpp(parser);
|
||||||
|
}
|
||||||
|
GuardPtr FactoryForCpp::newGuard(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new GuardForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
MapPtr FactoryForCpp::newMap(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new MapForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
ParameterPtr FactoryForCpp::newParameter(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new ParameterForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
StatePtr FactoryForCpp::newState(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new StateForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
EntryPtr FactoryForCpp::newEntry(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new EntryForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
ExitPtr FactoryForCpp::newExit(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new ExitForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
TransitionPtr FactoryForCpp::newTransition(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new TransitionForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
ReferencePtr FactoryForCpp::newReference(const VariablePtr variable, int lineno) const
|
||||||
|
{
|
||||||
|
return new ReferenceForCpp(variable, lineno);
|
||||||
|
}
|
||||||
|
ReferencePtr FactoryForCpp::newReference(const FunctionPtr function, int lineno) const
|
||||||
|
{
|
||||||
|
return new ReferenceForCpp(function, lineno);
|
||||||
|
}
|
||||||
|
ReferencePtr FactoryForCpp::newReference(const LiteralPtr literal, int lineno) const
|
||||||
|
{
|
||||||
|
return new ReferenceForCpp(literal, lineno);
|
||||||
|
}
|
||||||
|
VariablePtr FactoryForCpp::newVariable(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new VariableForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
FunctionPtr FactoryForCpp::newFunction(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new FunctionForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
LiteralPtr FactoryForCpp::newLiteral(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new LiteralForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
ArgumentPtr FactoryForCpp::newArgument(const string& name, int lineno) const
|
||||||
|
{
|
||||||
|
return new ArgumentForCpp(name, lineno);
|
||||||
|
}
|
||||||
|
UnaryOperationPtr FactoryForCpp::newUnaryOperation(Poco::FSM::MODEL::Operator op) const
|
||||||
|
{
|
||||||
|
return new UnaryOperationForCpp(op);
|
||||||
|
}
|
||||||
|
BinaryOperationPtr FactoryForCpp::newBinaryOperation(Poco::FSM::MODEL::Operator op) const
|
||||||
|
{
|
||||||
|
return new BinaryOperationForCpp(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
FSM/src/Function.cpp
Normal file
39
FSM/src/Function.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Function.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Function.h"
|
||||||
|
#include "model/Argument.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Function::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += name();
|
||||||
|
oneline += '(';
|
||||||
|
string arguments;
|
||||||
|
|
||||||
|
for (int no = 0; no < _arguments.size(); ++no)
|
||||||
|
{
|
||||||
|
arguments += _arguments[no]->name();
|
||||||
|
if (no + 1 < _arguments.size())
|
||||||
|
arguments += ", ";
|
||||||
|
}
|
||||||
|
oneline += arguments;
|
||||||
|
oneline += ')';
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
FSM/src/FunctionForCpp.cpp
Normal file
25
FSM/src/FunctionForCpp.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* FunctionForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/FunctionForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
const string FunctionForCpp::display(const string& prefix) const
|
||||||
|
{
|
||||||
|
return prefix + Function::display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
FSM/src/Guard.cpp
Normal file
57
FSM/src/Guard.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Guard.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
#include <algorithm>
|
||||||
|
using std::max;
|
||||||
|
|
||||||
|
|
||||||
|
#include "model/Guard.h"
|
||||||
|
#include "model/Action.h"
|
||||||
|
#include "model/State.h"
|
||||||
|
#include "model/Expression.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Guard::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
string guards;
|
||||||
|
if (_condition != nullptr)
|
||||||
|
{
|
||||||
|
guards += '[';
|
||||||
|
guards += _condition->display();
|
||||||
|
guards += ']';
|
||||||
|
}
|
||||||
|
guards.resize(max(guards.size(), (size_t)40), ' ');
|
||||||
|
oneline += guards;
|
||||||
|
|
||||||
|
string end = "nil";
|
||||||
|
if (endstate())
|
||||||
|
end = endstate()->name();
|
||||||
|
end.resize(max(end.size(), (size_t)10), ' ');
|
||||||
|
|
||||||
|
oneline += end;
|
||||||
|
|
||||||
|
string actions;
|
||||||
|
actions += '{';
|
||||||
|
for (auto action : _actions)
|
||||||
|
{
|
||||||
|
actions += action->display();
|
||||||
|
}
|
||||||
|
actions += '}';
|
||||||
|
|
||||||
|
oneline += actions;
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
FSM/src/GuardForCpp.cpp
Normal file
27
FSM/src/GuardForCpp.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* GuardForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/GuardForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void GuardForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void GuardForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
FSM/src/Identifier.cpp
Normal file
55
FSM/src/Identifier.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Identifier.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
#include "parser/Identifier.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
Token::Class
|
||||||
|
Identifier::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::IDENTIFIER_TOKEN;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
Identifier::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
if (c != -1 && Ascii::isAlpha(c))
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
Identifier::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int c = istr.peek();
|
||||||
|
while (c != -1 && (Ascii::isAlphaNumeric(c) || Ascii::isDigit(c) || c == '_') || c == '-')
|
||||||
|
{
|
||||||
|
istr.get();
|
||||||
|
_value += c;
|
||||||
|
c = istr.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
FSM/src/IndentStream.cpp
Normal file
22
FSM/src/IndentStream.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "parser/IndentStream.h"
|
||||||
|
|
||||||
|
std::ostream& tab(std::ostream& stream)
|
||||||
|
{
|
||||||
|
IndentStream* pIndentStream = dynamic_cast<IndentStream*>(&stream);
|
||||||
|
if (pIndentStream != nullptr)
|
||||||
|
{
|
||||||
|
pIndentStream->ib.tab();
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& back(std::ostream& stream)
|
||||||
|
{
|
||||||
|
IndentStream* pIndentStream = dynamic_cast<IndentStream*>(&stream);
|
||||||
|
if (pIndentStream != nullptr)
|
||||||
|
{
|
||||||
|
pIndentStream->ib.back();
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
111
FSM/src/Keyword.cpp
Normal file
111
FSM/src/Keyword.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Keyword.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Token.h"
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
|
||||||
|
#include "parser/Keyword.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
Keyword::Keyword()
|
||||||
|
{
|
||||||
|
_opMap["%start"] = START; // %start
|
||||||
|
_opMap["%class"] = CLASS; // %class
|
||||||
|
_opMap["%fsmclass"] = FFSMLASS, // %fsmclass
|
||||||
|
_opMap["%fsmfile"] = FSMFILE, // %fsmfile
|
||||||
|
_opMap["%header"] = HEADER; // %header
|
||||||
|
_opMap["%include"] = INCLUDE; // %include
|
||||||
|
_opMap["%package"] = PACKAGE; // %package
|
||||||
|
_opMap["%import"] = IMPORT; // %import
|
||||||
|
_opMap["%declare"] = DECLARE; // %declare
|
||||||
|
_opMap["%access"] = ACCESS; // %access
|
||||||
|
_opMap["%map"] = MAP; // %map
|
||||||
|
_opMap["%return"] = RETURN; // %return
|
||||||
|
}
|
||||||
|
Keyword::~Keyword()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::Class Keyword::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::KEYWORD_TOKEN;
|
||||||
|
}
|
||||||
|
bool Keyword::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
if (c != -1 && c == '%')
|
||||||
|
{
|
||||||
|
char next = istr.peek();
|
||||||
|
if (islower(next))
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void Keyword::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int c = istr.peek();
|
||||||
|
while (c != -1 && (Ascii::isLower(c)))
|
||||||
|
{
|
||||||
|
istr.get();
|
||||||
|
_value += c;
|
||||||
|
c = istr.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int Keyword::asInteger() const
|
||||||
|
{
|
||||||
|
OpMap::const_iterator it = _opMap.find(_value);
|
||||||
|
if (it != _opMap.end())
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const char* Keyword::asString(int kwno)
|
||||||
|
{
|
||||||
|
switch (kwno)
|
||||||
|
{
|
||||||
|
case START:
|
||||||
|
return "%start";
|
||||||
|
case CLASS:
|
||||||
|
return "%class";
|
||||||
|
case FSMFILE:
|
||||||
|
return "%fsmfile";
|
||||||
|
case FFSMLASS:
|
||||||
|
return "%fsmclass";
|
||||||
|
case HEADER:
|
||||||
|
return "%header";
|
||||||
|
case INCLUDE:
|
||||||
|
return "%include";
|
||||||
|
case PACKAGE:
|
||||||
|
return "%package";
|
||||||
|
case IMPORT:
|
||||||
|
return "%import";
|
||||||
|
case DECLARE:
|
||||||
|
return "%declare";
|
||||||
|
case ACCESS:
|
||||||
|
return "%access";
|
||||||
|
case MAP:
|
||||||
|
return "%map";
|
||||||
|
default:
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
FSM/src/Literal.cpp
Normal file
26
FSM/src/Literal.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Literal.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Literal.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Literal::display() const
|
||||||
|
{
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
const string Literal::display(const string& prefix) const
|
||||||
|
{
|
||||||
|
return display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
FSM/src/LiteralForCpp.cpp
Normal file
21
FSM/src/LiteralForCpp.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* LiteralForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 21 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/LiteralForCpp.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
FSM/src/Map.cpp
Normal file
58
FSM/src/Map.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Map.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Map.h"
|
||||||
|
#include "model/Transition.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
void Map::add(TransitionPtr transition)
|
||||||
|
{
|
||||||
|
if (transition->name() != "Default")
|
||||||
|
_transitions[transition->signature()] = transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::add(StatePtr state)
|
||||||
|
{
|
||||||
|
_states[state->name()] = state;
|
||||||
|
state->map() = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatePtr Map::lookfor(const string& state) const
|
||||||
|
{
|
||||||
|
StatePtr result = nullptr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = _states.at(state);
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Map::print(Print& print) const
|
||||||
|
{
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
state.second->print(print);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const string Map::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
252
FSM/src/MapForCpp.cpp
Normal file
252
FSM/src/MapForCpp.cpp
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* MapForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "parser/IndentStream.h"
|
||||||
|
#include "model/Parameter.h"
|
||||||
|
#include "cpp/MapForCpp.h"
|
||||||
|
#include "cpp/StateForCpp.h"
|
||||||
|
#include "cpp/FSMForCpp.h"
|
||||||
|
#include "cpp/TransitionForCpp.h"
|
||||||
|
|
||||||
|
using Poco::FSM::MODEL::Parameter;
|
||||||
|
using Poco::FSM::MODEL::StatePtr;
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
|
||||||
|
string MapForCpp::defaultStateName() const
|
||||||
|
{
|
||||||
|
return name() + '_' + defaultState()->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
string MapForCpp::startStateName() const
|
||||||
|
{
|
||||||
|
return fsm()->startState();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int LL = 50;
|
||||||
|
|
||||||
|
void MapForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
string comment;
|
||||||
|
{
|
||||||
|
comment = "// Forward declarations.";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
inc << "class " << name() << ";" << endl;
|
||||||
|
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
dynamic_cast<StateForCpp*>(state.second)->generateForwarDeclaration(inc, debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
inc << "class " << defaultStateName() << ";" << endl;
|
||||||
|
inc << "class " << fsm()->klass() << "State;" << endl;
|
||||||
|
inc << "template<typename Derived> class " << fsm()->fsmclass() << ";" << endl;
|
||||||
|
inc << "class " << fsm()->klass() << ";" << endl;
|
||||||
|
inc << endl;
|
||||||
|
inc << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
comment = "// Class State.";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
inc << "class " << fsm()->klass() << "State : public statemap::State {" << endl;
|
||||||
|
inc << "public:" << endl << tab;
|
||||||
|
|
||||||
|
inc << fsm()->klass() << "State(const char *name, int no) : statemap::State(name, no) {};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
inc << "virtual void Entry(" << fsm()->context() << "&) {};" << endl;
|
||||||
|
inc << "virtual void Exit(" << fsm()->context() << "&) {};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
StateForCpp* sfc = dynamic_cast<StateForCpp*>(state.second);
|
||||||
|
sfc->generateVirtualTransitions(inc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (const auto& transition : transitions())
|
||||||
|
if (transition.second)
|
||||||
|
{
|
||||||
|
Parameter context("context");
|
||||||
|
context.type() = fsm()->context() + '&';
|
||||||
|
TransitionForCpp* tfc = static_cast<TransitionForCpp*>(transition.second);
|
||||||
|
inc << "virtual void " << tfc->declaration(&context) << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
inc << back << "protected:" << endl << tab;
|
||||||
|
inc << "virtual void Default(" << fsm()->context() << "& context);" << endl << back;
|
||||||
|
inc << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
comment = "// FSM map default state class.";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
inc << "class " << defaultStateName() << " : public " << fsm()->klass() << "State {" << endl;
|
||||||
|
inc << "public:" << endl << tab;
|
||||||
|
inc << defaultStateName() << " (const char *name, int stateId) : " << fsm()->klass() << "State(name, stateId) {}" << endl;
|
||||||
|
inc << back << "};";
|
||||||
|
inc << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
comment = "// FSM map states class.";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
StateForCpp* sfc = dynamic_cast<StateForCpp*>(state.second);
|
||||||
|
sfc->generateDefinition(inc, debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
comment = "// FSM map class.";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
inc << "class " << name() << " {" << endl;
|
||||||
|
inc << "public:" << endl << tab;
|
||||||
|
inc << name() << "();" << endl;
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
const StatePtr sp = state.second;
|
||||||
|
inc << name() + '_' + sp->name() << ' ' << sp->name() << ";" << endl;
|
||||||
|
}
|
||||||
|
inc << back << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
comment = "// FSM context class ";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
inc << comment << endl;
|
||||||
|
|
||||||
|
inc << "template<typename Derived>" << endl;
|
||||||
|
inc << "class " << fsm()->fsmclass() << " : public statemap::FSMContext, public " << name() << " {" << endl;
|
||||||
|
inc << "public:" << endl << tab;
|
||||||
|
|
||||||
|
inc << "explicit " << endl;
|
||||||
|
inc << fsm()->fsmclass() << "(statemap::Notifier& notifier) : FSMContext(notifier, " << startStateName() << ") {};" << endl;
|
||||||
|
inc << fsm()->fsmclass() << "(statemap::Notifier& notifier, const statemap::State& state) : FSMContext(notifier, state) {};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
inc << "void setStartState(const statemap::State& state) {" << endl;
|
||||||
|
inc << " setState(state);" << endl;
|
||||||
|
inc << "}" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
inc << "virtual void enterStartState() {" << endl;
|
||||||
|
inc << " getState().Entry(*this);" << endl;
|
||||||
|
inc << " return;" << endl;
|
||||||
|
inc << "}" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
inc << "Derived& getOwner() {" << endl;
|
||||||
|
inc << " return (*static_cast<Derived*>(this));" << endl;
|
||||||
|
inc << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
inc << "const Derived& getOwner() const {" << endl;
|
||||||
|
inc << " return (*static_cast<const Derived*>(this));" << endl;
|
||||||
|
inc << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
inc << fsm()->klass() << "State& getState() const {" << endl;
|
||||||
|
inc << " if (_state == nullptr) {" << endl;
|
||||||
|
inc << " throw statemap::StateUndefinedException();" << endl;
|
||||||
|
inc << " }" << endl;
|
||||||
|
inc << " return (dynamic_cast<" << fsm()->klass() << "State&>(*_state));" << endl;
|
||||||
|
inc << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
for (const auto& transition : transitions())
|
||||||
|
if (transition.second)
|
||||||
|
{
|
||||||
|
TransitionForCpp* tfc = static_cast<TransitionForCpp*>(transition.second);
|
||||||
|
if (fsm()->returnt().empty())
|
||||||
|
inc << "void ";
|
||||||
|
else
|
||||||
|
inc << fsm()->returnt() + " ";
|
||||||
|
|
||||||
|
inc << tfc->declaration() << " {" << endl;
|
||||||
|
inc << " setTransition(\"" << tfc->Transition::name() << "\");" << endl;
|
||||||
|
inc << " getState()." << tfc->call("*this") << ";" << endl;
|
||||||
|
inc << " setTransition(nullptr);" << endl;
|
||||||
|
inc << "};" << endl;
|
||||||
|
}
|
||||||
|
inc << back;
|
||||||
|
inc << "};" << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void MapForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
string comment;
|
||||||
|
cpp << "// FSM Map constructor." << endl;
|
||||||
|
cpp << name() << "::" << name() << "() :" << endl << tab;
|
||||||
|
int no = 0;
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
StateForCpp* sfc = dynamic_cast<StateForCpp*>(state.second);
|
||||||
|
sfc->generateDeclaration(cpp, no++);
|
||||||
|
if (no < states().size())
|
||||||
|
cpp << ",";
|
||||||
|
cpp << endl;
|
||||||
|
}
|
||||||
|
cpp << back << "{}" << endl;
|
||||||
|
|
||||||
|
cpp << endl;
|
||||||
|
comment = "// Class state ";
|
||||||
|
comment.resize(LL, '-');
|
||||||
|
cpp << comment << endl;
|
||||||
|
for (const auto& transition : transitions())
|
||||||
|
if (transition.second)
|
||||||
|
{
|
||||||
|
Parameter context("context");
|
||||||
|
context.type() = fsm()->context() + '&';
|
||||||
|
TransitionForCpp* tfc = static_cast<TransitionForCpp*>(transition.second);
|
||||||
|
if (fsm()->returnt().empty())
|
||||||
|
cpp << "void ";
|
||||||
|
else
|
||||||
|
cpp << fsm()->returnt() + " ";
|
||||||
|
|
||||||
|
cpp << fsm()->klass() << "State::" << tfc->declaration(&context) << " {" << endl;
|
||||||
|
cpp << " Default(context);" << endl;
|
||||||
|
cpp << "}" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpp << "void " << fsm()->klass() << "State::Default(" << fsm()->context() << "& context) {" << endl;
|
||||||
|
cpp << " throw TransitionUndefinedException(context.getState().getName(), context.getTransition());" << endl;
|
||||||
|
cpp << " return;" << endl;
|
||||||
|
cpp << "}" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
for (const auto& state : states())
|
||||||
|
{
|
||||||
|
StateForCpp* sfc = dynamic_cast<StateForCpp*>(state.second);
|
||||||
|
sfc->generateCode(cpp, debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
FSM/src/Number.cpp
Normal file
49
FSM/src/Number.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Number.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Token.h"
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
#include "parser/Number.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
Token::Class Number::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::INTEGER_LITERAL_TOKEN;
|
||||||
|
}
|
||||||
|
bool Number::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
if (c != -1 && Ascii::isDigit(c))
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void Number::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int c = istr.peek();
|
||||||
|
while (c != -1 && Ascii::isDigit(c))
|
||||||
|
{
|
||||||
|
istr.get();
|
||||||
|
_value += c;
|
||||||
|
c = istr.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
FSM/src/Operation.cpp
Normal file
32
FSM/src/Operation.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Operation.cpp
|
||||||
|
*
|
||||||
|
* Created on: 20 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Operation.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
|
||||||
|
Operation::Operation(Operator op) :_operator(op)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Operation:: ~Operation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Operation::setNoContextuel()
|
||||||
|
{
|
||||||
|
if (_operator == Operator::equal || _operator == Operator::notequal)
|
||||||
|
{
|
||||||
|
_contextuel = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
212
FSM/src/Operator.cpp
Normal file
212
FSM/src/Operator.cpp
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Operator.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
|
||||||
|
#include "parser/Operator.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
Operator::Operator()
|
||||||
|
{
|
||||||
|
_opMap["["] = OP::OPENBRACKET;
|
||||||
|
_opMap["]"] = OP::CLOSBRACKET;
|
||||||
|
_opMap["("] = OP::OPENPARENT;
|
||||||
|
_opMap[")"] = OP::CLOSPARENT;
|
||||||
|
_opMap["{"] = OP::OPENBRACE;
|
||||||
|
_opMap["}"] = OP::CLOSBRACE;
|
||||||
|
_opMap["<"] = OP::LT;
|
||||||
|
_opMap["<="] = OP::LE;
|
||||||
|
_opMap["<<"] = OP::SHL;
|
||||||
|
_opMap["<<="] = OP::SHL_ASSIGN;
|
||||||
|
_opMap[">"] = OP::GT;
|
||||||
|
_opMap[">="] = OP::GE;
|
||||||
|
_opMap[">>"] = OP::SHR;
|
||||||
|
_opMap[">>="] = OP::SHR_ASSIGN;
|
||||||
|
_opMap["="] = OP::ASSIGN;
|
||||||
|
_opMap["=="] = OP::EQ;
|
||||||
|
_opMap["!"] = OP::NOT;
|
||||||
|
_opMap["!="] = OP::NE;
|
||||||
|
_opMap["&"] = OP::BITAND;
|
||||||
|
_opMap["&="] = OP::BITAND_ASSIGN;
|
||||||
|
_opMap["&&"] = OP::AND;
|
||||||
|
_opMap["|"] = OP::BITOR;
|
||||||
|
_opMap["|="] = OP::BITOR_ASSIGN;
|
||||||
|
_opMap["||"] = OP::OR;
|
||||||
|
_opMap["^"] = OP::XOR;
|
||||||
|
_opMap["^="] = OP::XOR_ASSIGN;
|
||||||
|
_opMap["~"] = OP::COMPL;
|
||||||
|
_opMap["*"] = OP::STAR;
|
||||||
|
_opMap["*="] = OP::STAR_ASSIGN;
|
||||||
|
_opMap["/"] = OP::SLASH;
|
||||||
|
_opMap["/="] = OP::SLASH_ASSIGN;
|
||||||
|
_opMap["+"] = OP::PLUS;
|
||||||
|
_opMap["+="] = OP::PLUS_ASSIGN;
|
||||||
|
_opMap["++"] = OP::INCR;
|
||||||
|
_opMap["-"] = OP::MINUS;
|
||||||
|
_opMap["-="] = OP::MINUS_ASSIGN;
|
||||||
|
_opMap["--"] = OP::DECR;
|
||||||
|
_opMap["->"] = OP::ARROW;
|
||||||
|
_opMap["%"] = OP::MOD;
|
||||||
|
_opMap["%="] = OP::MOD_ASSIGN;
|
||||||
|
_opMap[","] = OP::COMMA;
|
||||||
|
_opMap["."] = OP::PERIOD;
|
||||||
|
_opMap["..."] = OP::ELLIPSIS;
|
||||||
|
_opMap[":"] = OP::COLON;
|
||||||
|
_opMap["::"] = OP::DBL_COLON;
|
||||||
|
_opMap[";"] = OP::SEMICOLON;
|
||||||
|
_opMap["?"] = OP::QUESTION;
|
||||||
|
_opMap["%{"] = OP::OPENCODE;
|
||||||
|
_opMap["%}"] = OP::CLOSCODE;
|
||||||
|
_opMap["%%"] = OP::FSM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Operator::~Operator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Token::Class Operator::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::OPERATOR_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Operator::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
char next = (char) istr.peek();
|
||||||
|
switch (_value[0])
|
||||||
|
{
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '=':
|
||||||
|
case '!':
|
||||||
|
case '&':
|
||||||
|
case '|':
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
case '^':
|
||||||
|
case '~':
|
||||||
|
case ',':
|
||||||
|
case ':':
|
||||||
|
case ';':
|
||||||
|
case '%':
|
||||||
|
case '?':
|
||||||
|
return true;
|
||||||
|
case '.':
|
||||||
|
return !(next >= '0' && next <= '9');
|
||||||
|
case '/':
|
||||||
|
return !(next == '/' || next == '*');
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Operator::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int next = (char) istr.peek();
|
||||||
|
switch (_value[0])
|
||||||
|
{
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case ';':
|
||||||
|
case '?':
|
||||||
|
case '~':
|
||||||
|
case ',':
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
if (next == '.')
|
||||||
|
{
|
||||||
|
_value += (char) istr.get();
|
||||||
|
if (istr.peek() != '.') syntaxError(".", std::string(1, (char)istr.peek()));
|
||||||
|
_value += (char) istr.get();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
if (next == ':') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
if (next == '<')
|
||||||
|
{
|
||||||
|
_value += (char) istr.get();
|
||||||
|
next = (char) istr.peek();
|
||||||
|
}
|
||||||
|
if (next == '=') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
if (next == '>')
|
||||||
|
{
|
||||||
|
_value += (char) istr.get();
|
||||||
|
next = (char) istr.peek();
|
||||||
|
}
|
||||||
|
if (next == '=') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
if (next == '&' || next == '=') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
if (next == '|' || next == '=') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
if (next == '+' || next == '=') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (next == '-' || next == '=' || next == '>') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
case '!':
|
||||||
|
case '*':
|
||||||
|
case '/':
|
||||||
|
case '^':
|
||||||
|
case '%':
|
||||||
|
if (next == '=' || next == '{' || next == '}' || next == '%') _value += (char) istr.get();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
poco_bugcheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Operator::asInteger() const
|
||||||
|
{
|
||||||
|
OpMap::const_iterator it = _opMap.find(_value);
|
||||||
|
if (it != _opMap.end())
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
FSM/src/Parameter.cpp
Normal file
28
FSM/src/Parameter.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Parameter.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Parameter.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string Parameter::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline += name();
|
||||||
|
oneline += ':';
|
||||||
|
oneline += _type;
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
FSM/src/ParameterForCpp.cpp
Normal file
31
FSM/src/ParameterForCpp.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* ParameterForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include "cpp/ParameterForCpp.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void ParameterForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
inc << type() << ' ' << name();
|
||||||
|
}
|
||||||
|
void ParameterForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
cpp << type() << ' ' << name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1021
FSM/src/Parser.cpp
Normal file
1021
FSM/src/Parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
57
FSM/src/Print.cpp
Normal file
57
FSM/src/Print.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Print.cpp
|
||||||
|
*
|
||||||
|
* Created on: 22 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
using std::max;
|
||||||
|
|
||||||
|
#include "Poco/Logger.h"
|
||||||
|
using Poco::Logger;
|
||||||
|
|
||||||
|
#include "model/Parameter.h"
|
||||||
|
#include "model/Guard.h"
|
||||||
|
#include "model/Transition.h"
|
||||||
|
#include "model/Print.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
void Print::operator()(const char* message)
|
||||||
|
{
|
||||||
|
logger.information(message);
|
||||||
|
}
|
||||||
|
void Print::operator()(const string& message)
|
||||||
|
{
|
||||||
|
logger.information(message);
|
||||||
|
}
|
||||||
|
void Print::operator()(const TransitionPtr transition, const GuardPtr guard)
|
||||||
|
{
|
||||||
|
string line = transition->name();
|
||||||
|
|
||||||
|
string parameters;
|
||||||
|
if (!transition->parameters().empty())
|
||||||
|
parameters += '(';
|
||||||
|
for (auto parameter : transition->parameters())
|
||||||
|
{
|
||||||
|
parameters += parameter->display();
|
||||||
|
}
|
||||||
|
if (!transition->parameters().empty())
|
||||||
|
parameters += ')';
|
||||||
|
|
||||||
|
line += parameters;
|
||||||
|
line.resize(max(line.size(), (size_t)34), ' ');
|
||||||
|
|
||||||
|
string guards = guard->display();
|
||||||
|
logger.information("\t%s%s", line, guards);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
FSM/src/Reference.cpp
Normal file
33
FSM/src/Reference.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Reference.cpp
|
||||||
|
*
|
||||||
|
* Created on: 1 févr. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/Reference.h"
|
||||||
|
#include "model/Guard.h"
|
||||||
|
#include "model/Transition.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
bool Reference::isParameter() const
|
||||||
|
{
|
||||||
|
GuardPtr g = guard();
|
||||||
|
TransitionPtr transition = guard()->transition();
|
||||||
|
if (transition->hasParameter(reference()->Element::name()))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const string Reference::display() const
|
||||||
|
{
|
||||||
|
return reference()->display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
FSM/src/ReferenceForCpp.cpp
Normal file
58
FSM/src/ReferenceForCpp.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* ReferenceForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 24 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp/ReferenceForCpp.h"
|
||||||
|
#include "cpp/VariableForCpp.h"
|
||||||
|
#include "cpp/FunctionForCpp.h"
|
||||||
|
|
||||||
|
using namespace Poco::FSM::MODEL;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
void ReferenceForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ReferenceForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const string ReferenceForCpp::display(const string& prefix) const
|
||||||
|
{
|
||||||
|
VariableForCpp* vfc;
|
||||||
|
FunctionForCpp* ffc;
|
||||||
|
vfc = dynamic_cast<VariableForCpp*>(reference());
|
||||||
|
ffc = dynamic_cast<FunctionForCpp*>(reference());
|
||||||
|
if (isParameter() || (operation() && !operation()->contextuel()))
|
||||||
|
{
|
||||||
|
if (operation())
|
||||||
|
operation()->setNoContextuel();
|
||||||
|
if (vfc)
|
||||||
|
return vfc->Variable::display();
|
||||||
|
else if (ffc)
|
||||||
|
return ffc->Function::display();
|
||||||
|
else
|
||||||
|
poco_assert(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vfc)
|
||||||
|
return vfc->display(prefix);
|
||||||
|
else if (ffc)
|
||||||
|
return ffc->display(prefix);
|
||||||
|
else
|
||||||
|
poco_assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
FSM/src/State.cpp
Normal file
67
FSM/src/State.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* State.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "Poco/Format.h"
|
||||||
|
using Poco::format;
|
||||||
|
|
||||||
|
|
||||||
|
#include "model/State.h"
|
||||||
|
#include "model/Entry.h"
|
||||||
|
#include "model/Exit.h"
|
||||||
|
#include "model/Transition.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
TransitionPtr State::get(const string& name, const List<ParameterPtr>& parameters) const
|
||||||
|
{
|
||||||
|
TransitionPtr transition = nullptr;
|
||||||
|
string signature = Transition::signature(name, parameters);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
transition = maps.at(signature);
|
||||||
|
}
|
||||||
|
catch (std::out_of_range e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return transition;
|
||||||
|
}
|
||||||
|
TransitionPtr State::add(TransitionPtr transition)
|
||||||
|
{
|
||||||
|
transition->begstate() = this;
|
||||||
|
_transitions.push_back(transition);
|
||||||
|
maps[transition->signature()] = transition;
|
||||||
|
return transition;
|
||||||
|
}
|
||||||
|
void State::print(Print& print) const
|
||||||
|
{
|
||||||
|
print(Element::name());
|
||||||
|
if (entry())
|
||||||
|
entry()->print(print);
|
||||||
|
if (exit())
|
||||||
|
exit()->print(print);
|
||||||
|
print("{");
|
||||||
|
for (const auto& transition : transitions())
|
||||||
|
{
|
||||||
|
transition->print(print);
|
||||||
|
}
|
||||||
|
print("}");
|
||||||
|
}
|
||||||
|
const string State::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
oneline = name();
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
118
FSM/src/StateForCpp.cpp
Normal file
118
FSM/src/StateForCpp.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* StateForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "cpp/MapForCpp.h"
|
||||||
|
#include "cpp/StateForCpp.h"
|
||||||
|
#include "cpp/EntryForCpp.h"
|
||||||
|
#include "cpp/ExitForCpp.h"
|
||||||
|
#include "cpp/ActionForCpp.h"
|
||||||
|
#include "cpp/TransitionForCpp.h"
|
||||||
|
#include "parser/IndentStream.h"
|
||||||
|
#include "model/FSM.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
string StateForCpp::statename() const
|
||||||
|
{
|
||||||
|
return map()->name() + '_' + name();
|
||||||
|
}
|
||||||
|
void StateForCpp::generateForwarDeclaration(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
inc << "class " << statename() << ';' << endl;
|
||||||
|
}
|
||||||
|
void StateForCpp::generateVirtualTransitions(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
for (const auto& transition : _transitions)
|
||||||
|
{
|
||||||
|
TransitionForCpp* tfc = dynamic_cast<TransitionForCpp*>(transition);
|
||||||
|
if (tfc)
|
||||||
|
tfc->generateVirtualTransitions(inc, debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void StateForCpp::generateDefinition(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
inc << "// --------------------------------------------------" << endl;
|
||||||
|
inc << "class " << statename() << ": public " << map()->name() <<"_Default { " << endl;
|
||||||
|
inc << "public:" << endl << tab;
|
||||||
|
inc << statename() << "(const char* name, int no) : " << map()->name() << "_Default(name, no) {}" << endl;
|
||||||
|
|
||||||
|
inc << endl;
|
||||||
|
if (entry())
|
||||||
|
{
|
||||||
|
inc << "void " << "Entry" << "(" << map()->fsm()->context() << "& context);" << endl;
|
||||||
|
}
|
||||||
|
if (exit())
|
||||||
|
{
|
||||||
|
inc << "void " << "Exit" << "(" << map()->fsm()->context() << "& context);" << endl;
|
||||||
|
}
|
||||||
|
inc << endl;
|
||||||
|
|
||||||
|
for (auto transition : _transitions)
|
||||||
|
{
|
||||||
|
TransitionForCpp* tfc = dynamic_cast<TransitionForCpp*>(transition);
|
||||||
|
if (tfc)
|
||||||
|
tfc->generateDefinition(inc, debug);
|
||||||
|
}
|
||||||
|
inc << back << "};" << endl;
|
||||||
|
inc << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StateForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void StateForCpp::generateDeclaration(ostream& cpp, int no) const
|
||||||
|
{
|
||||||
|
// cpp << name() << "\t\t" << map()->name() << "::" << State::name();
|
||||||
|
cpp << State::name() << '(' << '"' << State::name() << '"' << ", " << no << ")";
|
||||||
|
}
|
||||||
|
void StateForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
if (entry())
|
||||||
|
{
|
||||||
|
cpp << "void " << statename() << "::Entry" << "(" << map()->fsm()->context() << "& context) {" << endl;
|
||||||
|
cpp << " " << map()->fsm()->klass() << "& ctxt = context.getOwner();" << endl;
|
||||||
|
for (const auto& action : entry()->actions())
|
||||||
|
if (action)
|
||||||
|
{
|
||||||
|
ActionForCpp* afc = static_cast<ActionForCpp*>(action);
|
||||||
|
cpp << tab << "ctxt." << afc->display() << endl << back;
|
||||||
|
}
|
||||||
|
cpp << "}" << endl;
|
||||||
|
}
|
||||||
|
if (exit())
|
||||||
|
{
|
||||||
|
cpp << "void " << statename() << "::Exit" << "(" << map()->fsm()->context() << "& context) {" << endl;
|
||||||
|
cpp << " " << map()->fsm()->klass() << "& ctxt = context.getOwner();" << endl;
|
||||||
|
for (const auto& action : exit()->actions())
|
||||||
|
if (action)
|
||||||
|
{
|
||||||
|
ActionForCpp* afc = static_cast<ActionForCpp*>(action);
|
||||||
|
cpp << tab << "ctxt." << afc->display() << endl << back;
|
||||||
|
}
|
||||||
|
cpp << "}" << endl;
|
||||||
|
}
|
||||||
|
for (const auto& transition : _transitions)
|
||||||
|
{
|
||||||
|
TransitionForCpp* tfc = dynamic_cast<TransitionForCpp*>(transition);
|
||||||
|
if (tfc)
|
||||||
|
tfc->generateCode(cpp, debug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
FSM/src/String.cpp
Normal file
90
FSM/src/String.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* String.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
|
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::SyntaxException;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
|
||||||
|
#include "parser/String.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
|
||||||
|
String::String()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::~String()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Token::Class String::tokenClass() const
|
||||||
|
{
|
||||||
|
return Token::STRING_LITERAL_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool String::start(char c, std::istream& istr)
|
||||||
|
{
|
||||||
|
_value = c;
|
||||||
|
return c == '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void String::finish(std::istream& istr)
|
||||||
|
{
|
||||||
|
int next = istr.peek();
|
||||||
|
while (next != -1 && next != '"' && next != '\n' && next != '\r')
|
||||||
|
{
|
||||||
|
if (next == '\\') _value += (char) istr.get();
|
||||||
|
_value += (char) istr.get();
|
||||||
|
next = istr.peek();
|
||||||
|
}
|
||||||
|
if (next == '"')
|
||||||
|
{
|
||||||
|
next = istr.get();
|
||||||
|
_value += (char) next;
|
||||||
|
}
|
||||||
|
else throw SyntaxException("Unterminated string literal");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string String::asString() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
std::string::const_iterator it = _value.begin();
|
||||||
|
std::string::const_iterator end = _value.end();
|
||||||
|
if (it != end)
|
||||||
|
{
|
||||||
|
if (*it == '"') ++it;
|
||||||
|
while (it != end && *it != '"')
|
||||||
|
{
|
||||||
|
if (*it == '\\') ++it;
|
||||||
|
if (it != end) result += *it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
FSM/src/Token.cpp
Normal file
50
FSM/src/Token.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Token.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Ascii.h"
|
||||||
|
#include "Poco/StreamTokenizer.h"
|
||||||
|
#include "Poco/Token.h"
|
||||||
|
#include "Poco/Exception.h"
|
||||||
|
using Poco::StreamTokenizer;
|
||||||
|
using Poco::Token;
|
||||||
|
using Poco::InvalidToken;
|
||||||
|
using Poco::EOFToken;
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
using Poco::Ascii;
|
||||||
|
using Poco::SyntaxException;
|
||||||
|
|
||||||
|
#include "parser/Token.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
|
||||||
|
Token::Token()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Token::~Token()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Token::syntaxError(const std::string& expected, const std::string& actual)
|
||||||
|
{
|
||||||
|
std::string msg("expected: ");
|
||||||
|
msg.append(expected);
|
||||||
|
msg.append(", got: ");
|
||||||
|
msg.append(actual);
|
||||||
|
throw SyntaxException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
FSM/src/Tokenizer.cpp
Normal file
47
FSM/src/Tokenizer.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Tokenizer.cpp
|
||||||
|
*
|
||||||
|
* Created on: 3 août 2014
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Poco/Token.h"
|
||||||
|
using Poco::WhitespaceToken;
|
||||||
|
#include "parser/Tokenizer.h"
|
||||||
|
#include "parser/Identifier.h"
|
||||||
|
#include "parser/Number.h"
|
||||||
|
#include "parser/Keyword.h"
|
||||||
|
#include "parser/Comment.h"
|
||||||
|
#include "parser/Character.h"
|
||||||
|
#include "parser/Operator.h"
|
||||||
|
#include "parser/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
Tokenizer::Tokenizer(std::istream& istr):
|
||||||
|
StreamTokenizer(istr)
|
||||||
|
{
|
||||||
|
addToken(new WhitespaceToken());
|
||||||
|
addToken(new Comment());
|
||||||
|
addToken(new Identifier());
|
||||||
|
addToken(new Number());
|
||||||
|
addToken(new Keyword());
|
||||||
|
addToken(new Operator());
|
||||||
|
addToken(new Character());
|
||||||
|
addToken(new String());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tokenizer::~Tokenizer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
155
FSM/src/Transition.cpp
Normal file
155
FSM/src/Transition.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Transition.cpp
|
||||||
|
*
|
||||||
|
* Created on: 16 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
using std::max;
|
||||||
|
using std::binary_search;
|
||||||
|
|
||||||
|
#include "Poco/Format.h"
|
||||||
|
using Poco::format;
|
||||||
|
|
||||||
|
#include "model/Transition.h"
|
||||||
|
#include "model/Parameter.h"
|
||||||
|
#include "model/Guard.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
Transition::Transition(const string& name, int lineno) : Element(name, lineno)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Transition::~Transition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parameterEqual(const Parameter* left, const Parameter* right)
|
||||||
|
{
|
||||||
|
return left->Element::name() < right->Element::name();
|
||||||
|
}
|
||||||
|
bool Transition::hasParameter(const string& name) const
|
||||||
|
{
|
||||||
|
for (const auto& parameter : _parameters)
|
||||||
|
{
|
||||||
|
if (parameter->Element::name() == name)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string Transition::declaration(const Parameter* added) const
|
||||||
|
{
|
||||||
|
string declaration(name());
|
||||||
|
declaration += '(';
|
||||||
|
if (added != nullptr)
|
||||||
|
{
|
||||||
|
declaration += added->type();
|
||||||
|
declaration += ' ';
|
||||||
|
declaration += added->name();
|
||||||
|
if (!parameters().empty())
|
||||||
|
declaration += ", ";
|
||||||
|
}
|
||||||
|
if (!parameters().empty())
|
||||||
|
{
|
||||||
|
for (int no = 0; no < parameters().size(); ++no)
|
||||||
|
{
|
||||||
|
declaration += parameters()[no]->type();
|
||||||
|
declaration += ' ';
|
||||||
|
declaration += parameters()[no]->name();
|
||||||
|
if (no + 1 < parameters().size())
|
||||||
|
declaration += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declaration += ')';
|
||||||
|
return declaration;
|
||||||
|
}
|
||||||
|
string Transition::call(const char* c) const
|
||||||
|
{
|
||||||
|
string embed(name());
|
||||||
|
embed += '(';
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
embed += c;
|
||||||
|
if (!parameters().empty())
|
||||||
|
{
|
||||||
|
embed += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!parameters().empty())
|
||||||
|
{
|
||||||
|
for (int no = 0; no < parameters().size(); ++no)
|
||||||
|
{
|
||||||
|
embed += parameters()[no]->name();
|
||||||
|
if (no + 1 < parameters().size())
|
||||||
|
embed += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
embed += ')';
|
||||||
|
return embed;
|
||||||
|
}
|
||||||
|
string Transition::signature(const string& name, const List<ParameterPtr>& parameters)
|
||||||
|
{
|
||||||
|
string signature(name);
|
||||||
|
signature += '(';
|
||||||
|
if (!parameters.empty())
|
||||||
|
{
|
||||||
|
for (int no = 0; no < parameters.size(); ++no)
|
||||||
|
{
|
||||||
|
signature += parameters[no]->type();
|
||||||
|
if (no + 1 < parameters.size())
|
||||||
|
signature += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signature += ')';
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
const string& Transition::signature() const
|
||||||
|
{
|
||||||
|
if (_signature.empty())
|
||||||
|
{
|
||||||
|
_signature = signature(Element::name(), _parameters);
|
||||||
|
}
|
||||||
|
return _signature;
|
||||||
|
}
|
||||||
|
const string Transition::display() const
|
||||||
|
{
|
||||||
|
if (oneline.empty())
|
||||||
|
{
|
||||||
|
string transition = name();
|
||||||
|
|
||||||
|
string parameters;
|
||||||
|
if (!_parameters.empty())
|
||||||
|
parameters += '(';
|
||||||
|
for (auto parameter : _parameters)
|
||||||
|
{
|
||||||
|
parameters += parameter->display();
|
||||||
|
}
|
||||||
|
if (!_parameters.empty())
|
||||||
|
parameters += ')';
|
||||||
|
|
||||||
|
transition += parameters;
|
||||||
|
transition.resize(max(transition.size(), (size_t)30), ' ');
|
||||||
|
|
||||||
|
string guards = _guards.at(0)->display();
|
||||||
|
|
||||||
|
oneline = format("\t%s%s", transition, guards);
|
||||||
|
}
|
||||||
|
return oneline;
|
||||||
|
}
|
||||||
|
void Transition::print(Print& print) const
|
||||||
|
{
|
||||||
|
for (auto guard : guards())
|
||||||
|
{
|
||||||
|
const TransitionPtr transitionptr = const_cast<TransitionPtr>(this);
|
||||||
|
const GuardPtr guardptr = guard;
|
||||||
|
print(transitionptr, guardptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
175
FSM/src/TransitionForCpp.cpp
Normal file
175
FSM/src/TransitionForCpp.cpp
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* TransitionForCpp.cpp
|
||||||
|
*
|
||||||
|
* Created on: 19 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "cpp/TransitionForCpp.h"
|
||||||
|
#include "cpp/ParameterForCpp.h"
|
||||||
|
#include "cpp/FSMForCpp.h"
|
||||||
|
#include "cpp/MapForCpp.h"
|
||||||
|
#include "cpp/StateForCpp.h"
|
||||||
|
#include "cpp/GuardForCpp.h"
|
||||||
|
#include "cpp/ActionForCpp.h"
|
||||||
|
#include "cpp/ExpressionForCpp.h"
|
||||||
|
#include "parser/IndentStream.h"
|
||||||
|
#include "model/Parameter.h"
|
||||||
|
|
||||||
|
using Poco::FSM::MODEL::Parameter;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const bool RAPP = false;
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace PARSER
|
||||||
|
{
|
||||||
|
namespace CPP
|
||||||
|
{
|
||||||
|
|
||||||
|
const string TransitionForCpp::name() const
|
||||||
|
{
|
||||||
|
string cppname = Element::name();
|
||||||
|
replace(cppname.begin(), cppname.end(), '-', '_');
|
||||||
|
return cppname;
|
||||||
|
}
|
||||||
|
void TransitionForCpp::generateVirtualTransitions(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
if (begstate()->entry())
|
||||||
|
{
|
||||||
|
inc << "virtual void " << "Entry" << "(" << begstate()->map()->fsm()->context() << "& context);";
|
||||||
|
}
|
||||||
|
if (begstate()->exit())
|
||||||
|
{
|
||||||
|
inc << "virtual void " << "Exit" << "(" << begstate()->map()->fsm()->context() << "& context);";
|
||||||
|
}
|
||||||
|
inc << "virtual void " << name() << "(" << begstate()->map()->fsm()->context() << "& context";
|
||||||
|
if (!_parameters.empty())
|
||||||
|
{
|
||||||
|
inc << ", ";
|
||||||
|
for (int no = 0; no < _parameters.size(); ++no)
|
||||||
|
{
|
||||||
|
dynamic_cast<ParameterForCpp*>(_parameters[no])->generateInclude(inc, debug);
|
||||||
|
if (no + 1 < _parameters.size())
|
||||||
|
inc << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inc << ");" << endl;
|
||||||
|
}
|
||||||
|
void TransitionForCpp::generateDefinition(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
inc << "void " << name() << "(" << begstate()->map()->fsm()->context() << "& context";
|
||||||
|
if (!_parameters.empty())
|
||||||
|
{
|
||||||
|
inc << ", ";
|
||||||
|
for (int no = 0; no < _parameters.size(); ++no)
|
||||||
|
{
|
||||||
|
dynamic_cast<ParameterForCpp*>(_parameters[no])->generateInclude(inc, debug);
|
||||||
|
if (no + 1 < _parameters.size())
|
||||||
|
inc << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inc << ");" << endl;
|
||||||
|
}
|
||||||
|
void TransitionForCpp::generateInclude(ostream& inc, bool debug) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void TransitionForCpp::generateCode(ostream& cpp, bool debug) const
|
||||||
|
{
|
||||||
|
cpp << endl;
|
||||||
|
cpp << "// ----------------------------------------------------" << endl;
|
||||||
|
cpp << "void " << _begstate->map()->name() << '_' << _begstate->name() << "::";
|
||||||
|
Parameter context("context");
|
||||||
|
context.type() = begstate()->map()->fsm()->context() + '&';
|
||||||
|
cpp << declaration(&context) << " {"<< endl;
|
||||||
|
// cpp << "(" << begstate()->map()->fsm()->context() << "&context) {" << endl ;
|
||||||
|
cpp << tab;
|
||||||
|
|
||||||
|
cpp << _begstate->map()->fsm()->klass() << "& ctxt = context.getOwner();" << endl;
|
||||||
|
cpp << endl;
|
||||||
|
|
||||||
|
|
||||||
|
for (auto guard : _guards)
|
||||||
|
{
|
||||||
|
if (guard != nullptr)
|
||||||
|
{
|
||||||
|
if (guard->endstate() == nullptr)
|
||||||
|
{
|
||||||
|
for (auto action : guard->actions())
|
||||||
|
if (action != nullptr)
|
||||||
|
{
|
||||||
|
ActionForCpp* afc = static_cast<ActionForCpp*>(action);
|
||||||
|
cpp << "ctxt." << action->display() << endl;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guard->condition())
|
||||||
|
{
|
||||||
|
ExpressionForCpp* efc = dynamic_cast<ExpressionForCpp*>(guard->condition());
|
||||||
|
cpp << "if (" << efc->display("ctxt.") << ") {" << endl << tab;
|
||||||
|
}
|
||||||
|
cpp << "(context.getState()).Exit(context);" << endl;
|
||||||
|
|
||||||
|
if (guard->actions().size() > 0)
|
||||||
|
{
|
||||||
|
if (RAPP)
|
||||||
|
{
|
||||||
|
cpp << "context.clearState();" << endl;
|
||||||
|
}
|
||||||
|
if (RAPP)
|
||||||
|
{
|
||||||
|
cpp << "try {" << endl << tab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpp << "context.setState(context." << guard->endstate()->name() << ");" << endl;
|
||||||
|
if (!RAPP)
|
||||||
|
{
|
||||||
|
cpp << "(context.getState()).Entry(context);" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto action : guard->actions())
|
||||||
|
if (action != nullptr)
|
||||||
|
{
|
||||||
|
ActionForCpp* afc = static_cast<ActionForCpp*>(action);
|
||||||
|
cpp << "ctxt." << action->display() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guard->actions().size() > 0)
|
||||||
|
{
|
||||||
|
if (RAPP)
|
||||||
|
{
|
||||||
|
cpp << back << "} catch (...) {" << endl << tab;
|
||||||
|
cpp << "context.setState(context." << guard->endstate()->name() << ");" << endl;
|
||||||
|
cpp << "throw;" << endl << back;
|
||||||
|
cpp << "}" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RAPP)
|
||||||
|
{
|
||||||
|
cpp << "(context.getState()).Entry(context);" << endl;
|
||||||
|
}
|
||||||
|
if (guard->condition())
|
||||||
|
cpp << back << "} else " << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_guards[0]->condition())
|
||||||
|
{
|
||||||
|
Parameter context("context");
|
||||||
|
cpp << "{" << endl;
|
||||||
|
MapForCpp* mfcpp = dynamic_cast<MapForCpp*>(_begstate->map());
|
||||||
|
cpp << " " << mfcpp->defaultStateName() << "::" << call("context") << ";" << endl;
|
||||||
|
cpp << "}" << endl;
|
||||||
|
}
|
||||||
|
cpp << "return;" << back << endl;
|
||||||
|
cpp << "};" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
FSM/src/UnaryOperation.cpp
Normal file
31
FSM/src/UnaryOperation.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* UnaryOperation.cpp
|
||||||
|
*
|
||||||
|
* Created on: 20 janv. 2016
|
||||||
|
* Author: FrancisANDRE
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "model/UnaryOperation.h"
|
||||||
|
|
||||||
|
namespace Poco
|
||||||
|
{
|
||||||
|
namespace FSM
|
||||||
|
{
|
||||||
|
namespace MODEL
|
||||||
|
{
|
||||||
|
const string UnaryOperation::display() const
|
||||||
|
{
|
||||||
|
if (_asstring.empty())
|
||||||
|
{
|
||||||
|
switch (_operator)
|
||||||
|
{
|
||||||
|
case Operator::not:
|
||||||
|
_asstring += '!';
|
||||||
|
}
|
||||||
|
_asstring += _operand->display();
|
||||||
|
}
|
||||||
|
return _asstring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user