#ifndef DOCPP_H #define DOCPP_H #include NAMESPACE_UPP bool IsCPPFile(const String& file); bool IsHFile(const String& path); const char *SkipString(const char *s); void RemoveComments(String& l, bool& incomment); String GetStdDefs(); void SetPPDefs(const String& defs); const VectorMap& GetNamespaceMacros(); const Index& GetNamespaceEndMacros(); struct CppMacro : Moveable { String param; String body; byte md5[16]; String Define(const char *s); void SetUndef() { body = "\x7f"; } bool IsUndef() const { return body[0] == '\x7f' && body[1] == '\0'; } String Expand(const Vector& p, const Vector& ep) const; void Serialize(Stream& s); String ToString() const; }; enum PPItemType { PP_DEFINES, PP_INCLUDE, PP_USING, PP_NAMESPACE, PP_NAMESPACE_END }; struct PPItem { int type; String text; int segment_id; void Serialize(Stream& s) { s % type % text % segment_id; } }; struct PPMacro : Moveable { CppMacro macro; int segment_id; // a group of macros in single file, between other elements (include, namespace. using, undef...) int line; // line in file int undef_segment_id; // macro has matching undef in the same file within this segment void Serialize(Stream& s) { s % macro % segment_id % line % undef_segment_id; } String ToString() const { return AsString(macro) + " " + AsString(segment_id); } PPMacro() { undef_segment_id = 0; } }; struct PPFile { // contains "macro extract" of file, only info about macros defined and namespaces Time filetime; Array item; Index includes; Vector keywords; String md5sum; void Parse(Stream& in); void Serialize(Stream& s) { s % filetime % item % includes % keywords % md5sum; } void Dump() const; private: Vector ppmacro; // indicies of macros in sAllMacros void CheckEndNamespace(Vector& namespace_block, int level, Md5Stream& md5); }; PPMacro *FindPPMacro(const String& id, Index& segment_id, int& segmenti); const CppMacro *FindMacro(const String& id, Index& segment_id, int& segmenti); void PPSync(const String& include_path); String GetIncludePath(); void CleanPP(); void SerializePPFiles(Stream& s); void SweepPPFiles(const Index& keep); String GetSegmentFile(int segment_id); const PPFile& GetPPFile(const char *path); void InvalidateFileTimeCache(); void InvalidateFileTimeCache(const String& path); Time GetFileTimeCached(const String& path); String GetIncludePath(const String& s, const String& filedir); bool IncludesFile(const String& parent_path, const String& header_path); struct FlatPP { Index segment_id; Index usings; }; const FlatPP& GetFlatPPFile(const char *path); // with #includes resolved String NormalizeSourcePath(const String& path, const String& currdir); String NormalizeSourcePath(const String& path); void ClearSources(); const Index& GetAllSources(); void GatherSources(const String& master_path, const String& path_); String GetMasterFile(const String& file); const VectorMap& GetAllSourceMasters(); struct Cpp { static Index kw; bool incomment; bool done; Index visited; Index segment_id; // segments of included macros VectorMap macro; // macros defined int std_macros; // standard macros (keywords and trick - fixed) Index notmacro; // accelerator / expanding helper String prefix_macro; // for handling multiline macros String output; // preprocessed file // Index usedmacro; Index namespace_using; // 'using namespace' up to start of file Vector namespace_stack; // namspace up to start of file Md5Stream md5; void Define(const char *s); void ParamAdd(Vector& param, const char *b, const char *e); String Expand(const char *s); void DoFlatInclude(const String& header_path); void Do(const String& sourcefile, Stream& in, const String& currentfile, bool get_macros); bool Preprocess(const String& sourcefile, Stream& in, const String& currentfile, bool just_get_macros = false); String GetDependeciesMd5(const Vector& m); typedef Cpp CLASSNAME; }; enum tk_Keywords { Tmarker_before_first = 255, #define CPPID(x) tk_##x, #include "keyword.i" #undef CPPID }; enum t_Terms { t_eof, t_string = -200, t_integer, t_double, t_character, t_dblcolon, t_mulass, t_divass, t_modass, t_xorass, t_neq, t_dot_asteriks, t_elipsis, t_inc, t_addass, t_dec, t_arrow_asteriks, t_arrow, t_subass, t_and, t_andass, t_or, t_orass, t_eq, t_shl, t_shlass, t_le, t_shr, t_shrass, t_ge, te_integeroverflow, te_badcharacter, te_badstring, }; const char **CppKeyword(); class LexSymbolStat { public: LexSymbolStat(); void Reset(int minSymbol, int maxSymbol); void IncStat(int symbol); int GetStat(int symbol) const; int SumStat(const Vector & symbols) const; void Merge(const LexSymbolStat & other); private: Vector v; int minSymbol; }; class Lex { #ifdef _DEBUG const char *pp; #endif const char *ptr; const char *pos; Index id; int endkey; int braceslevel; struct Term : Moveable{ const char *ptr; int code; String text; double number; bool grounding; Term() { grounding = false; } }; bool statsCollected; LexSymbolStat symbolStat; BiVector term; int body; bool grounding; bool Char(int c) { if(*ptr == c) { ptr++; return true; } else return false; } void AddCode(int code) { Term& tm = term.AddTail(); tm.code = code; tm.ptr = pos; tm.grounding = grounding; } void AssOp(int noass, int ass) { AddCode(Char('=') ? ass : noass); } void Next(); bool Prepare(int pos); int GetCharacter(); void ThrowError(const char *e); public: Callback1 WhenError; struct Grounding {}; int Code(int pos = 0); bool IsId(int pos = 0); String Id(int pos = 0); int Int(int pos = 0); double Double(int pos = 0); int Chr(int pos = 0); String Text(int pos = 0); void Get(int n = 1); int GetCode() { int q = Code(); Get(); return q; } String GetId() { String q = Id(); Get(); return q; } int GetInt() { int q = Int(); Get(); return q; } double GetDouble() { double q = Double(); Get(); return q; } int GetChr() { int q = Chr(); Get(); return q; } String GetText() { String q = Text(); Get(); return q; } int Id(const String& s) { return id.FindAdd(s) + 256; } int GetBracesLevel() const { return braceslevel; } void ClearBracesLevel() { braceslevel = 0; } void BeginBody() { body++; } void EndBody() { body--; } void ClearBody() { body = 0; } bool IsBody() const { return body; } bool IsGrounded() { Code(); return term.GetCount() && term[0].grounding; } void SkipToGrounding(); const char *Pos(int pos = 0); int operator[](int pos) { return Code(pos); } operator int() { return Code(0); } void operator++() { return Get(); } void Dump(int pos); void Init(const char *s); void StartStatCollection(); const LexSymbolStat & FinishStatCollection(); Lex(); }; struct SrcFile { SrcFile(); rval_default(SrcFile); String text; Vector linepos; int preprocessorLinesRemoved; int blankLinesRemoved; int commentLinesRemoved; }; struct Parser; SrcFile PreProcess(Stream& in, Parser& parser); enum Kind { STRUCT, STRUCTTEMPLATE, TYPEDEF, CONSTRUCTOR, DESTRUCTOR, FUNCTION, INSTANCEFUNCTION, CLASSFUNCTION, FUNCTIONTEMPLATE, INSTANCEFUNCTIONTEMPLATE, CLASSFUNCTIONTEMPLATE, INLINEFRIEND, VARIABLE, INSTANCEVARIABLE, CLASSVARIABLE, ENUM, MACRO, FRIENDCLASS, NAMESPACE, }; inline bool IsCppType(int i) { return i >= STRUCT && i <= TYPEDEF || i == FRIENDCLASS; } inline bool IsCppCode(int i) { return i >= CONSTRUCTOR && i <= INLINEFRIEND; }; inline bool IsCppData(int i) { return i >= VARIABLE && i <= ENUM; } inline bool IsCppMacro(int i) { return i == MACRO; } inline bool IsCppTemplate(int i) { return i == STRUCTTEMPLATE || i >= FUNCTIONTEMPLATE && i <= CLASSFUNCTIONTEMPLATE; } enum CppAccess { PUBLIC, PROTECTED, PRIVATE, }; enum FileTypeEnum { FILE_H, FILE_HPP, FILE_CPP, FILE_C, FILE_OTHER, }; struct CppItem { String qitem; String item; String name; String uname; String natural; String type; String qtype; String tparam; // complete template parameters list, like '' String param; String pname; String ptype; // fn: types of parameters, struct: base classes String qptype; String tname; String ctname; String using_namespaces; byte access; byte kind; int16 at; bool virt; bool decla; bool lvalue; bool isptr; byte filetype; bool impl; int file; int line; bool qualify; bool IsType() const { return IsCppType(kind); } bool IsCode() const { return IsCppCode(kind); } bool IsData() const { return IsCppData(kind); } bool IsMacro() const { return IsCppMacro(kind); } bool IsTemplate() const { return IsCppTemplate(kind); } void Serialize(Stream& s); void Dump(Stream& s) const; String ToString() const; CppItem() { at = decla = virt = false; qualify = true; isptr = false; } }; String CppItemKindAsString(int kind); int FindItem(const Array& x, const String& qitem); int FindName(const Array& x, const String& name, int i = 0); struct CppBase : ArrayMap > { String types_md5; Index namespaces; bool IsType(int i) const; void Sweep(const Index& keep_file); void RemoveFiles(const Index& remove_file); void RemoveFile(int filei); void Dump(Stream& s); }; struct Parser { struct Context { String scope; String ctname; Vector tparam; Index typenames; int access; String namespace_using; void operator<<=(const Context& t); String Dump() const; Context() {} rval_default(Context); }; struct Decla { bool s_static; bool s_extern; bool s_register; bool s_mutable; bool s_explicit; bool s_virtual; String name; bool function; bool type_def; bool isfriend; bool istemplate; bool istructor; bool isdestructor; bool isptr; bool nofn; bool oper; bool castoper; String tnames; String type; String natural; Decla(); }; struct Decl : Decla { Array param; rval_default(Decl); Decl() {} }; struct RecursionCounter { int change; int &count; RecursionCounter(int &count_i, int change_i = 1) : change(change_i), count(count_i) { count += change; } ~RecursionCounter() { count -= change; } }; Context context; SrcFile file; Lex lex; int filei; byte filetype; String title; bool inbody; int struct_level; Callback2 err; int lpos, line; CppBase *base; int RPtr(); bool Key(int code); bool EatBody(); String ResolveAutoType(); void Cv(); String TType(); String ReadType(Decla& d, const String& tname, const String& tparam); void Qualifier(); void ParamList(Decl& d); void Declarator(Decl& d, const char *p); void EatInitializers(); void Vars(Array& r, const char *p, bool type_def, bool more); void ReadMods(Decla& d); Array Declaration0(bool l0, bool more, const String& tname, const String& tparam); Array Declaration(bool l0/* = false*/, bool more/* = false*/, const String& tname, const String& tparam); bool IsParamList(int q); void Elipsis(Decl& d); Decl& Finish(Decl& d, const char *p); void AddNamespace(const String& n, const String& name); bool Scope(const String& tp, const String& tn); String TemplateParams(String& pnames); String TemplateParams(); String TemplatePnames(); String Name(String& h, bool& castoper, bool& oper); String Name(bool& castoper, bool& oper); String Constant(); String ReadOper(bool& castoper); int GetLine(const char *pos); void Line(); void Check(bool b, const char *err); void CheckKey(int c); bool UsingNamespace(); void SetScopeCurrent(); void ScopeBody(); void Do(); String AnonymousName(); String StructDeclaration(const String& tp, const String& tn); void Enum(); CppItem& Item(const String& scope, const String& using_namespace, const String& item, const String& name, bool impl); CppItem& Item(const String& scope, const String& using_namespace, const String& item, const String& name); CppItem& Fn(const Decl& d, const String& templ, bool body, const String& tname, const String& tparam); struct Error {}; void ThrowError(const String& e); void Resume(int bl); void MatchPars(); bool VCAttribute(); bool TryDecl(); void Statement(); void Locals(const String& type); String Tparam(int& q); friend class Lex; // Fix to make Lex::ThrowError typedef Parser CLASSNAME; public: void AddMacro(int lineno, const String& macro); struct FunctionStat { FunctionStat(const String & scope, const CppItem & cppItem, const LexSymbolStat &symbolStat, int maxScopeDepth); String scope; const CppItem & cppItem; const LexSymbolStat &symbolStat; int maxScopeDepth; }; bool IsInBody() const { return inbody; } typedef Callback1 FnEndCallback; bool dobody; String current_scope; String current_key; String current_name; CppItem current; int currentScopeDepth; int maxScopeDepth; String namespace_info; struct Local : Moveable { String type; bool isptr; int line; }; VectorMap local; FnEndCallback whenFnEnd; LexSymbolStat symbolsOutsideFunctions; const SrcFile &getPreprocessedFile() { return file; } Vector GetNamespaces() const; void Do(Stream& in, CppBase& _base, int file, int filetype, const String& title, Callback2 _err, const Vector& typenames, const Vector& namespace_stack, const Index& namespace_using); Parser() : dobody(false) { lex.WhenError = THISBACK(ThrowError); } }; String NoTemplatePars(const String& type); class ScopeInfo { // information about scope bool bvalid; // baselist is valid bool nvalid; // scopes is valid Vector baselist; // list of all base classes of scope Vector scopes; // list of scopes (Upp::String::Init::, Upp::String::, Upp::) int scopei; // index of this scope in base String usings; // using namespaces contained in scopes void Bases(int i, Vector& g); void Init(); public: const CppBase& base; VectorMap cache; const Vector& GetBases(); const Vector& GetScopes(const String& usings); int GetScope() const { return scopei; } void NoBases() { baselist.Clear(); bvalid = true; } ScopeInfo(const CppBase& base, int scopei = -1); ScopeInfo(int scopei, const CppBase& base); ScopeInfo(const CppBase& base, const String& scope); ScopeInfo(const ScopeInfo& f); }; String Qualify(const CppBase& base, const String& scope, const String& type, const String& usings); void QualifyTypes(CppBase& base, const String& scope, CppItem& m); String QualifyKey(const CppBase& base, const String& scope, const String& type, const String& usings); void Qualify(CppBase& base); const Array& GetTypeItems(const CppBase& codebase, const String& type); String ParseTemplatedType(const String& type, Vector& tparam); String ResolveTParam(const CppBase& codebase, const String& type, const Vector& tparam); void ResolveTParam(const CppBase& codebase, Vector& type, const Vector& tparam); Index GetExpressionType(const CppBase& codebase, const Parser& parser, const Vector& xp); Vector MakeXP(const char *s); END_UPP_NAMESPACE #endif