--- /dev/null
+#include <cpExtensions/Utility.h>
+#include <map>
+#include <vector>
+#include <sstream>
+
+// -------------------------------------------------------------------------
+typedef std::vector< std::string > TLines;
+typedef std::map< char, TLines > TParsedLines;
+typedef std::map< std::string, TLines > TVariables;
+
+// -------------------------------------------------------------------------
+bool ReadFile( TParsedLines& lines, const std::string& fname );
+void ExpandGroups( TLines& res, const TLines& lines );
+void ExpandDefinitions(
+ TLines& res, const TLines& lines, const TVariables& vars
+ );
+void PrintLines(
+ const std::string& prefix, const std::string& suffix,
+ const TLines& lines, std::ostream& out
+ );
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+ if( argc < 4 )
+ {
+ std::cerr
+ << "Usage: " << argv[ 0 ]
+ << " input_definitions library_name output_dir"
+ << std::endl;
+ return( 1 );
+
+ } // fi
+ std::string input_definitions_fname = cpExtensions::CanonicalPath( argv[ 1 ] );
+ std::string library_name = argv[ 2 ];
+ std::string output_dir = cpExtensions::CanonicalPath( argv[ 3 ] );
+
+ // Build source files names
+ std::stringstream str_dir;
+ str_dir << output_dir;
+ if( !cpExtensions::IsPathSeparator( output_dir.back( ) ) )
+ str_dir << cpExtensions_PATH_SEPARATOR;
+ std::string header_file_fname = str_dir.str( );
+ std::string source_file_fname = header_file_fname;
+ header_file_fname += library_name + std::string( ".h" );
+ source_file_fname += library_name + std::string( ".cxx" );
+
+ // Read file and simple parse it
+ TParsedLines lines;
+ if( !ReadFile( lines, input_definitions_fname ) )
+ {
+ std::cerr
+ << "Error opening file: \""
+ << input_definitions_fname << "\""
+ << std::endl;
+ return( 1 );
+
+ } // fi
+
+ // Expand definitions
+ TVariables vars;
+ for( auto dIt = lines[ 'd' ].begin( ); dIt != lines[ 'd' ].end( ); ++dIt )
+ {
+ TLines tokens;
+ cpExtensions::TokenizeString( tokens, *dIt, "=;" );
+ auto tIt = tokens.begin( );
+ auto vName = *tIt;
+ tIt++;
+ for( ; tIt != tokens.end( ); ++tIt )
+ vars[ vName ].push_back( *tIt );
+
+ TLines res;
+ ExpandDefinitions( res, vars[ vName ], vars );
+ vars[ vName ] = res;
+
+ } // rof
+
+ // Expand groups
+ TLines f_includes_groups, includes_groups, templates_groups, classes_groups;
+ ExpandGroups( f_includes_groups, lines[ 'f' ] );
+ ExpandGroups( includes_groups, lines[ 'i' ] );
+ ExpandGroups( templates_groups, lines[ 't' ] );
+ ExpandGroups( classes_groups, lines[ 'c' ] );
+
+ // Expand definitions
+ TLines f_includes_list, includes_list, templates_list, classes_list;
+ ExpandDefinitions( f_includes_list, f_includes_groups, vars );
+ ExpandDefinitions( includes_list, includes_groups, vars );
+ ExpandDefinitions( templates_list, templates_groups, vars );
+ ExpandDefinitions( classes_list, classes_groups, vars );
+
+ // Write header file
+ std::ofstream header_file( header_file_fname.c_str( ) );
+ if( !header_file )
+ {
+ std::cerr
+ << "Error opening \"" << header_file_fname
+ << "\" for writing." << std::endl;
+ return( 1 );
+
+ } // fi
+
+ // Print header
+ header_file
+ << "#ifndef __" << library_name << "__H__" << std::endl
+ << "#define __" << library_name << "__H__" << std::endl<< std::endl
+ << "#include <cpExtensions/Config.h>" << std::endl
+ << "#include <" << library_name << "_Export.h>" << std::endl << std::endl;
+ PrintLines( "", "", lines[ 'b' ], header_file );
+ header_file << std::endl;
+ PrintLines( "#include <", ">", f_includes_list, header_file );
+ header_file
+ << "#ifdef " << library_name << "_EXPORTS" << std::endl
+ << "# define " << library_name << "_PREFIX template class "
+ << library_name << "_EXPORT" << std::endl
+ << "#else // " << library_name << "_EXPORTS" << std::endl
+ << "# define " << library_name
+ << "_PREFIX extern template class" << std::endl
+ << "#endif // "
+ << library_name << "_EXPORTS" << std::endl << std::endl;
+ PrintLines( "#include <", ">", includes_list, header_file );
+ PrintLines( "#include <", ">", templates_list, header_file );
+ header_file
+ << std::endl << "#ifdef " << library_name << "_EXPORTS" << std::endl;
+ PrintLines( "#include <", "xx>", templates_list, header_file );
+ header_file
+ << "#endif // " << library_name << "_EXPORTS" << std::endl << std::endl;
+ PrintLines(
+ library_name + std::string( "_PREFIX " ), ";", classes_list, header_file
+ );
+ header_file
+ << std::endl << "#endif // __" << library_name << "__H__" << std::endl;
+ header_file.close( );
+
+ // Write source file
+ std::ofstream source_file( source_file_fname );
+ if( !source_file )
+ {
+ std::cerr
+ << "Error opening \"" << header_file_fname << "\" for writing." << std::endl;
+ return( 1 );
+
+ } // fi
+ source_file
+ << "#include \"" << header_file_fname << "\"" << std::endl;
+ source_file.close( );
+
+ return( 0 );
+}
+
+// -------------------------------------------------------------------------
+bool ReadFile( TParsedLines& lines, const std::string& fname )
+{
+ std::string buffer;
+ if( cpExtensions::ReadFileIntoBuffer( buffer, fname ) )
+ {
+ 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( !cpExtensions::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 );
+ }
+ else
+ return( false );
+}
+
+// -------------------------------------------------------------------------
+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 )
+ {
+ unsigned int braces_count = 1;
+ auto e_pos = b_pos;
+ e_pos += 2;
+ while( braces_count != 0 && e_pos < lIt->size( ) )
+ {
+ auto v = ( *lIt )[ e_pos ];
+ braces_count += ( v == '{' )? 1: ( ( v == '}' )? -1: 0 );
+ e_pos++;
+
+ } // elihw
+ if( braces_count == 0 )
+ {
+ auto replace = lIt->substr( b_pos, e_pos - b_pos );
+ auto expansion = replace.substr( 2, replace.size( ) - 3 );
+ TLines tokens;
+ cpExtensions::TokenizeString( tokens, expansion, ";" );
+ for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
+ *tIt = cpExtensions::ReplaceString( *lIt, replace, *tIt );
+ ExpandGroups( res, tokens );
+
+ } // fi
+ }
+ else
+ res.push_back( *lIt );
+
+ } // rof
+}
+
+// -------------------------------------------------------------------------
+void ExpandDefinitions(
+ TLines& res, const TLines& lines, const TVariables& vars
+ )
+{
+ std::string seps = " ,;:{}[]()\"$&<>*.";
+
+ for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
+ {
+ auto b_pos = lIt->find( "#" );
+ if( b_pos != std::string::npos )
+ {
+ TLines tokens;
+ cpExtensions::TokenizeString( tokens, lIt->substr( b_pos ), seps );
+ std::string cmd = tokens[ 0 ];
+ auto vIt = vars.find( cmd );
+ if( vIt != vars.end( ) )
+ {
+ if( vIt->second.size( ) > 0 )
+ {
+ TLines new_res;
+ for(
+ auto wIt = vIt->second.begin( ); wIt != vIt->second.end( ); ++wIt
+ )
+ new_res.push_back( cpExtensions::ReplaceString( *lIt, cmd, *wIt ) );
+ ExpandDefinitions( res, new_res, vars );
+
+ } // fi
+
+ } // fi
+ }
+ else
+ res.push_back(
+ cpExtensions::ReplaceString(
+ cpExtensions::ReplaceString( *lIt, "{", "" ), "}", ""
+ )
+ );
+
+ } // rof
+}
+
+// -------------------------------------------------------------------------
+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$