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