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