Merge pull request #1317 from Kampbell/FSM

FSM
This commit is contained in:
Günter Obiltschnig 2016-07-19 12:15:31 +02:00 committed by GitHub
commit 856a046e61
165 changed files with 15481 additions and 9 deletions

33
FSM/FSM_vs120.sln Normal file
View 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
View 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>

View 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
View 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

Binary file not shown.

BIN
FSM/SmcMan_6_6_0.tgz Normal file

Binary file not shown.

19
FSM/fsmc.properties Normal file
View 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

View 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
View 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)

View 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
View 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

View 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
View 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

View 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
View 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

View 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
View 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
{}
}
%%

View 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% &amp;&amp; ..\..\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% &amp;&amp; ..\..\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>

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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&)

View 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

View 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)

View 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

View 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
View 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
View 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)

View 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
View 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

View 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>

View 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

View 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) $<

View 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;
};
}

View 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

View 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); }
}
%%

View 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% &amp;&amp; ..\..\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% &amp;&amp; ..\..\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>

View 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>

View 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;
};
}

View 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)

View 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

View 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

View 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;
}
}

View 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

View 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

View 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

View 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>

View 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
View 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
View 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
View 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
View 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;
}
}
}
}

View 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
{
}
}
}
}
}

View 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;
}
}
}
}

View 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
View 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
View 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);
}
}
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,19 @@
/*
* Expression.cpp
*
* Created on: 21 janv. 2016
* Author: FrancisANDRE
*/
#include "model/Expression.h"
namespace Poco
{
namespace FSM
{
namespace MODEL
{
}
}
}

View 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
View 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
View 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
View 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
View 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;
}
}
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}
}
}
}

View 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

File diff suppressed because it is too large Load Diff

57
FSM/src/Print.cpp Normal file
View 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
View 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();
}
}
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
}
}
}
}

View 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;
}
}
}
}
}

View 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