]> Creatis software - cpPlugins.git/blobdiff - appli/bash/cpPlugins_CreateInstances.cxx
More macos issues...
[cpPlugins.git] / appli / bash / cpPlugins_CreateInstances.cxx
index a09b822e1ef5bb909e8ad2997d800736e6d7f7a8..a286d9311d1737034fe37feb8efe92fecbf926be 100644 (file)
@@ -1,25 +1,22 @@
-#include <algorithm>
-#include <cstring>
-#include <iostream>
-#include <iterator>
-#include <fstream>
+#include <cpPlugins_Config.h>
 #include <map>
-#include <set>
-#include <sstream>
-#include <streambuf>
-#include <string>
 #include <vector>
+#include <sstream>
 
 // -------------------------------------------------------------------------
-typedef std::set< std::string >       TSet;
-typedef std::map< std::string, TSet > TInstances;
-typedef std::vector< std::string >    TVector;
+typedef std::vector< std::string >      TLines;
+typedef std::map< char, TLines >        TParsedLines;
+typedef std::map< std::string, TLines > TVariables;
 
 // -------------------------------------------------------------------------
-TVector Tokenize( const std::string& str, const std::string& delims );
-TSet Combine( const TSet& X, const TSet& Y );
-void Replace(
-  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 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
   );
 
 // -------------------------------------------------------------------------
@@ -29,305 +26,252 @@ int main( int argc, char* argv[] )
   {
     std::cerr
       << "Usage: " << argv[ 0 ]
-      << " input_definitions dir library_name header_filename"
+      << " input_definitions library_name header_file source_file"
       << std::endl;
     return( 1 );
 
   } // fi
-  std::string input_definitions_file_name = argv[ 1 ];
-  std::string dir = argv[ 2 ];
-  std::string library_name = argv[ 3 ];
-  std::string head_fname = argv[ 4 ];
-
-  // Load file into a buffer
-  std::ifstream file_stream( input_definitions_file_name.c_str( ) );
-  if( !file_stream )
+  std::string input_definitions_fname = argv[ 1 ];
+  std::string library_name = argv[ 2 ];
+  std::string header_file_fname = argv[ 3 ];
+  std::string source_file_fname = argv[ 4 ];
+
+  // Read file and simple parse it
+  TParsedLines lines;
+  if( !ReadFile( lines, input_definitions_fname ) )
   {
     std::cerr
       << "Error opening file: \""
-      << input_definitions_file_name << "\""
+      << input_definitions_fname << "\""
       << std::endl;
     return( 1 );
 
   } // fi
