]> Creatis software - cpPlugins.git/blob - appli/bash/cpPlugins_CreateInstances.cxx
...
[cpPlugins.git] / appli / bash / cpPlugins_CreateInstances.cxx
1 #include <fstream>
2 #include <iostream>
3
4 #include <algorithm>
5 #include <cstring>
6 #include <map>
7 #include <vector>
8 #include <sstream>
9
10 #if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
11 #  define cpPlugins_STRTOK( A, B, N ) strtok_s( A, B, N )
12 #else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
13 #  define cpPlugins_STRTOK( A, B, N ) std::strtok( A, B )
14 #endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
15
16 // -------------------------------------------------------------------------
17 typedef std::vector< std::string >      TLines;
18 typedef std::map< char, TLines >        TParsedLines;
19 typedef std::map< std::string, TLines > TVariables;
20
21 // -------------------------------------------------------------------------
22 bool cpPlugins_ISBLANK( const char& value );
23 TLines Tokenize( const std::string& str, const std::string& delims );
24 std::string Replace(
25   const std::string& str, const std::string& sub, const std::string& nsub
26   );
27 bool ReadFile( TParsedLines& lines, const std::string& fname );
28 void ExpandGroups( TLines& res, const TLines& lines, const TVariables& vars );
29 void ExpandVariables( TLines& res, const TLines& lines, const TVariables& vars );
30 void ParseIncludes( TLines& res, const TLines& lines, const std::string& ext = "" );
31 void PrintLines(
32   const std::string& prefix, const std::string& suffix,
33   const TLines& lines, std::ostream& out
34   );
35
36 // -------------------------------------------------------------------------
37 int main( int argc, char* argv[] )
38 {
39   if( argc < 5 )
40   {
41     std::cerr
42       << "Usage: " << argv[ 0 ]
43       << " input_definitions library_name header_file source_file"
44       << std::endl;
45     return( 1 );
46
47   } // fi
48   std::string input_definitions_fname = argv[ 1 ];
49   std::string library_name = argv[ 2 ];
50   std::string header_file_fname = argv[ 3 ];
51   std::string source_file_fname = argv[ 4 ];
52
53   // Read file and simple parse it
54   TParsedLines lines;
55   if( !ReadFile( lines, input_definitions_fname ) )
56   {
57     std::cerr
58       << "Error opening file: \""
59       << input_definitions_fname << "\""
60       << std::endl;
61     return( 1 );
62
63   } // fi
64
65   // Expand variable definitions
66   TVariables vars;
67   for( auto dIt = lines[ 'd' ].begin( ); dIt != lines[ 'd' ].end( ); ++dIt )
68   {
69     auto tokens = Tokenize( *dIt, "=;" );
70     auto tIt = tokens.begin( );
71     auto vName = *tIt;
72     tIt++;
73     for( ; tIt != tokens.end( ); ++tIt )
74       vars[ vName ].push_back( *tIt );
75
76     TLines res;
77     ExpandVariables( res, vars[ vName ], vars );
78     vars[ vName ] = res;
79
80   } // rof
81
82   // First include section
83   TLines first_includes, normal_includes, template_includes, template_sources;
84   ParseIncludes( first_includes, lines[ 'f' ] );
85   ParseIncludes( normal_includes, lines[ 'i' ] );
86   ParseIncludes( template_includes, lines[ 't' ] );
87   ParseIncludes( template_sources, lines[ 't' ], "xx" );
88
89   // Expand groups
90   TLines pre_classes;
91   ExpandGroups( pre_classes, lines[ 'c' ], vars );
92
93   // Expand variables
94   TLines real_classes;
95   ExpandVariables( real_classes, pre_classes, vars );
96
97   // Prepare header file
98   std::ofstream header_file( header_file_fname.c_str( ) );
99   if( !header_file )
100   {
101     std::cerr
102       << "Error opening \"" << header_file_fname
103       << "\" for writing." << std::endl;
104     return( 1 );
105
106   } // fi
107
108   // Print header
109   header_file
110     << "#ifndef __" << library_name << "__H__" << std::endl
111     << "#define __" << library_name << "__H__" << std::endl<< std::endl
112     << "#include <cpPlugins_Config.h>" << std::endl
113     << "#include <" << library_name << "_Export.h>" << std::endl << std::endl;
114   PrintLines( "", "", lines[ 'b' ], header_file );
115   header_file << std::endl;
116   PrintLines( "", "", first_includes, header_file );
117   header_file
118     << "#ifdef " << library_name << "_EXPORTS" << std::endl
119     << "#  define " << library_name << "_PREFIX template class "
120     << library_name << "_EXPORT" << std::endl
121     << "#else // " << library_name << "_EXPORTS" << std::endl
122     << "#  define " << library_name
123     << "_PREFIX extern template class" << std::endl
124     << "#endif // "
125     << library_name << "_EXPORTS" << std::endl;
126   PrintLines( "", "", normal_includes, header_file );
127   PrintLines( "", "", template_includes, header_file );
128   header_file
129     << std::endl << "#ifdef " << library_name << "_EXPORTS" << std::endl;
130   PrintLines( "", "", template_sources, header_file );
131   header_file << "#endif // " << library_name << "_EXPORTS" << std::endl;
132   header_file << std::endl;
133   PrintLines(
134     library_name + std::string( "_PREFIX " ), ";", real_classes, header_file
135     );
136   header_file
137     << std::endl << "#endif // __" << library_name << "__H__" << std::endl;
138   header_file.close( );
139
140   // Write source file
141   std::ofstream source_file( source_file_fname );
142   if( !source_file )
143   {
144     std::cerr
145       << "Error opening \"" << header_file_fname << "\" for writing." << std::endl;
146     return( 1 );
147
148   } // fi
149   source_file
150     << "#include \"" << header_file_fname << "\"" << std::endl;
151   source_file.close( );
152   return( 0 );
153 }
154
155 // -------------------------------------------------------------------------
156 bool cpPlugins_ISBLANK( const char& value )
157 {
158   return( value == ' ' || value == '\t' || value == '\n' || value == '\r' );
159 }
160
161 // -------------------------------------------------------------------------
162 TLines Tokenize( const std::string& str, const std::string& delims )
163 {
164   TLines tokens;
165   if( str.size( ) > 0 )
166   {
167     auto ssize = str.size( );
168     char* buffer = new char[ ssize + 1 ];
169     for( unsigned long i = 0; i < ssize; ++i )
170       buffer[ i ] = str[ i ];
171     buffer[ ssize ] = '\0';
172     char* next;
173     char* it = cpPlugins_STRTOK( buffer, delims.c_str( ), &next );
174     while( it != NULL )
175     {
176       tokens.push_back( std::string( it ) );
177       it = cpPlugins_STRTOK( NULL, delims.c_str( ), &next );
178
179     } // elihw
180     delete [] buffer;
181
182   } // fi
183   return( tokens );
184 }
185
186 // -------------------------------------------------------------------------
187 std::string Replace(
188   const std::string& str, const std::string& sub, const std::string& nsub
189   )
190 {
191   std::string res = str;
192   size_t index;
193   while( ( index = res.find( sub ) ) != std::string::npos )
194     res.replace( index, sub.size( ), nsub );
195   return( res );
196 }
197
198 // -------------------------------------------------------------------------
199 bool ReadFile( TParsedLines& lines, const std::string& fname )
200 {
201   // Load file into a string stream
202   std::ifstream file_stream( fname.c_str( ) );
203   if( !file_stream )
204     return( false );
205   std::string buffer;
206   file_stream.seekg( 0, std::ios::end );
207   buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) );
208   file_stream.seekg( 0, std::ios::beg );
209   buffer.assign(
210     ( std::istreambuf_iterator< char >( file_stream ) ),
211     std::istreambuf_iterator< char >( )
212     );
213   file_stream.close( );
214   std::istringstream input_stream( buffer );
215
216   // Read line by line
217   std::string line;
218   while( std::getline( input_stream, line ) )
219   {
220     auto cmd_pos = line.end( );
221     auto arg_pos = line.end( );
222     auto lIt = line.begin( );
223     while( lIt != line.end( ) )
224     {
225       if( !cpPlugins_ISBLANK( *lIt ) )
226       {
227         if( cmd_pos == line.end( ) )
228         {
229           cmd_pos = lIt;
230           ++lIt;
231         }
232         else if( arg_pos == line.end( ) )
233         {
234           arg_pos = lIt;
235           lIt = line.end( );
236
237         } // fi
238       }
239       else
240         ++lIt;
241       
242     } // elihw
243     char cmd = *cmd_pos;
244     std::string arg;
245     arg.resize( line.end( ) - arg_pos );
246     std::copy( arg_pos, line.end( ), arg.begin( ) );
247     lines[ cmd ].push_back( arg );
248
249   } // elihw
250   return( true );
251 }
252
253 // -------------------------------------------------------------------------
254 void ExpandGroups( TLines& res, const TLines& lines, const TVariables& vars )
255 {
256   for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
257   {
258     auto b_pos = lIt->find( "@{" );
259     if( b_pos != std::string::npos )
260     {
261       auto e_pos = lIt->find( "}" );
262       auto expansion = lIt->substr( b_pos + 2, e_pos - b_pos - 2 );
263       auto tokens = Tokenize( expansion, ";" );
264       for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
265       {
266         auto vIt = vars.find( *tIt );
267         if( vIt != vars.end( ) )
268         {
269           auto wIt = vIt->second.begin( );
270           std::string values = *wIt;
271           for( wIt++; wIt != vIt->second.end( ); ++wIt )
272             values += ";" + *wIt;
273           *tIt = Replace( *lIt, vIt->first, values );
274         }
275         else
276           *tIt = lIt->substr( 0, b_pos ) + *tIt + lIt->substr( e_pos + 1 );
277
278       } // rof
279       ExpandGroups( res, tokens, vars );
280     }
281     else
282       res.push_back( *lIt );
283
284   } // rof
285 }
286
287 // -------------------------------------------------------------------------
288 void ExpandVariables( TLines& res, const TLines& lines, const TVariables& vars )
289 {
290   for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
291   {
292     auto b_pos = lIt->find( "#" );
293     if( b_pos != std::string::npos )
294     {
295       auto tokens = Tokenize( lIt->substr( b_pos ), " ,;:{}[]()\"$&<>*" );
296       std::string cmd = tokens[ 0 ];
297       auto vIt = vars.find( cmd );
298       if( vIt != vars.end( ) )
299       {
300         if( vIt->second.size( ) > 0 )
301         {
302           TLines new_res;
303           for( auto wIt = vIt->second.begin( ); wIt != vIt->second.end( ); ++wIt )
304             new_res.push_back( Replace( *lIt, cmd, *wIt ) );
305           ExpandVariables( res, new_res, vars );
306
307         } // fi
308
309       } // fi
310     }
311     else
312       res.push_back( *lIt );
313
314   } // rof
315 }
316
317 // -------------------------------------------------------------------------
318 void ParseIncludes( TLines& res, const TLines& lines, const std::string& ext )
319 {
320   for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt )
321     res.push_back(
322       std::string( "#include <" ) + *lIt + ext + std::string( ">" )
323       );
324 }
325
326 // -------------------------------------------------------------------------
327 void PrintLines(
328   const std::string& prefix, const std::string& suffix,
329   const TLines& lines, std::ostream& out
330   )
331 {
332   for( auto i = lines.begin( ); i != lines.end( ); ++i )
333     out << prefix << *i << suffix << std::endl;
334 }
335
336 // eof - $RCSfile$