// Created: 06/01/99
// RCS-ID: $Id$
// Copyright: (c) 1999 VZ
-// Licence: GPL
+// Licence: wxWindows Licence
/////////////////////////////////////////////////////////////////////////////
/*
// headers
// -----------------------------------------------------------------------------
-// wxWindows
+// wxWidgets
#include "wx/wxprec.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_UNICODE
+ #error "HelpGen doesn't build in Unicode mode"
+#endif
+
#ifndef WX_PRECOMP
- #include <wx/string.h>
- #include <wx/log.h>
- #include <wx/dynarray.h>
+ #include "wx/string.h"
+ #include "wx/log.h"
+ #include "wx/dynarray.h"
+ #include "wx/app.h"
#endif // WX_PRECOMP
-#include <wx/file.h>
+#include "wx/file.h"
+#include "wx/regex.h"
+#include "wx/hash.h"
// C++ parsing classes
#include "cjparser.h"
#include <stdio.h>
#include <time.h>
-// -----------------------------------------------------------------------------
-// global vars
-// -----------------------------------------------------------------------------
-
-// just a copy of argv
-static char **g_argv = NULL;
-
-class HelpGenApp: public wxApp
-{
-public:
- HelpGenApp() {};
-
- bool OnInit();
-};
-
-IMPLEMENT_APP(HelpGenApp);
-
// -----------------------------------------------------------------------------
// private functions
// -----------------------------------------------------------------------------
// return the label for the given function name (i.e. argument of \label)
-static wxString MakeLabel(const char *classname, const char *funcname = NULL);
+static wxString MakeLabel(const wxChar *classname, const wxChar *funcname = NULL);
// return the whole \helpref{arg}{arg_label} string
-static wxString MakeHelpref(const char *argument);
+static wxString MakeHelpref(const wxChar *argument);
// [un]quote special TeX characters (in place)
static void TeXFilter(wxString* str);
// get the string with current time (returns pointer to static buffer)
// timeFormat is used for the call of strftime(3)
-#ifdef GetCurrentTime
-#undef GetCurrentTime
-#endif
+static const char *GetCurrentTimeFormatted(const char *timeFormat);
-static const char *GetCurrentTime(const char *timeFormat);
+// get the string containing the program version
+static const wxString GetVersionString();
// -----------------------------------------------------------------------------
// private classes
// -----------------------------------------------------------------------------
-// add a function which sanitazes the string before writing it to the file
+// a function documentation entry
+struct FunctionDocEntry
+{
+ FunctionDocEntry(const wxString& name_, const wxString& text_)
+ : name(name_), text(text_) { }
+
+ // the function name
+ wxString name;
+
+ // the function doc text
+ wxString text;
+
+ // sorting stuff
+ static int Compare(FunctionDocEntry **pp1, FunctionDocEntry **pp2)
+ {
+ // the methods should appear in the following order: ctors, dtor, all
+ // the rest in the alphabetical order
+ bool isCtor1 = (*pp1)->name == classname;
+ bool isCtor2 = (*pp2)->name == classname;
+
+ if ( isCtor1 ) {
+ if ( isCtor2 ) {
+ // we don't order the ctors because we don't know how to do it
+ return 0;
+ }
+
+ // ctor comes before non-ctor
+ return -1;
+ }
+ else {
+ if ( isCtor2 ) {
+ // non-ctor must come after ctor
+ return 1;
+ }
+
+ wxString dtorname = wxString(_T("~")) + classname;
+
+ // there is only one dtor, so the logic here is simpler
+ if ( (*pp1)->name == dtorname ) {
+ return -1;
+ }
+ else if ( (*pp2)->name == dtorname ) {
+ return 1;
+ }
+
+ // two normal methods
+ return wxStrcmp((*pp1)->name, (*pp2)->name);
+ }
+ }
+
+ static wxString classname;
+};
+
+wxString FunctionDocEntry::classname;
+
+WX_DECLARE_OBJARRAY(FunctionDocEntry, FunctionDocEntries);
+
+#include "wx/arrimpl.cpp"
+
+WX_DEFINE_OBJARRAY(FunctionDocEntries);
+
+// add a function which sanitazes the string before writing it to the file and
+// also capable of delaying output and sorting it before really writing it to
+// the file (done from FlushAll())
class wxTeXFile : public wxFile
{
public:
wxTeXFile() { }
- bool WriteTeX(const wxString& s)
+ // write a string to file verbatim (should only be used for the strings
+ // inside verbatim environment)
+ void WriteVerbatim(const wxString& s)
+ {
+ m_text += s;
+ }
+
+ // write a string quoting TeX specials in it
+ void WriteTeX(const wxString& s)
{
wxString t(s);
TeXFilter(&t);
- return wxFile::Write(t);
+ m_text += t;
+ }
+
+ // do write everything to file
+ bool FlushAll()
+ {
+ if ( m_text.empty() )
+ return true;
+
+ if ( !Write(m_text) ) {
+ wxLogError(_T("Failed to output generated documentation."));
+
+ return false;
+ }
+
+ m_text.clear();
+
+ return true;
}
private:
wxTeXFile(const wxTeXFile&);
wxTeXFile& operator=(const wxTeXFile&);
+
+ wxString m_text;
};
// helper class which manages the classes and function names to ignore for
// already have)
bool AddNamesFromFile(const wxString& filename);
- // return TRUE if we ignore this function
+ // return true if we ignore this function
bool IgnoreMethod(const wxString& classname,
const wxString& funcname) const
{
if ( IgnoreClass(classname) )
- return TRUE;
+ return true;
IgnoreListEntry ignore(classname, funcname);
return m_ignore.Index(&ignore) != wxNOT_FOUND;
}
- // return TRUE if we ignore this class entirely
+ // return true if we ignore this class entirely
bool IgnoreClass(const wxString& classname) const
{
- IgnoreListEntry ignore(classname, "");
+ IgnoreListEntry ignore(classname, _T(""));
return m_ignore.Index(&ignore) != wxNOT_FOUND;
}
IgnoreListEntry *second);
// for efficiency, let's sort it
+public: // FIXME: macro requires it
WX_DEFINE_SORTED_ARRAY(IgnoreListEntry *, ArrayNamesToIgnore);
+protected:
ArrayNamesToIgnore m_ignore;
private:
// terminate the function documentation if it was started
void CloseFunction();
+ // write out all function docs when there are no more left in this class
+ // after sorting them in alphabetical order
+ void CloseClass();
+
wxString m_directoryOut, // directory for the output
m_fileHeader; // name of the .h file we parse
bool m_overwrite; // overwrite existing files?
wxTeXFile m_file; // file we're writing to now
// state variables
- bool m_inClass, // TRUE after file successfully opened
+ bool m_inClass, // true after file successfully opened
m_inTypesSection, // enums & typedefs go there
m_inMethodSection, // functions go here
- m_isFirstParam, // first parameter of current function?
- m_inFunction; // we're parsing a function declaration
+ m_isFirstParam; // first parameter of current function?
+
+ // non empty while parsing a class
+ wxString m_classname;
+
+ // these are only non-empty while parsing a method:
+ wxString m_funcName, // the function name
+ m_textFunc; // the function doc text
+
+ // the array containing the documentation entries for the functions in the
+ // class currently being parsed
+ FunctionDocEntries m_arrayFuncDocs;
// holders for "saved" documentation
- wxString m_textStoredEnums,
- m_textStoredTypedefs,
+ wxString m_textStoredTypedefs,
m_textStoredFunctionComment;
+ // for enums we have to use an array as we can't intermix the normal text
+ // and the text inside verbatim environment
+ wxArrayString m_storedEnums,
+ m_storedEnumsVerb;
+
// headers included by this file
wxArrayString m_headers;
DocManager(bool checkParamNames);
~DocManager();
- // returns FALSE on failure
+ // returns false on failure
bool ParseTeXFile(const wxString& filename);
- // returns FALSE if there were any differences
+ // returns false if there were any differences
bool DumpDifferences(spContext *ctxTop) const;
// get our `ignore' object
// returns the length of 'match' if the string 'str' starts with it or 0
// otherwise
- static size_t TryMatch(const char *str, const char *match);
+ static size_t TryMatch(const wxChar *str, const wxChar *match);
// skip spaces: returns pointer to first non space character (also
// updates the value of m_line)
}
// skips characters until the next 'c' in '*pp' unless it ends before in
- // which case FALSE is returned and pp points to '\0', otherwise TRUE is
+ // which case false is returned and pp points to '\0', otherwise true is
// returned and pp points to 'c'
bool SkipUntil(const char **pp, char c);
// the same as SkipUntil() but only spaces are skipped: on first non space
- // character different from 'c' the function stops and returns FALSE
+ // character different from 'c' the function stops and returns false
bool SkipSpaceUntil(const char **pp, char c);
// extract the string between {} and modify '*pp' to point at the
// information about all functions documented in the TeX file(s)
// -------------------------------------------------------------
+public: // Note: Sun C++ 5.5 requires TypeInfo and ParamInfo to be public
+
// info about a type: for now stored as text string, but must be parsed
// further later (to know that "char *" == "char []" - TODO)
class TypeInfo
wxString m_type;
};
+ friend class ParamInfo; // for access to TypeInfo
+
// info abotu a function parameter
class ParamInfo
{
wxString m_value; // default value
};
- WX_DEFINE_ARRAY(ParamInfo *, ArrayParamInfo);
+public: // FIXME: macro requires it
+ WX_DEFINE_ARRAY_PTR(ParamInfo *, ArrayParamInfo);
// info about a function
struct MethodInfo
ArrayParamInfo m_params;
};
- WX_DEFINE_ARRAY(MethodInfo *, ArrayMethodInfo);
- WX_DEFINE_ARRAY(ArrayMethodInfo *, ArrayMethodInfos);
+ WX_DEFINE_ARRAY_PTR(MethodInfo *, ArrayMethodInfo);
+ WX_DEFINE_ARRAY_PTR(ArrayMethodInfo *, ArrayMethodInfos);
+private:
// first array contains the names of all classes we found, the second has a
// pointer to the array of methods of the given class at the same index as
// the class name appears in m_classes
DocManager& operator=(const DocManager&);
};
-// -----------------------------------------------------------------------------
-// private functions
-// -----------------------------------------------------------------------------
-
// =============================================================================
// implementation
// =============================================================================
+static char **g_argv = NULL;
+
// this function never returns
static void usage()
{
wxString prog = g_argv[0];
- wxString basename = prog.BeforeLast('/');
+ wxString basename = prog.AfterLast('/');
#ifdef __WXMSW__
if ( !basename )
- basename = prog.BeforeLast('\\');
+ basename = prog.AfterLast('\\');
#endif
if ( !basename )
basename = prog;
- wxLogError(
+ wxLogMessage(
"usage: %s [global options] <mode> [mode options] <files...>\n"
"\n"
" where global options are:\n"
exit(1);
}
-/*
int main(int argc, char **argv)
{
-*/
+ g_argv = argv;
+
+ wxInitializer initializer;
+ if ( !initializer )
+ {
+ fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
+
+ return -1;
+ }
-bool HelpGenApp::OnInit()
-{
enum
{
Mode_None,
Mode_Diff
} mode = Mode_None;
- g_argv = argv;
-
if ( argc < 2 ) {
usage();
}
wxArrayString filesH, filesTeX;
wxString directoryOut, // directory for 'dmup' output
ignoreFile; // file with classes/functions to ignore
- bool overwrite = FALSE, // overwrite existing files during 'dump'?
- paramNames = FALSE; // check param names during 'diff'?
+ bool overwrite = false, // overwrite existing files during 'dump'?
+ paramNames = false; // check param names during 'diff'?
for ( int current = 1; current < argc ; current++ ) {
// all options have one letter
case 'q':
// be quiet
- wxLog::GetActiveTarget()->SetVerbose(FALSE);
+ wxLog::GetActiveTarget()->SetVerbose(false);
continue;
case 'H':
// help requested
usage();
+ // doesn't return
+
+ case 'V':
+ // version requested
+ wxLogMessage("HelpGen version %s\n"
+ "(c) 1999-2001 Vadim Zeitlin\n",
+ GetVersionString().c_str());
+ return 0;
case 'i':
current++;
break;
}
- paramNames = TRUE;
+ paramNames = true;
continue;
case 'f':
break;
}
- overwrite = TRUE;
+ overwrite = true;
continue;
case 'o':
}
directoryOut = argv[current];
- if ( !!directoryOut ) {
+ if ( !directoryOut.empty() ) {
// terminate with a '/' if it doesn't have it
switch ( directoryOut.Last() ) {
case '/':
// create a parser object and a visitor derivation
CJSourceParser parser;
HelpGenVisitor visitor(directoryOut, overwrite);
- if ( !!ignoreFile && mode == Mode_Dump )
+ if ( !ignoreFile.empty() && mode == Mode_Dump )
visitor.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
spContext *ctxTop = NULL;
}
}
- if ( !!ignoreFile )
+ if ( !ignoreFile.empty() )
docman.GetIgnoreHandler().AddNamesFromFile(ignoreFile);
docman.DumpDifferences(ctxTop);
}
- return false;
+ return 0;
}
// -----------------------------------------------------------------------------
void HelpGenVisitor::Reset()
{
m_inClass =
- m_inFunction =
m_inTypesSection =
- m_inMethodSection = FALSE;
+ m_inMethodSection = false;
+ m_classname =
+ m_funcName =
+ m_textFunc =
m_textStoredTypedefs =
- m_textStoredEnums =
m_textStoredFunctionComment = "";
+
+ m_arrayFuncDocs.Empty();
+
+ m_storedEnums.Empty();
+ m_storedEnumsVerb.Empty();
m_headers.Empty();
}
void HelpGenVisitor::InsertEnumDocs()
{
- m_file.WriteTeX(m_textStoredEnums);
- m_textStoredEnums.Empty();
+ size_t count = m_storedEnums.GetCount();
+ for ( size_t n = 0; n < count; n++ )
+ {
+ m_file.WriteTeX(m_storedEnums[n]);
+ m_file.WriteVerbatim(m_storedEnumsVerb[n] + '\n');
+ }
+
+ m_storedEnums.Empty();
+ m_storedEnumsVerb.Empty();
}
void HelpGenVisitor::InsertDataStructuresHeader()
{
if ( !m_inTypesSection ) {
- m_inTypesSection = TRUE;
+ m_inTypesSection = true;
- m_file.WriteTeX("\\wxheading{Data structures}\n\n");
+ m_file.WriteVerbatim("\\wxheading{Data structures}\n\n");
}
}
void HelpGenVisitor::InsertMethodsHeader()
{
if ( !m_inMethodSection ) {
- m_inMethodSection = TRUE;
+ m_inMethodSection = true;
- m_file.WriteTeX( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n");
+ m_file.WriteVerbatim( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n");
}
}
void HelpGenVisitor::CloseFunction()
{
- if ( m_inFunction ) {
- m_inFunction = FALSE;
-
- wxString totalText;
+ if ( !m_funcName.empty() ) {
if ( m_isFirstParam ) {
// no params found
- totalText << "\\void";
+ m_textFunc << "\\void";
}
- totalText << "}\n\n";
+ m_textFunc << "}\n\n";
- if ( !m_textStoredFunctionComment.IsEmpty() )
- totalText << m_textStoredFunctionComment << '\n';
+ if ( !m_textStoredFunctionComment.empty() ) {
+ m_textFunc << m_textStoredFunctionComment << '\n';
+ }
+
+ m_arrayFuncDocs.Add(new FunctionDocEntry(m_funcName, m_textFunc));
- m_file.WriteTeX(totalText);
+ m_funcName.clear();
}
}
+void HelpGenVisitor::CloseClass()
+{
+ CloseFunction();
+
+ if ( m_inClass )
+ {
+ size_t count = m_arrayFuncDocs.GetCount();
+ if ( count )
+ {
+ size_t n;
+ FunctionDocEntry::classname = m_classname;
+
+ m_arrayFuncDocs.Sort(FunctionDocEntry::Compare);
+
+ // Now examine each first line and if it's been seen, cut it
+ // off (it's a duplicate \membersection)
+ wxHashTable membersections(wxKEY_STRING);
+
+ for ( n = 0; n < count; n++ )
+ {
+ wxString section(m_arrayFuncDocs[n].text);
+
+ // Strip leading whitespace
+ int pos = section.Find("\\membersection");
+ if (pos > -1)
+ {
+ section = section.Mid(pos);
+ }
+
+ wxString ms(section.BeforeFirst(wxT('\n')));
+ if (membersections.Get(ms))
+ {
+ m_arrayFuncDocs[n].text = section.AfterFirst(wxT('\n'));
+ }
+ else
+ {
+ membersections.Put(ms.c_str(), & membersections);
+ }
+ }
+
+ for ( n = 0; n < count; n++ ) {
+ m_file.WriteTeX(m_arrayFuncDocs[n].text);
+ }
+
+ m_arrayFuncDocs.Empty();
+ }
+
+ m_inClass = false;
+ m_classname.clear();
+ }
+ m_file.FlushAll();
+}
+
void HelpGenVisitor::EndVisit()
{
CloseFunction();
+ CloseClass();
+
m_fileHeader.Empty();
+ m_file.FlushAll();
+ if (m_file.IsOpened())
+ {
+ m_file.Flush();
+ m_file.Close();
+ }
+
wxLogVerbose("%s: finished generating for the current file.",
- GetCurrentTime("%H:%M:%S"));
+ GetCurrentTimeFormatted("%H:%M:%S"));
}
void HelpGenVisitor::VisitFile( spFile& file )
{
m_fileHeader = file.mFileName;
wxLogVerbose("%s: started generating docs for classes from file '%s'...",
- GetCurrentTime("%H:%M:%S"), m_fileHeader.c_str());
+ GetCurrentTimeFormatted("%H:%M:%S"), m_fileHeader.c_str());
}
void HelpGenVisitor::VisitClass( spClass& cl )
{
- m_inClass = FALSE; // will be left FALSE on error
+ CloseClass();
+
+ if (m_file.IsOpened())
+ {
+ m_file.Flush();
+ m_file.Close();
+ }
wxString name = cl.GetName();
// the file name is built from the class name by removing the leading "wx"
// if any and converting it to the lower case
- wxString filename = m_directoryOut;
+ wxString filename;
if ( name(0, 2) == "wx" ) {
filename << name.c_str() + 2;
}
filename.MakeLower();
filename += ".tex";
+ filename.Prepend(m_directoryOut);
if ( !m_overwrite && wxFile::Exists(filename) ) {
wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
}
m_inMethodSection =
- m_inTypesSection = FALSE;
+ m_inTypesSection = false;
wxLogInfo("Created new file '%s' for class '%s'.",
filename.c_str(), name.c_str());
+ // write out the header
+ wxString header;
+ header.Printf("%%\n"
+ "%% automatically generated by HelpGen %s from\n"
+ "%% %s at %s\n"
+ "%%\n"
+ "\n"
+ "\n"
+ "\\section{\\class{%s}}\\label{%s}\n\n",
+ GetVersionString().c_str(),
+ m_fileHeader.c_str(),
+ GetCurrentTimeFormatted("%d/%b/%y %H:%M:%S"),
+ name.c_str(),
+ wxString(name).MakeLower().c_str());
+
+ m_file.WriteVerbatim(header);
+
// the entire text we're writing to file
wxString totalText;
- // write out the header
- {
- wxString header;
- header.Printf("%%\n"
- "%% automatically generated by HelpGen from\n"
- "%% %s at %s\n"
- "%%\n"
- "\n"
- "\n"
- "\\section{\\class{%s}}\\label{%s}\n",
- m_fileHeader.c_str(), GetCurrentTime("%d/%b/%y %H:%M:%S"),
- name.c_str(), wxString(name).MakeLower().c_str());
-
- totalText << header << '\n';
- }
-
// if the header includes other headers they must be related to it... try to
// automatically generate the "See also" clause
if ( !m_headers.IsEmpty() ) {
- // correspondence between wxWindows headers and class names
+ // correspondence between wxWidgets headers and class names
static const char *headers[] = {
"object",
"defs",
derived << "No base class";
}
else {
- bool first = TRUE;
+ bool first = true;
for ( StrListT::const_iterator i = baseClasses.begin();
i != baseClasses.end();
i++ ) {
derived << "\\\\\n";
}
else {
- first = FALSE;
+ first = false;
}
wxString baseclass = *i;
}
totalText << derived << "\n\n";
+ // include file section
+ wxString includeFile = "\\wxheading{Include files}\n\n";
+ includeFile << "<" << m_fileHeader << ">";
+
+ totalText << includeFile << "\n\n";
+
// write all this to file
m_file.WriteTeX(totalText);
InsertDataStructuresHeader();
InsertTypedefDocs();
InsertEnumDocs();
+
+ //m_file.Flush();
}
void HelpGenVisitor::VisitEnumeration( spEnumeration& en )
}
// simply copy the enum text in the docs
- wxString enumeration = GetAllComments(en);
- enumeration << "{\\small \\begin{verbatim}\n"
- << en.mEnumContent
- << "\n\\end{verbatim}}\n";
+ wxString enumeration = GetAllComments(en),
+ enumerationVerb;
+
+ enumerationVerb << "\\begin{verbatim}\n"
+ << en.mEnumContent
+ << "\n\\end{verbatim}\n";
// remember for later use if we're not inside a class yet
if ( !m_inClass ) {
- if ( !m_textStoredEnums.IsEmpty() ) {
- m_textStoredEnums << '\n';
- }
-
- m_textStoredEnums << enumeration;
+ m_storedEnums.Add(enumeration);
+ m_storedEnumsVerb.Add(enumerationVerb);
}
else {
// write the header for this section if not done yet
InsertDataStructuresHeader();
- enumeration << '\n';
m_file.WriteTeX(enumeration);
+ m_file.WriteVerbatim(enumerationVerb);
+ m_file.WriteVerbatim('\n');
}
}
// remember for later use if we're not inside a class yet
if ( !m_inClass ) {
- if ( !m_textStoredTypedefs.IsEmpty() ) {
+ if ( !m_textStoredTypedefs.empty() ) {
m_textStoredTypedefs << '\n';
}
return;
}
- wxString funcname = op.GetName(),
- classname = op.GetClass().GetName();
- if ( m_ignoreNames.IgnoreMethod(classname, funcname) ) {
+ m_classname = op.GetClass().GetName();
+ wxString funcname = op.GetName();
+
+ if ( m_ignoreNames.IgnoreMethod(m_classname, funcname) ) {
wxLogVerbose("Skipping ignored '%s::%s'.",
- classname.c_str(), funcname.c_str());
+ m_classname.c_str(), funcname.c_str());
return;
}
InsertMethodsHeader();
// save state info
- m_inFunction =
- m_isFirstParam = TRUE;
+ m_funcName = funcname;
+ m_isFirstParam = true;
m_textStoredFunctionComment = GetAllComments(op);
// check for the special case of dtor
wxString dtor;
- if ( (funcname[0] == '~') && (classname == funcname.c_str() + 1) ) {
- dtor.Printf("\\destruct{%s}", classname.c_str());
+ if ( (funcname[0u] == '~') && (m_classname == funcname.c_str() + 1) ) {
+ dtor.Printf("\\destruct{%s}", m_classname.c_str());
funcname = dtor;
}
- totalText.Printf("\n"
- "\\membersection{%s::%s}\\label{%s}\n"
- "\n"
- "\\%sfunc{%s%s}{%s}{",
- classname.c_str(), funcname.c_str(),
- MakeLabel(classname, funcname).c_str(),
- op.mIsConstant ? "const" : "",
- op.mIsVirtual ? "virtual " : "",
- op.mRetType.c_str(),
- funcname.c_str());
-
- m_file.WriteTeX(totalText);
+ m_textFunc.Printf("\n"
+ "\\membersection{%s::%s}\\label{%s}\n",
+ m_classname.c_str(), funcname.c_str(),
+ MakeLabel(m_classname, funcname).c_str());
+
+ wxString func;
+ func.Printf("\n"
+ "\\%sfunc{%s%s}{%s}{",
+ op.mIsConstant ? "const" : "",
+ op.mIsVirtual ? "virtual " : "",
+ op.m_RetType.c_str(),
+ funcname.c_str());
+ m_textFunc += func;
}
void HelpGenVisitor::VisitParameter( spParameter& param )
{
- if ( !m_inFunction )
+ if ( m_funcName.empty() )
return;
- wxString totalText;
if ( m_isFirstParam ) {
- m_isFirstParam = FALSE;
+ m_isFirstParam = false;
}
else {
- totalText << ", ";
+ m_textFunc << ", ";
}
- totalText << "\\param{" << param.mType << " }{" << param.GetName();
+ m_textFunc << "\\param{" << param.m_Type << " }{" << param.GetName();
wxString defvalue = param.mInitVal;
- if ( !defvalue.IsEmpty() ) {
- totalText << " = " << defvalue;
+ if ( !defvalue.empty() ) {
+ m_textFunc << " = " << defvalue;
}
- totalText << '}';
-
- m_file.WriteTeX(totalText);
+ m_textFunc << '}';
}
// ---------------------------------------------------------------------------
if ( !SkipSpaceUntil(pp, '{') ) {
wxLogWarning("file %s(%d): '{' expected after '\\param'",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
}
else {
if ( !SkipUntil(pp, '}') ) {
wxLogWarning("file %s(%d): '}' expected after '\\param'",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
}
else {
result = wxString(startParam, (*pp)++ - startParam);
wxFile file(m_filename, wxFile::read);
if ( !file.IsOpened() )
- return FALSE;
+ return false;
off_t len = file.Length();
if ( len == wxInvalidOffset )
- return FALSE;
+ return false;
char *buf = new char[len + 1];
buf[len] = '\0';
if ( file.Read(buf, len) == wxInvalidOffset ) {
delete [] buf;
- return FALSE;
+ return false;
}
// reinit everything
m_line = 1;
wxLogVerbose("%s: starting to parse doc file '%s'.",
- GetCurrentTime("%H:%M:%S"), m_filename.c_str());
+ GetCurrentTimeFormatted("%H:%M:%S"), m_filename.c_str());
// the name of the class from the last "\membersection" command: we assume
// that the following "\func" or "\constfunc" always documents a method of
- // this class (and it should always be like that in wxWindows documentation)
+ // this class (and it should always be like that in wxWidgets documentation)
wxString classname;
for ( const char *current = buf; current - buf < len; current++ ) {
if ( !SkipSpaceUntil(¤t, '{') ) {
wxLogWarning("file %s(%d): '{' expected after \\func, "
"\\constfunc or \\membersection.",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
const char *startClass = current;
if ( !SkipUntil(¤t, ':') || *(current + 1) != ':' ) {
wxLogWarning("file %s(%d): '::' expected after "
- "\\membersection.", m_filename.c_str(), m_line);
+ "\\membersection.", m_filename.c_str(), (int)m_line);
}
else {
classname = wxString(startClass, current - startClass);
if ( !SkipUntil(¤t, '}') ) {
wxLogWarning("file %s(%d): '}' expected after return type",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
TeXUnfilter(&returnType);
current++;
- if ( !SkipSpaceUntil(¤t, '{') ) {
+ if ( !SkipSpaceUntil(¤t, '{') ) {
wxLogWarning("file %s(%d): '{' expected after return type",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
const char *funcEnd = current;
if ( !SkipUntil(&funcEnd, '}') ) {
wxLogWarning("file %s(%d): '}' expected after function name",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
current = funcEnd + 1;
// trim spaces from both sides
- funcName.Trim(FALSE);
- funcName.Trim(TRUE);
+ funcName.Trim(false);
+ funcName.Trim(true);
// special cases: '$...$' may be used for LaTeX inline math, remove the
// '$'s
size_t len = strlen("\\destruct{");
if ( funcName(0, len) != "\\destruct{" ) {
wxLogWarning("file %s(%d): \\destruct expected",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
if ( !SkipSpaceUntil(¤t, '}') ) {
wxLogWarning("file %s(%d): '}' expected after destructor",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
if ( !SkipSpaceUntil(¤t, '{') ||
(current++, !SkipSpaceUntil(¤t, '\\')) ) {
wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
wxArrayString paramNames, paramTypes, paramValues;
- bool isVararg = FALSE;
+ bool isVararg = false;
current++; // skip '\\'
lenMatch = TryMatch(current, "void");
// now come {paramtype}{paramname}
wxString paramType = ExtractStringBetweenBraces(¤t);
- if ( !!paramType ) {
+ if ( !paramType.empty() ) {
wxString paramText = ExtractStringBetweenBraces(¤t);
- if ( !!paramText ) {
+ if ( !paramText.empty() ) {
// the param declaration may contain default value
wxString paramName = paramText.BeforeFirst('='),
paramValue = paramText.AfterFirst('=');
// vararg function?
wxString paramText = ExtractStringBetweenBraces(¤t);
if ( paramText == "..." ) {
- isVararg = TRUE;
+ isVararg = true;
}
else {
wxLogWarning("Parameters of '%s::%s' are in "
}
else {
wxLogWarning("file %s(%d): ',' or '}' expected after "
- "'\\param'", m_filename.c_str(), m_line);
+ "'\\param'", m_filename.c_str(), (int)m_line);
continue;
}
// if we got here there was no '\\void', so must have some params
if ( paramNames.IsEmpty() ) {
wxLogWarning("file %s(%d): '\\param' or '\\void' expected",
- m_filename.c_str(), m_line);
+ m_filename.c_str(), (int)m_line);
continue;
}
paramsAll << paramTypes[param] << ' ' << paramNames[param];
}
+ wxString constStr;
+ if (foundCommand == ConstFunc)
+ constStr = _T(" const");
+
wxLogVerbose("file %s(%d): found '%s %s::%s(%s)%s'",
- m_filename.c_str(), m_line,
+ m_filename.c_str(),
+ (int)m_line,
returnType.c_str(),
classname.c_str(),
funcName.c_str(),
paramsAll.c_str(),
- foundCommand == ConstFunc ? " const" : "");
+ constStr.c_str());
// store the info about the just found function
ArrayMethodInfo *methods;
delete [] buf;
wxLogVerbose("%s: finished parsing doc file '%s'.\n",
- GetCurrentTime("%H:%M:%S"), m_filename.c_str());
+ GetCurrentTimeFormatted("%H:%M:%S"), m_filename.c_str());
- return TRUE;
+ return true;
}
bool DocManager::DumpDifferences(spContext *ctxTop) const
{
typedef MMemberListT::const_iterator MemberIndex;
- bool foundDiff = FALSE;
+ bool foundDiff = false;
// flag telling us whether the given class was found at all in the header
size_t nClass, countClassesInDocs = m_classes.GetCount();
bool *classExists = new bool[countClassesInDocs];
for ( nClass = 0; nClass < countClassesInDocs; nClass++ ) {
- classExists[nClass] = FALSE;
+ classExists[nClass] = false;
}
// ctxTop is normally an spFile
}
spClass *ctxClass = (spClass *)ctx;
- const wxString& nameClass = ctxClass->mName;
+ const wxString& nameClass = ctxClass->m_Name;
int index = m_classes.Index(nameClass);
if ( index == wxNOT_FOUND ) {
if ( !m_ignoreNames.IgnoreClass(nameClass) ) {
- foundDiff = TRUE;
+ foundDiff = true;
wxLogError("Class '%s' is not documented at all.",
nameClass.c_str());
continue;
}
else {
- classExists[index] = TRUE;
+ classExists[index] = true;
}
// array of method descriptions for this class
// flags telling if we already processed given function
bool *methodExists = new bool[countMethods];
for ( nMethod = 0; nMethod < countMethods; nMethod++ ) {
- methodExists[nMethod] = FALSE;
+ methodExists[nMethod] = false;
}
wxArrayString aOverloadedMethods;
continue;
spOperation *ctxMethod = (spOperation *)ctx;
- const wxString& nameMethod = ctxMethod->mName;
+ const wxString& nameMethod = ctxMethod->m_Name;
// find all functions with the same name
wxArrayInt aMethodsWithSameName;
if ( aMethodsWithSameName.IsEmpty() && ctxMethod->IsPublic() ) {
if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
- foundDiff = TRUE;
+ foundDiff = true;
wxLogError("'%s::%s' is not documented.",
nameClass.c_str(),
}
else if ( aMethodsWithSameName.GetCount() == 1 ) {
index = (size_t)aMethodsWithSameName[0u];
- methodExists[index] = TRUE;
+ methodExists[index] = true;
if ( m_ignoreNames.IgnoreMethod(nameClass, nameMethod) )
continue;
"in the docs: should be %d instead of %d.",
nameClass.c_str(),
nameMethod.c_str(),
- params.size(), method.GetParamCount());
+ (int)params.size(), (int)method.GetParamCount());
}
else {
size_t nParam = 0;
spParameter *ctxParam = (spParameter *)ctx;
const ParamInfo& param = method.GetParam(nParam);
if ( m_checkParamNames &&
- (param.GetName() != ctxParam->mName) ) {
- foundDiff = TRUE;
+ (param.GetName() != ctxParam->m_Name.c_str()) ) {
+ foundDiff = true;
wxLogError("Parameter #%d of '%s::%s' should be "
"'%s' and not '%s'.",
- nParam + 1,
+ (int)(nParam + 1),
nameClass.c_str(),
nameMethod.c_str(),
- ctxParam->mName.c_str(),
+ ctxParam->m_Name.c_str(),
param.GetName().c_str());
continue;
}
- if ( param.GetType() != ctxParam->mType ) {
- foundDiff = TRUE;
+ if ( param.GetType() != ctxParam->m_Type ) {
+ foundDiff = true;
wxLogError("Type of parameter '%s' of '%s::%s' "
"should be '%s' and not '%s'.",
- ctxParam->mName.c_str(),
+ ctxParam->m_Name.c_str(),
nameClass.c_str(),
nameMethod.c_str(),
- ctxParam->mType.c_str(),
+ ctxParam->m_Type.c_str(),
param.GetType().GetName().c_str());
continue;
}
- if ( param.GetDefValue() != ctxParam->mInitVal ) {
+ if ( param.GetDefValue() != ctxParam->mInitVal.c_str() ) {
wxLogWarning("Default value of parameter '%s' of "
"'%s::%s' should be '%s' and not "
"'%s'.",
- ctxParam->mName.c_str(),
+ ctxParam->m_Name.c_str(),
nameClass.c_str(),
nameMethod.c_str(),
ctxParam->mInitVal.c_str(),
// mark all methods with this name as existing
for ( nMethod = 0; nMethod < countMethods; nMethod++ ) {
if ( methods[nMethod]->GetName() == nameMethod )
- methodExists[nMethod] = TRUE;
+ methodExists[nMethod] = true;
}
aOverloadedMethods.Add(nameMethod);
if ( !methodExists[nMethod] ) {
const wxString& nameMethod = methods[nMethod]->GetName();
if ( !m_ignoreNames.IgnoreMethod(nameClass, nameMethod) ) {
- foundDiff = TRUE;
+ foundDiff = true;
wxLogError("'%s::%s' is documented but doesn't exist.",
nameClass.c_str(),
// check that all classes we found in the docs really exist
for ( nClass = 0; nClass < countClassesInDocs; nClass++ ) {
if ( !classExists[nClass] ) {
- foundDiff = TRUE;
+ foundDiff = true;
wxLogError("Class '%s' is documented but doesn't exist.",
m_classes[nClass].c_str());
{
wxFile file(filename, wxFile::read);
if ( !file.IsOpened() )
- return FALSE;
+ return false;
off_t len = file.Length();
if ( len == wxInvalidOffset )
- return FALSE;
+ return false;
char *buf = new char[len + 1];
buf[len] = '\0';
if ( file.Read(buf, len) == wxInvalidOffset ) {
delete [] buf;
- return FALSE;
+ return false;
}
wxString line;
delete [] buf;
- return TRUE;
+ return true;
}
// -----------------------------------------------------------------------------
}
}
- if ( funcname )
- label << funcname;
+ if ( funcname ) {
+ // special treatment for operatorXXX() stuff because the C operators
+ // are not valid in LaTeX labels
+ wxString oper;
+ if ( wxString(funcname).StartsWith("operator", &oper) ) {
+ label << "operator";
+
+ static const struct
+ {
+ const char *oper;
+ const char *name;
+ } operatorNames[] =
+ {
+ { "=", "assign" },
+ { "==", "equal" },
+ };
+
+ size_t n;
+ for ( n = 0; n < WXSIZEOF(operatorNames); n++ ) {
+ if ( oper == operatorNames[n].oper ) {
+ label << operatorNames[n].name;
+
+ break;
+ }
+ }
+
+ if ( n == WXSIZEOF(operatorNames) ) {
+ wxLogWarning("unknown operator '%s' - making dummy label.",
+ oper.c_str());
+
+ label << "unknown";
+ }
+ }
+ else // simply use the func name
+ {
+ label << funcname;
+ }
+ }
label.MakeLower();
return helpref;
}
-static void TeXUnfilter(wxString* str)
+static void TeXFilter(wxString* str)
{
- // FIXME may be done much more quickly
- str->Trim(TRUE);
- str->Trim(FALSE);
+ // TeX special which can be quoted (don't include backslash nor braces as
+ // we generate them
+ static wxRegEx reNonSpecialSpecials("[#$%&_]"),
+ reAccents("[~^]");
+
+ // just quote
+ reNonSpecialSpecials.ReplaceAll(str, "\\\\\\0");
- str->Replace("\\&", "&");
- str->Replace("\\_", "_");
+ // can't quote these ones as they produce accents when preceded by
+ // backslash, so put them inside verb
+ reAccents.ReplaceAll(str, "\\\\verb|\\0|");
}
-static void TeXFilter(wxString* str)
+static void TeXUnfilter(wxString* str)
{
// FIXME may be done much more quickly
- str->Replace("&", "\\&");
- str->Replace("_", "\\_");
+ str->Trim(true);
+ str->Trim(false);
+
+ // undo TeXFilter
+ static wxRegEx reNonSpecialSpecials("\\\\([#$%&_{}])"),
+ reAccents("\\\\verb\\|([~^])\\|");
+
+ reNonSpecialSpecials.ReplaceAll(str, "\\1");
+ reAccents.ReplaceAll(str, "\\1");
}
static wxString GetAllComments(const spContext& ctx)
wxString comment = (*i)->GetText();
// don't take comments like "// ----------" &c
- comment.Trim(FALSE);
- if ( !!comment &&
+ comment.Trim(false);
+ if ( !comment.empty() &&
comment == wxString(comment[0u], comment.length() - 1) + '\n' )
comments << "\n";
else
return comments;
}
-static const char *GetCurrentTime(const char *timeFormat)
+static const char *GetCurrentTimeFormatted(const char *timeFormat)
{
static char s_timeBuffer[128];
time_t timeNow;
return s_timeBuffer;
}
+static const wxString GetVersionString()
+{
+ wxString version = "$Revision$";
+ wxRegEx("^\\$Revision$$").ReplaceFirst(&version, "\\1");
+ return version;
+}
+
/*
$Log$
+ Revision 1.40 2005/05/30 11:49:32 ABX
+ More warning and error fixes (work in progress with Tinderbox).
+
+ Revision 1.39 2005/05/30 09:26:42 ABX
+ More warning and error fixes (work in progress with Tinderbox).
+
+ Revision 1.38 2005/05/24 09:06:20 ABX
+ More fixes and wxWidgets coding standards.
+
+ Revision 1.37 2005/05/23 15:22:08 ABX
+ Initial HelpGen source cleaning.
+
+ Revision 1.36 2005/04/07 19:54:58 MW
+ Workarounds to allow compilation by Sun C++ 5.5
+
+ Revision 1.35 2004/12/12 11:03:31 VZ
+ give an error message if we're built in Unicode mode (in response to bug 1079224)
+
+ Revision 1.34 2004/11/23 09:53:31 JS
+ Changed GPL to wxWindows Licence
+
+ Revision 1.33 2004/11/12 03:30:07 RL
+
+ Cruft cleanup from MJW, strip the tabs out of sound.cpp
+
+ Revision 1.32 2004/11/10 21:02:58 VZ
+ 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)
+
+ Revision 1.31 2004/10/05 15:38:29 ABX
+ Warning fixes found under hardest mode of OpenWatcom. Seems clean in Borland, MinGW and DMC.
+
+ Revision 1.30 2004/06/18 19:25:50 ABX
+ Small step in making HelpGen up to date unicode application.
+
+ Revision 1.29 2004/06/17 19:00:22 ABX
+ Warning fixes. Code cleanup. Whitespaces and tabs removed.
+
+ Revision 1.28 2004/05/25 11:19:57 JS
+ More name changes
+
+ Revision 1.27 2003/10/13 17:21:30 MBN
+ Compilation fixes.
+
+ Revision 1.26 2003/09/29 15:18:35 MBN
+ (Blind) compilation fix for Sun compiler.
+
+ Revision 1.25 2003/09/03 17:39:27 MBN
+ Compilation fixes.
+
+ Revision 1.24 2003/08/13 22:59:37 VZ
+ compilation fix
+
+ Revision 1.23 2003/06/13 17:05:43 VZ
+ quote '|' inside regexes (fixes dump mode); fixed crash due to strange HelpGenApp code
+
+ Revision 1.22 2002/01/21 21:18:50 JS
+ Now adds 'include file' heading
+
+ Revision 1.21 2002/01/04 11:06:09 JS
+ Fixed missing membersections bug and also bug with functions not being written
+ in the right class
+
+ Revision 1.20 2002/01/03 14:23:33 JS
+ Added code to make it not duplicate membersections for overloaded functions
+
+ Revision 1.19 2002/01/03 13:34:12 JS
+ Added FlushAll to CloseClass, otherwise text was only flushed right at the end,
+ and appeared in one file.
+
+ Revision 1.18 2002/01/03 12:02:47 JS
+ Added main() and corrected VC++ project settings
+
+ Revision 1.17 2001/11/30 21:43:35 VZ
+ now the methods are sorted in the correct order in the generated docs
+
+ Revision 1.16 2001/11/28 19:27:33 VZ
+ HelpGen doesn't work in GUI mode
+
+ Revision 1.15 2001/11/22 21:59:58 GD
+ use "..." instead of <...> for wx headers
+
+ Revision 1.14 2001/07/19 13:51:29 VZ
+ fixes to version string
+
+ Revision 1.13 2001/07/19 13:44:57 VZ
+ 1. compilation fixes
+ 2. don't quote special characters inside verbatim environment
+
+ Revision 1.12 2000/10/09 13:53:33 juliansmart
+
+ Doc corrections; added HelpGen project files
+
+ Revision 1.11 2000/07/15 19:50:42 cvsuser
+ merged 2.2 branch
+
+ Revision 1.10.2.2 2000/03/27 15:33:10 VZ
+ don't trasnform output dir name to lower case
+
+ Revision 1.10 2000/03/11 10:05:23 VS
+ now compiles with wxBase
+
+ Revision 1.9 2000/01/16 13:25:21 VS
+ compilation fixes (gcc)
+
Revision 1.8 1999/09/13 14:29:39 JS
+
Made HelpGen into a wxWin app (still uses command-line args); moved includes
into src for simplicity; added VC++ 5 project file
date: 1999/01/08 17:45:55; author: VZ; state: Exp;
HelpGen is a prototype of the tool for automatic generation of the .tex files
- for wxWindows documentation from C++ headers
+ for wxWidgets documentation from C++ headers
*/
/* vi: set tw=80 et ts=4 sw=4: */