]> Creatis software - cpPlugins.git/blob - appli/bash/BuildInstances.cxx.in
...
[cpPlugins.git] / appli / bash / BuildInstances.cxx.in
1 #include <cmath>
2 #include <deque>
3 #include <iostream>
4 #include <map>
5 #include <sstream>
6 #include <vector>
7 #include <appli/bash/Utility.h>
8
9 // -------------------------------------------------------------------------
10 typedef std::map< char, std::vector< std::string > >        TCommands;
11 typedef std::map< std::string, std::vector< std::string > > TDefinitions;
12
13 // -------------------------------------------------------------------------
14 void AddDefinitions( TDefinitions& defs, const std::string& cmd );
15 void InitDefinitions( TDefinitions& defs );
16 void Lines( TCommands& commands, const std::deque< std::string >& lines );
17 void ExpandDefinitions( TDefinitions& defs );
18 std::vector< std::string > Expand(
19   const std::vector< std::string >& commands, const TDefinitions& defs
20   );
21
22 // -------------------------------------------------------------------------
23 int main( int argc, char* argv[] )
24 {
25   // Get parameters from input
26   if( argc < 5 )
27   {
28     std::cerr
29       << "Usage: " << argv[ 0 ]
30       << " definitions library_name source_prefix number_of_files" << std::endl;
31     return( 1 );
32
33   } // fi
34   std::string input_definitions = argv[ 1 ];
35   std::string library_name = argv[ 2 ];
36   std::string source_prefix = argv[ 3 ];
37   std::string header_file = source_prefix + std::string( ".h" );
38   std::stringstream nfiles_str( argv[ 4 ] );
39   unsigned int number_of_files;
40   nfiles_str >> number_of_files;
41
42   // Read input instances
43   std::string buffer;
44   if( !cpPlugins_bash::Read( buffer, input_definitions ) )
45   {
46     std::cerr
47       << "Error reading input instances from \""
48       << input_definitions << "\""
49       << std::endl;
50     return( 1 );
51
52   } // fi
53
54   // Put it in a line-by-line structure
55   std::deque< std::string > lines;
56   cpPlugins_bash::Tokenize( lines, buffer, "\n" );
57
58   // Parse commands
59   TCommands commands;
60   Lines( commands, lines );
61
62   // Init definitions
63   TDefinitions defs;
64   InitDefinitions( defs );
65   auto dIt = commands.find( 'd' );
66   if( dIt != commands.end( ) )
67   {
68     for( auto vIt = dIt->second.begin( ); vIt != dIt->second.end( ); ++vIt )
69       AddDefinitions( defs, *vIt );
70
71   } // fi
72
73   // Expand definitions
74   ExpandDefinitions( defs );
75
76   // Expand code
77   std::vector< std::string > before;
78   auto bIt = commands.find( 'b' );
79   if( bIt != commands.end( ) )
80     before = bIt->second;
81   auto templates = Expand( commands[ 't' ], defs );
82   auto includes = Expand( commands[ 'i' ], defs );
83   auto classes = Expand( commands[ 'c' ], defs );
84
85   // Write header file
86   std::stringstream header;
87   header
88     << "#ifndef __" << library_name << "__h__" << std::endl
89     << "#define __" << library_name << "__h__" << std::endl << std::endl
90     << "#define ITK_MANUAL_INSTANTIATION" << std::endl;
91   for( auto i = before.begin( ); i != before.end( ); ++i )
92     header << std::endl << *i;
93   header << std::endl;
94   for( auto i = includes.begin( ); i != includes.end( ); ++i )
95     header << "#include <" << *i << ">" << std::endl;
96   for( auto i = templates.begin( ); i != templates.end( ); ++i )
97     header << "#include <" << *i << ".h>" << std::endl;
98   header << std::endl;
99   /* TODO
100      for( auto i = classes.begin( ); i != classes.end( ); ++i )
101      header
102      << "extern template class " << *i << ";" << std::endl;
103   */
104   header
105     << std::endl << "#endif // __" << library_name << "__H__" << std::endl;
106   if( !( cpPlugins_bash::Write( header.str( ), header_file ) ) )
107   {
108     std::cerr << "Error writing header" << std::endl;
109     return( 1 );
110
111   } // fi
112
113   // Write source code
114   unsigned int classes_per_file =
115     ( unsigned int )(
116       std::floor( double( classes.size( ) ) / double( number_of_files ) )
117       );
118   if( classes_per_file == 0 )
119     classes_per_file = 1;
120   std::vector< std::vector< std::string > > all_lines( 1 );
121   for( unsigned int c_id = 0; c_id < classes.size( ); ++c_id )
122   {
123     all_lines[ all_lines.size( ) - 1 ].push_back( classes[ c_id ] );
124     if( c_id % classes_per_file == classes_per_file - 1 )
125       all_lines.push_back( std::vector< std::string >( ) );
126
127   } // rof
128
129   // Paranoiac code
130   while( all_lines.size( ) > number_of_files )
131   {
132     all_lines[ all_lines.size( ) - 2 ].insert(
133       all_lines[ all_lines.size( ) - 2 ].end( ),
134       all_lines[ all_lines.size( ) - 1 ].begin( ),
135       all_lines[ all_lines.size( ) - 1 ].end( )
136       );
137     all_lines.pop_back( );
138
139   } // elihw
140   while( all_lines.size( ) < number_of_files )
141     all_lines.push_back( std::vector< std::string >( ) );
142
143   // Real write
144   for( unsigned int f_id = 0; f_id < all_lines.size( ); ++f_id )
145   {
146     std::stringstream source;
147     source << "#define ITK_MANUAL_INSTANTIATION" << std::endl;
148     source
149       << "#include <" << library_name << "_Export.h>"
150       << std::endl;
151     for( auto i = before.begin( ); i != before.end( ); ++i )
152       source << std::endl << *i;
153     source << std::endl;
154     if( templates.size( ) > 0 )
155     {
156       for( auto i = includes.begin( ); i != includes.end( ); ++i )
157         source << "#include <" << *i << ">" << std::endl;
158
159       for( auto i = templates.begin( ); i != templates.end( ); ++i )
160       {
161         source << "#include <" << *i << ".h>" << std::endl;
162         source << "#include <" << *i << ".hxx>" << std::endl;
163
164       } // rof
165       source << std::endl;
166
167     } // fi
168     for(
169       auto c_it = all_lines[ f_id ].begin( );
170       c_it != all_lines[ f_id ].end( );
171       ++c_it
172       )
173       source
174         << "template class " << library_name << "_EXPORT "
175         << *c_it << ";" << std::endl;
176     source << std::endl << "// eof" << std::endl;
177     std::stringstream source_file;
178     source_file
179       << source_prefix << "_" << f_id << ".cxx";
180     if( !( cpPlugins_bash::Write( source.str( ), source_file.str( ) ) ) )
181     {
182       std::cerr << "Error writing header" << std::endl;
183       return( 1 );
184
185     } // fi
186
187   } // rof
188   return( 0 );
189 }
190
191 // -------------------------------------------------------------------------
192 void AddDefinitions( TDefinitions& defs, const std::string& cmd )
193 {
194   std::vector< std::string > tokens;
195   cpPlugins_bash::Tokenize( tokens, cmd, "=;" );
196   for( unsigned int i = 1; i < tokens.size( ); ++i )
197     defs[ tokens[ 0 ] ].push_back( tokens[ i ] );
198 }
199
200 // -------------------------------------------------------------------------
201 void InitDefinitions( TDefinitions& defs )
202 {
203   AddDefinitions( defs, "integers=@cpPlugins_INTEGER_TYPES@" );
204   AddDefinitions( defs, "reals=@cpPlugins_REAL_TYPES@" );
205   AddDefinitions( defs, "colors=RGBPixel;RGBAPixel" );
206   AddDefinitions( defs, "vectors=CovariantVector;Point;SymmetricSecondRankTensor;Vector" );
207   AddDefinitions( defs, "tensors=DiffusionTensor3D" );
208   AddDefinitions( defs, "matrices=Matrix" );
209   AddDefinitions( defs, "process_dims=@cpPlugins_PROCESS_DIMENSIONS@" );
210   AddDefinitions( defs, "visual_dims=@cpPlugins_VISUAL_DIMENSIONS@" );
211   AddDefinitions( defs, "naturals=unsigned #integers#" );
212   AddDefinitions( defs, "pixels=#integers#;#naturals#;#reals#" );
213 }
214
215 // -------------------------------------------------------------------------
216 void Lines( TCommands& commands, const std::deque< std::string >& lines )
217 {
218   std::string buffer;
219
220   for( auto l = lines.begin( ); l != lines.end( ); ++l )
221   {
222     auto pos = l->find_first_not_of( " " );
223     char cmd = tolower( ( *l )[ pos ] );
224     commands[ cmd ].push_back(
225       l->substr( l->find_first_not_of( " ", pos + 1 ) )
226       );
227
228   } // elihw
229 }
230
231 // -------------------------------------------------------------------------
232 void ExpandDefinitions( TDefinitions& defs )
233 {
234   for( auto d = defs.begin( ); d != defs.end( ); ++d )
235   {
236     std::deque< std::string > q;
237     q.insert( q.end( ), d->second.begin( ), d->second.end( ) );
238
239     std::vector< std::string > n;
240     while( q.size( ) > 0 )
241     {
242       auto v = q.front( );
243       q.pop_front( );
244
245       auto pos = v.find( "#" );
246       if( pos != std::string::npos )
247       {
248         auto epos = v.find( "#", pos + 1 );
249         auto tok = v.substr( pos, epos - pos + 1 );
250         auto id = tok.substr( 1, tok.size( ) - 2 );
251         auto rd = defs.find( id );
252         if( rd != defs.end( ) )
253           for( auto r = rd->second.begin( ); r != rd->second.end( ); ++r )
254             q.push_back( cpPlugins_bash::Replace( v, tok, *r ) );
255       }
256       else
257         n.push_back( v );
258       
259     } // elihw
260     d->second = n;
261
262   } // rof
263 }
264
265 // -------------------------------------------------------------------------
266 std::vector< std::string > Expand(
267   const std::vector< std::string >& commands, const TDefinitions& defs
268   )
269 {
270   std::vector< std::string > lines;
271   std::deque< std::string > q;
272   q.insert( q.end( ), commands.begin( ), commands.end( ) );
273   while( q.size( ) > 0 )
274   {
275     auto v = q.front( );
276     q.pop_front( );
277
278     auto d_pos = v.find( "$" );
279     auto n_pos = v.find( "#" );
280
281     if( d_pos != std::string::npos )
282     {
283       auto e_pos = v.find( "$", d_pos + 1 );
284       auto tok = v.substr( d_pos, e_pos - d_pos + 1 );
285       std::vector< std::string > tokens;
286       cpPlugins_bash::Tokenize( tokens, tok, "$;" );
287       for( auto t = tokens.begin( ); t != tokens.end( ); ++t )
288       {
289         if( *t == " ")
290           q.push_front( cpPlugins_bash::Replace( v, tok, "" ) );
291         else
292           q.push_front( cpPlugins_bash::Replace( v, tok, *t ) );
293
294       } // rof
295     }
296     else if( n_pos != std::string::npos )
297     {
298       auto e_pos = v.find( "#", n_pos + 1 );
299       auto tok = v.substr( n_pos, e_pos - n_pos + 1 );
300       auto id = tok.substr( 1, tok.size( ) - 2 );
301       auto rd = defs.find( id );
302       if( rd != defs.end( ) )
303         for( auto r = rd->second.begin( ); r != rd->second.end( ); ++r )
304           q.push_front( cpPlugins_bash::Replace( v, tok, *r ) );
305     }
306     else
307       lines.push_back( v );
308
309   } // elihw
310
311   return( lines );
312 }
313
314 // eof - $RCSfile$