mummy  1.0.2
MummyApplication.cxx
Go to the documentation of this file.
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 //----------------------------------------------------------------------------