1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Main program file for HelpGen
4 // Author: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Copyright: (c) 1999 VZ
9 // Licence: wxWindows Licence
10 /////////////////////////////////////////////////////////////////////////////
15 1. wx/string.h confuses C++ parser terribly
16 2. C++ parser doesn't know about virtual functions, nor static ones
17 3. param checking is not done for vararg functions
18 4. type comparison is dumb: it doesn't know that "char *" is the same
19 that "char []" nor that "const char *" is the same as "char const *"
21 TODO (+ means fixed), see also the change log at the end of the file.
23 (i) small fixes in the current version
25 +1. Quote special TeX characters like '&' and '_' (=> derive from wxFile)
27 3. Document global variables
30 6. Include file name/line number in the "diff" messages?
31 +7. Support for vararg functions
33 (ii) plans for version 2
34 1. Use wxTextFile for direct file access to avoid one scan method problems
35 2. Use command line parser class for the options
36 3. support for overloaded functions in diff mode (search for OVER)
38 (iii) plans for version 3
39 1. Merging with existing files
43 // =============================================================================
45 // =============================================================================
47 // -----------------------------------------------------------------------------
49 // -----------------------------------------------------------------------------
52 #include "wx/wxprec.h"
59 #include "wx/string.h"
61 #include "wx/dynarray.h"
69 // C++ parsing classes
76 // -----------------------------------------------------------------------------
78 // -----------------------------------------------------------------------------
80 // return the label for the given function name (i.e. argument of \label)
81 static wxString
MakeLabel(const char *classname
, const char *funcname
= NULL
);
83 // return the whole \helpref{arg}{arg_label} string
84 static wxString
MakeHelpref(const char *argument
);
86 // [un]quote special TeX characters (in place)
87 static void TeXFilter(wxString
* str
);
88 static void TeXUnfilter(wxString
* str
); // also trims spaces
90 // get all comments associated with this context
91 static wxString
GetAllComments(const spContext
& ctx
);
93 // get the string with current time (returns pointer to static buffer)
94 // timeFormat is used for the call of strftime(3)
95 static const char *GetCurrentTimeFormatted(const char *timeFormat
);
97 // get the string containing the program version
98 static const wxString
GetVersionString();
100 // -----------------------------------------------------------------------------
102 // -----------------------------------------------------------------------------
104 // a function documentation entry
105 struct FunctionDocEntry
107 FunctionDocEntry(const wxString
& name_
, const wxString
& text_
)
108 : name(name_
), text(text_
) { }
113 // the function doc text
117 static int Compare(FunctionDocEntry
**pp1
, FunctionDocEntry
**pp2
)
119 // the methods should appear in the following order: ctors, dtor, all
120 // the rest in the alphabetical order
121 bool isCtor1
= (*pp1
)->name
== classname
;
122 bool isCtor2
= (*pp2
)->name
== classname
;
126 // we don't order the ctors because we don't know how to do it
130 // ctor comes before non-ctor
135 // non-ctor must come after ctor
139 wxString dtorname
= wxString(_T("~")) + classname
;
141 // there is only one dtor, so the logic here is simpler
142 if ( (*pp1
)->name
== dtorname
) {
145 else if ( (*pp2
)->name
== dtorname
) {
149 // two normal methods
150 return wxStrcmp((*pp1
)->name
, (*pp2
)->name
);
154 static wxString classname
;
157 wxString
FunctionDocEntry::classname
;
159 WX_DECLARE_OBJARRAY(FunctionDocEntry
, FunctionDocEntries
);
161 #include "wx/arrimpl.cpp"
163 WX_DEFINE_OBJARRAY(FunctionDocEntries
);
165 // add a function which sanitazes the string before writing it to the file and
166 // also capable of delaying output and sorting it before really writing it to
167 // the file (done from FlushAll())
168 class wxTeXFile
: public wxFile
173 // write a string to file verbatim (should only be used for the strings
174 // inside verbatim environment)
175 void WriteVerbatim(const wxString
& s
)
180 // write a string quoting TeX specials in it
181 void WriteTeX(const wxString
& s
)
189 // do write everything to file
192 if ( m_text
.empty() )
195 if ( !Write(m_text
) ) {
196 wxLogError(_T("Failed to output generated documentation."));
207 wxTeXFile(const wxTeXFile
&);
208 wxTeXFile
& operator=(const wxTeXFile
&);
213 // helper class which manages the classes and function names to ignore for
214 // the documentation purposes (used by both HelpGenVisitor and DocManager)
215 class IgnoreNamesHandler
218 IgnoreNamesHandler() : m_ignore(CompareIgnoreListEntries
) { }
219 ~IgnoreNamesHandler() { WX_CLEAR_ARRAY(m_ignore
); }
221 // load file with classes/functions to ignore (add them to the names we
223 bool AddNamesFromFile(const wxString
& filename
);
225 // return true if we ignore this function
226 bool IgnoreMethod(const wxString
& classname
,
227 const wxString
& funcname
) const
229 if ( IgnoreClass(classname
) )
232 IgnoreListEntry
ignore(classname
, funcname
);
234 return m_ignore
.Index(&ignore
) != wxNOT_FOUND
;
237 // return true if we ignore this class entirely
238 bool IgnoreClass(const wxString
& classname
) const
240 IgnoreListEntry
ignore(classname
, wxEmptyString
);
242 return m_ignore
.Index(&ignore
) != wxNOT_FOUND
;
246 struct IgnoreListEntry
248 IgnoreListEntry(const wxString
& classname
,
249 const wxString
& funcname
)
250 : m_classname(classname
), m_funcname(funcname
)
254 wxString m_classname
;
255 wxString m_funcname
; // if empty, ignore class entirely
258 static int CompareIgnoreListEntries(IgnoreListEntry
*first
,
259 IgnoreListEntry
*second
);
261 // for efficiency, let's sort it
262 public: // FIXME: macro requires it
263 WX_DEFINE_SORTED_ARRAY(IgnoreListEntry
*, ArrayNamesToIgnore
);
266 ArrayNamesToIgnore m_ignore
;
269 IgnoreNamesHandler(const IgnoreNamesHandler
&);
270 IgnoreNamesHandler
& operator=(const IgnoreNamesHandler
&);
273 // visitor implementation which writes all collected data to a .tex file
274 class HelpGenVisitor
: public spVisitor
278 HelpGenVisitor(const wxString
& directoryOut
, bool overwrite
);
280 virtual void VisitFile( spFile
& fl
);
281 virtual void VisitClass( spClass
& cl
);
282 virtual void VisitEnumeration( spEnumeration
& en
);
283 virtual void VisitTypeDef( spTypeDef
& td
);
284 virtual void VisitPreprocessorLine( spPreprocessorLine
& pd
);
285 virtual void VisitAttribute( spAttribute
& attr
);
286 virtual void VisitOperation( spOperation
& op
);
287 virtual void VisitParameter( spParameter
& param
);
291 // get our `ignore' object
292 IgnoreNamesHandler
& GetIgnoreHandler() { return m_ignoreNames
; }
294 // shut up g++ warning (ain't it stupid?)
295 virtual ~HelpGenVisitor() { }
298 // (re)initialize the state
301 // insert documentation for enums/typedefs coming immediately before the
302 // class declaration into the class documentation
303 void InsertTypedefDocs();
304 void InsertEnumDocs();
306 // write the headers for corresponding sections (only once)
307 void InsertDataStructuresHeader();
308 void InsertMethodsHeader();
310 // terminate the function documentation if it was started
311 void CloseFunction();
313 // write out all function docs when there are no more left in this class
314 // after sorting them in alphabetical order
317 wxString m_directoryOut
, // directory for the output
318 m_fileHeader
; // name of the .h file we parse
319 bool m_overwrite
; // overwrite existing files?
320 wxTeXFile m_file
; // file we're writing to now
323 bool m_inClass
, // true after file successfully opened
324 m_inTypesSection
, // enums & typedefs go there
325 m_inMethodSection
, // functions go here
326 m_isFirstParam
; // first parameter of current function?
328 // non empty while parsing a class
329 wxString m_classname
;
331 // these are only non-empty while parsing a method:
332 wxString m_funcName
, // the function name
333 m_textFunc
; // the function doc text
335 // the array containing the documentation entries for the functions in the
336 // class currently being parsed
337 FunctionDocEntries m_arrayFuncDocs
;
339 // holders for "saved" documentation
340 wxString m_textStoredTypedefs
,
341 m_textStoredFunctionComment
;
343 // for enums we have to use an array as we can't intermix the normal text
344 // and the text inside verbatim environment
345 wxArrayString m_storedEnums
,
348 // headers included by this file
349 wxArrayString m_headers
;
351 // ignore handler: tells us which classes to ignore for doc generation
353 IgnoreNamesHandler m_ignoreNames
;
356 HelpGenVisitor(const HelpGenVisitor
&);
357 HelpGenVisitor
& operator=(const HelpGenVisitor
&);
360 // documentation manager - a class which parses TeX files and remembers the
361 // functions documented in them and can later compare them with all functions
362 // found under ctxTop by C++ parser
366 DocManager(bool checkParamNames
);
369 // returns false on failure
370 bool ParseTeXFile(const wxString
& filename
);
372 // returns false if there were any differences
373 bool DumpDifferences(spContext
*ctxTop
) const;
375 // get our `ignore' object
376 IgnoreNamesHandler
& GetIgnoreHandler() { return m_ignoreNames
; }
382 // returns the length of 'match' if the string 'str' starts with it or 0
384 static size_t TryMatch(const char *str
, const char *match
);
386 // skip spaces: returns pointer to first non space character (also
387 // updates the value of m_line)
388 const char *SkipSpaces(const char *p
)
390 while ( isspace(*p
) ) {
398 // skips characters until the next 'c' in '*pp' unless it ends before in
399 // which case false is returned and pp points to '\0', otherwise true is
400 // returned and pp points to 'c'
401 bool SkipUntil(const char **pp
, char c
);
403 // the same as SkipUntil() but only spaces are skipped: on first non space
404 // character different from 'c' the function stops and returns false
405 bool SkipSpaceUntil(const char **pp
, char c
);
407 // extract the string between {} and modify '*pp' to point at the
408 // character immediately after the closing '}'. The returned string is empty
410 wxString
ExtractStringBetweenBraces(const char **pp
);
412 // the current file and line while we're in ParseTeXFile (for error
417 // functions and classes to ignore during diff
418 // -------------------------------------------
420 IgnoreNamesHandler m_ignoreNames
;
422 // information about all functions documented in the TeX file(s)
423 // -------------------------------------------------------------
425 public: // Note: Sun C++ 5.5 requires TypeInfo and ParamInfo to be public
427 // info about a type: for now stored as text string, but must be parsed
428 // further later (to know that "char *" == "char []" - TODO)
432 TypeInfo(const wxString
& type
) : m_type(type
) { }
434 bool operator==(const wxString
& type
) const { return m_type
== type
; }
435 bool operator!=(const wxString
& type
) const { return m_type
!= type
; }
437 const wxString
& GetName() const { return m_type
; }
443 friend class ParamInfo
; // for access to TypeInfo
445 // info abotu a function parameter
449 ParamInfo(const wxString
& type
,
450 const wxString
& name
,
451 const wxString
& value
)
452 : m_type(type
), m_name(name
), m_value(value
)
456 const TypeInfo
& GetType() const { return m_type
; }
457 const wxString
& GetName() const { return m_name
; }
458 const wxString
& GetDefValue() const { return m_value
; }
461 TypeInfo m_type
; // type of parameter
462 wxString m_name
; // name
463 wxString m_value
; // default value
466 public: // FIXME: macro requires it
467 WX_DEFINE_ARRAY_PTR(ParamInfo
*, ArrayParamInfo
);
469 // info about a function
482 MethodInfo(const wxString
& type
,
483 const wxString
& name
,
484 const ArrayParamInfo
& params
)
485 : m_typeRet(type
), m_name(name
), m_params(params
)
490 void SetFlag(MethodFlags flag
) { m_flags
|= flag
; }
492 const TypeInfo
& GetType() const { return m_typeRet
; }
493 const wxString
& GetName() const { return m_name
; }
494 const ParamInfo
& GetParam(size_t n
) const { return *(m_params
[n
]); }
495 size_t GetParamCount() const { return m_params
.GetCount(); }
497 bool HasFlag(MethodFlags flag
) const { return (m_flags
& flag
) != 0; }
499 ~MethodInfo() { WX_CLEAR_ARRAY(m_params
); }
502 TypeInfo m_typeRet
; // return type
504 int m_flags
; // bit mask of the value from the enum above
506 ArrayParamInfo m_params
;
509 WX_DEFINE_ARRAY_PTR(MethodInfo
*, ArrayMethodInfo
);
510 WX_DEFINE_ARRAY_PTR(ArrayMethodInfo
*, ArrayMethodInfos
);
513 // first array contains the names of all classes we found, the second has a
514 // pointer to the array of methods of the given class at the same index as
515 // the class name appears in m_classes
516 wxArrayString m_classes
;
517 ArrayMethodInfos m_methods
;
519 // are we checking parameter names?
520 bool m_checkParamNames
;
523 DocManager(const DocManager
&);
524 DocManager
& operator=(const DocManager
&);
527 // =============================================================================
529 // =============================================================================
531 static char **g_argv
= NULL
;
533 // this function never returns
536 wxString prog
= g_argv
[0];
537 wxString basename
= prog
.AfterLast('/');
540 basename
= prog
.AfterLast('\\');
546 "usage: %s [global options] <mode> [mode options] <files...>\n"
548 " where global options are:\n"
551 " -H give this usage message\n"
552 " -V print the version info\n"
553 " -i file file with classes/function to ignore\n"
555 " where mode is one of: dump, diff\n"
557 " dump means generate .tex files for TeX2RTF converter from specified\n"
558 " headers files, mode options are:\n"
559 " -f overwrite existing files\n"
560 " -o outdir directory for generated files\n"
562 " diff means compare the set of methods documented .tex file with the\n"
563 " methods declared in the header:\n"
564 " %s diff <file.h> <files.tex...>.\n"
565 " mode specific options are:\n"
566 " -p do check parameter names (not done by default)\n"
567 "\n", basename
.c_str(), basename
.c_str());
572 int main(int argc
, char **argv
)
576 wxInitializer initializer
;
579 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
595 wxArrayString filesH
, filesTeX
;
596 wxString directoryOut
, // directory for 'dmup' output
597 ignoreFile
; // file with classes/functions to ignore
598 bool overwrite
= false, // overwrite existing files during 'dump'?
599 paramNames
= false; // check param names during 'diff'?
601 for ( int current
= 1; current
< argc
; current
++ ) {
602 // all options have one letter
603 if ( argv
[current
][0] == '-' ) {
604 if ( argv
[current
][2] == '\0' ) {
605 switch ( argv
[current
][1] ) {
608 wxLog::GetActiveTarget()->SetVerbose();
613 wxLog::GetActiveTarget()->SetVerbose(false);
623 wxLogMessage("HelpGen version %s\n"
624 "(c) 1999-2001 Vadim Zeitlin\n",
625 GetVersionString().c_str());
630 if ( current
>= argc
) {
631 wxLogError("-i option requires an argument.");
636 ignoreFile
= argv
[current
];
640 if ( mode
!= Mode_Diff
) {
641 wxLogError("-p is only valid with diff.");
650 if ( mode
!= Mode_Dump
) {
651 wxLogError("-f is only valid with dump.");
660 if ( mode
!= Mode_Dump
) {
661 wxLogError("-o is only valid with dump.");
667 if ( current
>= argc
) {
668 wxLogError("-o option requires an argument.");
673 directoryOut
= argv
[current
];
674 if ( !directoryOut
.empty() ) {
675 // terminate with a '/' if it doesn't have it
676 switch ( directoryOut
.Last().GetValue() ) {
687 //else: it's empty, do nothing
692 wxLogError("unknown option '%s'", argv
[current
]);
697 wxLogError("only one letter options are allowed, not '%s'.",
701 // only get here after a break from switch or from else branch of if
706 if ( mode
== Mode_None
) {
707 if ( strcmp(argv
[current
], "diff") == 0 )
709 else if ( strcmp(argv
[current
], "dump") == 0 )
712 wxLogError("unknown mode '%s'.", argv
[current
]);
718 if ( mode
== Mode_Dump
|| filesH
.IsEmpty() ) {
719 filesH
.Add(argv
[current
]);
722 // 2nd files and further are TeX files in diff mode
723 wxASSERT( mode
== Mode_Diff
);
725 filesTeX
.Add(argv
[current
]);
731 // create a parser object and a visitor derivation
732 CJSourceParser parser
;
733 HelpGenVisitor
visitor(directoryOut
, overwrite
);
734 if ( !ignoreFile
.empty() && mode
== Mode_Dump
)
735 visitor
.GetIgnoreHandler().AddNamesFromFile(ignoreFile
);
737 spContext
*ctxTop
= NULL
;
739 // parse all header files
740 size_t nFiles
= filesH
.GetCount();
741 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
742 wxString header
= filesH
[n
];
743 ctxTop
= parser
.ParseFile(header
);
745 wxLogWarning("Header file '%s' couldn't be processed.",
748 else if ( mode
== Mode_Dump
) {
749 ((spFile
*)ctxTop
)->m_FileName
= header
;
750 visitor
.VisitAll(*ctxTop
);
756 ctxTop
->Dump(wxEmptyString
);
757 #endif // __WXDEBUG__
760 // parse all TeX files
761 if ( mode
== Mode_Diff
) {
763 wxLogError("Can't complete diff.");
769 DocManager
docman(paramNames
);
771 size_t nFiles
= filesTeX
.GetCount();
772 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
773 wxString file
= filesTeX
[n
];
774 if ( !docman
.ParseTeXFile(file
) ) {
775 wxLogWarning("TeX file '%s' couldn't be processed.",
780 if ( !ignoreFile
.empty() )
781 docman
.GetIgnoreHandler().AddNamesFromFile(ignoreFile
);
783 docman
.DumpDifferences(ctxTop
);
789 // -----------------------------------------------------------------------------
790 // HelpGenVisitor implementation
791 // -----------------------------------------------------------------------------
793 HelpGenVisitor::HelpGenVisitor(const wxString
& directoryOut
,
795 : m_directoryOut(directoryOut
)
797 m_overwrite
= overwrite
;
802 void HelpGenVisitor::Reset()
806 m_inMethodSection
= false;
811 m_textStoredTypedefs
=
812 m_textStoredFunctionComment
= wxEmptyString
;
814 m_arrayFuncDocs
.Empty();
816 m_storedEnums
.Empty();
817 m_storedEnumsVerb
.Empty();
821 void HelpGenVisitor::InsertTypedefDocs()
823 m_file
.WriteTeX(m_textStoredTypedefs
);
824 m_textStoredTypedefs
.Empty();
827 void HelpGenVisitor::InsertEnumDocs()
829 size_t count
= m_storedEnums
.GetCount();
830 for ( size_t n
= 0; n
< count
; n
++ )
832 m_file
.WriteTeX(m_storedEnums
[n
]);
833 m_file
.WriteVerbatim(m_storedEnumsVerb
[n
] + '\n');
836 m_storedEnums
.Empty();
837 m_storedEnumsVerb
.Empty();
840 void HelpGenVisitor::InsertDataStructuresHeader()
842 if ( !m_inTypesSection
) {
843 m_inTypesSection
= true;
845 m_file
.WriteVerbatim("\\wxheading{Data structures}\n\n");
849 void HelpGenVisitor::InsertMethodsHeader()
851 if ( !m_inMethodSection
) {
852 m_inMethodSection
= true;
854 m_file
.WriteVerbatim( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n");
858 void HelpGenVisitor::CloseFunction()
860 if ( !m_funcName
.empty() ) {
861 if ( m_isFirstParam
) {
863 m_textFunc
<< "\\void";
866 m_textFunc
<< "}\n\n";
868 if ( !m_textStoredFunctionComment
.empty() ) {
869 m_textFunc
<< m_textStoredFunctionComment
<< '\n';
872 m_arrayFuncDocs
.Add(new FunctionDocEntry(m_funcName
, m_textFunc
));
878 void HelpGenVisitor::CloseClass()
884 size_t count
= m_arrayFuncDocs
.GetCount();
888 FunctionDocEntry::classname
= m_classname
;
890 m_arrayFuncDocs
.Sort(FunctionDocEntry::Compare
);
892 // Now examine each first line and if it's been seen, cut it
893 // off (it's a duplicate \membersection)
894 wxHashTable
membersections(wxKEY_STRING
);
896 for ( n
= 0; n
< count
; n
++ )
898 wxString
section(m_arrayFuncDocs
[n
].text
);
900 // Strip leading whitespace
901 int pos
= section
.Find(_T("\\membersection"));
904 section
= section
.Mid(pos
);
907 wxString
ms(section
.BeforeFirst(wxT('\n')));
908 if (membersections
.Get(ms
))
910 m_arrayFuncDocs
[n
].text
= section
.AfterFirst(wxT('\n'));
914 membersections
.Put(ms
.c_str(), & membersections
);
918 for ( n
= 0; n
< count
; n
++ ) {
919 m_file
.WriteTeX(m_arrayFuncDocs
[n
].text
);
922 m_arrayFuncDocs
.Empty();
931 void HelpGenVisitor::EndVisit()
937 m_fileHeader
.Empty();
940 if (m_file
.IsOpened())
946 wxLogVerbose("%s: finished generating for the current file.",
947 GetCurrentTimeFormatted("%H:%M:%S"));
950 void HelpGenVisitor::VisitFile( spFile
& file
)
952 m_fileHeader
= file
.m_FileName
;
953 wxLogVerbose("%s: started generating docs for classes from file '%s'...",
954 GetCurrentTimeFormatted("%H:%M:%S"), m_fileHeader
.c_str());
957 void HelpGenVisitor::VisitClass( spClass
& cl
)
961 if (m_file
.IsOpened())
967 wxString name
= cl
.GetName();
969 if ( m_ignoreNames
.IgnoreClass(name
) ) {
970 wxLogVerbose("Skipping ignored class '%s'.", name
.c_str());
975 // the file name is built from the class name by removing the leading "wx"
976 // if any and converting it to the lower case
978 if ( name(0, 2) == "wx" ) {
979 filename
<< name
.c_str() + 2;
985 filename
.MakeLower();
987 filename
.Prepend(m_directoryOut
);
989 if ( !m_overwrite
&& wxFile::Exists(filename
) ) {
990 wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
996 m_inClass
= m_file
.Open(filename
, wxFile::write
);
998 wxLogError("Can't generate documentation for the class '%s'.",
1005 m_inTypesSection
= false;
1007 wxLogInfo("Created new file '%s' for class '%s'.",
1008 filename
.c_str(), name
.c_str());
1010 // write out the header
1012 header
.Printf("%%\n"
1013 "%% automatically generated by HelpGen %s from\n"
1018 "\\section{\\class{%s}}\\label{%s}\n\n",
1019 GetVersionString().c_str(),
1020 m_fileHeader
.c_str(),
1021 GetCurrentTimeFormatted("%d/%b/%y %H:%M:%S"),
1023 wxString(name
).MakeLower().c_str());
1025 m_file
.WriteVerbatim(header
);
1027 // the entire text we're writing to file
1030 // if the header includes other headers they must be related to it... try to
1031 // automatically generate the "See also" clause
1032 if ( !m_headers
.IsEmpty() ) {
1033 // correspondence between wxWidgets headers and class names
1034 static const char *headers
[] = {
1043 // NULL here means not to insert anything in "See also" for the
1044 // corresponding header
1045 static const char *classes
[] = {
1054 wxASSERT_MSG( WXSIZEOF(headers
) == WXSIZEOF(classes
),
1055 "arrays must be in sync!" );
1057 wxArrayInt interestingClasses
;
1059 size_t count
= m_headers
.Count(), index
;
1060 for ( size_t n
= 0; n
< count
; n
++ ) {
1061 wxString baseHeaderName
= m_headers
[n
].Before('.');
1062 if ( baseHeaderName(0, 3) != "wx/" )
1065 baseHeaderName
.erase(0, 3);
1066 for ( index
= 0; index
< WXSIZEOF(headers
); index
++ ) {
1067 if ( wxStricmp(baseHeaderName
, headers
[index
]) == 0 )
1071 if ( (index
< WXSIZEOF(headers
)) && classes
[index
] ) {
1072 // interesting header
1073 interestingClasses
.Add(index
);
1077 if ( !interestingClasses
.IsEmpty() ) {
1078 // do generate "See also" clause
1079 totalText
<< "\\wxheading{See also:}\n\n";
1081 count
= interestingClasses
.Count();
1082 for ( index
= 0; index
< count
; index
++ ) {
1086 totalText
<< MakeHelpref(classes
[interestingClasses
[index
]]);
1089 totalText
<< "\n\n";
1093 // the comment before the class generally explains what is it for so put it
1094 // in place of the class description
1095 if ( cl
.HasComments() ) {
1096 wxString comment
= GetAllComments(cl
);
1098 totalText
<< '\n' << comment
<< '\n';
1101 // derived from section
1102 wxString derived
= "\\wxheading{Derived from}\n\n";
1104 const StrListT
& baseClasses
= cl
.m_SuperClassNames
;
1105 if ( baseClasses
.size() == 0 ) {
1106 derived
<< "No base class";
1110 for ( StrListT::const_iterator i
= baseClasses
.begin();
1111 i
!= baseClasses
.end();
1114 // separate from the previous one
1115 derived
<< "\\\\\n";
1121 wxString baseclass
= *i
;
1122 derived
<< "\\helpref{" << baseclass
<< "}";
1123 derived
<< "{" << baseclass
.MakeLower() << "}";
1126 totalText
<< derived
<< "\n\n";
1128 // include file section
1129 wxString includeFile
= "\\wxheading{Include files}\n\n";
1130 includeFile
<< "<" << m_fileHeader
<< ">";
1132 totalText
<< includeFile
<< "\n\n";
1134 // write all this to file
1135 m_file
.WriteTeX(totalText
);
1137 // if there were any enums/typedefs before, insert their documentation now
1138 InsertDataStructuresHeader();
1139 InsertTypedefDocs();
1145 void HelpGenVisitor::VisitEnumeration( spEnumeration
& en
)
1149 if ( m_inMethodSection
) {
1150 // FIXME that's a bug, but tell the user aboit it nevertheless... we
1151 // should be smart enough to process even the enums which come after the
1153 wxLogWarning("enum '%s' ignored, please put it before the class "
1154 "methods.", en
.GetName().c_str());
1158 // simply copy the enum text in the docs
1159 wxString enumeration
= GetAllComments(en
),
1162 enumerationVerb
<< _T("\\begin{verbatim}\n")
1164 << _T("\n\\end{verbatim}\n");
1166 // remember for later use if we're not inside a class yet
1168 m_storedEnums
.Add(enumeration
);
1169 m_storedEnumsVerb
.Add(enumerationVerb
);
1172 // write the header for this section if not done yet
1173 InsertDataStructuresHeader();
1175 m_file
.WriteTeX(enumeration
);
1176 m_file
.WriteVerbatim(enumerationVerb
);
1177 m_file
.WriteVerbatim('\n');
1181 void HelpGenVisitor::VisitTypeDef( spTypeDef
& td
)
1185 if ( m_inMethodSection
) {
1186 // FIXME that's a bug, but tell the user aboit it nevertheless...
1187 wxLogWarning("typedef '%s' ignored, please put it before the class "
1188 "methods.", td
.GetName().c_str());
1192 wxString typedefdoc
;
1193 typedefdoc
<< _T("{\\small \\begin{verbatim}\n")
1194 << _T("typedef ") << td
.m_OriginalType
<< _T(' ') << td
.GetName()
1195 << _T("\n\\end{verbatim}}\n")
1196 << GetAllComments(td
);
1198 // remember for later use if we're not inside a class yet
1200 if ( !m_textStoredTypedefs
.empty() ) {
1201 m_textStoredTypedefs
<< '\n';
1204 m_textStoredTypedefs
<< typedefdoc
;
1207 // write the header for this section if not done yet
1208 InsertDataStructuresHeader();
1211 m_file
.WriteTeX(typedefdoc
);
1215 void HelpGenVisitor::VisitPreprocessorLine( spPreprocessorLine
& pd
)
1217 switch ( pd
.GetStatementType() ) {
1218 case SP_PREP_DEF_INCLUDE_FILE
:
1219 m_headers
.Add(pd
.CPP_GetIncludedFileNeme());
1222 case SP_PREP_DEF_DEFINE_SYMBOL
:
1223 // TODO decide if it's a constant and document it if it is
1228 void HelpGenVisitor::VisitAttribute( spAttribute
& attr
)
1232 // only document the public member variables
1233 if ( !m_inClass
|| !attr
.IsPublic() )
1236 wxLogWarning("Ignoring member variable '%s'.", attr
.GetName().c_str());
1239 void HelpGenVisitor::VisitOperation( spOperation
& op
)
1244 // we don't generate docs right now - either we ignore this class
1245 // entirely or we couldn't open the file
1249 if ( !op
.IsInClass() ) {
1250 // TODO document global functions
1251 wxLogWarning("skipped global function '%s'.", op
.GetName().c_str());
1256 if ( op
.mVisibility
== SP_VIS_PRIVATE
) {
1257 // FIXME should we document protected functions?
1261 m_classname
= op
.GetClass().GetName();
1262 wxString funcname
= op
.GetName();
1264 if ( m_ignoreNames
.IgnoreMethod(m_classname
, funcname
) ) {
1265 wxLogVerbose("Skipping ignored '%s::%s'.",
1266 m_classname
.c_str(), funcname
.c_str());
1271 InsertMethodsHeader();
1274 m_funcName
= funcname
;
1275 m_isFirstParam
= true;
1277 m_textStoredFunctionComment
= GetAllComments(op
);
1279 // start function documentation
1282 // check for the special case of dtor
1284 if ( (funcname
[0u] == '~') && (m_classname
== funcname
.c_str() + 1) ) {
1285 dtor
.Printf("\\destruct{%s}", m_classname
.c_str());
1289 m_textFunc
.Printf("\n"
1290 "\\membersection{%s::%s}\\label{%s}\n",
1291 m_classname
.c_str(), funcname
.c_str(),
1292 MakeLabel(m_classname
, funcname
).c_str());
1295 if(op
.mIsConstant
) constStr
= _T("const");
1297 wxString virtualStr
;
1298 if(op
.mIsVirtual
) virtualStr
= _T("virtual ");
1301 func
.Printf(_T("\n")
1302 _T("\\%sfunc{%s%s}{%s}{"),
1305 op
.m_RetType
.c_str(),
1310 void HelpGenVisitor::VisitParameter( spParameter
& param
)
1312 if ( m_funcName
.empty() )
1315 if ( m_isFirstParam
) {
1316 m_isFirstParam
= false;
1322 m_textFunc
<< "\\param{" << param
.m_Type
<< " }{" << param
.GetName();
1323 wxString defvalue
= param
.m_InitVal
;
1324 if ( !defvalue
.empty() ) {
1325 m_textFunc
<< " = " << defvalue
;
1331 // ---------------------------------------------------------------------------
1333 // ---------------------------------------------------------------------------
1335 DocManager::DocManager(bool checkParamNames
)
1337 m_checkParamNames
= checkParamNames
;
1340 size_t DocManager::TryMatch(const char *str
, const char *match
)
1342 size_t lenMatch
= 0;
1343 while ( str
[lenMatch
] == match
[lenMatch
] ) {
1346 if ( match
[lenMatch
] == '\0' )
1353 bool DocManager::SkipUntil(const char **pp
, char c
)
1355 const char *p
= *pp
;
1371 bool DocManager::SkipSpaceUntil(const char **pp
, char c
)
1373 const char *p
= *pp
;
1375 if ( !isspace(*p
) || *p
== '\0' )
1389 wxString
DocManager::ExtractStringBetweenBraces(const char **pp
)
1393 if ( !SkipSpaceUntil(pp
, '{') ) {
1394 wxLogWarning("file %s(%d): '{' expected after '\\param'",
1395 m_filename
.c_str(), (int)m_line
);
1399 const char *startParam
= ++*pp
; // skip '{'
1401 if ( !SkipUntil(pp
, '}') ) {
1402 wxLogWarning("file %s(%d): '}' expected after '\\param'",
1403 m_filename
.c_str(), (int)m_line
);
1406 result
= wxString(startParam
, (*pp
)++ - startParam
);
1413 bool DocManager::ParseTeXFile(const wxString
& filename
)
1415 m_filename
= filename
;
1417 wxFile
file(m_filename
, wxFile::read
);
1418 if ( !file
.IsOpened() )
1421 off_t len
= file
.Length();
1422 if ( len
== wxInvalidOffset
)
1425 char *buf
= new char[len
+ 1];
1428 if ( file
.Read(buf
, len
) == wxInvalidOffset
) {
1434 // reinit everything
1437 wxLogVerbose("%s: starting to parse doc file '%s'.",
1438 GetCurrentTimeFormatted("%H:%M:%S"), m_filename
.c_str());
1440 // the name of the class from the last "\membersection" command: we assume
1441 // that the following "\func" or "\constfunc" always documents a method of
1442 // this class (and it should always be like that in wxWidgets documentation)
1445 for ( const char *current
= buf
; current
- buf
< len
; current
++ ) {
1446 // FIXME parsing is awfully inefficient
1448 if ( *current
== '%' ) {
1449 // comment, skip until the end of line
1451 SkipUntil(¤t
, '\n');
1456 // all the command we're interested in start with '\\'
1457 while ( *current
!= '\\' && *current
!= '\0' ) {
1458 if ( *current
++ == '\n' )
1462 if ( *current
== '\0' ) {
1463 // no more TeX commands left
1467 current
++; // skip '\\'
1475 } foundCommand
= Nothing
;
1477 size_t lenMatch
= TryMatch(current
, "func");
1479 foundCommand
= Func
;
1482 lenMatch
= TryMatch(current
, "constfunc");
1484 foundCommand
= ConstFunc
;
1486 lenMatch
= TryMatch(current
, "membersection");
1489 foundCommand
= MemberSect
;
1493 if ( foundCommand
== Nothing
)
1496 current
+= lenMatch
;
1498 if ( !SkipSpaceUntil(¤t
, '{') ) {
1499 wxLogWarning("file %s(%d): '{' expected after \\func, "
1500 "\\constfunc or \\membersection.",
1501 m_filename
.c_str(), (int)m_line
);
1508 if ( foundCommand
== MemberSect
) {
1509 // what follows has the form <classname>::<funcname>
1510 const char *startClass
= current
;
1511 if ( !SkipUntil(¤t
, ':') || *(current
+ 1) != ':' ) {
1512 wxLogWarning("file %s(%d): '::' expected after "
1513 "\\membersection.", m_filename
.c_str(), (int)m_line
);
1516 classname
= wxString(startClass
, current
- startClass
);
1517 TeXUnfilter(&classname
);
1523 // extract the return type
1524 const char *startRetType
= current
;
1526 if ( !SkipUntil(¤t
, '}') ) {
1527 wxLogWarning("file %s(%d): '}' expected after return type",
1528 m_filename
.c_str(), (int)m_line
);
1533 wxString returnType
= wxString(startRetType
, current
- startRetType
);
1534 TeXUnfilter(&returnType
);
1537 if ( !SkipSpaceUntil(¤t
, '{') ) {
1538 wxLogWarning("file %s(%d): '{' expected after return type",
1539 m_filename
.c_str(), (int)m_line
);
1545 const char *funcEnd
= current
;
1546 if ( !SkipUntil(&funcEnd
, '}') ) {
1547 wxLogWarning("file %s(%d): '}' expected after function name",
1548 m_filename
.c_str(), (int)m_line
);
1553 wxString funcName
= wxString(current
, funcEnd
- current
);
1554 current
= funcEnd
+ 1;
1556 // trim spaces from both sides
1557 funcName
.Trim(false);
1558 funcName
.Trim(true);
1560 // special cases: '$...$' may be used for LaTeX inline math, remove the
1562 if ( funcName
.Find('$') != wxNOT_FOUND
) {
1564 for ( const char *p
= funcName
.c_str(); *p
!= '\0'; p
++ ) {
1565 if ( *p
!= '$' && !isspace(*p
) )
1572 // \destruct{foo} is really ~foo
1573 if ( funcName
[0u] == '\\' ) {
1574 size_t len
= strlen("\\destruct{");
1575 if ( funcName(0, len
) != "\\destruct{" ) {
1576 wxLogWarning("file %s(%d): \\destruct expected",
1577 m_filename
.c_str(), (int)m_line
);
1582 funcName
.erase(0, len
);
1583 funcName
.Prepend('~');
1585 if ( !SkipSpaceUntil(¤t
, '}') ) {
1586 wxLogWarning("file %s(%d): '}' expected after destructor",
1587 m_filename
.c_str(), (int)m_line
);
1592 funcEnd
++; // there is an extra '}' to count
1595 TeXUnfilter(&funcName
);
1598 current
= funcEnd
+ 1; // skip '}'
1599 if ( !SkipSpaceUntil(¤t
, '{') ||
1600 (current
++, !SkipSpaceUntil(¤t
, '\\')) ) {
1601 wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
1602 m_filename
.c_str(), (int)m_line
);
1607 wxArrayString paramNames
, paramTypes
, paramValues
;
1609 bool isVararg
= false;
1611 current
++; // skip '\\'
1612 lenMatch
= TryMatch(current
, "void");
1614 lenMatch
= TryMatch(current
, "param");
1615 while ( lenMatch
&& (current
- buf
< len
) ) {
1616 current
+= lenMatch
;
1618 // now come {paramtype}{paramname}
1619 wxString paramType
= ExtractStringBetweenBraces(¤t
);
1620 if ( !paramType
.empty() ) {
1621 wxString paramText
= ExtractStringBetweenBraces(¤t
);
1622 if ( !paramText
.empty() ) {
1623 // the param declaration may contain default value
1624 wxString paramName
= paramText
.BeforeFirst('='),
1625 paramValue
= paramText
.AfterFirst('=');
1627 // sanitize all strings
1628 TeXUnfilter(¶mValue
);
1629 TeXUnfilter(¶mName
);
1630 TeXUnfilter(¶mType
);
1632 paramValues
.Add(paramValue
);
1633 paramNames
.Add(paramName
);
1634 paramTypes
.Add(paramType
);
1639 wxString paramText
= ExtractStringBetweenBraces(¤t
);
1640 if ( paramText
== "..." ) {
1644 wxLogWarning("Parameters of '%s::%s' are in "
1646 classname
.c_str(), funcName
.c_str());
1651 current
= SkipSpaces(current
);
1652 if ( *current
== ',' || *current
== '}' ) {
1653 current
= SkipSpaces(++current
);
1655 lenMatch
= TryMatch(current
, "\\param");
1658 wxLogWarning("file %s(%d): ',' or '}' expected after "
1659 "'\\param'", m_filename
.c_str(), (int)m_line
);
1665 // if we got here there was no '\\void', so must have some params
1666 if ( paramNames
.IsEmpty() ) {
1667 wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
1668 m_filename
.c_str(), (int)m_line
);
1674 // verbose diagnostic output
1676 size_t param
, paramCount
= paramNames
.GetCount();
1677 for ( param
= 0; param
< paramCount
; param
++ ) {
1682 paramsAll
<< paramTypes
[param
] << ' ' << paramNames
[param
];
1686 if (foundCommand
== ConstFunc
)
1687 constStr
= _T(" const");
1689 wxLogVerbose("file %s(%d): found '%s %s::%s(%s)%s'",
1698 // store the info about the just found function
1699 ArrayMethodInfo
*methods
;
1700 int index
= m_classes
.Index(classname
);
1701 if ( index
== wxNOT_FOUND
) {
1702 m_classes
.Add(classname
);
1704 methods
= new ArrayMethodInfo
;
1705 m_methods
.Add(methods
);
1708 methods
= m_methods
[(size_t)index
];
1711 ArrayParamInfo params
;
1712 for ( param
= 0; param
< paramCount
; param
++ ) {
1713 params
.Add(new ParamInfo(paramTypes
[param
],
1715 paramValues
[param
]));
1718 MethodInfo
*method
= new MethodInfo(returnType
, funcName
, params
);
1719 if ( foundCommand
== ConstFunc
)
1720 method
->SetFlag(MethodInfo::Const
);
1722 method
->SetFlag(MethodInfo::Vararg
);
1724 methods
->Add(method
);
1729 wxLogVerbose("%s: finished parsing doc file '%s'.\n",
1730 GetCurrentTimeFormatted("%H:%M:%S"), m_filename
.c_str());
1735 bool DocManager::DumpDifferences(spContext
*ctxTop
) const
1737 typedef MMemberListT::const_iterator MemberIndex
;
1739 bool foundDiff
= false;
1741 // flag telling us whether the given class was found at all in the header
1742 size_t nClass
, countClassesInDocs
= m_classes
.GetCount();
1743 bool *classExists
= new bool[countClassesInDocs
];
1744 for ( nClass
= 0; nClass
< countClassesInDocs
; nClass
++ ) {
1745 classExists
[nClass
] = false;
1748 // ctxTop is normally an spFile
1749 wxASSERT( ctxTop
->GetContextType() == SP_CTX_FILE
);
1751 const MMemberListT
& classes
= ctxTop
->GetMembers();
1752 for ( MemberIndex i
= classes
.begin(); i
!= classes
.end(); i
++ ) {
1753 spContext
*ctx
= *i
;
1754 if ( ctx
->GetContextType() != SP_CTX_CLASS
) {
1755 // TODO process also global functions, macros, ...
1759 spClass
*ctxClass
= (spClass
*)ctx
;
1760 const wxString
& nameClass
= ctxClass
->m_Name
;
1761 int index
= m_classes
.Index(nameClass
);
1762 if ( index
== wxNOT_FOUND
) {
1763 if ( !m_ignoreNames
.IgnoreClass(nameClass
) ) {
1766 wxLogError("Class '%s' is not documented at all.",
1770 // it makes no sense to check for its functions
1774 classExists
[index
] = true;
1777 // array of method descriptions for this class
1778 const ArrayMethodInfo
& methods
= *(m_methods
[index
]);
1779 size_t nMethod
, countMethods
= methods
.GetCount();
1781 // flags telling if we already processed given function
1782 bool *methodExists
= new bool[countMethods
];
1783 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1784 methodExists
[nMethod
] = false;
1787 wxArrayString aOverloadedMethods
;
1789 const MMemberListT
& functions
= ctxClass
->GetMembers();
1790 for ( MemberIndex j
= functions
.begin(); j
!= functions
.end(); j
++ ) {
1792 if ( ctx
->GetContextType() != SP_CTX_OPERATION
)
1795 spOperation
*ctxMethod
= (spOperation
*)ctx
;
1796 const wxString
& nameMethod
= ctxMethod
->m_Name
;
1798 // find all functions with the same name
1799 wxArrayInt aMethodsWithSameName
;
1800 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1801 if ( methods
[nMethod
]->GetName() == nameMethod
)
1802 aMethodsWithSameName
.Add(nMethod
);
1805 if ( aMethodsWithSameName
.IsEmpty() && ctxMethod
->IsPublic() ) {
1806 if ( !m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) ) {
1809 wxLogError("'%s::%s' is not documented.",
1811 nameMethod
.c_str());
1814 // don't check params
1817 else if ( aMethodsWithSameName
.GetCount() == 1 ) {
1818 index
= (size_t)aMethodsWithSameName
[0u];
1819 methodExists
[index
] = true;
1821 if ( m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) )
1824 if ( !ctxMethod
->IsPublic() ) {
1825 wxLogWarning("'%s::%s' is documented but not public.",
1827 nameMethod
.c_str());
1830 // check that the flags match
1831 const MethodInfo
& method
= *(methods
[index
]);
1833 bool isVirtual
= ctxMethod
->mIsVirtual
;
1834 if ( isVirtual
!= method
.HasFlag(MethodInfo::Virtual
) )
1836 wxString virtualStr
;
1837 if(isVirtual
)virtualStr
= _T("not ");
1839 wxLogWarning("'%s::%s' is incorrectly documented as %s"
1843 virtualStr
.c_str());
1846 bool isConst
= ctxMethod
->mIsConstant
;
1847 if ( isConst
!= method
.HasFlag(MethodInfo::Const
) )
1850 if(isConst
)constStr
= _T("not ");
1852 wxLogWarning("'%s::%s' is incorrectly documented as %s"
1859 // check that the params match
1860 const MMemberListT
& params
= ctxMethod
->GetMembers();
1862 if ( params
.size() != method
.GetParamCount() ) {
1863 wxLogError("Incorrect number of parameters for '%s::%s' "
1864 "in the docs: should be %d instead of %d.",
1867 (int)params
.size(), (int)method
.GetParamCount());
1871 for ( MemberIndex k
= params
.begin();
1876 // what else can a function have?
1877 wxASSERT( ctx
->GetContextType() == SP_CTX_PARAMETER
);
1879 spParameter
*ctxParam
= (spParameter
*)ctx
;
1880 const ParamInfo
& param
= method
.GetParam(nParam
);
1881 if ( m_checkParamNames
&&
1882 (param
.GetName() != ctxParam
->m_Name
.c_str()) ) {
1885 wxLogError("Parameter #%d of '%s::%s' should be "
1886 "'%s' and not '%s'.",
1890 ctxParam
->m_Name
.c_str(),
1891 param
.GetName().c_str());
1896 if ( param
.GetType() != ctxParam
->m_Type
) {
1899 wxLogError("Type of parameter '%s' of '%s::%s' "
1900 "should be '%s' and not '%s'.",
1901 ctxParam
->m_Name
.c_str(),
1904 ctxParam
->m_Type
.c_str(),
1905 param
.GetType().GetName().c_str());
1910 if ( param
.GetDefValue() != ctxParam
->m_InitVal
.c_str() ) {
1911 wxLogWarning("Default value of parameter '%s' of "
1912 "'%s::%s' should be '%s' and not "
1914 ctxParam
->m_Name
.c_str(),
1917 ctxParam
->m_InitVal
.c_str(),
1918 param
.GetDefValue().c_str());
1924 // TODO OVER add real support for overloaded methods
1926 if ( m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) )
1929 if ( aOverloadedMethods
.Index(nameMethod
) == wxNOT_FOUND
) {
1930 // mark all methods with this name as existing
1931 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1932 if ( methods
[nMethod
]->GetName() == nameMethod
)
1933 methodExists
[nMethod
] = true;
1936 aOverloadedMethods
.Add(nameMethod
);
1938 wxLogVerbose("'%s::%s' is overloaded and I'm too "
1939 "stupid to find the right match - skipping "
1940 "the param and flags checks.",
1942 nameMethod
.c_str());
1944 //else: warning already given
1948 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1949 if ( !methodExists
[nMethod
] ) {
1950 const wxString
& nameMethod
= methods
[nMethod
]->GetName();
1951 if ( !m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) ) {
1954 wxLogError("'%s::%s' is documented but doesn't exist.",
1956 nameMethod
.c_str());
1961 delete [] methodExists
;
1964 // check that all classes we found in the docs really exist
1965 for ( nClass
= 0; nClass
< countClassesInDocs
; nClass
++ ) {
1966 if ( !classExists
[nClass
] ) {
1969 wxLogError("Class '%s' is documented but doesn't exist.",
1970 m_classes
[nClass
].c_str());
1974 delete [] classExists
;
1979 DocManager::~DocManager()
1981 WX_CLEAR_ARRAY(m_methods
);
1984 // ---------------------------------------------------------------------------
1985 // IgnoreNamesHandler implementation
1986 // ---------------------------------------------------------------------------
1988 int IgnoreNamesHandler::CompareIgnoreListEntries(IgnoreListEntry
*first
,
1989 IgnoreListEntry
*second
)
1991 // first compare the classes
1992 int rc
= first
->m_classname
.Cmp(second
->m_classname
);
1994 rc
= first
->m_funcname
.Cmp(second
->m_funcname
);
1999 bool IgnoreNamesHandler::AddNamesFromFile(const wxString
& filename
)
2001 wxFile
file(filename
, wxFile::read
);
2002 if ( !file
.IsOpened() )
2005 off_t len
= file
.Length();
2006 if ( len
== wxInvalidOffset
)
2009 char *buf
= new char[len
+ 1];
2012 if ( file
.Read(buf
, len
) == wxInvalidOffset
) {
2019 for ( const char *current
= buf
; ; current
++ ) {
2021 // skip DOS line separator
2022 if ( *current
== '\r' )
2026 if ( *current
== '\n' || *current
== '\0' ) {
2027 if ( line
[0u] != '#' ) {
2028 if ( line
.Find(':') != wxNOT_FOUND
) {
2029 wxString classname
= line
.BeforeFirst(':'),
2030 funcname
= line
.AfterLast(':');
2031 m_ignore
.Add(new IgnoreListEntry(classname
, funcname
));
2035 m_ignore
.Add(new IgnoreListEntry(line
, wxEmptyString
));
2040 if ( *current
== '\0' )
2055 // -----------------------------------------------------------------------------
2056 // global function implementation
2057 // -----------------------------------------------------------------------------
2059 static wxString
MakeLabel(const char *classname
, const char *funcname
)
2061 wxString
label(classname
);
2062 if ( funcname
&& funcname
[0] == '\\' ) {
2063 // we may have some special TeX macro - so far only \destruct exists,
2064 // but may be later others will be added
2065 static const char *macros
[] = { "destruct" };
2066 static const char *replacement
[] = { "dtor" };
2069 for ( n
= 0; n
< WXSIZEOF(macros
); n
++ ) {
2070 if ( strncmp(funcname
+ 1, macros
[n
], strlen(macros
[n
])) == 0 ) {
2076 if ( n
== WXSIZEOF(macros
) ) {
2077 wxLogWarning("unknown function name '%s' - leaving as is.",
2081 funcname
= replacement
[n
];
2086 // special treatment for operatorXXX() stuff because the C operators
2087 // are not valid in LaTeX labels
2089 if ( wxString(funcname
).StartsWith("operator", &oper
) ) {
2090 label
<< "operator";
2103 for ( n
= 0; n
< WXSIZEOF(operatorNames
); n
++ ) {
2104 if ( oper
== operatorNames
[n
].oper
) {
2105 label
<< operatorNames
[n
].name
;
2111 if ( n
== WXSIZEOF(operatorNames
) ) {
2112 wxLogWarning("unknown operator '%s' - making dummy label.",
2118 else // simply use the func name
2129 static wxString
MakeHelpref(const char *argument
)
2132 helpref
<< "\\helpref{" << argument
<< "}{" << MakeLabel(argument
) << '}';
2137 static void TeXFilter(wxString
* str
)
2139 // TeX special which can be quoted (don't include backslash nor braces as
2141 static wxRegEx
reNonSpecialSpecials("[#$%&_]"),
2145 reNonSpecialSpecials
.ReplaceAll(str
, "\\\\\\0");
2147 // can't quote these ones as they produce accents when preceded by
2148 // backslash, so put them inside verb
2149 reAccents
.ReplaceAll(str
, "\\\\verb|\\0|");
2152 static void TeXUnfilter(wxString
* str
)
2154 // FIXME may be done much more quickly
2159 static wxRegEx
reNonSpecialSpecials("\\\\([#$%&_{}])"),
2160 reAccents("\\\\verb\\|([~^])\\|");
2162 reNonSpecialSpecials
.ReplaceAll(str
, "\\1");
2163 reAccents
.ReplaceAll(str
, "\\1");
2166 static wxString
GetAllComments(const spContext
& ctx
)
2169 const MCommentListT
& commentsList
= ctx
.GetCommentList();
2170 for ( MCommentListT::const_iterator i
= commentsList
.begin();
2171 i
!= commentsList
.end();
2173 wxString comment
= (*i
)->GetText();
2175 // don't take comments like "// ----------" &c
2176 comment
.Trim(false);
2177 if ( !comment
.empty() &&
2178 comment
== wxString(comment
[0u], comment
.length() - 1) + '\n' )
2181 comments
<< comment
;
2187 static const char *GetCurrentTimeFormatted(const char *timeFormat
)
2189 static char s_timeBuffer
[128];
2194 ptmNow
= localtime(&timeNow
);
2196 strftime(s_timeBuffer
, WXSIZEOF(s_timeBuffer
), timeFormat
, ptmNow
);
2198 return s_timeBuffer
;
2201 static const wxString
GetVersionString()
2203 wxString version
= "$Revision$";
2204 wxRegEx("^\\$Revision$$").ReplaceFirst(&version
, "\\1");
2210 Revision 1.45 2007/05/25 20:29:14 VS
2211 compilation fix: can't use wxUniCharRef in switch statement
2213 Revision 1.44 2005/05/31 17:47:45 ABX
2214 More warning and error fixes (work in progress with Tinderbox).
2216 Revision 1.43 2005/05/31 15:42:43 ABX
2217 More warning and error fixes (work in progress with Tinderbox).
2219 Revision 1.42 2005/05/31 15:32:49 ABX
2220 More warning and error fixes (work in progress with Tinderbox).
2222 Revision 1.41 2005/05/30 13:06:15 ABX
2223 More warning and error fixes (work in progress with Tinderbox).
2225 Revision 1.40 2005/05/30 11:49:32 ABX
2226 More warning and error fixes (work in progress with Tinderbox).
2228 Revision 1.39 2005/05/30 09:26:42 ABX
2229 More warning and error fixes (work in progress with Tinderbox).
2231 Revision 1.38 2005/05/24 09:06:20 ABX
2232 More fixes and wxWidgets coding standards.
2234 Revision 1.37 2005/05/23 15:22:08 ABX
2235 Initial HelpGen source cleaning.
2237 Revision 1.36 2005/04/07 19:54:58 MW
2238 Workarounds to allow compilation by Sun C++ 5.5
2240 Revision 1.35 2004/12/12 11:03:31 VZ
2241 give an error message if we're built in Unicode mode (in response to bug 1079224)
2243 Revision 1.34 2004/11/23 09:53:31 JS
2244 Changed GPL to wxWindows Licence
2246 Revision 1.33 2004/11/12 03:30:07 RL
2248 Cruft cleanup from MJW, strip the tabs out of sound.cpp
2250 Revision 1.32 2004/11/10 21:02:58 VZ
2251 new set of fixes for problems due to huge files support: drop wxFileSize_t, use wxFileOffset only, make wxInvalidOffset an int (main part of the patch 1063498)
2253 Revision 1.31 2004/10/05 15:38:29 ABX
2254 Warning fixes found under hardest mode of OpenWatcom. Seems clean in Borland, MinGW and DMC.
2256 Revision 1.30 2004/06/18 19:25:50 ABX
2257 Small step in making HelpGen up to date unicode application.
2259 Revision 1.29 2004/06/17 19:00:22 ABX
2260 Warning fixes. Code cleanup. Whitespaces and tabs removed.
2262 Revision 1.28 2004/05/25 11:19:57 JS
2265 Revision 1.27 2003/10/13 17:21:30 MBN
2268 Revision 1.26 2003/09/29 15:18:35 MBN
2269 (Blind) compilation fix for Sun compiler.
2271 Revision 1.25 2003/09/03 17:39:27 MBN
2274 Revision 1.24 2003/08/13 22:59:37 VZ
2277 Revision 1.23 2003/06/13 17:05:43 VZ
2278 quote '|' inside regexes (fixes dump mode); fixed crash due to strange HelpGenApp code
2280 Revision 1.22 2002/01/21 21:18:50 JS
2281 Now adds 'include file' heading
2283 Revision 1.21 2002/01/04 11:06:09 JS
2284 Fixed missing membersections bug and also bug with functions not being written
2287 Revision 1.20 2002/01/03 14:23:33 JS
2288 Added code to make it not duplicate membersections for overloaded functions
2290 Revision 1.19 2002/01/03 13:34:12 JS
2291 Added FlushAll to CloseClass, otherwise text was only flushed right at the end,
2292 and appeared in one file.
2294 Revision 1.18 2002/01/03 12:02:47 JS
2295 Added main() and corrected VC++ project settings
2297 Revision 1.17 2001/11/30 21:43:35 VZ
2298 now the methods are sorted in the correct order in the generated docs
2300 Revision 1.16 2001/11/28 19:27:33 VZ
2301 HelpGen doesn't work in GUI mode
2303 Revision 1.15 2001/11/22 21:59:58 GD
2304 use "..." instead of <...> for wx headers
2306 Revision 1.14 2001/07/19 13:51:29 VZ
2307 fixes to version string
2309 Revision 1.13 2001/07/19 13:44:57 VZ
2310 1. compilation fixes
2311 2. don't quote special characters inside verbatim environment
2313 Revision 1.12 2000/10/09 13:53:33 juliansmart
2315 Doc corrections; added HelpGen project files
2317 Revision 1.11 2000/07/15 19:50:42 cvsuser
2320 Revision 1.10.2.2 2000/03/27 15:33:10 VZ
2321 don't trasnform output dir name to lower case
2323 Revision 1.10 2000/03/11 10:05:23 VS
2324 now compiles with wxBase
2326 Revision 1.9 2000/01/16 13:25:21 VS
2327 compilation fixes (gcc)
2329 Revision 1.8 1999/09/13 14:29:39 JS
2331 Made HelpGen into a wxWin app (still uses command-line args); moved includes
2332 into src for simplicity; added VC++ 5 project file
2334 Revision 1.7 1999/02/21 22:32:32 VZ
2335 1. more C++ parser fixes - now it almost parses wx/string.h
2336 a) #if/#ifdef/#else (very) limited support
2337 b) param type fix - now indirection chars are correctly handled
2338 c) class/struct/union distinction
2339 d) public/private fixes
2340 e) Dump() function added - very useful for debugging
2342 2. option to ignore parameter names during 'diff' (in fact, they're ignored
2343 by default, and this option switches it on)
2345 Revision 1.6 1999/02/20 23:00:26 VZ
2346 1. new 'diff' mode which seems to work
2347 2. output files are not overwritten in 'dmup' mode
2348 3. fixes for better handling of const functions and operators
2349 ----------------------------
2351 date: 1999/02/15 23:07:25; author: VZ; state: Exp; lines: +106 -45
2352 1. Parser improvements
2353 a) const and virtual methods are parsed correctly (not static yet)
2354 b) "const" which is part of the return type is not swallowed
2356 2. HelpGen improvements: -o outputdir parameter added to the cmd line,
2357 "//---------" kind comments discarded now.
2358 ----------------------------
2360 date: 1999/01/13 14:23:31; author: JS; state: Exp; lines: +4 -4
2362 some tweaks to HelpGen
2363 ----------------------------
2365 date: 1999/01/09 20:18:03; author: JS; state: Exp; lines: +7 -2
2367 HelpGen starting to compile with VC++
2368 ----------------------------
2370 date: 1999/01/08 19:46:22; author: VZ; state: Exp; lines: +208 -35
2372 supports typedefs, generates "See also:" and adds "virtual " for virtual
2374 ----------------------------
2376 date: 1999/01/08 17:45:55; author: VZ; state: Exp;
2378 HelpGen is a prototype of the tool for automatic generation of the .tex files
2379 for wxWidgets documentation from C++ headers
2382 /* vi: set tw=80 et ts=4 sw=4: */