#include #include #include #include #include #include #include // ------------------------------------------------------------------------- typedef std::map< char, std::vector< std::string > > TCommands; typedef std::map< std::string, std::vector< std::string > > TDefinitions; // ------------------------------------------------------------------------- void AddDefinitions( TDefinitions& defs, const std::string& cmd ); void InitDefinitions( TDefinitions& defs ); void Lines( TCommands& commands, const std::deque< std::string >& lines ); void ExpandDefinitions( TDefinitions& defs ); std::vector< std::string > Expand( const std::vector< std::string >& commands, const TDefinitions& defs ); // ------------------------------------------------------------------------- int main( int argc, char* argv[] ) { // Get parameters from input if( argc < 5 ) { std::cerr << "Usage: " << argv[ 0 ] << " definitions library_name source_prefix number_of_files" << std::endl; return( 1 ); } // fi std::string input_definitions = argv[ 1 ]; std::string library_name = argv[ 2 ]; std::string source_prefix = argv[ 3 ]; std::string header_file = source_prefix + std::string( ".h" ); std::stringstream nfiles_str( argv[ 4 ] ); unsigned int number_of_files; nfiles_str >> number_of_files; // Read input instances std::string buffer; if( !cpPlugins_bash::Read( buffer, input_definitions ) ) { std::cerr << "Error reading input instances from \"" << input_definitions << "\"" << std::endl; return( 1 ); } // fi // Put it in a line-by-line structure std::deque< std::string > lines; cpPlugins_bash::Tokenize( lines, buffer, "\n" ); // Parse commands TCommands commands; Lines( commands, lines ); // Init definitions TDefinitions defs; InitDefinitions( defs ); auto dIt = commands.find( 'd' ); if( dIt != commands.end( ) ) { for( auto vIt = dIt->second.begin( ); vIt != dIt->second.end( ); ++vIt ) AddDefinitions( defs, *vIt ); } // fi // Expand definitions ExpandDefinitions( defs ); // Expand code std::vector< std::string > before; auto bIt = commands.find( 'b' ); if( bIt != commands.end( ) ) before = bIt->second; auto templates = Expand( commands[ 't' ], defs ); auto includes = Expand( commands[ 'i' ], defs ); auto classes = Expand( commands[ 'c' ], defs ); // Write header file std::stringstream header; header << "#ifndef __" << library_name << "__h__" << std::endl << "#define __" << library_name << "__h__" << std::endl << std::endl << "#define ITK_MANUAL_INSTANTIATION" << std::endl; for( auto i = before.begin( ); i != before.end( ); ++i ) header << std::endl << *i; header << std::endl; for( auto i = includes.begin( ); i != includes.end( ); ++i ) header << "#include <" << *i << ">" << std::endl; for( auto i = templates.begin( ); i != templates.end( ); ++i ) header << "#include <" << *i << ".h>" << std::endl; header << std::endl; /* TODO for( auto i = classes.begin( ); i != classes.end( ); ++i ) header << "extern template class " << *i << ";" << std::endl; */ header << std::endl << "#endif // __" << library_name << "__H__" << std::endl; if( !( cpPlugins_bash::Write( header.str( ), header_file ) ) ) { std::cerr << "Error writing header" << std::endl; return( 1 ); } // fi // Write source code unsigned int classes_per_file = ( unsigned int )( std::floor( double( classes.size( ) ) / double( number_of_files ) ) ); if( classes_per_file == 0 ) classes_per_file = 1; std::vector< std::vector< std::string > > all_lines( 1 ); for( unsigned int c_id = 0; c_id < classes.size( ); ++c_id ) { all_lines[ all_lines.size( ) - 1 ].push_back( classes[ c_id ] ); if( c_id % classes_per_file == classes_per_file - 1 ) all_lines.push_back( std::vector< std::string >( ) ); } // rof // Paranoiac code while( all_lines.size( ) > number_of_files ) { all_lines[ all_lines.size( ) - 2 ].insert( all_lines[ all_lines.size( ) - 2 ].end( ), all_lines[ all_lines.size( ) - 1 ].begin( ), all_lines[ all_lines.size( ) - 1 ].end( ) ); all_lines.pop_back( ); } // elihw while( all_lines.size( ) < number_of_files ) all_lines.push_back( std::vector< std::string >( ) ); // Real write for( unsigned int f_id = 0; f_id < all_lines.size( ); ++f_id ) { std::stringstream source; source << "#define ITK_MANUAL_INSTANTIATION" << std::endl; source << "#include <" << library_name << "_Export.h>" << std::endl; for( auto i = before.begin( ); i != before.end( ); ++i ) source << std::endl << *i; source << std::endl; if( templates.size( ) > 0 ) { for( auto i = includes.begin( ); i != includes.end( ); ++i ) source << "#include <" << *i << ">" << std::endl; for( auto i = templates.begin( ); i != templates.end( ); ++i ) { source << "#include <" << *i << ".h>" << std::endl; source << "#include <" << *i << ".hxx>" << std::endl; } // rof source << std::endl; } // fi for( auto c_it = all_lines[ f_id ].begin( ); c_it != all_lines[ f_id ].end( ); ++c_it ) source << "template class " << library_name << "_EXPORT " << *c_it << ";" << std::endl; source << std::endl << "// eof" << std::endl; std::stringstream source_file; source_file << source_prefix << "_" << f_id << ".cxx"; if( !( cpPlugins_bash::Write( source.str( ), source_file.str( ) ) ) ) { std::cerr << "Error writing header" << std::endl; return( 1 ); } // fi } // rof return( 0 ); } // ------------------------------------------------------------------------- void AddDefinitions( TDefinitions& defs, const std::string& cmd ) { std::vector< std::string > tokens; cpPlugins_bash::Tokenize( tokens, cmd, "=;" ); for( unsigned int i = 1; i < tokens.size( ); ++i ) defs[ tokens[ 0 ] ].push_back( tokens[ i ] ); } // ------------------------------------------------------------------------- void InitDefinitions( TDefinitions& defs ) { AddDefinitions( defs, "integers=@cpPlugins_INTEGER_TYPES@" ); AddDefinitions( defs, "reals=@cpPlugins_REAL_TYPES@" ); AddDefinitions( defs, "colors=RGBPixel;RGBAPixel" ); AddDefinitions( defs, "vectors=CovariantVector;Point;SymmetricSecondRankTensor;Vector" ); AddDefinitions( defs, "tensors=DiffusionTensor3D" ); AddDefinitions( defs, "matrices=Matrix" ); AddDefinitions( defs, "process_dims=@cpPlugins_PROCESS_DIMENSIONS@" ); AddDefinitions( defs, "visual_dims=@cpPlugins_VISUAL_DIMENSIONS@" ); AddDefinitions( defs, "naturals=unsigned #integers#" ); AddDefinitions( defs, "pixels=#integers#;#naturals#;#reals#" ); } // ------------------------------------------------------------------------- void Lines( TCommands& commands, const std::deque< std::string >& lines ) { std::string buffer; for( auto l = lines.begin( ); l != lines.end( ); ++l ) { auto pos = l->find_first_not_of( " " ); char cmd = tolower( ( *l )[ pos ] ); commands[ cmd ].push_back( l->substr( l->find_first_not_of( " ", pos + 1 ) ) ); } // elihw } // ------------------------------------------------------------------------- void ExpandDefinitions( TDefinitions& defs ) { for( auto d = defs.begin( ); d != defs.end( ); ++d ) { std::deque< std::string > q; q.insert( q.end( ), d->second.begin( ), d->second.end( ) ); std::vector< std::string > n; while( q.size( ) > 0 ) { auto v = q.front( ); q.pop_front( ); auto pos = v.find( "#" ); if( pos != std::string::npos ) { auto epos = v.find( "#", pos + 1 ); auto tok = v.substr( pos, epos - pos + 1 ); auto id = tok.substr( 1, tok.size( ) - 2 ); auto rd = defs.find( id ); if( rd != defs.end( ) ) for( auto r = rd->second.begin( ); r != rd->second.end( ); ++r ) q.push_back( cpPlugins_bash::Replace( v, tok, *r ) ); } else n.push_back( v ); } // elihw d->second = n; } // rof } // ------------------------------------------------------------------------- std::vector< std::string > Expand( const std::vector< std::string >& commands, const TDefinitions& defs ) { std::vector< std::string > lines; std::deque< std::string > q; q.insert( q.end( ), commands.begin( ), commands.end( ) ); while( q.size( ) > 0 ) { auto v = q.front( ); q.pop_front( ); auto d_pos = v.find( "$" ); auto n_pos = v.find( "#" ); if( d_pos != std::string::npos ) { auto e_pos = v.find( "$", d_pos + 1 ); auto tok = v.substr( d_pos, e_pos - d_pos + 1 ); std::vector< std::string > tokens; cpPlugins_bash::Tokenize( tokens, tok, "$;" ); for( auto t = tokens.begin( ); t != tokens.end( ); ++t ) { if( *t == " ") q.push_front( cpPlugins_bash::Replace( v, tok, "" ) ); else q.push_front( cpPlugins_bash::Replace( v, tok, *t ) ); } // rof } else if( n_pos != std::string::npos ) { auto e_pos = v.find( "#", n_pos + 1 ); auto tok = v.substr( n_pos, e_pos - n_pos + 1 ); auto id = tok.substr( 1, tok.size( ) - 2 ); auto rd = defs.find( id ); if( rd != defs.end( ) ) for( auto r = rd->second.begin( ); r != rd->second.end( ); ++r ) q.push_front( cpPlugins_bash::Replace( v, tok, *r ) ); } else lines.push_back( v ); } // elihw return( lines ); } // eof - $RCSfile$