#include "externals.hh" #include "common.hh" #include "c-project.hh" #include "c-buildcfg.hh" #include #include #include #include #include using namespace ebcl; namespace { /*= SRD PARSER FOR BUILD CONFIGURATIONS ======================================*/ using SP_Table_ = T_SharedPtr< T_BuildConfigurations >; bool BCLStartConfig_( T_SRDParserData const& data ) { *( data.targetData ) = T_BuildConfiguration{ }; return true; } bool BCLEndConfig_( T_SRDParserData const& data ) { auto const& in{ *data.input }; auto& table{ *( data.targetData->value< SP_Table_ >( ) ) }; auto& bCfg{ data.currentData->value< T_BuildConfiguration >( ) }; if ( !table.add( in[ 1 ].stringValue( ) , std::move( bCfg ) ) ) { data.errors.add( "duplicate configuration" , in[ 1 ] ); } return true; } /*----------------------------------------------------------------------------*/ bool BCLResolutions_( T_SRDParserData const& data ) { auto const& in{ *data.input }; auto& bCfg{ data.currentData->value< T_BuildConfiguration >( ) }; const uint32_t nin{ in.size( ) }; if ( nin == 2 && in[ 1 ].type( ) == E_SRDTokenType::WORD ) { bCfg.resolutionChooser = true; bCfg.resolutions.clear( ); return true; } bCfg.resolutionChooser = false; for ( auto i = 1u ; i < nin ; i ++ ) { auto const& l{ in[ i ].list( ) }; const auto w{ l[ 0 ].longValue( ) }; const auto h{ l[ 1 ].longValue( ) }; bool fail{ false }; if ( w <= 0 || w >= 16384 ) { fail = true; data.errors.add( "invalid width" , l[ 0 ] ); } if ( h <= 0 || h >= 16384 ) { fail = true; data.errors.add( "invalid height" , l[ 1 ] ); } if ( fail ) { continue; } const auto res{ std::make_pair< uint32_t , uint32_t >( w , h ) }; if ( bCfg.resolutions.contains( res ) ) { data.errors.add( InPlace( ) , "duplicate resolution" , in[ i ].location( ) , E_SRDErrorType::WARNING ); } else { bCfg.resolutions.add( res ); } } return true; } /*----------------------------------------------------------------------------*/ F_SRDHandler BCLToggle_( ptrdiff_t const fldOffset ) noexcept { return [=]( T_SRDParserData const& d ) -> bool { auto const& in{ *d.input }; char* bCfg{ (char*) &d.currentData->value< T_BuildConfiguration >( ) }; *(bool*)( bCfg + fldOffset ) = ( in[ 1 ].stringValue( ) == "on" ); return true; }; } #define M_BCL_TOGGLE_( N ) \ BCLToggle_( offsetof( T_BuildConfiguration , N ) ) /*----------------------------------------------------------------------------*/ T_SRDParserConfig BCLInitDefinitions_( ) noexcept { using namespace ebcl::SRD; T_SRDParserDefs defs{ "default" }; defs.enumeration( "on-off" ) << "off" << "on"; defs << OnStart( []( T_SRDParserData const& data ) -> bool { *( data.currentData ) = NewShared< T_BuildConfigurations >( ); return true; } ); defs.context( "default" ) << ( Rule( ) << "cfg" << Text( ) << EnterContext( "config" ) << OnEnter( BCLStartConfig_ ) << OnExit( BCLEndConfig_ ) ) ; defs.context( "config" ) << ( Rule( ) << "resolutions" << ( Alt( ) << "chooser" << ( AtLeast( 1 ) << ( List( ) << Int32( ) << Int32( ) ) ) ) << BCLResolutions_ ) << ( Rule( ) << "optimizer" << "off" << []( T_SRDParserData const& d ) -> bool { auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; bCfg.optimize = false; return true; } ) << ( Rule( ) << "optimizer" << "on" << EnterContext( "optim" ) << []( T_SRDParserData const& d ) -> bool { auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; bCfg.optimize = true; return true; } ) ; defs.context( "optim" ) << ( Rule( ) << "constant-folding" << "off" << M_BCL_TOGGLE_( constantFolding ) ) << ( Rule( ) << "constant-folding" << "on" << EnterContext( "opt-cf" ) << M_BCL_TOGGLE_( constantFolding ) ) << ( Rule( ) << "constant-propagation" << Enum( "on-off" ) << M_BCL_TOGGLE_( constantPropagation ) ) << ( Rule( ) << "dead-code-elimination" << Enum( "on-off" ) << M_BCL_TOGGLE_( deadCodeElimination ) ) << ( Rule( ) << "function-inlining" << Enum( "on-off" ) << M_BCL_TOGGLE_( inlineFunctions ) ) ; defs.context( "opt-cf" ) << ( Rule( ) << "fixed-resolution" << Enum( "on-off" ) << M_BCL_TOGGLE_( cfFixedSize ) ) << ( Rule( ) << "inputs" << Enum( "on-off" ) << M_BCL_TOGGLE_( cfInputs ) ) ; return T_SRDParserConfig{ defs }; } /*= BUILD CONFIGURATIONS LOADER ==============================================*/ struct T_BCLImpl_ { const T_String fileName{ T_String::Pooled( "build.srd" ) }; T_SRDParserConfig pConfig; T_BCLImpl_( ) noexcept; T_BuildConfigurations load( ); }; /*----------------------------------------------------------------------------*/ T_BCLImpl_::T_BCLImpl_( ) noexcept : pConfig{ BCLInitDefinitions_( ) } { } T_BuildConfigurations T_BCLImpl_::load( ) { // TODO: keep errors so we get warnings/notes too T_SRDParser parser{ pConfig }; T_SRDTextReader srdReader{ parser }; T_File input{ Common::Project( ).pathOf( fileName ) , E_FileMode::READ_ONLY }; T_FileInputStream fis{ input }; srdReader.read( fileName , fis ); return std::move( *parser.getData< T_SharedPtr< T_BuildConfigurations > >( ) ); } } // namespace /*----------------------------------------------------------------------------*/ T_BuildConfigurationLoader::T_BuildConfigurationLoader( ) noexcept : A_PrivateImplementation( new T_BCLImpl_( ) ) { } T_BuildConfigurations T_BuildConfigurationLoader::load( ) { return p< T_BCLImpl_ >( ).load( ); }