1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Main program file for HelpGen
4 // Author: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Copyright: (c) 1999 VZ
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 wxChar
*classname
, const wxChar
*funcname
= NULL
);
83 // return the whole \helpref{arg}{arg_label} string
84 static wxString
MakeHelpref(const wxChar
*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
, _T(""));
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 wxChar
*str
, const wxChar
*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 // info about a type: for now stored as text string, but must be parsed
426 // further later (to know that "char *" == "char []" - TODO)
430 TypeInfo(const wxString
& type
) : m_type(type
) { }
432 bool operator==(const wxString
& type
) const { return m_type
== type
; }
433 bool operator!=(const wxString
& type
) const { return m_type
!= type
; }
435 const wxString
& GetName() const { return m_type
; }
441 friend class ParamInfo
; // for access to TypeInfo
443 // info abotu a function parameter
447 ParamInfo(const wxString
& type
,
448 const wxString
& name
,
449 const wxString
& value
)
450 : m_type(type
), m_name(name
), m_value(value
)
454 const TypeInfo
& GetType() const { return m_type
; }
455 const wxString
& GetName() const { return m_name
; }
456 const wxString
& GetDefValue() const { return m_value
; }
459 TypeInfo m_type
; // type of parameter
460 wxString m_name
; // name
461 wxString m_value
; // default value
464 public: // FIXME: macro requires it
465 WX_DEFINE_ARRAY_PTR(ParamInfo
*, ArrayParamInfo
);
467 // info about a function
480 MethodInfo(const wxString
& type
,
481 const wxString
& name
,
482 const ArrayParamInfo
& params
)
483 : m_typeRet(type
), m_name(name
), m_params(params
)
488 void SetFlag(MethodFlags flag
) { m_flags
|= flag
; }
490 const TypeInfo
& GetType() const { return m_typeRet
; }
491 const wxString
& GetName() const { return m_name
; }
492 const ParamInfo
& GetParam(size_t n
) const { return *(m_params
[n
]); }
493 size_t GetParamCount() const { return m_params
.GetCount(); }
495 bool HasFlag(MethodFlags flag
) const { return (m_flags
& flag
) != 0; }
497 ~MethodInfo() { WX_CLEAR_ARRAY(m_params
); }
500 TypeInfo m_typeRet
; // return type
502 int m_flags
; // bit mask of the value from the enum above
504 ArrayParamInfo m_params
;
507 WX_DEFINE_ARRAY_PTR(MethodInfo
*, ArrayMethodInfo
);
508 WX_DEFINE_ARRAY_PTR(ArrayMethodInfo
*, ArrayMethodInfos
);
511 // first array contains the names of all classes we found, the second has a
512 // pointer to the array of methods of the given class at the same index as
513 // the class name appears in m_classes
514 wxArrayString m_classes
;
515 ArrayMethodInfos m_methods
;
517 // are we checking parameter names?
518 bool m_checkParamNames
;
521 DocManager(const DocManager
&);
522 DocManager
& operator=(const DocManager
&);
525 // =============================================================================
527 // =============================================================================
529 static char **g_argv
= NULL
;
531 // this function never returns
534 wxString prog
= g_argv
[0];
535 wxString basename
= prog
.AfterLast('/');
538 basename
= prog
.AfterLast('\\');
544 "usage: %s [global options] <mode> [mode options] <files...>\n"
546 " where global options are:\n"
549 " -H give this usage message\n"
550 " -V print the version info\n"
551 " -i file file with classes/function to ignore\n"
553 " where mode is one of: dump, diff\n"
555 " dump means generate .tex files for TeX2RTF converter from specified\n"
556 " headers files, mode options are:\n"
557 " -f overwrite existing files\n"
558 " -o outdir directory for generated files\n"
560 " diff means compare the set of methods documented .tex file with the\n"
561 " methods declared in the header:\n"
562 " %s diff <file.h> <files.tex...>.\n"
563 " mode specific options are:\n"
564 " -p do check parameter names (not done by default)\n"
565 "\n", basename
.c_str(), basename
.c_str());
570 int main(int argc
, char **argv
)
574 wxInitializer initializer
;
577 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
593 wxArrayString filesH
, filesTeX
;
594 wxString directoryOut
, // directory for 'dmup' output
595 ignoreFile
; // file with classes/functions to ignore
596 bool overwrite
= false, // overwrite existing files during 'dump'?
597 paramNames
= false; // check param names during 'diff'?
599 for ( int current
= 1; current
< argc
; current
++ ) {
600 // all options have one letter
601 if ( argv
[current
][0] == '-' ) {
602 if ( argv
[current
][2] == '\0' ) {
603 switch ( argv
[current
][1] ) {
606 wxLog::GetActiveTarget()->SetVerbose();
611 wxLog::GetActiveTarget()->SetVerbose(false);
621 wxLogMessage("HelpGen version %s\n"
622 "(c) 1999-2001 Vadim Zeitlin\n",
623 GetVersionString().c_str());
628 if ( current
>= argc
) {
629 wxLogError("-i option requires an argument.");
634 ignoreFile
= argv
[current
];
638 if ( mode
!= Mode_Diff
) {
639 wxLogError("-p is only valid with diff.");
648 if ( mode
!= Mode_Dump
) {
649 wxLogError("-f is only valid with dump.");
658 if ( mode
!= Mode_Dump
) {
659 wxLogError("-o is only valid with dump.");
665 if ( current
>= argc
) {
666 wxLogError("-o option requires an argument.");
671 directoryOut
= argv
[current
];
672 if ( !!directoryOut
) {
673 // terminate with a '/' if it doesn't have it
674 switch ( directoryOut
.Last() ) {
685 //else: it's empty, do nothing
690 wxLogError("unknown option '%s'", argv
[current
]);
695 wxLogError("only one letter options are allowed, not '%s'.",
699 // only get here after a break from switch or from else branch of if
704 if ( mode
== Mode_None
) {
705 if ( strcmp(argv
[current
], "diff") == 0 )
707 else if ( strcmp(argv
[current
], "dump") == 0 )
710 wxLogError("unknown mode '%s'.", argv
[current
]);
716 if ( mode
== Mode_Dump
|| filesH
.IsEmpty() ) {
717 filesH
.Add(argv
[current
]);
720 // 2nd files and further are TeX files in diff mode
721 wxASSERT( mode
== Mode_Diff
);
723 filesTeX
.Add(argv
[current
]);
729 // create a parser object and a visitor derivation
730 CJSourceParser parser
;
731 HelpGenVisitor
visitor(directoryOut
, overwrite
);
732 if ( !!ignoreFile
&& mode
== Mode_Dump
)
733 visitor
.GetIgnoreHandler().AddNamesFromFile(ignoreFile
);
735 spContext
*ctxTop
= NULL
;
737 // parse all header files
738 size_t nFiles
= filesH
.GetCount();
739 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
740 wxString header
= filesH
[n
];
741 ctxTop
= parser
.ParseFile(header
);
743 wxLogWarning("Header file '%s' couldn't be processed.",
746 else if ( mode
== Mode_Dump
) {
747 ((spFile
*)ctxTop
)->mFileName
= header
;
748 visitor
.VisitAll(*ctxTop
);
755 #endif // __WXDEBUG__
758 // parse all TeX files
759 if ( mode
== Mode_Diff
) {
761 wxLogError("Can't complete diff.");
767 DocManager
docman(paramNames
);
769 size_t nFiles
= filesTeX
.GetCount();
770 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
771 wxString file
= filesTeX
[n
];
772 if ( !docman
.ParseTeXFile(file
) ) {
773 wxLogWarning("TeX file '%s' couldn't be processed.",
779 docman
.GetIgnoreHandler().AddNamesFromFile(ignoreFile
);
781 docman
.DumpDifferences(ctxTop
);
787 // -----------------------------------------------------------------------------
788 // HelpGenVisitor implementation
789 // -----------------------------------------------------------------------------
791 HelpGenVisitor::HelpGenVisitor(const wxString
& directoryOut
,
793 : m_directoryOut(directoryOut
)
795 m_overwrite
= overwrite
;
800 void HelpGenVisitor::Reset()
804 m_inMethodSection
= false;
809 m_textStoredTypedefs
=
810 m_textStoredFunctionComment
= "";
812 m_arrayFuncDocs
.Empty();
814 m_storedEnums
.Empty();
815 m_storedEnumsVerb
.Empty();
819 void HelpGenVisitor::InsertTypedefDocs()
821 m_file
.WriteTeX(m_textStoredTypedefs
);
822 m_textStoredTypedefs
.Empty();
825 void HelpGenVisitor::InsertEnumDocs()
827 size_t count
= m_storedEnums
.GetCount();
828 for ( size_t n
= 0; n
< count
; n
++ )
830 m_file
.WriteTeX(m_storedEnums
[n
]);
831 m_file
.WriteVerbatim(m_storedEnumsVerb
[n
] + '\n');
834 m_storedEnums
.Empty();
835 m_storedEnumsVerb
.Empty();
838 void HelpGenVisitor::InsertDataStructuresHeader()
840 if ( !m_inTypesSection
) {
841 m_inTypesSection
= true;
843 m_file
.WriteVerbatim("\\wxheading{Data structures}\n\n");
847 void HelpGenVisitor::InsertMethodsHeader()
849 if ( !m_inMethodSection
) {
850 m_inMethodSection
= true;
852 m_file
.WriteVerbatim( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n");
856 void HelpGenVisitor::CloseFunction()
858 if ( !m_funcName
.empty() ) {
859 if ( m_isFirstParam
) {
861 m_textFunc
<< "\\void";
864 m_textFunc
<< "}\n\n";
866 if ( !m_textStoredFunctionComment
.IsEmpty() ) {
867 m_textFunc
<< m_textStoredFunctionComment
<< '\n';
870 m_arrayFuncDocs
.Add(new FunctionDocEntry(m_funcName
, m_textFunc
));
876 void HelpGenVisitor::CloseClass()
882 size_t count
= m_arrayFuncDocs
.GetCount();
886 FunctionDocEntry::classname
= m_classname
;
888 m_arrayFuncDocs
.Sort(FunctionDocEntry::Compare
);
890 // Now examine each first line and if it's been seen, cut it
891 // off (it's a duplicate \membersection)
892 wxHashTable
membersections(wxKEY_STRING
);
894 for ( n
= 0; n
< count
; n
++ )
896 wxString
section(m_arrayFuncDocs
[n
].text
);
898 // Strip leading whitespace
899 int pos
= section
.Find("\\membersection");
902 section
= section
.Mid(pos
);
905 wxString
ms(section
.BeforeFirst(wxT('\n')));
906 if (membersections
.Get(ms
))
908 m_arrayFuncDocs
[n
].text
= section
.AfterFirst(wxT('\n'));
912 membersections
.Put(ms
, & membersections
);
916 for ( n
= 0; n
< count
; n
++ ) {
917 m_file
.WriteTeX(m_arrayFuncDocs
[n
].text
);
920 m_arrayFuncDocs
.Empty();
929 void HelpGenVisitor::EndVisit()
935 m_fileHeader
.Empty();
938 if (m_file
.IsOpened())
944 wxLogVerbose("%s: finished generating for the current file.",
945 GetCurrentTimeFormatted("%H:%M:%S"));
948 void HelpGenVisitor::VisitFile( spFile
& file
)
950 m_fileHeader
= file
.mFileName
;
951 wxLogVerbose("%s: started generating docs for classes from file '%s'...",
952 GetCurrentTimeFormatted("%H:%M:%S"), m_fileHeader
.c_str());
955 void HelpGenVisitor::VisitClass( spClass
& cl
)
959 if (m_file
.IsOpened())
965 wxString name
= cl
.GetName();
967 if ( m_ignoreNames
.IgnoreClass(name
) ) {
968 wxLogVerbose("Skipping ignored class '%s'.", name
.c_str());
973 // the file name is built from the class name by removing the leading "wx"
974 // if any and converting it to the lower case
976 if ( name(0, 2) == "wx" ) {
977 filename
<< name
.c_str() + 2;
983 filename
.MakeLower();
985 filename
.Prepend(m_directoryOut
);
987 if ( !m_overwrite
&& wxFile::Exists(filename
) ) {
988 wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
994 m_inClass
= m_file
.Open(filename
, wxFile::write
);
996 wxLogError("Can't generate documentation for the class '%s'.",
1003 m_inTypesSection
= false;
1005 wxLogInfo("Created new file '%s' for class '%s'.",
1006 filename
.c_str(), name
.c_str());
1008 // write out the header
1010 header
.Printf("%%\n"
1011 "%% automatically generated by HelpGen %s from\n"
1016 "\\section{\\class{%s}}\\label{%s}\n\n",
1017 GetVersionString().c_str(),
1018 m_fileHeader
.c_str(),
1019 GetCurrentTimeFormatted("%d/%b/%y %H:%M:%S"),
1021 wxString(name
).MakeLower().c_str());
1023 m_file
.WriteVerbatim(header
);
1025 // the entire text we're writing to file
1028 // if the header includes other headers they must be related to it... try to
1029 // automatically generate the "See also" clause
1030 if ( !m_headers
.IsEmpty() ) {
1031 // correspondence between wxWidgets headers and class names
1032 static const char *headers
[] = {
1041 // NULL here means not to insert anything in "See also" for the
1042 // corresponding header
1043 static const char *classes
[] = {
1052 wxASSERT_MSG( WXSIZEOF(headers
) == WXSIZEOF(classes
),
1053 "arrays must be in sync!" );
1055 wxArrayInt interestingClasses
;
1057 size_t count
= m_headers
.Count(), index
;
1058 for ( size_t n
= 0; n
< count
; n
++ ) {
1059 wxString baseHeaderName
= m_headers
[n
].Before('.');
1060 if ( baseHeaderName(0, 3) != "wx/" )
1063 baseHeaderName
.erase(0, 3);
1064 for ( index
= 0; index
< WXSIZEOF(headers
); index
++ ) {
1065 if ( Stricmp(baseHeaderName
, headers
[index
]) == 0 )
1069 if ( (index
< WXSIZEOF(headers
)) && classes
[index
] ) {
1070 // interesting header
1071 interestingClasses
.Add(index
);
1075 if ( !interestingClasses
.IsEmpty() ) {
1076 // do generate "See also" clause
1077 totalText
<< "\\wxheading{See also:}\n\n";
1079 count
= interestingClasses
.Count();
1080 for ( index
= 0; index
< count
; index
++ ) {
1084 totalText
<< MakeHelpref(classes
[interestingClasses
[index
]]);
1087 totalText
<< "\n\n";
1091 // the comment before the class generally explains what is it for so put it
1092 // in place of the class description
1093 if ( cl
.HasComments() ) {
1094 wxString comment
= GetAllComments(cl
);
1096 totalText
<< '\n' << comment
<< '\n';
1099 // derived from section
1100 wxString derived
= "\\wxheading{Derived from}\n\n";
1102 const StrListT
& baseClasses
= cl
.mSuperClassNames
;
1103 if ( baseClasses
.size() == 0 ) {
1104 derived
<< "No base class";
1108 for ( StrListT::const_iterator i
= baseClasses
.begin();
1109 i
!= baseClasses
.end();
1112 // separate from the previous one
1113 derived
<< "\\\\\n";
1119 wxString baseclass
= *i
;
1120 derived
<< "\\helpref{" << baseclass
<< "}";
1121 derived
<< "{" << baseclass
.MakeLower() << "}";
1124 totalText
<< derived
<< "\n\n";
1126 // include file section
1127 wxString includeFile
= "\\wxheading{Include files}\n\n";
1128 includeFile
<< "<" << m_fileHeader
<< ">";
1130 totalText
<< includeFile
<< "\n\n";
1132 // write all this to file
1133 m_file
.WriteTeX(totalText
);
1135 // if there were any enums/typedefs before, insert their documentation now
1136 InsertDataStructuresHeader();
1137 InsertTypedefDocs();
1143 void HelpGenVisitor::VisitEnumeration( spEnumeration
& en
)
1147 if ( m_inMethodSection
) {
1148 // FIXME that's a bug, but tell the user aboit it nevertheless... we
1149 // should be smart enough to process even the enums which come after the
1151 wxLogWarning("enum '%s' ignored, please put it before the class "
1152 "methods.", en
.GetName().c_str());
1156 // simply copy the enum text in the docs
1157 wxString enumeration
= GetAllComments(en
),
1160 enumerationVerb
<< "\\begin{verbatim}\n"
1162 << "\n\\end{verbatim}\n";
1164 // remember for later use if we're not inside a class yet
1166 m_storedEnums
.Add(enumeration
);
1167 m_storedEnumsVerb
.Add(enumerationVerb
);
1170 // write the header for this section if not done yet
1171 InsertDataStructuresHeader();
1173 m_file
.WriteTeX(enumeration
);
1174 m_file
.WriteVerbatim(enumerationVerb
);
1175 m_file
.WriteVerbatim('\n');
1179 void HelpGenVisitor::VisitTypeDef( spTypeDef
& td
)
1183 if ( m_inMethodSection
) {
1184 // FIXME that's a bug, but tell the user aboit it nevertheless...
1185 wxLogWarning("typedef '%s' ignored, please put it before the class "
1186 "methods.", td
.GetName().c_str());
1190 wxString typedefdoc
;
1191 typedefdoc
<< "{\\small \\begin{verbatim}\n"
1192 << "typedef " << td
.mOriginalType
<< ' ' << td
.GetName()
1193 << "\n\\end{verbatim}}\n"
1194 << GetAllComments(td
);
1196 // remember for later use if we're not inside a class yet
1198 if ( !m_textStoredTypedefs
.IsEmpty() ) {
1199 m_textStoredTypedefs
<< '\n';
1202 m_textStoredTypedefs
<< typedefdoc
;
1205 // write the header for this section if not done yet
1206 InsertDataStructuresHeader();
1209 m_file
.WriteTeX(typedefdoc
);
1213 void HelpGenVisitor::VisitPreprocessorLine( spPreprocessorLine
& pd
)
1215 switch ( pd
.GetStatementType() ) {
1216 case SP_PREP_DEF_INCLUDE_FILE
:
1217 m_headers
.Add(pd
.CPP_GetIncludedFileNeme());
1220 case SP_PREP_DEF_DEFINE_SYMBOL
:
1221 // TODO decide if it's a constant and document it if it is
1226 void HelpGenVisitor::VisitAttribute( spAttribute
& attr
)
1230 // only document the public member variables
1231 if ( !m_inClass
|| !attr
.IsPublic() )
1234 wxLogWarning("Ignoring member variable '%s'.", attr
.GetName().c_str());
1237 void HelpGenVisitor::VisitOperation( spOperation
& op
)
1242 // we don't generate docs right now - either we ignore this class
1243 // entirely or we couldn't open the file
1247 if ( !op
.IsInClass() ) {
1248 // TODO document global functions
1249 wxLogWarning("skipped global function '%s'.", op
.GetName().c_str());
1254 if ( op
.mVisibility
== SP_VIS_PRIVATE
) {
1255 // FIXME should we document protected functions?
1259 m_classname
= op
.GetClass().GetName();
1260 wxString funcname
= op
.GetName();
1262 if ( m_ignoreNames
.IgnoreMethod(m_classname
, funcname
) ) {
1263 wxLogVerbose("Skipping ignored '%s::%s'.",
1264 m_classname
.c_str(), funcname
.c_str());
1269 InsertMethodsHeader();
1272 m_funcName
= funcname
;
1273 m_isFirstParam
= true;
1275 m_textStoredFunctionComment
= GetAllComments(op
);
1277 // start function documentation
1280 // check for the special case of dtor
1282 if ( (funcname
[0u] == '~') && (m_classname
== funcname
.c_str() + 1) ) {
1283 dtor
.Printf("\\destruct{%s}", m_classname
.c_str());
1287 m_textFunc
.Printf("\n"
1288 "\\membersection{%s::%s}\\label{%s}\n",
1289 m_classname
.c_str(), funcname
.c_str(),
1290 MakeLabel(m_classname
, funcname
).c_str());
1294 "\\%sfunc{%s%s}{%s}{",
1295 op
.mIsConstant
? "const" : "",
1296 op
.mIsVirtual
? "virtual " : "",
1297 op
.mRetType
.c_str(),
1302 void HelpGenVisitor::VisitParameter( spParameter
& param
)
1304 if ( m_funcName
.empty() )
1307 if ( m_isFirstParam
) {
1308 m_isFirstParam
= false;
1314 m_textFunc
<< "\\param{" << param
.mType
<< " }{" << param
.GetName();
1315 wxString defvalue
= param
.mInitVal
;
1316 if ( !defvalue
.IsEmpty() ) {
1317 m_textFunc
<< " = " << defvalue
;
1323 // ---------------------------------------------------------------------------
1325 // ---------------------------------------------------------------------------
1327 DocManager::DocManager(bool checkParamNames
)
1329 m_checkParamNames
= checkParamNames
;
1332 size_t DocManager::TryMatch(const char *str
, const char *match
)
1334 size_t lenMatch
= 0;
1335 while ( str
[lenMatch
] == match
[lenMatch
] ) {
1338 if ( match
[lenMatch
] == '\0' )
1345 bool DocManager::SkipUntil(const char **pp
, char c
)
1347 const char *p
= *pp
;
1363 bool DocManager::SkipSpaceUntil(const char **pp
, char c
)
1365 const char *p
= *pp
;
1367 if ( !isspace(*p
) || *p
== '\0' )
1381 wxString
DocManager::ExtractStringBetweenBraces(const char **pp
)
1385 if ( !SkipSpaceUntil(pp
, '{') ) {
1386 wxLogWarning("file %s(%d): '{' expected after '\\param'",
1387 m_filename
.c_str(), m_line
);
1391 const char *startParam
= ++*pp
; // skip '{'
1393 if ( !SkipUntil(pp
, '}') ) {
1394 wxLogWarning("file %s(%d): '}' expected after '\\param'",
1395 m_filename
.c_str(), m_line
);
1398 result
= wxString(startParam
, (*pp
)++ - startParam
);
1405 bool DocManager::ParseTeXFile(const wxString
& filename
)
1407 m_filename
= filename
;
1409 wxFile
file(m_filename
, wxFile::read
);
1410 if ( !file
.IsOpened() )
1413 off_t len
= file
.Length();
1414 if ( len
== wxInvalidOffset
)
1417 char *buf
= new char[len
+ 1];
1420 if ( file
.Read(buf
, len
) == wxInvalidOffset
) {
1426 // reinit everything
1429 wxLogVerbose("%s: starting to parse doc file '%s'.",
1430 GetCurrentTimeFormatted("%H:%M:%S"), m_filename
.c_str());
1432 // the name of the class from the last "\membersection" command: we assume
1433 // that the following "\func" or "\constfunc" always documents a method of
1434 // this class (and it should always be like that in wxWidgets documentation)
1437 for ( const char *current
= buf
; current
- buf
< len
; current
++ ) {
1438 // FIXME parsing is awfully inefficient
1440 if ( *current
== '%' ) {
1441 // comment, skip until the end of line
1443 SkipUntil(¤t
, '\n');
1448 // all the command we're interested in start with '\\'
1449 while ( *current
!= '\\' && *current
!= '\0' ) {
1450 if ( *current
++ == '\n' )
1454 if ( *current
== '\0' ) {
1455 // no more TeX commands left
1459 current
++; // skip '\\'
1467 } foundCommand
= Nothing
;
1469 size_t lenMatch
= TryMatch(current
, "func");
1471 foundCommand
= Func
;
1474 lenMatch
= TryMatch(current
, "constfunc");
1476 foundCommand
= ConstFunc
;
1478 lenMatch
= TryMatch(current
, "membersection");
1481 foundCommand
= MemberSect
;
1485 if ( foundCommand
== Nothing
)
1488 current
+= lenMatch
;
1490 if ( !SkipSpaceUntil(¤t
, '{') ) {
1491 wxLogWarning("file %s(%d): '{' expected after \\func, "
1492 "\\constfunc or \\membersection.",
1493 m_filename
.c_str(), m_line
);
1500 if ( foundCommand
== MemberSect
) {
1501 // what follows has the form <classname>::<funcname>
1502 const char *startClass
= current
;
1503 if ( !SkipUntil(¤t
, ':') || *(current
+ 1) != ':' ) {
1504 wxLogWarning("file %s(%d): '::' expected after "
1505 "\\membersection.", m_filename
.c_str(), m_line
);
1508 classname
= wxString(startClass
, current
- startClass
);
1509 TeXUnfilter(&classname
);
1515 // extract the return type
1516 const char *startRetType
= current
;
1518 if ( !SkipUntil(¤t
, '}') ) {
1519 wxLogWarning("file %s(%d): '}' expected after return type",
1520 m_filename
.c_str(), m_line
);
1525 wxString returnType
= wxString(startRetType
, current
- startRetType
);
1526 TeXUnfilter(&returnType
);
1529 if ( !SkipSpaceUntil(¤t
, '{') ) {
1530 wxLogWarning("file %s(%d): '{' expected after return type",
1531 m_filename
.c_str(), m_line
);
1537 const char *funcEnd
= current
;
1538 if ( !SkipUntil(&funcEnd
, '}') ) {
1539 wxLogWarning("file %s(%d): '}' expected after function name",
1540 m_filename
.c_str(), m_line
);
1545 wxString funcName
= wxString(current
, funcEnd
- current
);
1546 current
= funcEnd
+ 1;
1548 // trim spaces from both sides
1549 funcName
.Trim(false);
1550 funcName
.Trim(true);
1552 // special cases: '$...$' may be used for LaTeX inline math, remove the
1554 if ( funcName
.Find('$') != wxNOT_FOUND
) {
1556 for ( const char *p
= funcName
.c_str(); *p
!= '\0'; p
++ ) {
1557 if ( *p
!= '$' && !isspace(*p
) )
1564 // \destruct{foo} is really ~foo
1565 if ( funcName
[0u] == '\\' ) {
1566 size_t len
= strlen("\\destruct{");
1567 if ( funcName(0, len
) != "\\destruct{" ) {
1568 wxLogWarning("file %s(%d): \\destruct expected",
1569 m_filename
.c_str(), m_line
);
1574 funcName
.erase(0, len
);
1575 funcName
.Prepend('~');
1577 if ( !SkipSpaceUntil(¤t
, '}') ) {
1578 wxLogWarning("file %s(%d): '}' expected after destructor",
1579 m_filename
.c_str(), m_line
);
1584 funcEnd
++; // there is an extra '}' to count
1587 TeXUnfilter(&funcName
);
1590 current
= funcEnd
+ 1; // skip '}'
1591 if ( !SkipSpaceUntil(¤t
, '{') ||
1592 (current
++, !SkipSpaceUntil(¤t
, '\\')) ) {
1593 wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
1594 m_filename
.c_str(), m_line
);
1599 wxArrayString paramNames
, paramTypes
, paramValues
;
1601 bool isVararg
= false;
1603 current
++; // skip '\\'
1604 lenMatch
= TryMatch(current
, "void");
1606 lenMatch
= TryMatch(current
, "param");
1607 while ( lenMatch
&& (current
- buf
< len
) ) {
1608 current
+= lenMatch
;
1610 // now come {paramtype}{paramname}
1611 wxString paramType
= ExtractStringBetweenBraces(¤t
);
1612 if ( !!paramType
) {
1613 wxString paramText
= ExtractStringBetweenBraces(¤t
);
1614 if ( !!paramText
) {
1615 // the param declaration may contain default value
1616 wxString paramName
= paramText
.BeforeFirst('='),
1617 paramValue
= paramText
.AfterFirst('=');
1619 // sanitize all strings
1620 TeXUnfilter(¶mValue
);
1621 TeXUnfilter(¶mName
);
1622 TeXUnfilter(¶mType
);
1624 paramValues
.Add(paramValue
);
1625 paramNames
.Add(paramName
);
1626 paramTypes
.Add(paramType
);
1631 wxString paramText
= ExtractStringBetweenBraces(¤t
);
1632 if ( paramText
== "..." ) {
1636 wxLogWarning("Parameters of '%s::%s' are in "
1638 classname
.c_str(), funcName
.c_str());
1643 current
= SkipSpaces(current
);
1644 if ( *current
== ',' || *current
== '}' ) {
1645 current
= SkipSpaces(++current
);
1647 lenMatch
= TryMatch(current
, "\\param");
1650 wxLogWarning("file %s(%d): ',' or '}' expected after "
1651 "'\\param'", m_filename
.c_str(), m_line
);
1657 // if we got here there was no '\\void', so must have some params
1658 if ( paramNames
.IsEmpty() ) {
1659 wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
1660 m_filename
.c_str(), m_line
);
1666 // verbose diagnostic output
1668 size_t param
, paramCount
= paramNames
.GetCount();
1669 for ( param
= 0; param
< paramCount
; param
++ ) {
1674 paramsAll
<< paramTypes
[param
] << ' ' << paramNames
[param
];
1677 wxLogVerbose("file %s(%d): found '%s %s::%s(%s)%s'",
1678 m_filename
.c_str(), m_line
,
1683 foundCommand
== ConstFunc
? " const" : "");
1685 // store the info about the just found function
1686 ArrayMethodInfo
*methods
;
1687 int index
= m_classes
.Index(classname
);
1688 if ( index
== wxNOT_FOUND
) {
1689 m_classes
.Add(classname
);
1691 methods
= new ArrayMethodInfo
;
1692 m_methods
.Add(methods
);
1695 methods
= m_methods
[(size_t)index
];
1698 ArrayParamInfo params
;
1699 for ( param
= 0; param
< paramCount
; param
++ ) {
1700 params
.Add(new ParamInfo(paramTypes
[param
],
1702 paramValues
[param
]));
1705 MethodInfo
*method
= new MethodInfo(returnType
, funcName
, params
);
1706 if ( foundCommand
== ConstFunc
)
1707 method
->SetFlag(MethodInfo::Const
);
1709 method
->SetFlag(MethodInfo::Vararg
);
1711 methods
->Add(method
);
1716 wxLogVerbose("%s: finished parsing doc file '%s'.\n",
1717 GetCurrentTimeFormatted("%H:%M:%S"), m_filename
.c_str());
1722 bool DocManager::DumpDifferences(spContext
*ctxTop
) const
1724 typedef MMemberListT::const_iterator MemberIndex
;
1726 bool foundDiff
= false;
1728 // flag telling us whether the given class was found at all in the header
1729 size_t nClass
, countClassesInDocs
= m_classes
.GetCount();
1730 bool *classExists
= new bool[countClassesInDocs
];
1731 for ( nClass
= 0; nClass
< countClassesInDocs
; nClass
++ ) {
1732 classExists
[nClass
] = false;
1735 // ctxTop is normally an spFile
1736 wxASSERT( ctxTop
->GetContextType() == SP_CTX_FILE
);
1738 const MMemberListT
& classes
= ctxTop
->GetMembers();
1739 for ( MemberIndex i
= classes
.begin(); i
!= classes
.end(); i
++ ) {
1740 spContext
*ctx
= *i
;
1741 if ( ctx
->GetContextType() != SP_CTX_CLASS
) {
1742 // TODO process also global functions, macros, ...
1746 spClass
*ctxClass
= (spClass
*)ctx
;
1747 const wxString
& nameClass
= ctxClass
->mName
;
1748 int index
= m_classes
.Index(nameClass
);
1749 if ( index
== wxNOT_FOUND
) {
1750 if ( !m_ignoreNames
.IgnoreClass(nameClass
) ) {
1753 wxLogError("Class '%s' is not documented at all.",
1757 // it makes no sense to check for its functions
1761 classExists
[index
] = true;
1764 // array of method descriptions for this class
1765 const ArrayMethodInfo
& methods
= *(m_methods
[index
]);
1766 size_t nMethod
, countMethods
= methods
.GetCount();
1768 // flags telling if we already processed given function
1769 bool *methodExists
= new bool[countMethods
];
1770 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1771 methodExists
[nMethod
] = false;
1774 wxArrayString aOverloadedMethods
;
1776 const MMemberListT
& functions
= ctxClass
->GetMembers();
1777 for ( MemberIndex j
= functions
.begin(); j
!= functions
.end(); j
++ ) {
1779 if ( ctx
->GetContextType() != SP_CTX_OPERATION
)
1782 spOperation
*ctxMethod
= (spOperation
*)ctx
;
1783 const wxString
& nameMethod
= ctxMethod
->mName
;
1785 // find all functions with the same name
1786 wxArrayInt aMethodsWithSameName
;
1787 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1788 if ( methods
[nMethod
]->GetName() == nameMethod
)
1789 aMethodsWithSameName
.Add(nMethod
);
1792 if ( aMethodsWithSameName
.IsEmpty() && ctxMethod
->IsPublic() ) {
1793 if ( !m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) ) {
1796 wxLogError("'%s::%s' is not documented.",
1798 nameMethod
.c_str());
1801 // don't check params
1804 else if ( aMethodsWithSameName
.GetCount() == 1 ) {
1805 index
= (size_t)aMethodsWithSameName
[0u];
1806 methodExists
[index
] = true;
1808 if ( m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) )
1811 if ( !ctxMethod
->IsPublic() ) {
1812 wxLogWarning("'%s::%s' is documented but not public.",
1814 nameMethod
.c_str());
1817 // check that the flags match
1818 const MethodInfo
& method
= *(methods
[index
]);
1820 bool isVirtual
= ctxMethod
->mIsVirtual
;
1821 if ( isVirtual
!= method
.HasFlag(MethodInfo::Virtual
) ) {
1822 wxLogWarning("'%s::%s' is incorrectly documented as %s"
1826 isVirtual
? "not " : "");
1829 bool isConst
= ctxMethod
->mIsConstant
;
1830 if ( isConst
!= method
.HasFlag(MethodInfo::Const
) ) {
1831 wxLogWarning("'%s::%s' is incorrectly documented as %s"
1835 isConst
? "not " : "");
1838 // check that the params match
1839 const MMemberListT
& params
= ctxMethod
->GetMembers();
1841 if ( params
.size() != method
.GetParamCount() ) {
1842 wxLogError("Incorrect number of parameters for '%s::%s' "
1843 "in the docs: should be %d instead of %d.",
1846 params
.size(), method
.GetParamCount());
1850 for ( MemberIndex k
= params
.begin();
1855 // what else can a function have?
1856 wxASSERT( ctx
->GetContextType() == SP_CTX_PARAMETER
);
1858 spParameter
*ctxParam
= (spParameter
*)ctx
;
1859 const ParamInfo
& param
= method
.GetParam(nParam
);
1860 if ( m_checkParamNames
&&
1861 (param
.GetName() != ctxParam
->mName
) ) {
1864 wxLogError("Parameter #%d of '%s::%s' should be "
1865 "'%s' and not '%s'.",
1869 ctxParam
->mName
.c_str(),
1870 param
.GetName().c_str());
1875 if ( param
.GetType() != ctxParam
->mType
) {
1878 wxLogError("Type of parameter '%s' of '%s::%s' "
1879 "should be '%s' and not '%s'.",
1880 ctxParam
->mName
.c_str(),
1883 ctxParam
->mType
.c_str(),
1884 param
.GetType().GetName().c_str());
1889 if ( param
.GetDefValue() != ctxParam
->mInitVal
) {
1890 wxLogWarning("Default value of parameter '%s' of "
1891 "'%s::%s' should be '%s' and not "
1893 ctxParam
->mName
.c_str(),
1896 ctxParam
->mInitVal
.c_str(),
1897 param
.GetDefValue().c_str());
1903 // TODO OVER add real support for overloaded methods
1905 if ( m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) )
1908 if ( aOverloadedMethods
.Index(nameMethod
) == wxNOT_FOUND
) {
1909 // mark all methods with this name as existing
1910 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1911 if ( methods
[nMethod
]->GetName() == nameMethod
)
1912 methodExists
[nMethod
] = true;
1915 aOverloadedMethods
.Add(nameMethod
);
1917 wxLogVerbose("'%s::%s' is overloaded and I'm too "
1918 "stupid to find the right match - skipping "
1919 "the param and flags checks.",
1921 nameMethod
.c_str());
1923 //else: warning already given
1927 for ( nMethod
= 0; nMethod
< countMethods
; nMethod
++ ) {
1928 if ( !methodExists
[nMethod
] ) {
1929 const wxString
& nameMethod
= methods
[nMethod
]->GetName();
1930 if ( !m_ignoreNames
.IgnoreMethod(nameClass
, nameMethod
) ) {
1933 wxLogError("'%s::%s' is documented but doesn't exist.",
1935 nameMethod
.c_str());
1940 delete [] methodExists
;
1943 // check that all classes we found in the docs really exist
1944 for ( nClass
= 0; nClass
< countClassesInDocs
; nClass
++ ) {
1945 if ( !classExists
[nClass
] ) {
1948 wxLogError("Class '%s' is documented but doesn't exist.",
1949 m_classes
[nClass
].c_str());
1953 delete [] classExists
;
1958 DocManager::~DocManager()
1960 WX_CLEAR_ARRAY(m_methods
);
1963 // ---------------------------------------------------------------------------
1964 // IgnoreNamesHandler implementation
1965 // ---------------------------------------------------------------------------
1967 int IgnoreNamesHandler::CompareIgnoreListEntries(IgnoreListEntry
*first
,
1968 IgnoreListEntry
*second
)
1970 // first compare the classes
1971 int rc
= first
->m_classname
.Cmp(second
->m_classname
);
1973 rc
= first
->m_funcname
.Cmp(second
->m_funcname
);
1978 bool IgnoreNamesHandler::AddNamesFromFile(const wxString
& filename
)
1980 wxFile
file(filename
, wxFile::read
);
1981 if ( !file
.IsOpened() )
1984 off_t len
= file
.Length();
1985 if ( len
== wxInvalidOffset
)
1988 char *buf
= new char[len
+ 1];
1991 if ( file
.Read(buf
, len
) == wxInvalidOffset
) {
1998 for ( const char *current
= buf
; ; current
++ ) {
2000 // skip DOS line separator
2001 if ( *current
== '\r' )
2005 if ( *current
== '\n' || *current
== '\0' ) {
2006 if ( line
[0u] != '#' ) {
2007 if ( line
.Find(':') != wxNOT_FOUND
) {
2008 wxString classname
= line
.BeforeFirst(':'),
2009 funcname
= line
.AfterLast(':');
2010 m_ignore
.Add(new IgnoreListEntry(classname
, funcname
));
2014 m_ignore
.Add(new IgnoreListEntry(line
, ""));
2019 if ( *current
== '\0' )
2034 // -----------------------------------------------------------------------------
2035 // global function implementation
2036 // -----------------------------------------------------------------------------
2038 static wxString
MakeLabel(const char *classname
, const char *funcname
)
2040 wxString
label(classname
);
2041 if ( funcname
&& funcname
[0] == '\\' ) {
2042 // we may have some special TeX macro - so far only \destruct exists,
2043 // but may be later others will be added
2044 static const char *macros
[] = { "destruct" };
2045 static const char *replacement
[] = { "dtor" };
2048 for ( n
= 0; n
< WXSIZEOF(macros
); n
++ ) {
2049 if ( strncmp(funcname
+ 1, macros
[n
], strlen(macros
[n
])) == 0 ) {
2055 if ( n
== WXSIZEOF(macros
) ) {
2056 wxLogWarning("unknown function name '%s' - leaving as is.",
2060 funcname
= replacement
[n
];
2065 // special treatment for operatorXXX() stuff because the C operators
2066 // are not valid in LaTeX labels
2068 if ( wxString(funcname
).StartsWith("operator", &oper
) ) {
2069 label
<< "operator";
2082 for ( n
= 0; n
< WXSIZEOF(operatorNames
); n
++ ) {
2083 if ( oper
== operatorNames
[n
].oper
) {
2084 label
<< operatorNames
[n
].name
;
2090 if ( n
== WXSIZEOF(operatorNames
) ) {
2091 wxLogWarning("unknown operator '%s' - making dummy label.",
2097 else // simply use the func name
2108 static wxString
MakeHelpref(const char *argument
)
2111 helpref
<< "\\helpref{" << argument
<< "}{" << MakeLabel(argument
) << '}';
2116 static void TeXFilter(wxString
* str
)
2118 // TeX special which can be quoted (don't include backslash nor braces as
2120 static wxRegEx
reNonSpecialSpecials("[#$%&_]"),
2124 reNonSpecialSpecials
.ReplaceAll(str
, "\\\\\\0");
2126 // can't quote these ones as they produce accents when preceded by
2127 // backslash, so put them inside verb
2128 reAccents
.ReplaceAll(str
, "\\\\verb|\\0|");
2131 static void TeXUnfilter(wxString
* str
)
2133 // FIXME may be done much more quickly
2138 static wxRegEx
reNonSpecialSpecials("\\\\([#$%&_{}])"),
2139 reAccents("\\\\verb\\|([~^])\\|");
2141 reNonSpecialSpecials
.ReplaceAll(str
, "\\1");
2142 reAccents
.ReplaceAll(str
, "\\1");
2145 static wxString
GetAllComments(const spContext
& ctx
)
2148 const MCommentListT
& commentsList
= ctx
.GetCommentList();
2149 for ( MCommentListT::const_iterator i
= commentsList
.begin();
2150 i
!= commentsList
.end();
2152 wxString comment
= (*i
)->GetText();
2154 // don't take comments like "// ----------" &c
2155 comment
.Trim(false);
2157 comment
== wxString(comment
[0u], comment
.length() - 1) + '\n' )
2160 comments
<< comment
;
2166 static const char *GetCurrentTimeFormatted(const char *timeFormat
)
2168 static char s_timeBuffer
[128];
2173 ptmNow
= localtime(&timeNow
);
2175 strftime(s_timeBuffer
, WXSIZEOF(s_timeBuffer
), timeFormat
, ptmNow
);
2177 return s_timeBuffer
;
2180 static const wxString
GetVersionString()
2182 wxString version
= "$Revision$";
2183 wxRegEx("^\\$Revision$$").ReplaceFirst(&version
, "\\1");
2189 Revision 1.30 2004/06/18 19:25:50 ABX
2190 Small step in making HelpGen up to date unicode application.
2192 Revision 1.29 2004/06/17 19:00:22 ABX
2193 Warning fixes. Code cleanup. Whitespaces and tabs removed.
2195 Revision 1.28 2004/05/25 11:19:57 JS
2198 Revision 1.27 2003/10/13 17:21:30 MBN
2201 Revision 1.26 2003/09/29 15:18:35 MBN
2202 (Blind) compilation fix for Sun compiler.
2204 Revision 1.25 2003/09/03 17:39:27 MBN
2207 Revision 1.24 2003/08/13 22:59:37 VZ
2210 Revision 1.23 2003/06/13 17:05:43 VZ
2211 quote '|' inside regexes (fixes dump mode); fixed crash due to strange HelpGenApp code
2213 Revision 1.22 2002/01/21 21:18:50 JS
2214 Now adds 'include file' heading
2216 Revision 1.21 2002/01/04 11:06:09 JS
2217 Fixed missing membersections bug and also bug with functions not being written
2220 Revision 1.20 2002/01/03 14:23:33 JS
2221 Added code to make it not duplicate membersections for overloaded functions
2223 Revision 1.19 2002/01/03 13:34:12 JS
2224 Added FlushAll to CloseClass, otherwise text was only flushed right at the end,
2225 and appeared in one file.
2227 Revision 1.18 2002/01/03 12:02:47 JS
2228 Added main() and corrected VC++ project settings
2230 Revision 1.17 2001/11/30 21:43:35 VZ
2231 now the methods are sorted in the correct order in the generated docs
2233 Revision 1.16 2001/11/28 19:27:33 VZ
2234 HelpGen doesn't work in GUI mode
2236 Revision 1.15 2001/11/22 21:59:58 GD
2237 use "..." instead of <...> for wx headers
2239 Revision 1.14 2001/07/19 13:51:29 VZ
2240 fixes to version string
2242 Revision 1.13 2001/07/19 13:44:57 VZ
2243 1. compilation fixes
2244 2. don't quote special characters inside verbatim environment
2246 Revision 1.12 2000/10/09 13:53:33 juliansmart
2248 Doc corrections; added HelpGen project files
2250 Revision 1.11 2000/07/15 19:50:42 cvsuser
2253 Revision 1.10.2.2 2000/03/27 15:33:10 VZ
2254 don't trasnform output dir name to lower case
2256 Revision 1.10 2000/03/11 10:05:23 VS
2257 now compiles with wxBase
2259 Revision 1.9 2000/01/16 13:25:21 VS
2260 compilation fixes (gcc)
2262 Revision 1.8 1999/09/13 14:29:39 JS
2264 Made HelpGen into a wxWin app (still uses command-line args); moved includes
2265 into src for simplicity; added VC++ 5 project file
2267 Revision 1.7 1999/02/21 22:32:32 VZ
2268 1. more C++ parser fixes - now it almost parses wx/string.h
2269 a) #if/#ifdef/#else (very) limited support
2270 b) param type fix - now indirection chars are correctly handled
2271 c) class/struct/union distinction
2272 d) public/private fixes
2273 e) Dump() function added - very useful for debugging
2275 2. option to ignore parameter names during 'diff' (in fact, they're ignored
2276 by default, and this option switches it on)
2278 Revision 1.6 1999/02/20 23:00:26 VZ
2279 1. new 'diff' mode which seems to work
2280 2. output files are not overwritten in 'dmup' mode
2281 3. fixes for better handling of const functions and operators
2282 ----------------------------
2284 date: 1999/02/15 23:07:25; author: VZ; state: Exp; lines: +106 -45
2285 1. Parser improvements
2286 a) const and virtual methods are parsed correctly (not static yet)
2287 b) "const" which is part of the return type is not swallowed
2289 2. HelpGen improvements: -o outputdir parameter added to the cmd line,
2290 "//---------" kind comments discarded now.
2291 ----------------------------
2293 date: 1999/01/13 14:23:31; author: JS; state: Exp; lines: +4 -4
2295 some tweaks to HelpGen
2296 ----------------------------
2298 date: 1999/01/09 20:18:03; author: JS; state: Exp; lines: +7 -2
2300 HelpGen starting to compile with VC++
2301 ----------------------------
2303 date: 1999/01/08 19:46:22; author: VZ; state: Exp; lines: +208 -35
2305 supports typedefs, generates "See also:" and adds "virtual " for virtual
2307 ----------------------------
2309 date: 1999/01/08 17:45:55; author: VZ; state: Exp;
2311 HelpGen is a prototype of the tool for automatic generation of the .tex files
2312 for wxWidgets documentation from C++ headers
2315 /* vi: set tw=80 et ts=4 sw=4: */