#include #include #include #include #include #include #include #include // ------------------------------------------------------------------------- typedef std::vector< std::string > TLines; typedef std::map< char, TLines > TParsedLines; typedef std::map< std::string, TLines > TVariables; // ------------------------------------------------------------------------- TLines Tokenize( const std::string& str, const std::string& delims ); std::string Replace( const std::string& str, const std::string& sub, const std::string& nsub ); bool ReadFile( TParsedLines& lines, const std::string& fname ); void ExpandGroups( TLines& res, const TLines& lines ); void ExpandVariables( TLines& res, const TLines& lines, const TVariables& vars ); void ParseIncludes( TLines& res, const TLines& lines, const std::string& ext ); void PrintLines( const std::string& prefix, const std::string& suffix, const TLines& lines, std::ostream& out ); // ------------------------------------------------------------------------- int main( int argc, char* argv[] ) { if( argc < 5 ) { std::cerr << "Usage: " << argv[ 0 ] << " input_definitions library_name header_file source_file" << std::endl; return( 1 ); } // fi std::string lname = argv[ 2 ]; // Read file and simple parse it TParsedLines lines; if( !ReadFile( lines, argv[ 1 ] ) ) { std::cerr << "Error opening file: \"" << argv[ 1 ] << "\"" << std::endl; return( 1 ); } // fi // Build definitions TVariables vars; for( auto dIt = lines[ 'd' ].begin( ); dIt != lines[ 'd' ].end( ); ++dIt ) { auto tokens = Tokenize( *dIt, "=;" ); auto tIt = tokens.begin( ); auto vName = *tIt; tIt++; for( ; tIt != tokens.end( ); ++tIt ) vars[ vName ].push_back( *tIt ); } // rof // First include section TLines first_includes; ParseIncludes( first_includes, lines[ 'f' ], "" ); TLines normal_includes; ParseIncludes( normal_includes, lines[ 'i' ], "" ); TLines template_includes; ParseIncludes( template_includes, lines[ 't' ], "" ); TLines template_sources; ParseIncludes( template_sources, lines[ 't' ], "xx" ); // Expand groups TLines classes; ExpandGroups( classes, lines[ 'c' ] ); // Expand variables TLines real_classes; ExpandVariables( real_classes, classes, vars ); // Prepare precompiler options TLines global_header; std::stringstream global_header_stream; global_header_stream << "#ifndef __" << lname << "__H__" << std::endl << "#define __" << lname << "__H__" << std::endl<< std::endl << "#include " << std::endl << std::endl; global_header.push_back( global_header_stream.str( ) ); TLines macro_header; std::stringstream macro_header_stream; macro_header_stream << "#ifdef " << lname << "_EXPORTS" << std::endl << "# define " << lname << "_PREFIX template class " << lname << "_EXPORT" << std::endl << "#else // " << lname << "_EXPORTS" << std::endl << "# define " << lname << "_PREFIX extern template class" << std::endl << "#endif // " << lname << "_EXPORTS" << std::endl; macro_header.push_back( macro_header_stream.str( ) ); TLines end_global_header; std::stringstream end_global_header_stream; end_global_header_stream << "#endif // __" << lname << "__H__" << std::endl; end_global_header.push_back( end_global_header_stream.str( ) ); // Write header file std::ofstream header_file( argv[ 3 ] ); if( !header_file ) { std::cerr << "Error opening \"" << argv[ 3 ] << "\" for writing." << std::endl; return( 1 ); } // fi PrintLines( "", "", global_header, header_file ); header_file << "#include <" << lname << "_Export.h>" << std::endl << std::endl; PrintLines( "", "", lines[ 'b' ], header_file ); header_file << std::endl; PrintLines( "", "", first_includes, header_file ); PrintLines( "", "", macro_header, header_file ); PrintLines( "", "", normal_includes, header_file ); PrintLines( "", "", template_includes, header_file ); header_file << std::endl << "#ifdef " << lname << "_EXPORTS" << std::endl; PrintLines( "", "", template_sources, header_file ); header_file << "#endif // " << lname << "_EXPORTS" << std::endl; header_file << std::endl; PrintLines( lname + std::string( "_PREFIX " ), ";", real_classes, header_file ); header_file << std::endl; PrintLines( "", "", end_global_header, header_file ); header_file.close( ); // Write source file std::ofstream source_file( argv[ 4 ] ); if( !source_file ) { std::cerr << "Error opening \"" << argv[ 3 ] << "\" for writing." << std::endl; return( 1 ); } // fi source_file << "#include \"" << argv[ 3 ] << "\"" << std::endl; /* TODO PrintLines( "", "", first_includes, source_file ); PrintLines( "", "", template_includes, source_file ); source_file << std::endl; PrintLines( std::string( "template class " ) + lname + std::string( "_EXPORT " ), ";", real_classes, source_file ); */ source_file.close( ); return( 0 ); } // ------------------------------------------------------------------------- TLines Tokenize( const std::string& str, const std::string& delims ) { TLines tokens; if( str.size( ) > 0 ) { char* buffer = new char[ str.size( ) + 1 ]; std::strcpy( buffer, str.c_str( ) ); buffer[ str.size( ) ] = '\0'; char* it = std::strtok( buffer, delims.c_str( ) ); while( it != NULL ) { tokens.push_back( std::string( it ) ); it = std::strtok( NULL, delims.c_str( ) ); } // elihw delete buffer; } // fi return( tokens ); } // ------------------------------------------------------------------------- std::string Replace( const std::string& str, const std::string& sub, const std::string& nsub ) { std::string res = str; size_t index = 0; while( true ) { index = res.find( sub, index ); if( index == std::string::npos ) break; res.replace( index, sub.size( ), nsub ); index += sub.size( ); } // elihw return( res ); } // ------------------------------------------------------------------------- bool ReadFile( TParsedLines& lines, const std::string& fname ) { // Load file into a string stream std::ifstream file_stream( fname.c_str( ) ); if( !file_stream ) return( false ); std::string buffer; file_stream.seekg( 0, std::ios::end ); buffer.reserve( file_stream.tellg( ) ); file_stream.seekg( 0, std::ios::beg ); buffer.assign( ( std::istreambuf_iterator< char >( file_stream ) ), std::istreambuf_iterator< char >( ) ); file_stream.close( ); std::istringstream input_stream( buffer ); // Read line by line std::string line; while( std::getline( input_stream, line ) ) { auto cmd_pos = line.end( ); auto arg_pos = line.end( ); auto lIt = line.begin( ); while( lIt != line.end( ) ) { if( !std::isblank( *lIt ) ) { if( cmd_pos == line.end( ) ) { cmd_pos = lIt; ++lIt; } else if( arg_pos == line.end( ) ) { arg_pos = lIt; lIt = line.end( ); } // fi } else ++lIt; } // elihw char cmd = *cmd_pos; std::string arg; arg.resize( line.end( ) - arg_pos ); std::copy( arg_pos, line.end( ), arg.begin( ) ); lines[ cmd ].push_back( arg ); } // elihw return( true ); } // ------------------------------------------------------------------------- void ExpandGroups( TLines& res, const TLines& lines ) { for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt ) { auto b_pos = lIt->find( "#{" ); if( b_pos != std::string::npos ) { auto e_pos = lIt->find( "}" ); auto expansion = lIt->substr( b_pos + 2, e_pos - b_pos - 2 ); auto tokens = Tokenize( expansion, ";" ); for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt ) *tIt = lIt->substr( 0, b_pos ) + *tIt + lIt->substr( e_pos + 1 ); ExpandGroups( res, tokens ); } else res.push_back( *lIt ); } // rof } // ------------------------------------------------------------------------- void ExpandVariables( TLines& res, const TLines& lines, const TVariables& vars ) { const char* int_types[] = { "char", "short", "int", "long" }; const char* float_types[] = { "float", "double" }; unsigned int n_int_types = 4, n_float_types = 2; for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt ) { auto b_pos = lIt->find( "#" ); if( b_pos != std::string::npos ) { auto tokens = Tokenize( lIt->substr( b_pos ), " ,;:{}[]()\"$&<>" ); std::string cmd = tokens[ 0 ]; if( cmd == "#int_types" || cmd == "#uint_types" || cmd == "#float_types" ) { const char** types = ( cmd == "#float_types" )? float_types: int_types; unsigned int size = ( cmd == "#float_types" )? n_float_types: n_int_types; std::string ustr = ( ( cmd == "#uint_types" )? "unsigned ": "" ); TLines new_res; for( unsigned int i = 0; i < size; ++i ) new_res.push_back( Replace( *lIt, cmd, ustr + types[ i ] ) ); ExpandVariables( res, new_res, vars ); } else { auto vIt = vars.find( cmd ); if( vIt != vars.end( ) ) { TLines new_res; for( auto wIt = vIt->second.begin( ); wIt != vIt->second.end( ); ++wIt ) new_res.push_back( Replace( *lIt, cmd, *wIt ) ); ExpandVariables( res, new_res, vars ); } // fi } // fi } else res.push_back( *lIt ); } // rof } // ------------------------------------------------------------------------- void ParseIncludes( TLines& res, const TLines& lines, const std::string& ext ) { for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt ) res.push_back( std::string( "#include <" ) + *lIt + ext + std::string( ">" ) ); } // ------------------------------------------------------------------------- void PrintLines( const std::string& prefix, const std::string& suffix, const TLines& lines, std::ostream& out ) { for( auto i = lines.begin( ); i != lines.end( ); ++i ) out << prefix << *i << suffix << std::endl; } // eof - $RCSfile$