1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        xmlparser.h
3 // Purpose:     Parser of the API/interface XML files
4 // Author:      Francesco Montorsi
5 // Created:     2008/03/17
6 // Copyright:   (c) 2008 Francesco Montorsi
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 
11 #ifndef _XMLPARSER_H_
12 #define _XMLPARSER_H_
13 
14 #include <wx/txtstrm.h>
15 #include <wx/dynarray.h>
16 #include <wx/xml/xml.h>
17 #include <wx/platinfo.h>
18 #include <wx/log.h>
19 
20 
21 /*
22     IMPORTANT
23     =========
24 
25     Any fix aimed to reduce "false positives" which involves
26     references to a specific wxWidgets class is marked in
27     ifacecheck sources with the string:
28 
29     // ADHOC-FIX:
30     // ...fix description...
31 */
32 
33 // NOTE: all messages in this way are printed on the stderr
34 //#define wxLogWarning   wxLogMessage
35 
36 
37 // ----------------------------------------------------------------------------
38 // Represents a type with or without const/static/ qualifier
39 // and with or without & and * operators
40 // ----------------------------------------------------------------------------
41 class wxType
42 {
43 public:
wxType()44     wxType() {}
wxType(const wxString & type)45     wxType(const wxString& type)
46         { SetTypeFromString(type); }
47 
48     void SetTypeFromString(const wxString& t);
GetAsString()49     wxString GetAsString() const
50         { return m_strType; }
51 
52     // returns this type _without_ any decoration,
53     // including the & (which indicates this is a reference),
54     // the * (which indicates this is a pointer), etc.
GetAsCleanString()55     wxString GetAsCleanString() const
56         { return m_strTypeClean; }
57 
IsConst()58     bool IsConst() const
59         { return m_strType.Contains("const"); }
IsStatic()60     bool IsStatic() const
61         { return m_strType.Contains("static"); }
IsPointer()62     bool IsPointer() const
63         { return m_strType.Contains("*"); }
IsReference()64     bool IsReference() const
65         { return m_strType.Contains("&"); }
66 
67     bool operator==(const wxType& m) const;
68     bool operator!=(const wxType& m) const
69         { return !(*this == m); }
70 
71     bool IsOk() const;
72 
73 protected:
74     wxString m_strType,
75              m_strTypeClean;   // m_strType "cleaned" of its attributes
76                                // (only for internal use)
77 };
78 
79 extern wxType wxEmptyType;
80 WX_DECLARE_OBJARRAY(wxType, wxTypeArray);
81 
82 
83 // ----------------------------------------------------------------------------
84 // Represents a type used as argument for some wxMethod
85 // ----------------------------------------------------------------------------
86 class wxArgumentType : public wxType
87 {
88 public:
wxArgumentType()89     wxArgumentType() {}
90     wxArgumentType(const wxString& type, const wxString& defVal,
91                    const wxString& argName = wxEmptyString)
92         { SetTypeFromString(type); SetDefaultValue(defVal); m_strArgName = argName; }
93 
SetArgumentName(const wxString & name)94     void SetArgumentName(const wxString& name)
95         { m_strArgName=name.Strip(wxString::both); }
GetArgumentName()96     wxString GetArgumentName() const
97         { return m_strArgName; }
98 
99     void SetDefaultValue(const wxString& defval,
100                          const wxString& defvalForCmp = wxEmptyString);
GetDefaultValue()101     wxString GetDefaultValue() const
102         { return m_strDefaultValue; }
103 
104     // returns the default value used for comparisons
GetDefaultCleanValue()105     wxString GetDefaultCleanValue() const
106         { return m_strDefaultValueForCmp; }
107 
HasDefaultValue()108     bool HasDefaultValue() const
109         { return !m_strDefaultValue.IsEmpty(); }
110 
111     bool operator==(const wxArgumentType& m) const;
112     bool operator!=(const wxArgumentType& m) const
113         { return !(*this == m); }
114 
115 protected:
116     wxString m_strDefaultValue;
117 
118     // this string may differ from m_strDefaultValue if there were
119     // preprocessor substitutions or other "replacements" done to
120     // avoid false errors.
121     wxString m_strDefaultValueForCmp;
122 
123     // the argument name
124     wxString m_strArgName;
125 };
126 
127 extern wxArgumentType wxEmptyArgumentType;
128 WX_DECLARE_OBJARRAY(wxArgumentType, wxArgumentTypeArray);
129 
130 
131 enum wxMethodAccessSpecifier
132 {
133     wxMAS_PUBLIC,
134     wxMAS_PROTECTED,
135     wxMAS_PRIVATE
136 };
137 
138 // ----------------------------------------------------------------------------
139 // Represents a single prototype of a class' member.
140 // ----------------------------------------------------------------------------
141 class wxMethod
142 {
143 public:
wxMethod()144     wxMethod()
145         { m_bConst=m_bVirtual=m_bPureVirtual=m_bStatic=m_bDeprecated=false;
146           m_nLine=-1; m_nAvailability=wxPORT_UNKNOWN; m_access=wxMAS_PUBLIC; }
147 
wxMethod(const wxType & rettype,const wxString & name,const wxArgumentTypeArray & arguments,bool isConst,bool isStatic,bool isVirtual)148     wxMethod(const wxType& rettype, const wxString& name,
149              const wxArgumentTypeArray& arguments,
150              bool isConst, bool isStatic, bool isVirtual)
151         : m_retType(rettype), m_strName(name.Strip(wxString::both)),
152           m_bConst(isConst), m_bStatic(isStatic), m_bVirtual(isVirtual)
153         { SetArgumentTypes(arguments); m_nLine=-1; }
154 
155 
156 public:     // getters
157 
158     // bWithArgumentNames = output argument names?
159     // bCleanDefaultValues = output clean argument default values?
160     // bDeprecated = output [deprecated] next to deprecated methods?
161     // bAccessSpec = output [public], [protected] or [private] next to method?
162     //
163     // TODO: convert to readable flags this set of bools
164     wxString GetAsString(bool bWithArgumentNames = true,
165                          bool bCleanDefaultValues = false,
166                          bool bDeprecated = false,
167                          bool bAccessSpec = false) const;
168 
169     // parser of the prototype:
170     // all these functions return strings with spaces stripped
GetReturnType()171     wxType GetReturnType() const
172         { return m_retType; }
GetName()173     wxString GetName() const
174         { return m_strName; }
GetArgumentTypes()175     const wxArgumentTypeArray& GetArgumentTypes() const
176         { return m_args; }
GetArgumentTypes()177     wxArgumentTypeArray& GetArgumentTypes()
178         { return m_args; }
GetLocation()179     int GetLocation() const
180         { return m_nLine; }
GetAvailability()181     int GetAvailability() const
182         { return m_nAvailability; }
GetAccessSpecifier()183     wxMethodAccessSpecifier GetAccessSpecifier() const
184         { return m_access; }
185 
IsConst()186     bool IsConst() const
187         { return m_bConst; }
IsStatic()188     bool IsStatic() const
189         { return m_bStatic; }
IsVirtual()190     bool IsVirtual() const
191         { return m_bVirtual; }
IsPureVirtual()192     bool IsPureVirtual() const
193         { return m_bPureVirtual; }
194 
195     bool IsOk() const;
IsCtor()196     bool IsCtor() const
197         { return m_retType==wxEmptyType && !m_strName.StartsWith("~"); }
IsDtor()198     bool IsDtor() const
199         { return m_retType==wxEmptyType && m_strName.StartsWith("~"); }
IsOperator()200     bool IsOperator() const
201         { return m_strName.StartsWith("operator"); }
202 
IsDeprecated()203     bool IsDeprecated() const
204         { return m_bDeprecated; }
205 
206 
207 
208 public:     // setters
209 
SetReturnType(const wxType & t)210     void SetReturnType(const wxType& t)
211         { m_retType=t; }
SetName(const wxString & name)212     void SetName(const wxString& name)
213         { m_strName=name; }
SetArgumentTypes(const wxArgumentTypeArray & arr)214     void SetArgumentTypes(const wxArgumentTypeArray& arr)
215         { m_args=arr; }
216     void SetConst(bool c = true)
217         { m_bConst=c; }
218     void SetStatic(bool c = true)
219         { m_bStatic=c; }
220     void SetVirtual(bool c = true)
221         { m_bVirtual=c; }
222     void SetPureVirtual(bool c = true)
223         {
224             m_bPureVirtual=c;
225             if (c) m_bVirtual=c;        // pure virtual => virtual
226         }
227     void SetDeprecated(bool c = true)
228         { m_bDeprecated=c; }
SetLocation(int lineNumber)229     void SetLocation(int lineNumber)
230         { m_nLine=lineNumber; }
SetAvailability(int nAvail)231     void SetAvailability(int nAvail)
232         { m_nAvailability=nAvail; }
SetAccessSpecifier(wxMethodAccessSpecifier spec)233     void SetAccessSpecifier(wxMethodAccessSpecifier spec)
234         { m_access=spec; }
235 
236 public:     // misc
237 
238     bool operator==(const wxMethod&) const;
239     bool operator!=(const wxMethod& m) const
240         { return !(*this == m); }
241 
242     // this function works like operator== but tests everything:
243     // - method name
244     // - return type
245     // - argument types
246     // except for the method attributes (const,static,virtual,pureVirtual,deprecated)
247     bool MatchesExceptForAttributes(const wxMethod& m) const;
248 
249     // returns true if this is a ctor which has default values for all its
250     // argument, thus is able to act also as default ctor
251     bool ActsAsDefaultCtor() const;
252 
253     // dumps the contents of this class in the given stream
254     void Dump(wxTextOutputStream& stream) const;
255 
256 protected:
257     wxType m_retType;
258     wxString m_strName;
259     wxArgumentTypeArray m_args;
260 
261     // misc attributes:
262     bool m_bConst;
263     bool m_bStatic;
264     bool m_bVirtual;
265     bool m_bPureVirtual;
266     bool m_bDeprecated;
267 
268     // m_nLine can be -1 if no location infos are available
269     int m_nLine;
270 
271     // this is a combination of wxPORT_* flags (see wxPortId) or wxPORT_UNKNOWN
272     // if this method should be available for all wxWidgets ports.
273     // NOTE: this is not used for comparing wxMethod objects
274     //       (gccXML never gives this kind of info).
275     int m_nAvailability;
276 
277     // the access specifier for this method
278     wxMethodAccessSpecifier m_access;
279 };
280 
281 WX_DECLARE_OBJARRAY(wxMethod, wxMethodArray);
282 WX_DEFINE_ARRAY(const wxMethod*, wxMethodPtrArray);
283 
284 
285 // we need wxClassPtrArray to be defined _before_ wxClass itself,
286 // since wxClass uses wxClassPtrArray.
287 class wxClass;
288 WX_DEFINE_ARRAY(const wxClass*, wxClassPtrArray);
289 
290 class wxXmlInterface;
291 
292 
293 // ----------------------------------------------------------------------------
294 // Represents a class of the wx API/interface.
295 // ----------------------------------------------------------------------------
296 class wxClass
297 {
298 public:
wxClass()299     wxClass() {}
wxClass(const wxString & name,const wxString & headername)300     wxClass(const wxString& name, const wxString& headername)
301         : m_strName(name), m_strHeader(headername) {}
302 
303 
304 public:     // setters
305 
SetHeader(const wxString & header)306     void SetHeader(const wxString& header)
307         { m_strHeader=header; }
SetName(const wxString & name)308     void SetName(const wxString& name)
309         { m_strName=name; }
SetAvailability(int nAvail)310     void SetAvailability(int nAvail)
311         { m_nAvailability=nAvail; }
SetParent(unsigned int k,const wxString & name)312     void SetParent(unsigned int k, const wxString& name)
313         { m_parents[k]=name; }
314 
315 public:     // getters
316 
IsOk()317     bool IsOk() const
318         { return !m_strName.IsEmpty() && !m_methods.IsEmpty(); }
319 
320     bool IsValidCtorForThisClass(const wxMethod& m) const;
321     bool IsValidDtorForThisClass(const wxMethod& m) const;
322 
GetName()323     wxString GetName() const
324         { return m_strName; }
GetHeader()325     wxString GetHeader() const
326         { return m_strHeader; }
327     wxString GetNameWithoutTemplate() const;
328 
GetMethodCount()329     unsigned int GetMethodCount() const
330         { return m_methods.GetCount(); }
GetMethod(unsigned int n)331     wxMethod& GetMethod(unsigned int n) const
332         { return m_methods[n]; }
GetLastMethod()333     wxMethod& GetLastMethod() const
334         { return m_methods.Last(); }
335 
GetAvailability()336     int GetAvailability() const
337         { return m_nAvailability; }
338 
339     //const wxClass *GetParent(unsigned int i) const
GetParent(unsigned int i)340     const wxString& GetParent(unsigned int i) const
341         { return m_parents[i]; }
GetParentCount()342     unsigned int GetParentCount() const
343         { return m_parents.GetCount(); }
344 
345 public:     // misc
346 
AddMethod(const wxMethod & func)347     void AddMethod(const wxMethod& func)
348         { m_methods.Add(func); }
349 
AddParent(const wxString & parent)350     void AddParent(const wxString& parent)//wxClass* parent)
351         { m_parents.Add(parent); }
352 
353     // returns a single result (the first, which is also the only
354     // one if CheckConsistency() return true)
355     const wxMethod* FindMethod(const wxMethod& m) const;
356 
357     // like FindMethod() but this one searches also recursively in
358     // the parents of this class.
359     const wxMethod* RecursiveUpwardFindMethod(const wxMethod& m,
360                                               const wxXmlInterface* allclasses) const;
361 
362     // returns an array of pointers to the overloaded methods with the
363     // same given name
364     wxMethodPtrArray FindMethodsNamed(const wxString& name) const;
365 
366     // like FindMethodsNamed() but this one searches also recursively in
367     // the parents of this class.
368     wxMethodPtrArray RecursiveUpwardFindMethodsNamed(const wxString& name,
369                                                      const wxXmlInterface* allclasses) const;
370 
371     // dumps all methods to the given output stream
372     void Dump(wxTextOutputStream& stream) const;
373 
374     // slow check
375     bool CheckConsistency() const;
376 
377 protected:
378     wxString m_strName;
379     wxString m_strHeader;
380     wxMethodArray m_methods;
381 
382     // name of the base classes: we store the names and not the pointers
383     // because this makes _much_ easier the parsing process!
384     // (basically because when parsing class X which derives from Y,
385     //  we may have not parsed yet class Y!)
386     wxArrayString m_parents;
387 
388     // see the wxMethod::m_nAvailability field for more info
389     int m_nAvailability;
390 };
391 
392 WX_DECLARE_OBJARRAY(wxClass, wxClassArray);
393 
394 
395 
396 // ----------------------------------------------------------------------------
397 // wxXmlInterface
398 // ----------------------------------------------------------------------------
399 class wxXmlInterface
400 {
401 public:
wxXmlInterface()402     wxXmlInterface() {}
403 
FindClass(const wxString & classname)404     const wxClass* FindClass(const wxString& classname) const
405         {
406             for (unsigned int i=0; i<m_classes.GetCount(); i++)
407                 if (m_classes[i].GetName() == classname)
408                     return &m_classes[i];
409             return NULL;
410         }
411 
412     void Dump(const wxString& filename);
413 
GetClasses()414     const wxClassArray& GetClasses() const
415         { return m_classes; }
416 
GetClassesCount()417     unsigned int GetClassesCount() const
418         { return m_classes.GetCount(); }
419 
GetMethodCount()420     unsigned int GetMethodCount() const
421         {
422             unsigned int methods = 0;
423             for (unsigned i=0; i < m_classes.GetCount(); i++)
424                 methods += m_classes[i].GetMethodCount();
425             return methods;
426         }
427 
428     // pass a full-path header filename:
429     wxClassPtrArray FindClassesDefinedIn(const wxString& headerfile) const;
430 
ShowProgress()431     void ShowProgress()
432         { /*wxFprintf(stderr, ".");*/ }
433 
434     // is this interface coherent?
435     bool CheckConsistency() const;
436 
437 protected:
438     wxClassArray m_classes;
439 };
440 
441 #if 1
442 // for wxTypeIdHashMap, keys == gccxml IDs  and  values == associated type strings
443 // e.g. key = "0x123f" and value = "const wxAboutDialogInfo&"
444 WX_DECLARE_HASH_MAP( unsigned long, wxString,
445                      wxIntegerHash, wxIntegerEqual,
446                      wxTypeIdHashMap );
447 
448 WX_DECLARE_STRING_HASH_MAP( wxString, wxStringHashMap );
449 #else
450 #include <map>
451 typedef std::basic_string<char> stlString;
452 typedef std::map<unsigned long, stlString> wxTypeIdHashMap;
453 #endif
454 
455 
456 // ----------------------------------------------------------------------------
457 // Represents the real interface of wxWidgets
458 // Loads it from the XML produced by gccXML: http://www.gccxml.org
459 // ----------------------------------------------------------------------------
460 class wxXmlGccInterface : public wxXmlInterface
461 {
462 public:
wxXmlGccInterface()463     wxXmlGccInterface()
464     {
465         // FIXME: we should retrieve this from the XML file!
466         //        here we suppose the XML was created for the currently-running port
467         m_portId = wxPlatformInfo::Get().GetPortId();
468     }
469 
470     bool Parse(const wxString& filename);
471     bool ParseMethod(const wxXmlNode *p,
472                      const wxTypeIdHashMap& types,
473                      wxMethod& m);
474 
GetInterfacePort()475     wxPortId GetInterfacePort() const
476         { return m_portId; }
477 
GetInterfacePortName()478     wxString GetInterfacePortName() const
479         { return wxPlatformInfo::GetPortIdName(m_portId, false); }
480 
481 protected:
482     // the port for which the gcc XML was generated
483     wxPortId m_portId;
484 };
485 
486 
487 // ----------------------------------------------------------------------------
488 // Represents the interface of the doxygen headers of wxWidgets
489 // Loads it from the XML produced by Doxygen: http://www.doxygen.org
490 // ----------------------------------------------------------------------------
491 class wxXmlDoxygenInterface : public wxXmlInterface
492 {
493 public:
wxXmlDoxygenInterface()494     wxXmlDoxygenInterface() {}
495 
496     // !!SPEEDUP-TODO!!
497     // Using wxXmlDocument::Load as is, the entire XML file is parsed
498     // and an entire tree of wxXmlNodes is built in memory.
499     // We need however only small portions of the Doxygen-generated XML: to speedup the
500     // processing we could detach the expat callbacks when we detect the beginning of a
501     // node we're not interested about, or just don't create a wxXmlNode for it!
502     // This needs a modification of wxXml API.
503 
504     bool Parse(const wxString& filename);
505     bool ParseCompoundDefinition(const wxString& filename);
506     bool ParseMethod(const wxXmlNode*, wxMethod&, wxString& header);
507 
508     // this class can take advantage of the preprocessor output to give
509     // a minor number of false positive warnings in the final comparison
AddPreprocessorValue(const wxString & name,const wxString & val)510     void AddPreprocessorValue(const wxString& name, const wxString& val)
511         { m_preproc[name]=val; }
512 
513 protected:
514     wxStringHashMap m_preproc;
515 };
516 
517 
518 
519 #endif      // _XMLPARSER_H_
520 
521