-  std::string buf;
-  file_stream.seekg( 0, std::ios::end );
-  buf.reserve( file_stream.tellg( ) );
-  file_stream.seekg( 0, std::ios::beg );
-  buf.assign(
-    ( std::istreambuf_iterator< char >( file_stream ) ),
-    std::istreambuf_iterator< char >( )
-    );
-  file_stream.close( );
-  std::istringstream input_str( buf );
-
-  // Process file
-  std::string line;
-  TVector incl, first_incl;
-  TInstances instances;
-  TVector classes;
-  while( std::getline( input_str, line ) )
-  {
-    if( line[ 0 ] == 'f' )
-    {
-      first_incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
-    }
-    else if( line[ 0 ] == 'i' )
-    {
-      incl.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
-    }
-    else if( line[ 0 ] == 'c' )
-    {
-      classes.push_back( line.substr( line.find_first_not_of( ' ', 1 ) ) );
-    }
-    else if( line[ 0 ] == 'a' )
-    {
-      TVector tokens = Tokenize( line, "=" );
-
-      // Get argument name
-      TVector arg_tokens = Tokenize( tokens[ 0 ], " " );
-      std::string arg = arg_tokens[ 0 ];
-      unsigned int i = 0;
-      while( arg[ 0 ] != '#' && i < arg_tokens.size( ) )
-        arg = arg_tokens[ ++i ];
-
-      // Get values
-      TVector values_tokens = Tokenize( tokens[ 1 ], ";" );
-      for( auto t = values_tokens.begin( ); t != values_tokens.end( ); ++t )
-      {
-        std::string value = t->substr( t->find_first_not_of( ' ' ) );
-        unsigned int value_len = value.size( );
-        while( value[ value_len - 1 ] == ' ' && value_len > 0 )
-          value_len--;
-        value = value.substr( 0, value_len );
 
-        if( value == "#integers" )
-        {
-          instances[ arg ].insert( "char" );
-          instances[ arg ].insert( "short" );
-          instances[ arg ].insert( "int" );
-          instances[ arg ].insert( "long" );
-          instances[ arg ].insert( "unsigned char" );
-          instances[ arg ].insert( "unsigned short" );
-          instances[ arg ].insert( "unsigned int" );
-          instances[ arg ].insert( "unsigned long" );
-        }
-        else if( value == "#integers_ptr" )
-        {
-          instances[ arg ].insert( "char*" );
-          instances[ arg ].insert( "short*" );
-          instances[ arg ].insert( "int*" );
-          instances[ arg ].insert( "long*" );
-          instances[ arg ].insert( "unsigned char*" );
-          instances[ arg ].insert( "unsigned short*" );
-          instances[ arg ].insert( "unsigned int*" );
-          instances[ arg ].insert( "unsigned long*" );
-        }
-        else if( value == "#floats" )
-        {
-          instances[ arg ].insert( "double" );
-          instances[ arg ].insert( "float" );
-        }
-        else if( value == "#floats_ptr" )
-        {
-          instances[ arg ].insert( "double*" );
-          instances[ arg ].insert( "float*" );
-        }
-        else if( value == "#all_dims" )
-        {
-          instances[ arg ].insert( "1" );
-          instances[ arg ].insert( "2" );
-          instances[ arg ].insert( "3" );
-          instances[ arg ].insert( "4" );
-        }
-        else if( value == "#all_visual_dims" )
-        {
-          instances[ arg ].insert( "2" );
-          instances[ arg ].insert( "3" );
-        }
-        else
-          instances[ arg ].insert( value );
-
-      } // rof
-
-    } // fi
-
-  } // elihw
-
-  // Span all possible types
-  TVector all_real_classes;
-  for( auto clsIt = classes.begin( ); clsIt != classes.end( ); ++clsIt )
+  // Expand definitions
+  TVariables vars;
+  for( auto dIt = lines[ 'd' ].begin( ); dIt != lines[ 'd' ].end( ); ++dIt )
   {
-    // Extract types
-    std::string name = clsIt->substr( clsIt->find_first_not_of( " " ) );
-    std::string tok = name;
-    auto sharpPos = tok.find_first_of( "#" );
-    TInstances li;
-    while( sharpPos != std::string::npos )
-    {
-      tok = tok.substr( sharpPos );
-      auto spacePos = tok.find_first_of( " " );
-      auto arg = tok.substr( 0, spacePos );
-      auto aIt = instances.find( arg );
-      if( aIt != instances.end( ) )
-        li[ arg ] = aIt->second;
-      tok = tok.substr( spacePos );
-      sharpPos = tok.find_first_of( "#" );
-
-    } // eliwh
-    if( li.size( ) > 0 )
-    {
-      // Combine types
-      TSet combs;
-      if( li.size( ) > 1 )
-      {
-        auto iIt = li.begin( );
-        auto jIt = iIt;
-        jIt++;
-        for( ; jIt != li.end( ); ++iIt, ++jIt )
-        {
-          if( iIt == li.begin( ) )
-            combs = Combine( iIt->second, jIt->second );
-          else
-            combs = Combine( combs, jIt->second );
-
-        } // rof
-      }
-      else
-        combs = li.begin( )->second;
-
-      // Write instantiations
-      for( auto combIt = combs.begin( ); combIt != combs.end( ); ++combIt )
-      {
-        char* buffer = new char[ combIt->size( ) ];
-        std::strcpy( buffer, combIt->c_str( ) );
-        char* tok = std::strtok( buffer, "#" );
-        std::map< std::string, std::string > real_instance;
-        for( auto lIt = li.begin( ); lIt != li.end( ); ++lIt )
-        {
-          real_instance[ lIt->first ] = std::string( tok );
-          tok = std::strtok( NULL, "#" );
+    TLines tokens;
+    cpPlugins::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
+  } // rof
 
-        std::string real_name = name;
-        auto riIt = real_instance.begin( );
-        for( ; riIt != real_instance.end( ); ++riIt )
-          Replace( real_name, riIt->first, riIt->second );
-        all_real_classes.push_back( real_name );
-        delete buffer;
+  // 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 );
 
-      } // rof
-    }
-    else
-      all_real_classes.push_back( name );
+  } // fi
 
-  } // rof
+  // Print header
+  header_file
+    << "#ifndef __" << library_name << "__H__" << std::endl
+    << "#define __" << library_name << "__H__" << std::endl<< std::endl
+    << "#include <cpPlugins_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 files
-  std::ofstream out_str( head_fname.c_str( ) );
-  if( !out_str )
+  // Write source file
+  std::ofstream source_file( source_file_fname );
+  if( !source_file )
   {
-    std::cerr << "Error opening file \"" << head_fname << "\"" << std::endl;
+    std::cerr
+      << "Error opening \"" << header_file_fname << "\" for writing." << std::endl;
     return( 1 );
 
   } // fi
