📄 helpgen.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Name: HelpGen.cpp// Purpose: Main program file for HelpGen// Author: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>// Modified by:// Created: 06/01/99// RCS-ID: $Id: HelpGen.cpp,v 1.44 2005/05/31 17:47:45 ABX Exp $// Copyright: (c) 1999 VZ// Licence: wxWindows Licence//////////////////////////////////////////////////////////////////////////////* BUGS 1. wx/string.h confuses C++ parser terribly 2. C++ parser doesn't know about virtual functions, nor static ones 3. param checking is not done for vararg functions 4. type comparison is dumb: it doesn't know that "char *" is the same that "char []" nor that "const char *" is the same as "char const *" TODO (+ means fixed), see also the change log at the end of the file. (i) small fixes in the current version +1. Quote special TeX characters like '&' and '_' (=> derive from wxFile) 2. Document typedefs 3. Document global variables 4. Document #defines +5. Program options 6. Include file name/line number in the "diff" messages? +7. Support for vararg functions (ii) plans for version 2 1. Use wxTextFile for direct file access to avoid one scan method problems 2. Use command line parser class for the options 3. support for overloaded functions in diff mode (search for OVER) (iii) plans for version 3 1. Merging with existing files 2. GUI*/// =============================================================================// declarations// =============================================================================// -----------------------------------------------------------------------------// headers// -----------------------------------------------------------------------------// 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/app.h"#endif // WX_PRECOMP#include "wx/file.h"#include "wx/regex.h"#include "wx/hash.h"// C++ parsing classes#include "cjparser.h"// standard headers#include <stdio.h>#include <time.h>// -----------------------------------------------------------------------------// private functions// -----------------------------------------------------------------------------// return the label for the given function name (i.e. argument of \label)static wxString MakeLabel(const wxChar *classname, const wxChar *funcname = NULL);// return the whole \helpref{arg}{arg_label} stringstatic wxString MakeHelpref(const wxChar *argument);// [un]quote special TeX characters (in place)static void TeXFilter(wxString* str);static void TeXUnfilter(wxString* str); // also trims spaces// get all comments associated with this contextstatic wxString GetAllComments(const spContext& ctx);// get the string with current time (returns pointer to static buffer)// timeFormat is used for the call of strftime(3)static const char *GetCurrentTimeFormatted(const char *timeFormat);// get the string containing the program versionstatic const wxString GetVersionString();// -----------------------------------------------------------------------------// private classes// -----------------------------------------------------------------------------// a function documentation entrystruct 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() { } // 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); 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// the documentation purposes (used by both HelpGenVisitor and DocManager)class IgnoreNamesHandler{public: IgnoreNamesHandler() : m_ignore(CompareIgnoreListEntries) { } ~IgnoreNamesHandler() { WX_CLEAR_ARRAY(m_ignore); } // load file with classes/functions to ignore (add them to the names we // already have) bool AddNamesFromFile(const wxString& filename); // return true if we ignore this function bool IgnoreMethod(const wxString& classname, const wxString& funcname) const { if ( IgnoreClass(classname) ) return true; IgnoreListEntry ignore(classname, funcname); return m_ignore.Index(&ignore) != wxNOT_FOUND; } // return true if we ignore this class entirely bool IgnoreClass(const wxString& classname) const { IgnoreListEntry ignore(classname, wxEmptyString); return m_ignore.Index(&ignore) != wxNOT_FOUND; }protected: struct IgnoreListEntry { IgnoreListEntry(const wxString& classname, const wxString& funcname) : m_classname(classname), m_funcname(funcname) { } wxString m_classname; wxString m_funcname; // if empty, ignore class entirely }; static int CompareIgnoreListEntries(IgnoreListEntry *first, IgnoreListEntry *second); // for efficiency, let's sort itpublic: // FIXME: macro requires it WX_DEFINE_SORTED_ARRAY(IgnoreListEntry *, ArrayNamesToIgnore);protected: ArrayNamesToIgnore m_ignore;private: IgnoreNamesHandler(const IgnoreNamesHandler&); IgnoreNamesHandler& operator=(const IgnoreNamesHandler&);};// visitor implementation which writes all collected data to a .tex fileclass HelpGenVisitor : public spVisitor{public: // ctor HelpGenVisitor(const wxString& directoryOut, bool overwrite); virtual void VisitFile( spFile& fl ); virtual void VisitClass( spClass& cl ); virtual void VisitEnumeration( spEnumeration& en ); virtual void VisitTypeDef( spTypeDef& td ); virtual void VisitPreprocessorLine( spPreprocessorLine& pd ); virtual void VisitAttribute( spAttribute& attr ); virtual void VisitOperation( spOperation& op ); virtual void VisitParameter( spParameter& param ); void EndVisit(); // get our `ignore' object IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; } // shut up g++ warning (ain't it stupid?) virtual ~HelpGenVisitor() { }protected: // (re)initialize the state void Reset(); // insert documentation for enums/typedefs coming immediately before the // class declaration into the class documentation void InsertTypedefDocs(); void InsertEnumDocs(); // write the headers for corresponding sections (only once) void InsertDataStructuresHeader(); void InsertMethodsHeader(); // 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 m_inTypesSection, // enums & typedefs go there m_inMethodSection, // functions go here 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_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; // ignore handler: tells us which classes to ignore for doc generation // purposes IgnoreNamesHandler m_ignoreNames;private: HelpGenVisitor(const HelpGenVisitor&); HelpGenVisitor& operator=(const HelpGenVisitor&);};// documentation manager - a class which parses TeX files and remembers the// functions documented in them and can later compare them with all functions// found under ctxTop by C++ parserclass DocManager{public: DocManager(bool checkParamNames); ~DocManager(); // returns false on failure bool ParseTeXFile(const wxString& filename); // returns false if there were any differences bool DumpDifferences(spContext *ctxTop) const; // get our `ignore' object IgnoreNamesHandler& GetIgnoreHandler() { return m_ignoreNames; }protected: // parsing TeX files // ----------------- // returns the length of 'match' if the string 'str' starts with it or 0 // otherwise 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) const char *SkipSpaces(const char *p) { while ( isspace(*p) ) { if ( *p++ == '\n' ) m_line++; } return p; } // 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 // 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 bool SkipSpaceUntil(const char **pp, char c); // extract the string between {} and modify '*pp' to point at the // character immediately after the closing '}'. The returned string is empty // on error. wxString ExtractStringBetweenBraces(const char **pp); // the current file and line while we're in ParseTeXFile (for error // messages) wxString m_filename; size_t m_line; // functions and classes to ignore during diff // ------------------------------------------- IgnoreNamesHandler m_ignoreNames; // 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 { public: TypeInfo(const wxString& type) : m_type(type) { }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -