mummy
1.0.2
|
00001 //---------------------------------------------------------------------------- 00002 // 00003 // $Id: MummyApplication.cxx 506 2010-07-27 15:30:53Z david.cole $ 00004 // 00005 // $Author: david.cole $ 00006 // $Date: 2010-07-27 11:30:53 -0400 (Tue, 27 Jul 2010) $ 00007 // $Revision: 506 $ 00008 // 00009 // Copyright (C) 2006-2009 Kitware, Inc. 00010 // 00011 //---------------------------------------------------------------------------- 00012 00013 #include "MummyApplication.h" 00014 #include "MummyCsharpGenerator.h" 00015 #include "MummyCsharpExportLayerGenerator.h" 00016 #include "MummyCsharpShadowLayerGenerator.h" 00017 #include "MummyCsharpUnitTestGenerator.h" 00018 #include "MummyLog.h" 00019 #include "MummySettings.h" 00020 00021 #include "cableClass.h" 00022 #include "cableClassType.h" 00023 #include "cableContext.h" 00024 #include "cableMethod.h" 00025 #include "cableNamespace.h" 00026 #include "cableSourceRepresentation.h" 00027 #include "cableTypedef.h" 00028 #include "cableVariable.h" 00029 #include "cableXMLSourceParser.h" 00030 #include "cxxFundamentalType.h" 00031 00032 #include "gxsys/ios/fstream" 00033 #include "gxsys/ios/iostream" 00034 #include "gxsys/ios/sstream" 00035 #include "gxsys/stl/map" 00036 #include "gxsys/stl/set" 00037 #include "gxsys/stl/string" 00038 00039 #include "string.h" // strlen 00040 00041 00042 //---------------------------------------------------------------------------- 00043 MummyApplication::MummyApplication() 00044 { 00045 this->Settings = 0; 00046 } 00047 00048 00049 //---------------------------------------------------------------------------- 00050 MummyApplication::~MummyApplication() 00051 { 00052 } 00053 00054 00055 //---------------------------------------------------------------------------- 00056 int MummyApplication::Main(int argc, char *argv[]) 00057 { 00058 int err = 0; 00059 00060 MummySettings settings; 00061 this->SetSettings(&settings); 00062 00063 err = settings.Initialize(argc, argv); 00064 00065 if (!err && settings.ShouldRun()) 00066 { 00067 cable::SourceRepresentation::Pointer sr = BuildSourceRepresentation(); 00068 00069 err = ProcessSource(sr); 00070 } 00071 00072 this->SetSettings(0); 00073 00074 return GetFirstErrorValue(); 00075 } 00076 00077 00078 //---------------------------------------------------------------------------- 00079 MummySettings* MummyApplication::GetSettings() 00080 { 00081 return this->Settings; 00082 } 00083 00084 00085 //---------------------------------------------------------------------------- 00086 void MummyApplication::SetSettings(MummySettings* settings) 00087 { 00088 this->Settings = settings; 00089 } 00090 00091 00092 //---------------------------------------------------------------------------- 00093 cable::SourceRepresentation* MummyApplication::BuildSourceRepresentation() 00094 { 00095 const char* inFileName = this->GetSettings()->GetGccxmlFileName(); 00096 00097 if (!inFileName || (0 == strlen(inFileName))) 00098 { 00099 LogError(me_InvalidArg, << "Must specify valid --gccxml-file (use --help for options)."); 00100 return 0; 00101 } 00102 00103 LogVerboseInfo(<< "Using --gccxml-file '" << inFileName << "'"); 00104 00105 // Open the XML input file produced by GCC-XML. 00106 gxsys_ios::ifstream inFile(inFileName, std::ios_base::in|std::ios_base::binary); 00107 if (!inFile) 00108 { 00109 LogError(me_CouldNotOpen, << "Could not open GCC-XML output: " << inFileName); 00110 return 0; 00111 } 00112 00113 // Parse the XML input file. 00114 cable::XMLSourceParser::Pointer parser = cable::XMLSourceParser::New(); 00115 parser->SetStream(&inFile); 00116 if(!parser->Parse()) 00117 { 00118 LogError(me_CouldNotParse, << "Could not parse GCC-XML output: " << inFileName); 00119 return 0; 00120 } 00121 parser->SetStream(0); 00122 inFile.close(); 00123 00124 // Get the parsed source representation. 00125 return parser->GetSourceRepresentation(); 00126 } 00127 00128 00129 //---------------------------------------------------------------------------- 00130 int MummyApplication::ProcessSource(cable::SourceRepresentation* sr) 00131 { 00132 int err = 0; 00133 00134 if (!sr) 00135 { 00136 LogError(me_InvalidArg, << "MummyApplication::ProcessSource"); 00137 return me_InvalidArg; 00138 } 00139 00140 gxsys_stl::string s; 00141 const cable::Namespace* gns = sr->GetGlobalNamespace(); 00142 00143 // Look inside the _cable_ namespace for a wrappers namespace 00144 // and classes within: 00145 // 00146 cable::Context::Iterator lower = gns->LowerBound("_cable_"); 00147 cable::Context::Iterator upper = gns->UpperBound("_cable_"); 00148 cable::Namespace* cns = 0; 00149 if (lower != upper) 00150 { 00151 cns = cable::Namespace::SafeDownCast(*lower); 00152 } 00153 if (!cns) 00154 { 00155 LogError(me_UnexpectedGccxmlInput, << "MummyApplication::ProcessSource"); 00156 return me_UnexpectedGccxmlInput; 00157 } 00158 00159 // Give the settings object a chance to read package, packageVersion 00160 // and group info out of the source rep: 00161 // 00162 err = this->GetSettings()->ProcessSource(sr); 00163 00164 // Collect up all the classes to be wrapped: 00165 // 00166 gxsys_stl::map<const cable::Class*, cable::Typedef*> TypedefLookup; 00167 gxsys_stl::set<const cable::Class*> ClassesToBeIncluded; 00168 00169 const cable::Namespace* wns = 0; 00170 cable::Context::Iterator wlower = cns->LowerBound("wrappers"); 00171 cable::Context::Iterator wupper = cns->UpperBound("wrappers"); 00172 if (wlower != wupper) 00173 { 00174 wns = cable::Namespace::SafeDownCast(*wlower); 00175 } 00176 if (!wns) 00177 { 00178 LogError(me_UnexpectedGccxmlInput, << "MummyApplication::ProcessSource"); 00179 return me_UnexpectedGccxmlInput; 00180 } 00181 00182 for (cable::Context::Iterator w = wns->Begin(); w != wns->End(); ++w) 00183 { 00184 cable::Typedef* td = cable::Typedef::SafeDownCast(*w); 00185 if(td) 00186 { 00187 const cable::ClassType* ct = cable::ClassType::SafeDownCast(td->GetType()); 00188 if(ct) 00189 { 00190 const cable::Class* c = ct->GetClass(); 00191 TypedefLookup.insert(gxsys_stl::make_pair(c, td)); 00192 ClassesToBeIncluded.insert(c); 00193 } 00194 } 00195 } 00196 00197 // Wrap 'em: 00198 // 00199 for (gxsys_stl::set<const cable::Class*>::iterator i = 00200 ClassesToBeIncluded.begin(); !err && i != ClassesToBeIncluded.end(); ++i) 00201 { 00202 const cable::Class* c = *i; 00203 00204 //cable::Typedef* td = 0; 00205 //gxsys_stl::map<const cable::Class*, cable::Typedef*>::iterator tdi = 00206 // TypedefLookup.find(c); 00207 //if(tdi != TypedefLookup.end()) 00208 // { 00209 // td = tdi->second; 00210 // } 00211 00212 err = this->ProcessClass(sr, c); 00213 } 00214 00215 return err; 00216 } 00217 00218 00219 //---------------------------------------------------------------------------- 00220 int MummyApplication::ProcessClass(cable::SourceRepresentation* sr, const cable::Class* c) 00221 { 00222 int err = 0; 00223 00224 if (!ValidateBaseClasses(c)) 00225 { 00226 LogError(me_CouldNotValidate, << "ValidateBaseClasses failed for class '" << c->GetName() << "'"); 00227 return me_CouldNotValidate; 00228 } 00229 00230 if (!this->GetSettings()->ClassIsWrappable(c)) 00231 { 00232 LogError(me_CouldNotWrap, << "ClassIsWrappable returned false for class '" << c->GetName() << "'"); 00233 return me_CouldNotWrap; 00234 } 00235 00236 MummyCsharpGenerator csg; 00237 gxsys_ios::ostringstream ossCS; 00238 csg.SetSettings(this->GetSettings()); 00239 csg.SetSourceRepresentation(sr); 00240 csg.SetStream(&ossCS); 00241 csg.SetTargetClass(c); 00242 csg.Generate(); 00243 00244 MummyCsharpExportLayerGenerator cselg; 00245 gxsys_ios::ostringstream ossEL; 00246 cselg.SetCsharpGenerator(&csg); 00247 cselg.SetSettings(this->GetSettings()); 00248 cselg.SetSourceRepresentation(sr); 00249 cselg.SetStream(&ossEL); 00250 cselg.SetTargetClass(c); 00251 cselg.Generate(); 00252 00253 if (this->GetSettings()->GetUseShadow(c)) 00254 { 00255 MummyCsharpShadowLayerGenerator csslg; 00256 csslg.SetCsharpGenerator(&csg); 00257 csslg.SetSettings(this->GetSettings()); 00258 csslg.SetSourceRepresentation(sr); 00259 csslg.SetStream(&ossEL); 00260 csslg.SetTargetClass(c); 00261 csslg.Generate(); 00262 } 00263 00264 MummyCsharpUnitTestGenerator csutg; 00265 gxsys_ios::ostringstream ossUT; 00266 csutg.SetCsharpGenerator(&csg); 00267 csutg.SetSettings(this->GetSettings()); 00268 csutg.SetSourceRepresentation(sr); 00269 csutg.SetStream(&ossUT); 00270 csutg.SetTargetClass(c); 00271 csutg.Generate(); 00272 00273 WriteToFile(this->GetSettings()->GetCsharpFileName(c).c_str(), ossCS.str().c_str()); 00274 LogVerboseInfo("Wrote file: " << this->GetSettings()->GetCsharpFileName(c)); 00275 00276 WriteToFile(this->GetSettings()->GetExportLayerFileName(c).c_str(), ossEL.str().c_str()); 00277 LogVerboseInfo("Wrote file: " << this->GetSettings()->GetExportLayerFileName(c)); 00278 00279 // Not yet ready for prime time: 00280 // WriteToFile(this->GetSettings()->GetCsharpUnitTestFileName(c).c_str(), ossUT.str().c_str()); 00281 // LogVerboseInfo("Wrote file: " << this->GetSettings()->GetCsharpUnitTestFileName(c)); 00282 00283 return err; 00284 } 00285 00286 00378 00379 00380 // // // DONE // // // 00381 00382 // get rid of "ref" args for things like "double*" and "int*" where 00383 // we do not know how much memory the thing points to... Translate to an 00384 // array if size is known, otherwise, translate to IntPtr -- only use 00385 // "ref" for "double&" (actual reference-type args...) 00386 00387 // configure or generate an AssemblyInfo.cs with version number info in it 00388 // for each managed dll... 00389 00390 // pull in VTK hints file (similar to inline hint iwhArraySize) 00391 00392 // hand-craft(?) VTK events 00393 00394 // "install" 00395 00396 // identify all methods that require the iwhCounted hint because they 00397 // return objects that have already been registered (anything "like" 00398 // a factory method) 00399 00400 // flesh out C# keywords table to include *all* C# keywords 00401 00402 // Make getters const -- add warnings to mummy for void/non-const getters... 00403 // (added mw_PropGetReturnsVoid and mw_PropGetNotConst) 00404 00405 // hint to remove "property get/set or just set" code from *some* generated C# 00406 // structs?? -- iwhNoFieldAccess -- (add the hint, then write gets/sets 00407 // manually...) 00408 00409 // other Session Manager ModelCreated/Deleting events (namespace qualification 00410 // required...) 00411 00412 // handle NULL object pointer return values from methods properly 00413 00414 // test infrastructure work : mummy wrapping of "main" style funcs 00415 // recognize argc/argv param pairs and transform to a single string[] param in 00416 // the C# method (automatic "main" wrapping...) -- if name is "main" transform 00417 // to "Main"?? 00418 00419 // handle Register/UnRegister properly 00420 00421 // turn warnings back on 00422 00423 // add "iwhPropGet/iwhPropSet needed?" for "^[gGsS]et" methods warning 00424 00425 // warning suppression code, so we can ignore the many, many warnings 00426 // from wrapping VTK while still keeping them for other code bases... 00427 00428 // make header file header blocks uniform -- update copyright everywhere: 00429 // header and source file leading comment blocks 00430 00431 // re-structuring (table of all objects, one-to-one map, 00432 // methodology for removing objects from table, a working "KeepAlive" strategy) 00433 00434 // table stuff and other incidentals while I'm in there... 00435 00436 // consistently log errors when functions that return type strings encounter 00437 // an unknown type 00438 00439 // make sure wrapped reference args work at runtime - done in SignatureSeries 00440 // example class 00441 00442 // search for any generated "ERROR_" chunks 00443 00444 00445 //----------------------------------------------------------------------------