-
-  out_str << "#ifndef __" << dir << "__" << library_name << "__H__" << std::endl;
-  out_str << "#define __" << dir << "__" << library_name << "__H__" << std::endl << std::endl;
-  out_str << "#include <" << dir << "/" << library_name << "_Export.h>" << std::endl;
-
-  // First incl
-  for( auto inclIt = first_incl.begin( ); inclIt != first_incl.end( ); ++inclIt )
-    out_str
-      << "#include <" << *inclIt << ">" << std::endl;
-  out_str << std::endl;
-
-  std::string base_name = dir + std::string( "_" ) + library_name;
-  out_str
-    << std::endl
-    << "#ifdef " << base_name << "_EXPORTS" << std::endl
-    << "#  undef  ITK_MANUAL_INSTANTIATION" << std::endl
-    << "#  define " << base_name << "_PREFIX template class " << base_name << "_EXPORT" << std::endl
-    << "#else" << std::endl
-    << "#  define ITK_MANUAL_INSTANTIATION" << std::endl
-    << "#  define " << base_name << "_PREFIX extern template class" << std::endl
-    << "#endif" << std::endl << std::endl;
-
-  // Incl
-  for( auto inclIt = incl.begin( ); inclIt != incl.end( ); ++inclIt )
-    out_str
-      << "#include <" << *inclIt << ">" << std::endl;
-  out_str << std::endl;
-
-  // All classes
-  for( auto clsIt = all_real_classes.begin( ); clsIt != all_real_classes.end( ); ++clsIt )
-    out_str
-      << base_name << "_PREFIX " << *clsIt << ";" << std::endl;
-  out_str << std::endl;
-
-  out_str << "#endif // __" << dir << "__" << library_name << "__H__" << std::endl;
-  out_str << std::endl << "// eof" << std::endl;
-
-  out_str.close( );
+  source_file
+    << "#include \"" << header_file_fname << "\"" << std::endl;
+  source_file.close( );
 
   return( 0 );
 }
 
 // -------------------------------------------------------------------------
-TVector Tokenize( const std::string& str, const std::string& delims )
+bool ReadFile( TParsedLines& lines, const std::string& fname )
 {
-  TVector tokens;
-  if( str.size( ) > 0 )
+  std::string buffer;
+  if( cpPlugins::ReadFileIntoString( buffer, fname ) )
   {
-    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 )
+    std::istringstream input_stream( buffer );
+
+    // Read line by line
+    std::string line;
+    while( std::getline( input_stream, line ) )
     {
-      tokens.push_back( std::string( it ) );
-      it = std::strtok( NULL, delims.c_str( ) );
+      auto cmd_pos = line.end( );
+      auto arg_pos = line.end( );
+      auto lIt = line.begin( );
+      while( lIt != line.end( ) )
+      {
+        if( !cpPlugins::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
-    delete buffer;
+      } // 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 );
 
-  } // fi
-  return( tokens );
+    } // elihw
+    return( true );
+  }
+  else
+    return( false );
 }
 
 // -------------------------------------------------------------------------
-TSet Combine( const TSet& X, const TSet& Y )
+void ExpandGroups( TLines& res, const TLines& lines )
 {
-  TSet Z;
-  for( auto xIt = X.begin( ); xIt != X.end( ); ++xIt )
+  for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
   {
-    for( auto yIt = Y.begin( ); yIt != Y.end( ); ++yIt )
+    auto b_pos = lIt->find( "@{" );
+    if( b_pos != std::string::npos )
     {
-      std::stringstream val;
-      val << *xIt << "#" << *yIt;
-      Z.insert( val.str( ) );
+      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++;
 
-    } // rof
+      } // 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;
+        cpPlugins::TokenizeString( tokens, expansion, ";" );
+        for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
+          *tIt = cpPlugins::ReplaceString( *lIt, replace, *tIt );
+        ExpandGroups( res, tokens );
+
+      } // fi
+    }
+    else
+      res.push_back( *lIt );
 
   } // rof
-  return( Z );
 }
 
 // -------------------------------------------------------------------------
-void Replace(
-  std::string& str, const std::string& sub, const std::string& nsub
+void ExpandDefinitions(
+  TLines& res, const TLines& lines, const TVariables& vars
   )
 {
-  size_t index = 0;
-  while( true )
+  std::string seps = " ,;:{}[]()\"$&<>*.";
+
+  for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
   {
-    index = str.find( sub,  index );
-    if( index == std::string::npos ) break;
-    str.replace( index, sub.size( ), nsub );
-    index += sub.size( );
+    auto b_pos = lIt->find( "#" );
+    if( b_pos != std::string::npos )
+    {
+      TLines tokens;
+      cpPlugins::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( cpPlugins::ReplaceString( *lIt, cmd, *wIt ) );
+          ExpandDefinitions( res, new_res, vars );
+
+        } // fi
 
-  } // elihw
+      } // fi
+    }
+    else
+      res.push_back(
+        cpPlugins::ReplaceString(
+          cpPlugins::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$