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