mummy  1.0.3
MummySettings.cxx
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // $Id: MummySettings.cxx 64 2008-03-08 18:10:51Z david.cole $
4 //
5 // $Author: david.cole $
6 // $Date: 2008-03-08 13:10:51 -0500 (Sat, 08 Mar 2008) $
7 // $Revision: 64 $
8 //
9 // Copyright (C) 2006-2007 Kitware, Inc.
10 //
11 //----------------------------------------------------------------------------
12 
13 #include "MummySettings.h"
14 #include "MummyDummyGenerator.h"
16 #include "MummyLog.h"
17 #include "MummyVersion.h"
18 
19 #include "cableClass.h"
20 #include "cableNamespace.h"
21 #include "cableSourceRepresentation.h"
22 #include "cableVariable.h"
23 #include "cableXMLParser.h"
24 
25 #include "gxsys/CommandLineArguments.hxx"
26 #include "gxsys/RegularExpression.hxx"
27 #include "gxsys/ios/fstream"
28 #include "gxsys/ios/iostream"
29 #include "gxsys/stl/algorithm"
30 #include "gxsys/stl/map"
31 #include "gxsys/stl/set"
32 #include "gxsys/stl/string"
33 #include "gxsys/stl/vector"
34 
35 
36 //----------------------------------------------------------------------------
37 static gxsys_stl::string Mummy_SVN_STATUS(Mummy_SVN_STATUS_ENCODED);
38 
39 //----------------------------------------------------------------------------
41 {
42 public:
43  gxsys_stl::string ArgsHelpString;
44  gxsys_stl::string CsharpFile;
45  gxsys_stl::string CsharpUnitTestFile;
46  gxsys_stl::string ExportLayerFile;
47  gxsys_stl::string GccxmlFile;
48  gxsys_stl::string Group;
49  gxsys_stl::string Header;
50  bool Help;
51  gxsys_stl::string Package;
52  gxsys_stl::string PackageVersion;
53  gxsys_stl::vector<gxsys_stl::string> References;
54  bool Run;
55  gxsys_stl::string SettingsFile;
56  gxsys_stl::vector<int> SuppressedWarnings;
57  gxsys_stl::map<gxsys_stl::string, ClassWrappingSettings> unwrappable_classes;
58  gxsys_stl::vector<ClassWrappingSettings> unwrappable_patterns;
59  bool Verbose;
60  bool Version;
61  gxsys_stl::map<gxsys_stl::string, ClassWrappingSettings> wrappable_classes;
62  gxsys_stl::vector<ClassWrappingSettings> wrappable_patterns;
63 };
64 
65 
66 //----------------------------------------------------------------------------
68 {
70  this->Reset();
71 }
72 
73 
74 //----------------------------------------------------------------------------
76 {
77  delete this->Internals;
78 }
79 
80 
81 //----------------------------------------------------------------------------
83 {
84  this->Internals->ArgsHelpString = "";
85  this->Internals->CsharpFile = "";
86  this->Internals->CsharpUnitTestFile = "";
87  this->Internals->ExportLayerFile = "";
88  this->Internals->GccxmlFile = "";
89  this->Internals->Group = "";
90  this->Internals->Header = "";
91  this->Internals->Help = false;
92  this->Internals->Package = "";
93  this->Internals->PackageVersion = "";
94  this->Internals->References.clear();
95  this->Internals->Run = true;
96  this->Internals->SettingsFile = "";
97  this->Internals->SuppressedWarnings.clear();
98  this->Internals->unwrappable_classes.clear();
99  this->Internals->unwrappable_patterns.clear();
100  this->Internals->Verbose = false;
101  this->Internals->Version = false;
102  this->Internals->wrappable_classes.clear();
103  this->Internals->wrappable_patterns.clear();
104 }
105 
106 
107 //----------------------------------------------------------------------------
108 void MummySettings::AddArgumentHandlers(gxsys::CommandLineArguments& arguments)
109 {
110  arguments.AddArgument(
111  "--settings-file",
112  gxsys::CommandLineArguments::SPACE_ARGUMENT,
113  &this->Internals->SettingsFile,
114  "Input file describing mummy configuration settings, including the set of wrapped classes. Required."
115  );
116 
117  arguments.AddArgument(
118  "--csharp-file",
119  gxsys::CommandLineArguments::SPACE_ARGUMENT,
120  &this->Internals->CsharpFile,
121  "C# output file. Default value is 'ClassName.cs' in the current directory."
122  );
123 
124  arguments.AddArgument(
125  "--export-layer-file",
126  gxsys::CommandLineArguments::SPACE_ARGUMENT,
127  &this->Internals->ExportLayerFile,
128  "C++ output file. Default value is 'ClassNameEL.cxx' in the current directory."
129  );
130 
131  arguments.AddArgument(
132  "--csharp-unit-test-file",
133  gxsys::CommandLineArguments::SPACE_ARGUMENT,
135  "C# output file. Default value is 'ClassNameUnitTest.cs' in the current directory."
136  );
137 
138  arguments.AddArgument(
139  "--gccxml-file",
140  gxsys::CommandLineArguments::SPACE_ARGUMENT,
141  &this->Internals->GccxmlFile,
142  "Input file (output of gccxml) describing class to be wrapped. Required."
143  );
144 
145  arguments.AddCallback(
146  "--help",
147  gxsys::CommandLineArguments::NO_ARGUMENT,
149  this,
150  "Display (this) detailed help information."
151  );
152 
153  arguments.AddArgument(
154  "--verbose",
155  gxsys::CommandLineArguments::NO_ARGUMENT,
156  &this->Internals->Verbose,
157  "Overwhelm me with output, I don't have enough reading material... ;)"
158  );
159 
160  arguments.AddCallback(
161  "--version",
162  gxsys::CommandLineArguments::NO_ARGUMENT,
164  this,
165  "Display the program version."
166  );
167 
168  arguments.AddArgument(
169  "--suppress-warnings",
170  gxsys::CommandLineArguments::MULTI_ARGUMENT,
172  "Space separated list of warning numbers to suppress."
173  );
174 }
175 
176 
177 //----------------------------------------------------------------------------
178 int MummySettings::Initialize(int argc, char *argv[])
179 {
180  int err = 0;
181 
182  gxsys::CommandLineArguments arguments;
183 
184  this->Reset();
185 
186  arguments.Initialize(argc, argv);
187 
188  this->AddArgumentHandlers(arguments);
189 
190  // Stash big help string in case we process "--help" during the Parse:
191  this->Internals->ArgsHelpString = arguments.GetHelp();
192 
193  if (!arguments.Parse())
194  {
195  err = me_CouldNotParse;
196  LogError(err, << "Could not parse all arguments in MummySettings::Initialize. Use --help for detailed help information.");
197  }
198 
199  if (!err && this->ShouldRun())
200  {
201  gxsys_stl::vector<int>::iterator wit;
202  for (wit = this->Internals->SuppressedWarnings.begin();
203  wit != this->Internals->SuppressedWarnings.end();
204  ++wit)
205  {
206  SuppressMsg(*wit);
207  }
208 
209  if (this->Internals->SettingsFile == "")
210  {
212  LogError(err, << "Required setting --settings-file not given. Use --help for detailed help information.");
213  }
214 
215  if (!err && this->Internals->GccxmlFile == "")
216  {
218  LogError(err, << "Required setting --gccxml-file not given. Use --help for detailed help information.");
219  }
220 
221  if (!err && this->Internals->Verbose)
222  {
223  LogInfo(mi_VerboseInfo, << "--verbose mode turned on.");
224  }
225 
226  if (!err)
227  {
228  err = this->ParseSettingsFile(this->GetSettingsFileName());
229  }
230  }
231 
232  return err;
233 }
234 
235 
236 //----------------------------------------------------------------------------
238 {
239  this->Internals->unwrappable_classes.insert(gxsys_stl::make_pair(cws.name, cws));
240 }
241 
242 
243 //----------------------------------------------------------------------------
245 {
246  this->Internals->wrappable_classes.insert(gxsys_stl::make_pair(cws.name, cws));
247 }
248 
249 
250 //----------------------------------------------------------------------------
252 {
253  this->Internals->unwrappable_patterns.push_back(cws);
254 }
255 
256 
257 //----------------------------------------------------------------------------
259 {
261  {
262  return c1.sortkey < c2.sortkey;
263  }
264 };
265 
266 
267 //----------------------------------------------------------------------------
269 {
270  this->Internals->wrappable_patterns.push_back(cws);
271 
272  // Sort the vector by sortkey now that a new pattern has been added:
273  //
274  gxsys_stl::sort(this->Internals->wrappable_patterns.begin(),
275  this->Internals->wrappable_patterns.end(), SortBySortKey());
276 }
277 
278 
279 //----------------------------------------------------------------------------
280 void MummySettings::AddReference(const char *name)
281 {
282  if (name)
283  {
284  this->Internals->References.push_back(gxsys_stl::string(name));
285  }
286 }
287 
288 
289 //----------------------------------------------------------------------------
290 void MummySettings::GetReferences(gxsys_stl::vector<gxsys_stl::string>& references)
291 {
292  references.clear();
293  references.insert(references.begin(),
294  this->Internals->References.begin(), this->Internals->References.end());
295 }
296 
297 
298 //----------------------------------------------------------------------------
300 {
301  bool found = false;
302 
303  if (name)
304  {
305  gxsys_stl::map<gxsys_stl::string, ClassWrappingSettings>::iterator mit;
306  gxsys_stl::vector<ClassWrappingSettings>::iterator vit;
307  gxsys::RegularExpression re;
308  gxsys_stl::string s(name);
309 
310  mit = this->Internals->wrappable_classes.find(s);
311  if (mit != this->Internals->wrappable_classes.end())
312  {
313  found = true;
314  if (cws)
315  {
316  (*cws) = mit->second;
317  }
318  }
319 
320  for (vit = this->Internals->wrappable_patterns.begin();
321  !found && vit != this->Internals->wrappable_patterns.end(); ++vit)
322  {
323  re.compile(vit->pattern.c_str());
324  if (re.find(s.c_str()))
325  {
326  found = true;
327  if (cws)
328  {
329  (*cws) = *vit;
330  }
331  }
332  }
333  }
334 
335  return found;
336 }
337 
338 
339 //----------------------------------------------------------------------------
340 bool MummySettings::ClassIsWrappable(const cable::Class *c)
341 {
342  bool wrappable = false;
343 
344  // A class is wrappable if:
345  // - it is not excluded by name or pattern match *and*
346  // - it is included by name or pattern match
347 
348  if (c)
349  {
350  gxsys_stl::map<gxsys_stl::string, ClassWrappingSettings>::iterator mit;
351  gxsys_stl::vector<ClassWrappingSettings>::iterator vit;
352  gxsys::RegularExpression re;
353  gxsys_stl::string s(GetFullyQualifiedNameForCPlusPlus(c));
354 
355  mit = this->Internals->unwrappable_classes.find(s);
356  if (mit != this->Internals->unwrappable_classes.end())
357  {
358  return false;
359  }
360 
361  for (vit = this->Internals->unwrappable_patterns.begin();
362  vit != this->Internals->unwrappable_patterns.end(); ++vit)
363  {
364  re.compile(vit->pattern.c_str());
365  if (re.find(s.c_str()))
366  {
367  return false;
368  }
369  }
370 
371  wrappable = FindClassWrappingSettings(s.c_str(), 0);
372  }
373 
374  return wrappable;
375 }
376 
377 
378 //----------------------------------------------------------------------------
379 #define READ_MummySettings_ATTS() \
380 { \
381  if (s=="beginExcludeRegex"){attBeginExcludeRegex = atts[i+1];knownAttribute = true;} \
382  if (s=="countedMethodsRegex"){attCountedMethodsRegex = atts[i+1];knownAttribute = true;} \
383  if (s=="csharpConstructorModifier"){attCsharpConstructorModifier = atts[i+1];knownAttribute = true;} \
384  if (s=="defaultDisposalMethod"){attDefaultDisposalMethod = atts[i+1];knownAttribute = true;} \
385  if (s=="defaultFactoryMethod"){attDefaultFactoryMethod = atts[i+1];knownAttribute = true;} \
386  if (s=="emitDefaultFactoryMethod"){attEmitDefaultFactoryMethod = atts[i+1];knownAttribute = true;} \
387  if (s=="endExcludeRegex"){attEndExcludeRegex = atts[i+1];knownAttribute = true;} \
388  if (s=="exceptionBaseClass"){attExceptionBaseClass = atts[i+1];knownAttribute = true;} \
389  if (s=="exceptionCloneMethod"){attExceptionCloneMethod = atts[i+1];knownAttribute = true;} \
390  if (s=="exceptionInclude"){attExceptionInclude = atts[i+1];knownAttribute = true;} \
391  if (s=="excludeMarkedLines"){attExcludeMarkedLines = atts[i+1];knownAttribute = true;} \
392  if (s=="externalHints"){attExternalHints = atts[i+1];knownAttribute = true;} \
393  if (s=="extraCsharpCode"){attExtraCsharpCode = atts[i+1];knownAttribute = true;} \
394  if (s=="extraCsharpUnitTestCode"){attExtraCsharpUnitTestCode = atts[i+1];knownAttribute = true;} \
395  if (s=="extraExportLayerCode"){attExtraExportLayerCode = atts[i+1];knownAttribute = true;} \
396  if (s=="getMummyTypeEntryMethod"){attGetMummyTypeEntryMethod = atts[i+1];knownAttribute = true;} \
397  if (s=="getRefCountMethod"){attGetRefCountMethod = atts[i+1];knownAttribute = true;} \
398  if (s=="partial"){attPartial = atts[i+1];knownAttribute = true;} \
399  if (s=="registerBaseClass"){attRegisterBaseClass = atts[i+1];knownAttribute = true;} \
400  if (s=="registerMethod"){attRegisterMethod = atts[i+1];knownAttribute = true;} \
401  if (s=="registerInclude"){attRegisterInclude = atts[i+1];knownAttribute = true;} \
402  if (s=="setMummyTypeEntryMethod"){attSetMummyTypeEntryMethod = atts[i+1];knownAttribute = true;} \
403  if (s=="shadow"){attShadow = atts[i+1];knownAttribute = true;} \
404  if (s=="unRegisterMethod"){attUnRegisterMethod = atts[i+1];knownAttribute = true;} \
405  if (s=="wrappedObjectBase"){attWrappedObjectBase = atts[i+1];knownAttribute = true;} \
406 }
407 
408 
409 //----------------------------------------------------------------------------
410 namespace cable
411 {
412 class SettingsParser : public XMLParser
413 {
414 public:
415  cableTypeMacro(SettingsParser, XMLParser);
416  static Pointer New() { return new Self; }
417 
418  MummySettings* GetSettings() { return this->Settings; }
419  void SetSettings(MummySettings* settings) { this->Settings = settings; }
420 
421 protected:
422  virtual void StartElement(const char* name, const char** atts)
423  {
424  gxsys_stl::string elementName(name);
425 
426  gxsys_stl::string attName;
427  gxsys_stl::string attPattern;
428  gxsys_stl::string attSortKey;
429  gxsys_stl::string attWrappable;
430 
431  gxsys_stl::string attCsharpConstructorModifier("");
432  gxsys_stl::string attDefaultDisposalMethod("");
433  gxsys_stl::string attDefaultFactoryMethod("");
434  gxsys_stl::string attEmitDefaultFactoryMethod("false");
435  gxsys_stl::string attCountedMethodsRegex("");
436  gxsys_stl::string attShadow("false");
437  gxsys_stl::string attExceptionBaseClass("");
438  gxsys_stl::string attExceptionCloneMethod("");
439  gxsys_stl::string attExceptionInclude("");
440  gxsys_stl::string attExternalHints("");
441  gxsys_stl::string attExtraCsharpCode("");
442  gxsys_stl::string attExtraCsharpUnitTestCode("");
443  gxsys_stl::string attExtraExportLayerCode("");
444  gxsys_stl::string attPartial("false");
445  gxsys_stl::string attRegisterMethod("");
446  gxsys_stl::string attUnRegisterMethod("");
447  gxsys_stl::string attRegisterBaseClass("");
448  gxsys_stl::string attRegisterInclude("");
449  gxsys_stl::string attGetRefCountMethod("");
450  gxsys_stl::string attGetMummyTypeEntryMethod("");
451  gxsys_stl::string attSetMummyTypeEntryMethod("");
452  gxsys_stl::string attExcludeMarkedLines("false");
453  gxsys_stl::string attBeginExcludeRegex("");
454  gxsys_stl::string attEndExcludeRegex("");
455  gxsys_stl::string attWrappedObjectBase("");
456 
457  gxsys_stl::string s;
458  bool knownAttribute = false;
459 
460 
461  if (elementName == "Class")
462  {
463  for (unsigned int i=0; atts[i] && atts[i+1]; i+=2)
464  {
465  s = atts[i];
466  knownAttribute = false;
467 
468  if (s=="name"){attName = atts[i+1];knownAttribute = true;}
469  if (s=="wrappable"){attWrappable = atts[i+1];knownAttribute = true;}
470 
472 
473  if (!knownAttribute)
474  {
475  LogWarning(mw_UnknownAttribute, "Unknown XML attribute '"
476  << elementName << "/@" << s << "'");
477  }
478  }
479 
481  attName,
482  attPattern,
483  attSortKey,
484  attDefaultFactoryMethod,
485  attEmitDefaultFactoryMethod == "false" ? false : true,
486  attCountedMethodsRegex,
487  attDefaultDisposalMethod,
488  attShadow == "false" ? false : true,
489  attExternalHints,
490  attExtraExportLayerCode,
491  attExtraCsharpCode,
492  attExtraCsharpUnitTestCode,
493  attCsharpConstructorModifier,
494  attRegisterMethod,
495  attUnRegisterMethod,
496  attGetRefCountMethod,
497  attRegisterBaseClass,
498  attRegisterInclude,
499  attGetMummyTypeEntryMethod,
500  attSetMummyTypeEntryMethod,
501  attExcludeMarkedLines == "false" ? false : true,
502  attBeginExcludeRegex,
503  attEndExcludeRegex,
504  attPartial == "false" ? false : true,
505  attExceptionBaseClass,
506  attExceptionCloneMethod,
507  attExceptionInclude,
508  attWrappedObjectBase
509  );
510 
511  if (attWrappable == "false")
512  {
513  this->GetSettings()->AddUnwrappableClass(cws);
514  }
515  else
516  {
517  this->GetSettings()->AddWrappableClass(cws);
518  }
519  }
520 
521 
522  if (elementName == "ClassPattern")
523  {
524  for (unsigned int i=0; atts[i] && atts[i+1]; i+=2)
525  {
526  s = atts[i];
527  knownAttribute = false;
528 
529  if (s=="pattern"){attPattern = atts[i+1];knownAttribute = true;}
530  if (s=="wrappable"){attWrappable = atts[i+1];knownAttribute = true;}
531  if (s=="sortkey"){attSortKey = atts[i+1];knownAttribute = true;}
532 
534 
535  if (!knownAttribute)
536  {
537  LogWarning(mw_UnknownAttribute, "Unknown XML attribute '"
538  << elementName << "/@" << s << "'");
539  }
540  }
541 
543  attName,
544  attPattern,
545  attSortKey,
546  attDefaultFactoryMethod,
547  attEmitDefaultFactoryMethod == "false" ? false : true,
548  attCountedMethodsRegex,
549  attDefaultDisposalMethod,
550  attShadow == "false" ? false : true,
551  attExternalHints,
552  attExtraExportLayerCode,
553  attExtraCsharpCode,
554  attExtraCsharpUnitTestCode,
555  attCsharpConstructorModifier,
556  attRegisterMethod,
557  attUnRegisterMethod,
558  attGetRefCountMethod,
559  attRegisterBaseClass,
560  attRegisterInclude,
561  attGetMummyTypeEntryMethod,
562  attSetMummyTypeEntryMethod,
563  attExcludeMarkedLines == "false" ? false : true,
564  attBeginExcludeRegex,
565  attEndExcludeRegex,
566  attPartial == "false" ? false : true,
567  attExceptionBaseClass,
568  attExceptionCloneMethod,
569  attExceptionInclude,
570  attWrappedObjectBase
571  );
572 
573  if (attWrappable == "false")
574  {
575  this->GetSettings()->AddUnwrappablePattern(cws);
576  }
577  else
578  {
579  this->GetSettings()->AddWrappablePattern(cws);
580  }
581  }
582 
583 
584  if (elementName == "Reference")
585  {
586  for (unsigned int i=0; atts[i] && atts[i+1]; i+=2)
587  {
588  s = atts[i];
589  knownAttribute = false;
590 
591  if (s=="name"){attName = atts[i+1];knownAttribute = true;}
592 
593  if (!knownAttribute)
594  {
595  LogWarning(mw_UnknownAttribute, "Unknown XML attribute '"
596  << elementName << "/@" << s << "'");
597  }
598  }
599 
600  this->GetSettings()->AddReference(attName.c_str());
601  }
602  }
603 
604 private:
606 };
607 }
608 
609 
610 //----------------------------------------------------------------------------
611 int MummySettings::ParseSettingsFile(const char *filename)
612 {
613  int err = 0;
614 
615  // The settings file shall be an XML file that lists classes explicitly
616  // declared as wrapped or not, something like this:
617  //
618  // <MummySettings>
619  // <Class name="vtkCommand" wrappable="true" defaultFactoryMethod="New" defaultDisposalMethod="Delete" shadow="true"/>
620  // <ClassPattern pattern="^vtk" wrappable="true" defaultFactoryMethod="New" defaultDisposalMethod="Delete" shadow="false"/>
621  // </MummySettings>
622  //
623  // Where the name of the class is the fully qualified C++ class name and
624  // the only valid values for the wrapped attribute are the lower case
625  // boolean constants "true" and "false".
626 
627  if (this->GetVerbose())
628  {
629  LogInfo(mi_VerboseInfo, << "Using --settings-file '" << filename << "'");
630  }
631 
632  gxsys_ios::ifstream inFile(filename, std::ios_base::in|std::ios_base::binary);
633  if (!inFile)
634  {
635  err = me_CouldNotOpen;
636  LogFileLineErrorMsg(filename, 1,
637  err, << "Could not open file: '" << filename << "'");
638  }
639 
640  if (!err)
641  {
642  cable::SettingsParser::Pointer parser = cable::SettingsParser::New();
643  parser->SetStream(&inFile);
644  parser->SetSettings(this);
645  if(!parser->Parse())
646  {
647  err = me_CouldNotParse;
648  LogFileLineErrorMsg(filename, 1,
649  err, << "Could not parse file: '" << filename << "'");
650  }
651  parser->SetStream(0);
652  parser->SetSettings(0);
653  inFile.close();
654  }
655 
656  return err;
657 }
658 
659 
660 //----------------------------------------------------------------------------
661 bool ParseName(const char* name, gxsys_stl::string& result)
662 {
663  gxsys_stl::string group = name;
664  gxsys_stl::string::size_type l = group.find('"');
665  gxsys_stl::string::size_type r = group.rfind('"');
666  if((l != gxsys_stl::string::npos) && (r != gxsys_stl::string::npos) && (r > l))
667  {
668  result = group.substr(l+1, r-l-1);
669  return true;
670  }
671  return false;
672 }
673 
674 
675 //----------------------------------------------------------------------------
676 bool GetGroupAndPackageInformation(cable::Namespace* cns,
677  gxsys_stl::string& groupName,
678  gxsys_stl::vector<gxsys_stl::string>& groupsNames,
679  gxsys_stl::string& packageName,
680  gxsys_stl::string& packageVersion,
681  gxsys_stl::string& headerName,
682  gxsys_stl::string& configFile)
683 {
684  // Find the group, if any.
685  const cable::Variable* group = 0;
686  cable::Context::Iterator lower = cns->LowerBound("group");
687  cable::Context::Iterator upper = cns->UpperBound("group");
688  if (lower != upper)
689  {
690  group = cable::Variable::SafeDownCast(*lower);
691  if (!group)
692  {
693  LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::group is not a variable.");
694  return false;
695  }
696  }
697 
698  // Find the groups list, if any.
699  const cable::Variable* groups = 0;
700  lower = cns->LowerBound("groups");
701  upper = cns->UpperBound("groups");
702  if (lower != upper)
703  {
704  groups = cable::Variable::SafeDownCast(*lower);
705  if (!groups)
706  {
707  LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::groups is not a variable.");
708  return false;
709  }
710  }
711 
712  // Find the package name, if any.
713  const cable::Variable* package = 0;
714  lower = cns->LowerBound("package");
715  upper = cns->UpperBound("package");
716  if (lower != upper)
717  {
718  package = cable::Variable::SafeDownCast(*lower);
719  if (!package)
720  {
721  LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::package is not a variable.");
722  return false;
723  }
724  }
725 
726  // Find the package version, if any.
727  const cable::Variable* package_version = 0;
728  lower = cns->LowerBound("package_version");
729  upper = cns->UpperBound("package_version");
730  if (lower != upper)
731  {
732  package_version = cable::Variable::SafeDownCast(*lower);
733  if (!package_version)
734  {
735  LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::package_version is not a variable.");
736  return false;
737  }
738  }
739 
740  // Find the header, if any.
741  const cable::Variable* header = 0;
742  lower = cns->LowerBound("header");
743  upper = cns->UpperBound("header");
744  if (lower != upper)
745  {
746  header = cable::Variable::SafeDownCast(*lower);
747  if (!header)
748  {
749  LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::header is not a variable.");
750  return false;
751  }
752  }
753 
754  // Parse the strings out of the found entities:
755  //
756  if (group)
757  {
758  if (!ParseName(group->GetInitializer(), groupName))
759  {
760  LogError(me_CouldNotParse, << "Error parsing group name.");
761  return false;
762  }
763 
764  // Hold on to the name of the configuration file.
765  configFile = group->GetFile();
766  }
767 
768  if (package && !ParseName(package->GetInitializer(), packageName))
769  {
770  LogError(me_CouldNotParse, << "Error parsing package name.");
771  return false;
772  }
773 
774  if (package_version &&
775  !ParseName(package_version->GetInitializer(), packageVersion))
776  {
777  LogError(me_CouldNotParse, << "Error parsing package_version string.");
778  return false;
779  }
780 
781  if (groups)
782  {
783  gxsys_stl::string gl = groups->GetInitializer();
784  gxsys_stl::string::size_type lpos = gl.find('"');
785  while((lpos != gxsys_stl::string::npos) && (lpos < gl.length()))
786  {
787  gxsys_stl::string::size_type rpos = gl.find_first_of(",}", lpos);
788  gxsys_stl::string result;
789  if((rpos == gxsys_stl::string::npos) ||
790  !ParseName(gl.substr(lpos, rpos-lpos).c_str(), result))
791  {
792  LogError(me_CouldNotParse, << "Error parsing groups list.");
793  return false;
794  }
795  groupsNames.push_back(result);
796  lpos = rpos+1;
797  }
798  }
799 
800  if (header)
801  {
802  if (!ParseName(header->GetInitializer(), headerName))
803  {
804  LogError(me_CouldNotParse, << "Error parsing header name.");
805  return false;
806  }
807  }
808 
809  return true;
810 }
811 
812 
813 //----------------------------------------------------------------------------
814 int MummySettings::ProcessSource(cable::SourceRepresentation* sr)
815 {
816  int err = 0;
817 
818  if (!sr)
819  {
820  LogError(me_InvalidArg, << "NULL pointer!");
821  return me_InvalidArg;
822  }
823 
824  gxsys_stl::string s;
825  const cable::Namespace* gns = sr->GetGlobalNamespace();
826 
827  // Look inside the _cable_ namespace for package, packageversion and
828  // group settings:
829  //
830  cable::Context::Iterator lower = gns->LowerBound("_cable_");
831  cable::Context::Iterator upper = gns->UpperBound("_cable_");
832  cable::Namespace* cns = 0;
833  if (lower != upper)
834  {
835  cns = cable::Namespace::SafeDownCast(*lower);
836  }
837  if (!cns)
838  {
839  LogError(me_UnexpectedGccxmlInput, << "No _cable_ namespace.");
841  }
842 
843  gxsys_stl::string group;
844  gxsys_stl::vector<gxsys_stl::string> groups;
845  gxsys_stl::string package;
846  gxsys_stl::string packageVersion;
847  gxsys_stl::string header;
848  gxsys_stl::string configFile;
849  GetGroupAndPackageInformation(cns, group, groups, package, packageVersion, header, configFile);
850  if (group.size() == 0)
851  {
852  if (package.size() == 0)
853  {
854  LogError(me_UnexpectedGccxmlInput, << "No group or package name specified.");
856  }
857  }
858 
859  // Save for when clients query us later:
860  //
861  this->Internals->Group = group;
862  this->Internals->Header = header;
863  this->Internals->Package = package;
864  this->Internals->PackageVersion = packageVersion;
865 
866  return err;
867 }
868 
869 
870 //----------------------------------------------------------------------------
871 static void IncreaseCoverage(MummySettings *settings)
872 {
873  // This function exists only to add test calls to functions that are
874  // otherwise not commonly called so that they get some sort of coverage
875  // on coverage dashboards...
876  //
877  Trace("IncreaseCoverage\n");
878 
881  mg.TypeIsWrappable(0);
883  mg.MethodIsWrappable(0, cable::Context::Public);
884  mg.ClassIsWrappable(0);
885  mg.GenerateWrappers();
886 
888  GetNthErrorValue(-10);
889  GetNthErrorValue(0); // valid if there have been any errors...
890  GetNthErrorValue(GetErrorCount()-1); // valid if there have been any errors...
893 
894  // Can't do this... then the test that calls this code fails because there
895  // was an "error"......
896  //
897  //LogError(me_InternalError,
898  // << "This is not really an error." << gxsys_ios::endl
899  // << " This is IncreaseCoverage increasing the coverage of the" << gxsys_ios::endl
900  // << " MummyUtilities error functions..."
901  // );
902  //GetNthErrorValue(-10);
903  //GetNthErrorValue(0); // valid if there have been any errors...
904  //GetNthErrorValue(GetErrorCount()-1); // valid if there have been any errors...
905  //GetNthErrorValue(GetErrorCount());
906  //GetNthErrorValue(GetErrorCount()+10);
907 
909  EncodeStringForXml("");
910 
911  settings->GetHeader();
912  settings->GetPackageVersion();
913 
915  reader.SetFileName(0);
916 }
917 
918 
919 //----------------------------------------------------------------------------
920 int MummySettings::DisplayHelp(const char* argument, const char* value,
921  void* call_data)
922 {
923  MummySettings *settings = (MummySettings *) call_data;
924 
925  DisplayVersion(argument, value, call_data);
926 
927  // If run under a ctest driven dashboard test, emit the string that tells
928  // ctest not to truncate the test output:
929  //
930  if (getenv("DART_TEST_FROM_DART"))
931  {
932  gxsys_ios::cout << gxsys_ios::endl;
933  gxsys_ios::cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << gxsys_ios::endl;
934  }
935 
936  gxsys_ios::cout << gxsys_ios::endl;
937  gxsys_ios::cout << "Command line options:" << gxsys_ios::endl;
938  gxsys_ios::cout << settings->Internals->ArgsHelpString << gxsys_ios::endl;
939 
940  if (!Mummy_SVN_STATUS.empty())
941  {
942  gxsys_ios::cout << gxsys_ios::endl;
943  gxsys_ios::cout << "svn status (retrieved at CMake configure time):" << gxsys_ios::endl;
944  gxsys_ios::cout << "===============================================" << gxsys_ios::endl;
945  gxsys_ios::cout << Mummy_SVN_STATUS.c_str() << gxsys_ios::endl;
946  gxsys_ios::cout << gxsys_ios::endl;
947  }
948 
949  IncreaseCoverage(settings);
950 
951  settings->Internals->Help = true;
952  settings->Internals->Run = false;
953  return 1;
954 }
955 
956 
957 //----------------------------------------------------------------------------
958 int MummySettings::DisplayVersion(const char*, const char*, void* call_data)
959 {
960  MummySettings *settings = (MummySettings *) call_data;
961 
962  gxsys_ios::cout << settings->GetMummyVersion() << gxsys_ios::endl;
963 
964  settings->Internals->Version = true;
965  settings->Internals->Run = false;
966  return 1;
967 }
968 
969 
970 //----------------------------------------------------------------------------
972 {
973  return Mummy_FULL_VERSION_STRING;
974 }
975 
976 
977 //----------------------------------------------------------------------------
979 {
980  return this->Internals->SettingsFile.c_str();
981 }
982 
983 
984 //----------------------------------------------------------------------------
986 {
987  return this->Internals->CsharpFile.c_str();
988 }
989 
990 
991 //----------------------------------------------------------------------------
993 {
994  return this->Internals->ExportLayerFile.c_str();
995 }
996 
997 
998 //----------------------------------------------------------------------------
1000 {
1001  return this->Internals->CsharpUnitTestFile.c_str();
1002 }
1003 
1004 
1005 //----------------------------------------------------------------------------
1007 {
1008  return this->Internals->GccxmlFile.c_str();
1009 }
1010 
1011 
1012 //----------------------------------------------------------------------------
1014 {
1015  return this->Internals->Group.c_str();
1016 }
1017 
1018 
1019 //----------------------------------------------------------------------------
1021 {
1022  return this->Internals->Header.c_str();
1023 }
1024 
1025 
1026 //----------------------------------------------------------------------------
1028 {
1029  return this->Internals->Package.c_str();
1030 }
1031 
1032 
1033 //----------------------------------------------------------------------------
1035 {
1036  return this->Internals->PackageVersion.c_str();
1037 }
1038 
1039 
1040 //----------------------------------------------------------------------------
1042 {
1043  return this->Internals->Run;
1044 }
1045 
1046 
1047 //----------------------------------------------------------------------------
1049 {
1050  return this->Internals->Verbose;
1051 }
1052 
1053 
1054 //----------------------------------------------------------------------------
1055 gxsys_stl::string MummySettings::GetCsharpFileName(const cable::Class* c)
1056 {
1057  gxsys_stl::string s(this->GetCsharpFileName());
1058 
1059  if (s == "")
1060  {
1061  s = c->GetName();
1062  s += ".cs";
1063  }
1064 
1065  return s;
1066 }
1067 
1068 
1069 //----------------------------------------------------------------------------
1070 gxsys_stl::string MummySettings::GetExportLayerFileName(const cable::Class* c)
1071 {
1072  gxsys_stl::string s(this->GetExportLayerFileName());
1073 
1074  if (s == "")
1075  {
1076  s = c->GetName();
1077  s += "EL.cxx";
1078  }
1079 
1080  return s;
1081 }
1082 
1083 
1084 //----------------------------------------------------------------------------
1085 gxsys_stl::string MummySettings::GetCsharpUnitTestFileName(const cable::Class* c)
1086 {
1087  gxsys_stl::string s(this->GetCsharpUnitTestFileName());
1088 
1089  if (s == "")
1090  {
1091  s = c->GetName();
1092  s += "UnitTest.cs";
1093  }
1094 
1095  return s;
1096 }
1097 
1098 
1099 //----------------------------------------------------------------------------
1100 gxsys_stl::string MummySettings::GetCsharpConstructorModifier(const cable::Class* c)
1101 {
1102  gxsys_stl::string s;
1104 
1106  {
1107  s = cws.csharpConstructorModifier;
1108  }
1109  else
1110  {
1111  s = "ERROR_NoCsharpConstructorModifier";
1113  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1114  }
1115 
1116  return s;
1117 }
1118 
1119 
1120 //----------------------------------------------------------------------------
1121 gxsys_stl::string MummySettings::GetFactoryMethod(const cable::Class* c)
1122 {
1123  gxsys_stl::string s;
1125 
1127  {
1128  s = cws.defaultFactoryMethod;
1129  }
1130  else
1131  {
1132  s = "ERROR_NoFactoryMethod";
1134  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1135  }
1136 
1137  return s;
1138 }
1139 
1140 
1141 //----------------------------------------------------------------------------
1143 {
1144  bool b = false;
1146 
1148  {
1149  b = cws.emitDefaultFactoryMethod;
1150  }
1151  else
1152  {
1154  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1155  }
1156 
1157  return b;
1158 }
1159 
1160 
1161 //----------------------------------------------------------------------------
1162 gxsys_stl::string MummySettings::GetCountedMethodsRegex(const cable::Class* c)
1163 {
1164  gxsys_stl::string s;
1166 
1168  {
1169  s = cws.countedMethodsRegex;
1170  }
1171  else
1172  {
1173  s = "ERROR_NoCountedMethodsRegex";
1175  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1176  }
1177 
1178  return s;
1179 }
1180 
1181 
1182 //----------------------------------------------------------------------------
1183 gxsys_stl::string MummySettings::GetDisposalMethod(const cable::Class* c)
1184 {
1185  gxsys_stl::string s;
1187 
1189  {
1190  s = cws.defaultDisposalMethod;
1191  }
1192  else
1193  {
1194  s = "ERROR_NoDisposalMethod";
1196  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1197  }
1198 
1199  return s;
1200 }
1201 
1202 
1203 //----------------------------------------------------------------------------
1204 bool MummySettings::GetUseShadow(const cable::Class* c)
1205 {
1206  bool shadow = false;
1208 
1210  {
1211  shadow = cws.shadow;
1212  }
1213  else
1214  {
1216  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1217  }
1218 
1219  return shadow;
1220 }
1221 
1222 
1223 //----------------------------------------------------------------------------
1224 gxsys_stl::string MummySettings::GetExternalHints(const cable::Class* c)
1225 {
1226  gxsys_stl::string s;
1228 
1230  {
1231  s = cws.externalHints;
1232  }
1233  else
1234  {
1235  s = "ERROR_NoExternalHints";
1237  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1238  }
1239 
1240  return s;
1241 }
1242 
1243 
1244 //----------------------------------------------------------------------------
1245 gxsys_stl::string MummySettings::GetExtraCsharpCode(const cable::Class* c)
1246 {
1247  gxsys_stl::string s;
1249 
1251  {
1252  s = cws.extraCsharpCode;
1253  }
1254  else
1255  {
1256  s = "ERROR_NoExtraCsharpCode";
1258  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1259  }
1260 
1261  return s;
1262 }
1263 
1264 
1265 //----------------------------------------------------------------------------
1266 gxsys_stl::string MummySettings::GetExtraExportLayerCode(const cable::Class* c)
1267 {
1268  gxsys_stl::string s;
1270 
1272  {
1273  s = cws.extraExportLayerCode;
1274  }
1275  else
1276  {
1277  s = "ERROR_NoExtraExportLayerCode";
1279  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1280  }
1281 
1282  return s;
1283 }
1284 
1285 
1286 //----------------------------------------------------------------------------
1287 gxsys_stl::string MummySettings::GetExtraCsharpUnitTestCode(const cable::Class* c)
1288 {
1289  gxsys_stl::string s;
1291 
1293  {
1294  s = cws.extraCsharpUnitTestCode;
1295  }
1296  else
1297  {
1298  s = "ERROR_NoExtraCsharpUnitTestCode";
1300  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1301  }
1302 
1303  return s;
1304 }
1305 
1306 
1307 //----------------------------------------------------------------------------
1308 gxsys_stl::string MummySettings::GetRegisterMethod(const cable::Class* c)
1309 {
1310  gxsys_stl::string s;
1312 
1314  {
1315  s = cws.registerMethod;
1316  }
1317  else
1318  {
1319  s = "ERROR_NoRegisterMethod";
1321  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1322  }
1323 
1324  return s;
1325 }
1326 
1327 
1328 //----------------------------------------------------------------------------
1329 gxsys_stl::string MummySettings::GetUnRegisterMethod(const cable::Class* c)
1330 {
1331  gxsys_stl::string s;
1333 
1335  {
1336  s = cws.unRegisterMethod;
1337  }
1338  else
1339  {
1340  s = "ERROR_NoUnRegisterMethod";
1342  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1343  }
1344 
1345  return s;
1346 }
1347 
1348 
1349 //----------------------------------------------------------------------------
1350 gxsys_stl::string MummySettings::GetRegisterBaseClass(const cable::Class* c)
1351 {
1352  gxsys_stl::string s;
1354 
1356  {
1357  s = cws.registerBaseClass;
1358  }
1359  else
1360  {
1361  s = "ERROR_NoRegisterBaseClass";
1363  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1364  }
1365 
1366  return s;
1367 }
1368 
1369 
1370 //----------------------------------------------------------------------------
1371 gxsys_stl::string MummySettings::GetRegisterInclude(const cable::Class* c)
1372 {
1373  gxsys_stl::string s;
1375 
1377  {
1378  s = cws.registerInclude;
1379  }
1380  else
1381  {
1382  s = "ERROR_NoRegisterInclude";
1384  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1385  }
1386 
1387  return s;
1388 }
1389 
1390 
1391 //----------------------------------------------------------------------------
1392 bool MummySettings::GetPartialClass(const cable::Class* c)
1393 {
1394  bool partial = false;
1396 
1398  {
1399  partial = cws.partialClass;
1400  }
1401  else
1402  {
1404  << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'");
1405  }
1406 
1407  return partial;
1408 }