#include "externals.hh" #include "c-opast.hh" #include "c-ops.hh" #include "c-opcomp.hh" #include "c-opopt.hh" #include #include #include #include using namespace ebcl; using namespace opast; namespace { const struct option CmdLineOpts_[] = { { "log-level" , required_argument , 0 , 'L' } , { "source-path" , required_argument , 0 , 's' } , { "config" , required_argument , 0 , 'c' } , { 0 , 0 , 0 , 0 } }; /*============================================================================*/ void PrintStreamError( char const* const prefix , T_String const& name , X_StreamError const& error ) { T_StringBuilder sb; sb << prefix << " '" << name << "': " << error.what( ); if ( error.code( ) == E_StreamError::SYSTEM_ERROR ) { sb << " (error code " << error.systemError( ) << ")"; } sb << '\n' << '\0'; fprintf( stderr , "%s" , sb.data( ) ); } void WriteSRDError( T_StringBuilder& sb , T_SRDError const& error ) { switch ( error.type( ) ) { case E_SRDErrorType::ERROR: sb << "[ERROR"; break; case E_SRDErrorType::WARNING: sb << " [WARN"; break; case E_SRDErrorType::NOTE: sb << " [NOTE"; break; } sb << '(' << error.location( ) << ")] " << error.error( ) << '\n'; } /*============================================================================*/ } // namespace int main( int argc , char** argv ) { // Parse command line T_Optional< uint32_t > oLogLevel; T_String oSrcPath; T_String oBuildCfg; int c; while ( ( c = getopt_long( argc , argv , "L:s:c:" , CmdLineOpts_ , nullptr ) ) != -1 ) { switch ( c ) { case 'L': oLogLevel = uint32_t( atoi( optarg ) ); break; case 's': if ( oSrcPath ) { fprintf( stderr , "Duplicate source path\n" ); return EXIT_FAILURE; } oSrcPath = optarg; break; case 'c': if ( oSrcPath ) { fprintf( stderr , "Duplicate build configuration\n" ); return EXIT_FAILURE; } oBuildCfg = optarg; break; } } // Logger setup const uint32_t logLevel{ oLogLevel ? *oLogLevel : 0 }; const auto logger{ [=]( F_OPGenLog func , uint32_t level ) { if ( level > logLevel ) { return; } auto sb{ func( ) }; sb << '\0'; printf( "(%d) %s\n" , level , sb.data( ) ); } }; // Build configurations const T_String bcfgFile( [&]() { T_StringBuilder sb; if ( oSrcPath ) { sb << oSrcPath; if ( !oSrcPath.endsWith( "/" ) ) { sb << '/'; } } sb << "build.srd"; return T_String{ std::move( sb ) }; }( ) ); const T_BuildConfiguration cfg{ [&]() { try { T_BuildConfigurationLoader bcfgLoader; T_BuildConfigurations cfs{ bcfgLoader.load( bcfgFile ) }; if ( oBuildCfg && !cfs.contains( oBuildCfg ) ) { fprintf( stderr , "===== BUILD CONFIGURATIONS\n" ); fprintf( stderr , "Build configuration not found\n" ); exit( EXIT_FAILURE ); } if ( oBuildCfg ) { return *cfs.get( oBuildCfg ); } if ( cfs.size( ) ) { return cfs[ 0 ]; } return T_BuildConfiguration{ }; } catch ( X_StreamError const& e ) { fprintf( stderr , "===== BUILD CONFIGURATIONS\n" ); PrintStreamError( "Could not open" , bcfgFile , e ); exit( EXIT_FAILURE ); } catch ( X_SRDErrors const& e ) { T_StringBuilder sb; sb << "===== BUILD CONFIGURATIONS\n"; const auto nErrors( e.errors.size( ) ); for ( auto i = 0u ; i < nErrors ; i ++ ) { WriteSRDError( sb , e.errors[ i ] ); } sb << '\0'; fprintf( stderr , "%s" , sb.data( ) ); exit( EXIT_FAILURE ); } } () }; // Open file const T_String inputName( [&]() { T_StringBuilder sb; if ( oSrcPath ) { sb << oSrcPath; if ( !oSrcPath.endsWith( "/" ) ) { sb << '/'; } } sb << "demo.srd"; return T_String{ std::move( sb ) }; }( ) ); T_File input( inputName , E_FileMode::READ_ONLY ); try { input.open( ); } catch ( X_StreamError const& e ) { PrintStreamError( "Could not open" , inputName , e ); return 1; } // Load SRD data T_SRDMemoryTarget srdOut; srdOut.clearComments( true ).clearFlushToken( true ); try { T_SRDTextReader srdReader{ srdOut }; T_FileInputStream fis{ input }; srdReader.read( inputName , fis ); } catch ( X_StreamError const& e ) { PrintStreamError( "Could not open" , inputName , e ); return 1; } catch ( X_SRDErrors const& e ) { T_StringBuilder sb; const auto nErrors( e.errors.size( ) ); for ( auto i = 0u ; i < nErrors ; i ++ ) { WriteSRDError( sb , e.errors[ i ] ); } sb << "No parsing happened due to format errors\n" << '\0'; fprintf( stderr , "%s" , sb.data( ) ); return 2; } // Parse T_OpsParser parser; parser.setLogger( logger ); if ( !parser.parse( srdOut.list( ) ) ) { T_StringBuilder sb; for ( auto const& err : parser.errors( ) ) { WriteSRDError( sb , err ); } sb << "Parser failed\n" << '\0'; fprintf( stderr , "%s" , sb.data( ) ); return 3; } auto parsed{ parser.result( ) }; // Optimize opopt::T_OptData od; od.logger = logger; //od.fixedSize = std::make_pair( 1280u , 720u ); bool doneStuff{ false }; do { doneStuff = opopt::FoldConstants( *parsed , od ); doneStuff = opopt::RemoveDeadCode( *parsed , od ) || doneStuff; } while ( doneStuff ); // Compile T_OpsCompiler compiler; compiler.compile( *parsed ); return 0; }