From e8035690b984f06c1d3794b6ef6b4dcd2e0505b4 Mon Sep 17 00:00:00 2001 From: mirek-fidler Date: Fri, 16 Sep 2022 10:31:14 +0200 Subject: [PATCH] libclang ide #94 - Assist/Autocomplete refactored to use libclang Other minor changes: - Removed CoWork Pipe - .dli runtime loading of dynamic libraries now supports path to library in access function - EditField::SetBackground - RichTextView::GotoLabel variant with Gate for matching - RichEdit::GotoLabel variant with Gate for matching --- uppsrc/CodeEditor/CodeEditor.h | 8 +- uppsrc/CodeEditor/EditorBar.cpp | 2 + uppsrc/Core/CoWork.cpp | 30 - uppsrc/Core/CoWork.h | 6 - uppsrc/Core/Core.h | 2 - uppsrc/Core/Dli.cpp | 22 +- uppsrc/Core/Fn.h | 15 - uppsrc/Core/Mt.cpp | 29 +- uppsrc/Core/Mt.h | 4 +- uppsrc/Core/SplitMerge.h | 23 - uppsrc/Core/Topt.h | 48 +- uppsrc/Core/Util.h | 4 +- uppsrc/Core/dli.h | 8 + uppsrc/CppBase/Base.cpp | 103 -- uppsrc/CppBase/Body.cpp | 308 ---- uppsrc/CppBase/Copying | 22 - uppsrc/CppBase/CppBase.h | 260 --- uppsrc/CppBase/CppBase.upp | 28 - uppsrc/CppBase/CppItem.cpp | 82 - uppsrc/CppBase/Expression.cpp | 546 ------ uppsrc/CppBase/Iface.cpp | 83 - uppsrc/CppBase/Internal.h | 450 ----- uppsrc/CppBase/Parser.cpp | 1796 -------------------- uppsrc/CppBase/Pre.cpp | 188 -- uppsrc/CppBase/Qualify.cpp | 315 ---- uppsrc/CppBase/ScopeInfo.cpp | 133 -- uppsrc/CppBase/cpp.cpp | 391 ----- uppsrc/CppBase/cpplex.cpp | 499 ------ uppsrc/CppBase/keyword.i | 101 -- uppsrc/CppBase/macro.cpp | 158 -- uppsrc/CppBase/ppconfig.cpp | 52 - uppsrc/CppBase/ppfile.cpp | 693 -------- uppsrc/CppBase/srcfiles.cpp | 89 - uppsrc/CppBase/util.cpp | 78 - uppsrc/CtrlCore/CocoCtrl.h | 2 - uppsrc/CtrlCore/CocoTop.h | 2 - uppsrc/CtrlCore/CtrlMt.cpp | 4 +- uppsrc/CtrlCore/Gtk.h | 2 - uppsrc/CtrlCore/GtkApp.cpp | 4 + uppsrc/CtrlCore/GtkCtrl.h | 6 +- uppsrc/CtrlCore/GtkEvent.cpp | 2 +- uppsrc/CtrlCore/GtkTop.h | 2 - uppsrc/CtrlCore/GtkWnd.cpp | 2 +- uppsrc/CtrlCore/Win32Ctrl.h | 4 - uppsrc/CtrlCore/Win32Top.h | 2 - uppsrc/CtrlCore/X11Ctrl.h | 3 - uppsrc/CtrlCore/X11Top.h | 3 +- uppsrc/CtrlCore/src.tpp/Ctrl_en-us.tpp | 3 +- uppsrc/CtrlLib/ArrayCtrl.cpp | 2 - uppsrc/CtrlLib/ArrayCtrl.h | 2 - uppsrc/CtrlLib/EditCtrl.h | 2 + uppsrc/CtrlLib/EditField.cpp | 22 +- uppsrc/CtrlLib/Help.cpp | 7 +- uppsrc/CtrlLib/RichText.h | 3 + uppsrc/CtrlLib/RichTextView.cpp | 11 +- uppsrc/CtrlLib/src.tpp/EditField_en-us.tpp | 7 +- uppsrc/Draw/iml_header.h | 2 - uppsrc/Draw/iml_source.h | 2 - uppsrc/IconDes/IconDes.key | 1 + uppsrc/RichEdit/Cursor.cpp | 9 +- uppsrc/RichEdit/RichEdit.h | 1 + uppsrc/ide/About.cpp | 19 +- uppsrc/ide/Annotations.cpp | 81 +- uppsrc/ide/Assist.cpp | 601 +++---- uppsrc/ide/Assist.h | 209 +-- uppsrc/ide/AssistDisplay.cpp | 123 ++ uppsrc/ide/Browser/Base.cpp | 565 ------ uppsrc/ide/Browser/Browser.h | 199 +-- uppsrc/ide/Browser/Browser.lay | 22 - uppsrc/ide/Browser/Browser.upp | 10 - uppsrc/ide/Browser/CodeBrowser.cpp | 378 ---- uppsrc/ide/Browser/CodeRef.cpp | 224 ++- uppsrc/ide/Browser/Iml.cpp | 59 - uppsrc/ide/Browser/Item.cpp | 200 --- uppsrc/ide/Browser/ItemDisplay.cpp | 212 --- uppsrc/ide/Browser/Lay.cpp | 87 - uppsrc/ide/Browser/Move.cpp | 2 +- uppsrc/ide/Browser/Reference.cpp | 32 - uppsrc/ide/Browser/Sch.cpp | 152 -- uppsrc/ide/Browser/TopicBase.cpp | 78 +- uppsrc/ide/Browser/TopicI.cpp | 10 +- uppsrc/ide/Browser/TopicWin.cpp | 8 +- uppsrc/ide/Browser/Util.cpp | 64 +- uppsrc/ide/Build.cpp | 21 - uppsrc/ide/Builders/Build.cpp | 1 - uppsrc/ide/Builders/Build.h | 1 - uppsrc/ide/Config.cpp | 18 +- uppsrc/ide/ContextGoto.cpp | 485 ++---- uppsrc/ide/Core/Cache.cpp | 56 + uppsrc/ide/Core/Core.h | 142 +- uppsrc/ide/Core/Core.upp | 2 + uppsrc/ide/Core/Hdepend.cpp | 233 ++- uppsrc/ide/Core/Hdepend2.cpp | 400 +++++ uppsrc/ide/Core/Host.cpp | 12 +- uppsrc/ide/Core/Host.h | 2 + uppsrc/ide/Core/Ide.cpp | 16 +- uppsrc/ide/Core/Workspace.cpp | 29 +- uppsrc/ide/Cpp.cpp | 173 -- uppsrc/ide/DCopy.cpp | 221 ++- uppsrc/ide/Events.cpp | 174 ++ uppsrc/ide/FindInFiles.cpp | 26 +- uppsrc/ide/IconDes/IconDes.cpp | 9 +- uppsrc/ide/IncludeTrick.cpp | 84 + uppsrc/ide/InstantSetup.cpp | 2 +- uppsrc/ide/Jump.cpp | 10 +- uppsrc/ide/LayDes/LayDes.upp | 1 - uppsrc/ide/LayDes/laydes.key | 2 +- uppsrc/ide/LayDes/laywin.cpp | 23 +- uppsrc/ide/MainConfig.cpp | 43 +- uppsrc/ide/Methods.cpp | 59 +- uppsrc/ide/Navigator.cpp | 575 ++----- uppsrc/ide/OnlineSearch.cpp | 26 +- uppsrc/ide/OutputMode.cpp | 4 +- uppsrc/ide/ParamInfo.cpp | 13 +- uppsrc/ide/Setup.cpp | 7 +- uppsrc/ide/Swaps.cpp | 191 ++- uppsrc/ide/Thisbacks.cpp | 186 -- uppsrc/ide/UppHub.cpp | 1 + uppsrc/ide/Virtuals.cpp | 130 +- uppsrc/ide/clang/CurrentFile.cpp | 281 +++ uppsrc/ide/clang/CxxIcon.cpp | 1040 ++++++++++++ uppsrc/ide/clang/Indexer.cpp | 434 +++++ uppsrc/ide/clang/Signature.cpp | 462 +++++ uppsrc/ide/clang/Visitor.cpp | 414 +++++ uppsrc/ide/clang/clang.cpp | 185 ++ uppsrc/ide/clang/clang.dli | 67 + uppsrc/ide/clang/clang.h | 291 ++++ uppsrc/ide/clang/clang.upp | 21 + uppsrc/ide/clang/libclang.cpp | 224 +++ uppsrc/ide/clang/libclang.h | 1719 +++++++++++++++++++ uppsrc/ide/clang/macros.cpp | 857 ++++++++++ uppsrc/ide/clang/util.cpp | 102 ++ uppsrc/ide/ide.cpp | 91 +- uppsrc/ide/ide.h | 80 +- uppsrc/ide/ide.iml | 44 +- uppsrc/ide/ide.key | 4 +- uppsrc/ide/ide.lay | 38 +- uppsrc/ide/ide.upp | 8 +- uppsrc/ide/idebar.cpp | 28 +- uppsrc/ide/idefile.cpp | 96 +- uppsrc/ide/idetool.cpp | 59 +- uppsrc/ide/idewin.cpp | 33 +- uppsrc/ide/main.cpp | 62 +- uppsrc/umk/umake.cpp | 2 +- upptst/ide_CleanupId/etalon.log | 29 + upptst/ide_CleanupId/ide_CleanupId.cpp | 32 + upptst/ide_CleanupId/ide_CleanupId.upp | 11 + 147 files changed, 8943 insertions(+), 11172 deletions(-) delete mode 100644 uppsrc/CppBase/Base.cpp delete mode 100644 uppsrc/CppBase/Body.cpp delete mode 100644 uppsrc/CppBase/Copying delete mode 100644 uppsrc/CppBase/CppBase.h delete mode 100644 uppsrc/CppBase/CppBase.upp delete mode 100644 uppsrc/CppBase/CppItem.cpp delete mode 100644 uppsrc/CppBase/Expression.cpp delete mode 100644 uppsrc/CppBase/Iface.cpp delete mode 100644 uppsrc/CppBase/Internal.h delete mode 100644 uppsrc/CppBase/Parser.cpp delete mode 100644 uppsrc/CppBase/Pre.cpp delete mode 100644 uppsrc/CppBase/Qualify.cpp delete mode 100644 uppsrc/CppBase/ScopeInfo.cpp delete mode 100644 uppsrc/CppBase/cpp.cpp delete mode 100644 uppsrc/CppBase/cpplex.cpp delete mode 100644 uppsrc/CppBase/keyword.i delete mode 100644 uppsrc/CppBase/macro.cpp delete mode 100644 uppsrc/CppBase/ppconfig.cpp delete mode 100644 uppsrc/CppBase/ppfile.cpp delete mode 100644 uppsrc/CppBase/srcfiles.cpp delete mode 100644 uppsrc/CppBase/util.cpp create mode 100644 uppsrc/ide/AssistDisplay.cpp delete mode 100644 uppsrc/ide/Browser/Base.cpp delete mode 100644 uppsrc/ide/Browser/Browser.lay delete mode 100644 uppsrc/ide/Browser/CodeBrowser.cpp delete mode 100644 uppsrc/ide/Browser/Iml.cpp delete mode 100644 uppsrc/ide/Browser/Item.cpp delete mode 100644 uppsrc/ide/Browser/ItemDisplay.cpp delete mode 100644 uppsrc/ide/Browser/Lay.cpp delete mode 100644 uppsrc/ide/Browser/Reference.cpp delete mode 100644 uppsrc/ide/Browser/Sch.cpp create mode 100644 uppsrc/ide/Core/Cache.cpp create mode 100644 uppsrc/ide/Core/Hdepend2.cpp delete mode 100644 uppsrc/ide/Cpp.cpp create mode 100644 uppsrc/ide/Events.cpp create mode 100644 uppsrc/ide/IncludeTrick.cpp delete mode 100644 uppsrc/ide/Thisbacks.cpp create mode 100644 uppsrc/ide/clang/CurrentFile.cpp create mode 100644 uppsrc/ide/clang/CxxIcon.cpp create mode 100644 uppsrc/ide/clang/Indexer.cpp create mode 100644 uppsrc/ide/clang/Signature.cpp create mode 100644 uppsrc/ide/clang/Visitor.cpp create mode 100644 uppsrc/ide/clang/clang.cpp create mode 100644 uppsrc/ide/clang/clang.dli create mode 100644 uppsrc/ide/clang/clang.h create mode 100644 uppsrc/ide/clang/clang.upp create mode 100644 uppsrc/ide/clang/libclang.cpp create mode 100644 uppsrc/ide/clang/libclang.h create mode 100644 uppsrc/ide/clang/macros.cpp create mode 100644 uppsrc/ide/clang/util.cpp create mode 100644 upptst/ide_CleanupId/etalon.log create mode 100644 upptst/ide_CleanupId/ide_CleanupId.cpp create mode 100644 upptst/ide_CleanupId/ide_CleanupId.upp diff --git a/uppsrc/CodeEditor/CodeEditor.h b/uppsrc/CodeEditor/CodeEditor.h index 931664a6f..d5b98d2bc 100644 --- a/uppsrc/CodeEditor/CodeEditor.h +++ b/uppsrc/CodeEditor/CodeEditor.h @@ -82,6 +82,7 @@ private: bool ignored_next_edit; int next_age; int active_annotation; + Vector animate; String& PointBreak(int& y); void sPaintImage(Draw& w, int y, int fy, const Image& img); @@ -136,6 +137,8 @@ public: bool IsHiliteIfEndif() const { return hilite_if_endif; } int GetActiveAnnotationLine() const { return active_annotation; } + + void SetAnimate(const Vector& a) { if(a != animate) { animate = clone(a); Refresh(); } } EditorBar(); virtual ~EditorBar(); @@ -509,15 +512,16 @@ public: void SetAnnotation(int i, const Image& icon, const String& a) { bar.SetAnnotation(i, icon, a); } String GetAnnotation(int i) const { return bar.GetAnnotation(i); } int GetActiveAnnotationLine() const { return bar.GetActiveAnnotationLine(); } - + Size GetBarSize() const { return bar.GetSize(); } void HideBar() { bar.Hide(); } + void AnimateBar(const Vector& a) { bar.SetAnimate(a); } void SyncTip(); void CloseTip() { if(tip.IsOpen()) tip.Close(); tip.d = NULL; } void Illuminate(const WString& text); WString GetIlluminated() const { return illuminated; } - + void Zoom(int d); One GetSyntax(int line); diff --git a/uppsrc/CodeEditor/EditorBar.cpp b/uppsrc/CodeEditor/EditorBar.cpp index eef249da9..f7660b33c 100644 --- a/uppsrc/CodeEditor/EditorBar.cpp +++ b/uppsrc/CodeEditor/EditorBar.cpp @@ -58,6 +58,8 @@ void EditorBar::Paint(Draw& w) Color bg = IsDarkTheme() ? GrayColor(70) : SColorLtFace(); Size sz = GetSize(); w.DrawRect(0, 0, sz.cx, sz.cy, bg); + for(int i = 0; i < animate.GetCount(); i++) + w.DrawRect(i, 0, 1, sz.cy, animate[i]); if(!editor) return; int fy = editor->GetFontSize().cy; int hy = fy >> 1; diff --git a/uppsrc/Core/CoWork.cpp b/uppsrc/Core/CoWork.cpp index 08f7c5411..11455d4b1 100644 --- a/uppsrc/Core/CoWork.cpp +++ b/uppsrc/Core/CoWork.cpp @@ -311,36 +311,6 @@ void CoWork::SetPoolSize(int n) p.InitThreads(n); } -void CoWork::Pipe(int stepi, Function&& fn) -{ - Mutex::Lock __(stepmutex); - auto& q = step.At(stepi); - LLOG("Step " << stepi << ", count: " << q.GetCount() << ", running: " << steprunning.GetCount()); - q.AddHead(pick(fn)); - if(!steprunning.At(stepi, false)) { - steprunning.At(stepi) = true; - *this & [=]() { - LLOG("Starting step " << stepi << " processor"); - stepmutex.Enter(); - for(;;) { - Function f; - auto& q = step[stepi]; - LLOG("StepWork " << stepi << ", todo:" << q.GetCount()); - if(q.GetCount() == 0) - break; - f = pick(q.Tail()); - q.DropTail(); - stepmutex.Leave(); - f(); - stepmutex.Enter(); - } - steprunning.At(stepi) = false; - stepmutex.Leave(); - LLOG("Exiting step " << stepi << " processor"); - }; - } -} - void CoWork::Reset() { try { diff --git a/uppsrc/Core/CoWork.h b/uppsrc/Core/CoWork.h index 1cd45b34d..cf37e48d9 100644 --- a/uppsrc/Core/CoWork.h +++ b/uppsrc/Core/CoWork.h @@ -57,11 +57,6 @@ public: Atomic index; -// experimental pipe support - Mutex stepmutex; - Array>> step; - Vector steprunning; - public: static bool TrySchedule(Function&& fn); static bool TrySchedule(const Function& fn) { return TrySchedule(clone(fn)); } @@ -83,7 +78,6 @@ public: int Next() { return ++index - 1; } int GetScheduledCount() const { return todo; } - void Pipe(int stepi, Function&& lambda); // experimental static void FinLock(); diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index f9796ae87..0a5cae8a8 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -419,13 +419,11 @@ NTL_MOVEABLE(RECT) //Place it to the begining of each file to be the first function called in whole executable... //This is now backup to init_priority attribute in heapdbg.cpp -//$- struct MemDiagCls { MemDiagCls(); ~MemDiagCls(); }; static const MemDiagCls sMemDiagHelper__upp__; -//$+ #endif diff --git a/uppsrc/Core/Dli.cpp b/uppsrc/Core/Dli.cpp index f2ea50675..f1fb3939c 100644 --- a/uppsrc/Core/Dli.cpp +++ b/uppsrc/Core/Dli.cpp @@ -106,7 +106,7 @@ const char *PeFile::FindExportRaw(const char *name, bool case_sensitive) const HMODULE CheckDll__(const char *fn, const char *const *names, UPP::Vector& plist) { HMODULE hmod = LoadLibrary(fn); - + if(!hmod) return 0; @@ -154,18 +154,10 @@ void FreeDll__(HMODULE hmod) void *CheckDll__(const char *fn, const char *const *names, UPP::Vector& plist) { + Upp::MemoryIgnoreLeaksBlock __; void *hmod = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL); - if(!hmod) { - RLOG("Error loading library " << fn << ": " << dlerror()); -/* - for(int i = 0; i < 100; i++) { - hmod = dlopen(fn + ("." + UPP::AsString(i)), RTLD_LAZY | RTLD_GLOBAL); - if(hmod) - break; - } - if(!hmod) -*/ return 0; - } + if(!hmod) + return 0; int missing = 0; for(const char *const *p = names; *p; p++) { @@ -175,15 +167,15 @@ void *CheckDll__(const char *fn, const char *const *names, UPP::Vector& void *proc = dlsym(hmod, exp); if(!proc && !optional) { if(!missing) { - RLOG(fn << " missing exports:"); + LOG(fn << " missing exports:"); } - RLOG(exp); + LOG(exp); } plist.Add(proc); } if(missing) { - RLOG(missing << " missing symbols total"); + LOG(missing << " missing symbols total"); dlclose(hmod); return 0; } diff --git a/uppsrc/Core/Fn.h b/uppsrc/Core/Fn.h index eec0a62e3..100df095b 100644 --- a/uppsrc/Core/Fn.h +++ b/uppsrc/Core/Fn.h @@ -6,9 +6,6 @@ #undef max #endif -//$-template inline constexpr const T& min(const T& a, const T& b, ...); -//$-template inline constexpr const T& max(const T& a, const T& b, ...); - template constexpr const T& min(const T& a, const T& b) { @@ -33,16 +30,12 @@ constexpr const T& max(const T& a, const T& b, const Args& ...args) return max(a, max(b, args...)); } -//$+ - template constexpr T clamp(const T& x, const T& min_, const T& max_) { return min(max(x, min_), max_); } -//$-constexpr int findarg(const T& x, const T1& p0, ...); - template constexpr int findarg(const T& x, const K& k) { @@ -58,8 +51,6 @@ constexpr int findarg(const T& sel, const K& k, const L& ...args) return q >= 0 ? q + 1 : -1; } -//$-constexpr auto decode(const T& x, const T1& p0, const V1& v0, ...); - template constexpr const char *decode_chr_(const T& sel, const char *def) { @@ -90,8 +81,6 @@ constexpr V decode(const T& sel, const K& k, const V& v, const L& ...args) return sel == k ? v : (V)decode(sel, args...); } -//$-constexpr T get_i(int i, const T& p0, const T1& p1, ...); - template constexpr A get_i(int i, const A& p0, const T& ...args) { @@ -106,8 +95,6 @@ constexpr const P *get_i(int i, const P* p0, const T& ...args) return list[clamp(i, 0, (int)sizeof...(args))]; } -//$-void foreach_arg(F fn, const T& p0, const T1& p1, ...); - template void foreach_arg(F fn, V&& v) { @@ -121,8 +108,6 @@ void foreach_arg(F fn, V&& v, Args&& ...args) foreach_arg(fn, std::forward(args)...); } -//$+ - template void iter_set(I t, Args&& ...args) { diff --git a/uppsrc/Core/Mt.cpp b/uppsrc/Core/Mt.cpp index e7b77e47c..809c6c85c 100644 --- a/uppsrc/Core/Mt.cpp +++ b/uppsrc/Core/Mt.cpp @@ -112,7 +112,7 @@ Mutex vm; //a common access synchronizer #endif #endif -//to sMain: an Application can start more than one thread, without having *any* one of them called Run() of any Thread instace +//to sMain: an Application can start more than one thread, without having *any* one of them called Run() of any Thread instance //when Run() is called *anytime*, it means, the term of *MainThread* has to be running anyway, //otherwise no child threads could run. they are created by main. //now each thread, having any Thread instance can start a first Run() @@ -243,11 +243,36 @@ void Thread::EndShutdownThreads() sShutdown--; } + +// TODO: Document this + +static StaticMutex mtx; + +static Vector& sShutdownFns() +{ + static Vector m; + return m; +} + +void Thread::AtShutdown(void (*shutdownfn)()) +{ + Mutex::Lock __(mtx); + sShutdownFns().Add(shutdownfn); +} + +void Thread::TryShutdownThreads() +{ + for(auto fn : sShutdownFns()) + (*fn)(); +} + void Thread::ShutdownThreads() { BeginShutdownThreads(); - while(GetCount()) + while(GetCount()) { + TryShutdownThreads(); Sleep(100); + } EndShutdownThreads(); } diff --git a/uppsrc/Core/Mt.h b/uppsrc/Core/Mt.h index 34ed72490..998176dcd 100644 --- a/uppsrc/Core/Mt.h +++ b/uppsrc/Core/Mt.h @@ -83,6 +83,8 @@ public: static bool IsUpp(); static int GetCount(); static void BeginShutdownThreads(); + static void AtShutdown(void (*shutdownfn)()); + static void TryShutdownThreads(); static void EndShutdownThreads(); static void ShutdownThreads(); static bool IsShutdownThreads(); @@ -415,7 +417,7 @@ typedef StaticMutex StaticCriticalSection; #endif // Auxiliary multithreading - this is not using/cannot use U++ heap, so does not need cleanup. -// Used to resolve some host platform issues. +// Used to resolve some host platform issues. Do not use. #ifdef PLATFORM_WIN32 #define auxthread_t DWORD diff --git a/uppsrc/Core/SplitMerge.h b/uppsrc/Core/SplitMerge.h index 1d9cc39b6..4a2a98e62 100644 --- a/uppsrc/Core/SplitMerge.h +++ b/uppsrc/Core/SplitMerge.h @@ -19,27 +19,6 @@ Vector Split(const wchar *s, const wchar *text, bool ignoreempty = true String Join(const Vector& im, const String& delim, bool ignoreempty = false); WString Join(const Vector& im, const WString& delim, bool ignoreempty = false); -//$ bool SplitTo(const char *s, int delim, bool ignoreempty, String& p1...); -//$ bool SplitTo(const char *s, int delim, String& p1...); -//$ bool SplitTo(const char *s, int (*filter)(int), String& p1...); -//$ bool SplitTo(const char *s, int (*filter)(int), String& p1...); -//$ bool SplitTo(const char *s, const char *delim, bool ignoreempty, String& p1...); -//$ bool SplitTo(const char *s, const char *delim, String& p1...); - -//$ bool SplitTo(const wchar *s, int delim, bool ignoreempty, WString& p1...); -//$ bool SplitTo(const wchar *s, int delim, WString& p1...); -//$ bool SplitTo(const wchar *s, int (*filter)(int), WString& p1...); -//$ bool SplitTo(const wchar *s, int (*filter)(int), WString& p1...); -//$ bool SplitTo(const wchar *s, const wchar *delim, bool ignoreempty, WString& p1...); -//$ bool SplitTo(const wchar *s, const wchar *delim, WString& p1...); - -//$ String Merge(const char *delim, String& p1...); -//$ WString Merge(const wchar *delim, WString& p1...); - -//$ void MergeWith(String& dest, const char *delim, String& p1...); -//$ void MergeWith(WString& dest, const wchar *delim, WString& p1...); - -//$- template bool SplitTo(const char *s, int delim, bool ignoreempty, Args& ...args) { @@ -151,5 +130,3 @@ WString Merge(const wchar *delim, const Args& ...args) MergeWith(r, delim, args...); return r; } - -//$- diff --git a/uppsrc/Core/Topt.h b/uppsrc/Core/Topt.h index 16b0f1a8c..b8c6cf76f 100644 --- a/uppsrc/Core/Topt.h +++ b/uppsrc/Core/Topt.h @@ -429,29 +429,6 @@ hash_t memhash(const void *ptr, size_t size); template inline hash_t GetHashValue(const T& x) { return x.GetHashValue(); } -struct CombineHash { - hash_t hash; - - template CombineHash& Do(const T& x) { Put(GetHashValue(x)); return *this; } - -public: - CombineHash& Put(hash_t h) { hash = HASH_CONST2 * hash + h; return *this; } - - operator hash_t() const { return hash; } - - CombineHash() { hash = HASH_CONST1; } - template - CombineHash(const T& h1) { hash = HASH_CONST1; Do(h1); } - template - CombineHash(const T& h1, const U& h2) { hash = HASH_CONST1; Do(h1); Do(h2); } - template - CombineHash(const T& h1, const U& h2, const V& h3) { hash = HASH_CONST1; Do(h1); Do(h2); Do(h3); } - template - CombineHash(const T& h1, const U& h2, const V& h3, const W& h4) { hash = HASH_CONST1; Do(h1); Do(h2); Do(h3); Do(h4); } - - template CombineHash& operator<<(const T& x) { Do(x); return *this; } -}; - template<> inline hash_t GetHashValue(const char& a) { return (hash_t)a; } template<> inline hash_t GetHashValue(const signed char& a) { return (const hash_t)a; } template<> inline hash_t GetHashValue(const unsigned char& a) { return (const hash_t)a; } @@ -478,12 +455,35 @@ template<> inline hash_t GetHashValue(const double& a) { return memhash( #ifdef CPU_32 inline hash_t GetPtrHashValue(const void *a) { return (int)a; } #else -inline hash_t GetPtrHashValue(const void *a) { return CombineHash((hash_t)(uintptr_t)a); } +inline hash_t GetPtrHashValue(const void *a) { return (hash_t)(uintptr_t)a; } #endif template inline hash_t GetHashValue(T *ptr) { return GetPtrHashValue(reinterpret_cast(ptr)); } +struct CombineHash { + hash_t hash; + + template CombineHash& Do(const T& x) { Put(GetHashValue(x)); return *this; } + +public: + CombineHash& Put(hash_t h) { hash = HASH_CONST2 * hash + h; return *this; } + + operator hash_t() const { return hash; } + + CombineHash() { hash = HASH_CONST1; } + template + CombineHash(const T& h1) { hash = HASH_CONST1; Do(h1); } + template + CombineHash(const T& h1, const U& h2) { hash = HASH_CONST1; Do(h1); Do(h2); } + template + CombineHash(const T& h1, const U& h2, const V& h3) { hash = HASH_CONST1; Do(h1); Do(h2); Do(h3); } + template + CombineHash(const T& h1, const U& h2, const V& h3, const W& h4) { hash = HASH_CONST1; Do(h1); Do(h2); Do(h3); Do(h4); } + + template CombineHash& operator<<(const T& x) { Do(x); return *this; } +}; + template struct Data_S_ : Moveable< Data_S_ > { diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index 23418abbf..d2460c021 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -25,10 +25,10 @@ public: }; struct TimeStopper { - const char *name; + String name; TimeStop tm; - TimeStopper(const char *name) : name(name) {} + TimeStopper(const String& name) : name(name) {} ~TimeStopper() { RLOG(name << " " << tm); } }; diff --git a/uppsrc/Core/dli.h b/uppsrc/Core/dli.h index fe6e13cbe..f2541d3dd 100644 --- a/uppsrc/Core/dli.h +++ b/uppsrc/Core/dli.h @@ -71,6 +71,7 @@ private: // --------- DLLTYPE& DLIMODULE(); +DLLTYPE& DLIMODULE(const char *path); DLLTYPE& COMBINE(DLIMODULE, _)(); #endif @@ -91,6 +92,13 @@ DLLTYPE& DLIMODULE() return out; } +DLLTYPE& DLIMODULE(const char *path) +{ + DLLTYPE& out = COMBINE(DLIMODULE, _)(); + out.Load(path); + return out; +} + DLLTYPE::DLLTYPE() { checked = false; diff --git a/uppsrc/CppBase/Base.cpp b/uppsrc/CppBase/Base.cpp deleted file mode 100644 index ff5b262e2..000000000 --- a/uppsrc/CppBase/Base.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LLOG(x) -#define LTIMING(x) DTIMING(x) - -void CppItem::Serialize(Stream& s) -{ - s % kind % access - % item % name % natural % at % tparam % param % pname - % tname % ctname % type % ptype % virt % filetype % file % line % impl - % using_namespaces; -} - -struct CmpItem { - bool operator()(const CppItem& a, const String& b) const - { - return a.qitem < b; - } -}; - -int FindItem(const Array& x, const String& qitem) -{ - for(int i = 0; i < x.GetCount(); i++) - if(x[i].qitem == qitem) - return i; - return -1; -} - -int FindNext(const Array& x, int i) -{ - if(i >= x.GetCount()) - return i; - String q = x[i].qitem; - while(i < x.GetCount() && x[i].qitem == q) - i++; - return i; -} - -int GetCount(const Array& x, int i) -{ - return FindNext(x, i) - i; -} - -int FindName(const Array& x, const String& name, int i) -{ - while(i < x.GetCount()) { - if(x[i].name == name) - return i; - i++; - } - return -1; -} - -bool CppBase::IsType(int i) const -{ - return GetKey(i).GetCount(); -} - -void CppBase::Dump(Stream& s) -{ - for(int i = 0; i < GetCount(); i++) { - s << Nvl(GetKey(i), "<>") << "\n"; - const Array& m = (*this)[i]; - for(int j = 0; j < m.GetCount(); j++) - s << '\t' << m[j] << "\n"; - } -} - -void CppBase::Sweep(const Index& file, bool keep) -{ - Vector remove; - for(int ni = 0; ni < GetCount(); ni++) { - Array& n = (*this)[ni]; - Vector nr; - for(int i = 0; i < n.GetCount(); i++) - if((file.Find(n[i].file) < 0) == keep) - nr.Add(i); - if(nr.GetCount() == n.GetCount()) - remove.Add(ni); // remove whole array (later) - else - n.Remove(nr); // only remove some items - } - Remove(remove); -} - -void CppBase::Append(CppBase&& base) -{ - for(int i = 0; i < base.GetCount(); i++) - GetAdd(base.GetKey(i)).Append(pick(base[i])); -} - -void CppBase::RemoveFile(int filei) -{ - Index h; - h.Add(filei); - RemoveFiles(h); -} - - -} diff --git a/uppsrc/CppBase/Body.cpp b/uppsrc/CppBase/Body.cpp deleted file mode 100644 index 5699f53bb..000000000 --- a/uppsrc/CppBase/Body.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -#define LLOG(x) // DLOG(x) - -namespace Upp { - -void Parser::Locals(const String& type) -{ - Line(); - Array d = Declaration(true, true, Null, Null); - for(int i = 0; i < d.GetCount(); i++) { - Local& l = local.Add(d[i].name); - l.type = *type == '*' ? d[i].type : type; - l.isptr = d[i].isptr; - l.line = line + 1; - LLOG("== Local variable " << d[i].name << ": " << l.type); - } -} - -bool Parser::TryDecl() -{ // attempt to interpret code as local variable declaration - for(;;) { - if(findarg(lex[0], tk_static, tk_const, tk_register, tk_volatile) >= 0) - ++lex; - else - if(!VCAttribute()) - break; - } - int t = lex[0]; - int q = 0; - if(t == tk_int || t == tk_bool || t == tk_float || t == tk_double || t == tk_void || - t == tk_long || t == tk_signed || t == tk_unsigned || t == tk_short || - t == tk_char || t == tk___int8 || t == tk___int16 || t == tk___int32 || t == tk___int64 || - t == tk_auto) { - q++; - if(findarg(lex[q], tk_long, tk_int, tk_char) >= 0) - q++; - if(findarg(lex[q], tk_long, tk_int, tk_char) >= 0) - q++; - while(findarg(lex[q], '*', '&', t_and, tk_const) >= 0) // t_and is r-value here - q++; - if(!lex.IsId(q)) - return false; - static String aut("*"), empty; - Locals(t == tk_auto ? aut : empty); - return true; - } - String type; - if(t == tk_decltype && lex[q + 1] == '(') { - q += 2; - int q0 = q; - int lvl = 1; - for(;;) { - if(lex[q] == t_eof) - break; - if(lex[q] == '(') - lvl++; - else - if(lex[q] == ')' && --lvl == 0) { - Locals("@" + String(lex.Pos(q0), lex.Pos(q))); - return true; - } - ++q; - } - return false; - } - if(lex[q] == t_dblcolon) { - type << "::"; - q++; - } - if(lex.IsId(q)) { - type << lex.Id(q++); - type << Tparam(q); - } - else - return false; - while(lex[q] == t_dblcolon) { - type << "::"; - if(lex.IsId(++q)) - type << lex.Id(q++); - else - return false; - type << Tparam(q); - } - while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and) // t_and is r-value here - q++; - if(!lex.IsId(q)) - return false; - type = qualify(current_scope, type, context.namespace_using); - if(type.GetCount()) { - Locals(type); - return true; - } - return false; -} - -void Parser::MatchPars() -{ - int level = 1; - while(level && lex != t_eof) { - if(Key('(')) level++; - else - if(Key(')')) level--; - else - ++lex; - } -} - -void Parser::Statement() -{ - RecursionCounter recursionCounter(currentScopeDepth, lex == '{' ? 0 : 1); - maxScopeDepth = max(maxScopeDepth, currentScopeDepth); - - if(Key(tk_case)) { - if(lex.IsId()) - ++lex; - Key(':'); - } - if(Key(tk_default)) - Key(':'); - if(lex.IsId() && lex[1] == ':') { - ++lex; - ++lex; - } - if(Key('{')) { - Context cc; - cc <<= context; - int l = local.GetCount(); - while(!Key('}')) { - if(lex == t_eof) - ThrowError("eof"); - Statement(); - } - context <<= cc; - local.Trim(l); - } - else - if(Key(tk_if)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - if(Key(tk_else)) - Statement(); - local.Trim(l); - } - else - if(Key(tk_for)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(Key(tk_while)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(Key(tk_try)) - Statement(); - else - if(Key(tk_catch)) { - Key('('); - MatchPars(); - Statement(); - } - else - if(Key(tk_do)) { - Statement(); - Key(tk_while); - Key('('); - MatchPars(); - } - else - if(Key(tk_switch)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(UsingNamespace()) - ; - else - if(TryDecl()) - Key(';'); - else - for(;;) { - if(lex == t_eof) - ThrowError(""); - TryLambda(); - if(Key(';') || lex == '{' || lex == '}' || lex >= tk_if && lex <= tk_do) - break; - ++lex; - } -} - -bool Parser::Skipars(int& q) -{ - int par = lex[q]; - q++; - int lvl = 1; - while(lex[q] != t_eof) { - int c = lex[q++]; - if(c == '(' || c == '[' || c == '{') - lvl++; - else - if(c == ')' || c == ']' || c == '}') { - lvl--; - if(lvl == 0) - return c == decode(par, '(', ')', '[', ']', '{', '}', 0); - } - } - return false; -} - -void Parser::TryLambda() -{ - if(lex != '[' || !dobody) - return; - int q = 0; - if(!Skipars(q)) - return; - int params = q; - if(lex[q] == '(') - if(!Skipars(q)) - return; - if(lex[q] == tk_mutable) - q++; - if(lex[q] == t_arrow) { - q++; // TODO: auto declaration could assign a return type here - for(;;) { - if(lex[q] == ';' || lex[q] == t_eof) - return; - if(lex[q] == '{') - break; - q++; - } - } - if(lex[q] == '{') { - int n = local.GetCount(); - lex.Get(params); - if(Key('(')) { - Decl d; - Line(); - ParamList(d); - } - while(lex != '{' && lex != t_eof) - ++lex; - Statement(); - local.Trim(n); - } -} - -bool Parser::EatBody() -{ - if(lex == t_eof) - return false; - if(lex != '{') { - local.Clear(); - return false; - } - lex.BeginBody(); - maxScopeDepth = currentScopeDepth = dobody ? 0 : 1; - if(dobody) { - inbody = true; - Statement(); - inbody = false; - local.Clear(); - } - else { - Key('{'); - int level = 1; - while(level && lex != t_eof) { - if(Key('{')) level++; - else - if(Key('}')) level--; - else - ++lex; - maxScopeDepth = max(level, maxScopeDepth); - } - } - lex.EndBody(); - return true; -} - -String Parser::ResolveAutoType() -{ - Vector xp = MakeXP(lex.Pos()); - if(lex == ':') // resolve for declaration, like 'for(auto i: vector)' - xp << "." << "begin" << "()" << "->"; // incorrect, should rather use operator*(), but sufficient for now - Index s = GetExpressionType(*base, *this, xp); - int i = FindMax(s); // Ugly hack: we are not resolving overloading at all, so just choose stable type if there are more, not Null - return i < 0 ? String() : s[i]; -} - -} diff --git a/uppsrc/CppBase/Copying b/uppsrc/CppBase/Copying deleted file mode 100644 index 7f9f88164..000000000 --- a/uppsrc/CppBase/Copying +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 1998, 2022, The U++ Project -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/uppsrc/CppBase/CppBase.h b/uppsrc/CppBase/CppBase.h deleted file mode 100644 index c114ae2b5..000000000 --- a/uppsrc/CppBase/CppBase.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef DOCPP_H -#define DOCPP_H - -#include - -namespace Upp { - -// These functions can only but executed by single thread, unless said otherwise - -bool IsCPPFile(const String& file); -bool IsHFile(const String& path); - -String GetStdDefs(); - -void SetPPDefs(const String& defs); - -void InvalidatePPCache(); - -void PPSync(const String& include_path); - -enum Kind { - STRUCT, - STRUCTTEMPLATE, - TYPEDEF, - CONSTRUCTOR, - DESTRUCTOR, - FUNCTION, - INSTANCEFUNCTION, - CLASSFUNCTION, - FUNCTIONTEMPLATE, - INSTANCEFUNCTIONTEMPLATE, - CLASSFUNCTIONTEMPLATE, - INLINEFRIEND, - VARIABLE, - INSTANCEVARIABLE, - CLASSVARIABLE, - ENUM, - MACRO, - FRIENDCLASS, - NAMESPACE, - FLAGTEST, -}; - -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; -} - -void CleanPP(); -void SerializePPFiles(Stream& s); -void SweepPPFiles(const Index& keep); - -void InvalidateFileTimeCache(); -void InvalidateFileTimeCache(const String& path); -Time GetFileTimeCached(const String& path); - -String NormalizeSourcePath(const String& path, const String& currdir); -String NormalizeSourcePath(const String& path); - -void ClearSources(); -const Index& GetAllSources(); -void GatherSources(const String& path); -String GetMasterFile(const String& file); -const VectorMap& GetAllSourceMasters(); - -const char **CppKeyword(); - -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 = PUBLIC; - byte kind = STRUCT; - int16 at = 0; - bool virt = false; - - bool decla = false; - bool lvalue = false; - bool isptr = false; - - byte filetype = FILE_OTHER; - bool impl = false; - int file = 0; - int line = 0; - - bool qualify = true; - - 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 IsFlagTest() const { return kind == FLAGTEST; } - bool IsTemplate() const { return IsCppTemplate(kind); } - - void Serialize(Stream& s); - - void Dump(Stream& s) const; - String ToString() const; -}; - -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& file, bool keep = true); - void RemoveFiles(const Index& remove_file) { Sweep(remove_file, false); } - void RemoveFile(int filei); - void Append(CppBase&& base); - - void Dump(Stream& s); -}; - -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); -}; - -struct ParserContext { - struct Context { - String ns; - 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); - }; - - Context context; - String current_scope; - String current_key; - String current_name; - CppItem current; - bool inbody; - - struct Local : Moveable { - String type; - bool isptr; - int line; - }; - - VectorMap local; - - Vector GetNamespaces() const; - bool IsInBody() const { return inbody; } -}; - -// Parse CAN be run in parallel -void Parse(CppBase& base, const String& src, int file, int filetype, const String& path, - Event error, const Vector& namespace_stack, - const Index& namespace_using); - - -String NoTemplatePars(const String& type); - -// PreprocessParse CAN be run in parallel -void PreprocessParse(CppBase& base, Stream& in, int file, const String& path, - Event error); -String PreprocessCpp(const String& src, const String& path); - -ParserContext AssistParse(const String& src, const String& path_, Event error, - Function qualify); - -void SimpleParse(CppBase& cpp, const String& txt, const String& cls); - -void Qualify(CppBase& base); - -String Qualify(const CppBase& base, const String& scope, const String& type, const String& usings); - -String ResolveTParam(const CppBase& codebase, const String& type, const Vector& tparam); -void ResolveTParam(const CppBase& codebase, Vector& type, const Vector& tparam); - -String ParseTemplatedType(const String& type, Vector& tparam); - -bool HasCPPFileKeyword(const String& path, const String& id); - -String GetPPMD5(const String& fn); - -// GetDependeciesMD5 CAN be run in parallel -String GetDependeciesMD5(const String& path, Index& visited); - -Index GetExpressionType(const CppBase& codebase, const ParserContext& parser, const Vector& xp); - -} - -#endif diff --git a/uppsrc/CppBase/CppBase.upp b/uppsrc/CppBase/CppBase.upp deleted file mode 100644 index 66db0c3b7..000000000 --- a/uppsrc/CppBase/CppBase.upp +++ /dev/null @@ -1,28 +0,0 @@ -description "Partly heurestic (imprecise) C++ parser for purposes of Assist++ (intellisense)\377"; - -uses - Core; - -file - CppBase.h options(BUILDER_OPTION) PCH, - Internal.h, - keyword.i, - ppconfig.cpp, - macro.cpp, - util.cpp, - ppfile.cpp, - srcfiles.cpp, - cpp.cpp, - Pre.cpp, - cpplex.cpp, - Parser.cpp, - Body.cpp, - Base.cpp, - ScopeInfo.cpp, - Qualify.cpp, - CppItem.cpp, - Expression.cpp, - Iface.cpp, - Info readonly separator, - Copying; - diff --git a/uppsrc/CppBase/CppItem.cpp b/uppsrc/CppBase/CppItem.cpp deleted file mode 100644 index ecb0aa1f6..000000000 --- a/uppsrc/CppBase/CppItem.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -String CppItem::ToString() const -{ - StringStream ss; - Dump(ss); - return ss; -} - -String CppItemKindAsString(int kind) -{ - return decode(kind, - STRUCT, "STRUCT", - STRUCTTEMPLATE, "STRUCTTEMPLATE", - TYPEDEF, "TYPEDEF", - CONSTRUCTOR, "CONSTRUCTOR", - DESTRUCTOR, "DESTRUCTOR", - FUNCTION, "FUNCTION", - INSTANCEFUNCTION, "INSTANCEFUNCTION", - CLASSFUNCTION, "CLASSFUNCTION", - FUNCTIONTEMPLATE, "FUNCTIONTEMPLATE", - INSTANCEFUNCTIONTEMPLATE, "INSTANCEFUNCTIONTEMPLATE", - CLASSFUNCTIONTEMPLATE, "CLASSFUNCTIONTEMPLATE", - INLINEFRIEND, "INLINEFRIEND", - VARIABLE, "VARIABLE", - INSTANCEVARIABLE, "INSTANCEVARIABLE", - CLASSVARIABLE, "CLASSVARIABLE", - ENUM, "ENUM", - MACRO, "MACRO", - FRIENDCLASS, "FRIENDCLASS", - NAMESPACE, "NAMESPACE", - "?kind:" + AsString(kind)); -} - -void CppItem::Dump(Stream& s) const -{ - s << Nvl(qitem, "?") << ' '; - s << CppItemKindAsString(kind) << ' ' - << decode(access, - PUBLIC, "PUBLIC", - PROTECTED, "PROTECTED", - PRIVATE, "PRIVATE", - "?access:" + AsString(access)) << ' ' - << decode(filetype, - FILE_H, "FILE_H", - FILE_HPP, "FILE_HPP", - FILE_CPP, "FILE_CPP", - FILE_C, "FILE_C", - FILE_OTHER, "FILE_OTHER", - "?filetype:" + AsString(filetype)) - ; -#define PUT(x) if(x) s << ' ' << #x; - PUT(virt); - PUT(decla); - PUT(lvalue); - PUT(isptr); - PUT(impl); - PUT(qualify); -#undef PUT - s << ' ' << line << '\n'; -#define PUT(x) if(x.GetCount()) s << " " << #x << ": " << x << '\n'; - PUT(item); - PUT(name); - PUT(uname); - PUT(natural); - PUT(type); - PUT(qtype); - PUT(tparam); - PUT(param); - PUT(pname); - PUT(ptype); - PUT(qptype); - PUT(tname); - PUT(ctname); - PUT(using_namespaces); -#undef PUT -} - -} diff --git a/uppsrc/CppBase/Expression.cpp b/uppsrc/CppBase/Expression.cpp deleted file mode 100644 index d1d0f61cb..000000000 --- a/uppsrc/CppBase/Expression.cpp +++ /dev/null @@ -1,546 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -#if 0 -#define LDUMP(x) DDUMP(x) -#define LDUMPC(x) DDUMPC(x) -#define LLOG(x) DLOG(x) -#else -#define LDUMP(x) -#define LDUMPC(x) -#define LLOG(x) -#endif - -#define LTIMING(x) // DTIMING(x) - -namespace Upp { - -const Array& GetTypeItems(const CppBase& codebase, const String& type) -{ - static Array sEmpty; - int q = codebase.Find(type); - if(q < 0) - return sEmpty; - return codebase[q]; -} - -String ParseTemplatedType(const String& type, Vector& tparam) -{ - const char *s = type; - String r; - while(*s) { - if(*s == '<') { - s++; - int lvl = 0; - String t; - while(*s) { - int c = *s++; - if(c == ',' && lvl == 0) { - tparam.Add(t); - t.Clear(); - } - else { - if(c == '>') { - if(lvl == 0) - break; - lvl--; - } - if(c == '<') - lvl++; - t.Cat(c); - } - } - tparam.Add(t); - } - else - r.Cat(*s++); - } - LLOG("ParseTemplatedType " << type << " -> " << r); - LDUMPC(tparam); - return r; -} - -String ResolveTParam(const CppBase& codebase, const String& type, const Vector& tparam) -{ - LLOG("ResolveTParam " << type << ' ' << tparam); - String r; - const char *s = type; - while(*s) { - if(IsDigit(*s)) { - int i = *s++ - '0'; - if(i >= 0 && i < tparam.GetCount()) - r.Cat(tparam[i]); - } - else - if(iscib(*s)) - while(iscid(*s)) - r.Cat(*s++); - else - r.Cat(*s++); - } - LLOG("Resolved " << type << " -> " << r); - const Array& x = GetTypeItems(codebase, r); - if(x.GetCount() && x[0].kind == TYPEDEF) { - LLOG("Is typedef " << x[0].qtype << ", unqualified " << x[0].type << ", natural " << x[0].natural); - String h = x[0].qtype; - if(h != type && h != r) - return ResolveTParam(codebase, h, tparam); - return h; - } - return r; -} - -void ResolveTParam(const CppBase& codebase, Vector& type, const Vector& tparam) -{ - for(int i = 0; i < type.GetCount(); i++) - type[i] = ResolveTParam(codebase, type[i], tparam); -} - -struct ExpressionTyper { - const CppBase& codebase; - int scan_counter; // limit permutations - String context_type; - String usings; - const Vector& xp; - Index typeset; - const ParserContext& parser; - - Vector GetTypeBases(const String& type); - String ResolveReturnType(const CppItem& m, const Vector& tparam); - - void ExpressionType(bool isptr, const String& ttype, int ii, - bool variable, bool can_shortcut_operator, - Index& visited_bases, int lvl); - void ExpressionType(bool isptr, const String& ttype, int ii, bool variable, int lvl); - - Index ExpressionType(); - - enum { MAX_COUNT = 1000 }; - - ExpressionTyper(const CppBase& codebase, const ParserContext& parser, const Vector& xp); -}; - -ExpressionTyper::ExpressionTyper(const CppBase& codebase, const ParserContext& parser, const Vector& xp) -: codebase(codebase), xp(xp), parser(parser) -{ - scan_counter = 0; - context_type = parser.current_scope; - usings = parser.context.namespace_using; -} - -Vector ExpressionTyper::GetTypeBases(const String& type) -{ - const Array& n = GetTypeItems(codebase, type); - String bases; - for(int i = 0; i < n.GetCount(); i++) { - const CppItem& im = n[i]; - if(im.IsType()) - bases << im.qptype << ';'; - } - Index r; - Vector h = Split(bases, ';'); - for(int i = 0; i < h.GetCount(); i++) - r.FindAdd(h[i]); - return r.PickKeys(); -} - -String ExpressionTyper::ResolveReturnType(const CppItem& m, const Vector& tparam) -{ - if(m.tparam.GetCount()) { - int q = InScListIndex(m.qtype, m.tname); - if(q >= 0 && q < tparam.GetCount()) - return tparam[q]; - } - return m.qtype; -} - -Vector SplitTScope(const char *s) -{ - Vector r; - const char *b = s; - while(*s) { - if(*s == '<') { - s++; - int lvl = 0; - while(*s) { - int c = *s++; - if(c == '>') { - if(lvl == 0) - break; - lvl--; - } - if(c == '<') - lvl++; - } - } - else - if(*s == ':') { - if(s > b) - r.Add(String(b, s)); - while(*s == ':') - s++; - b = s; - } - else - s++; - } - if(s > b) - r.Add(String(b, s)); - return r; -} - -String AddTParams(const String& type, const String& ttype) -{ // Upp::Vector::Foo, Upp::Vector::Bar -> Upp::Vector::Foo - if(ttype.Find('<') < 0) - return type; - Vector t = SplitTScope(type); - Vector tt = SplitTScope(ttype); - int i = 0; - String r; - while(i < t.GetCount() && i < tt.GetCount()) { - int q = tt[i].Find('<'); - if(q < 0) - q = tt[i].GetLength(); - if(tt[i].Mid(0, q) != t[i]) - break; - if(i) - r << "::"; - r << tt[i]; - i++; - } - while(i < t.GetCount()) { - if(i) - r << "::"; - r << t[i]; - i++; - } - LLOG("AddTParam " << type << ", " << ttype << " -> " << r); - return r; -} - -void ExpressionTyper::ExpressionType(bool isptr, const String& ttype, int ii, - bool variable, bool can_shortcut_operator, - Index& visited_bases, int lvl) -{ - LLOG("--- ExpressionType " << scan_counter << ", lvl " << lvl << ", ttype " << ttype << ", isptr " << isptr - << ", ii: " << ii << ", " << (ii < xp.GetCount() ? xp[ii] : "")); - if(++scan_counter >= MAX_COUNT || lvl > 100) // sort of ugly limitation of parsing permutations - return; - LDUMP(can_shortcut_operator); - Vector tparam; - String type = ParseTemplatedType(ttype, tparam); - int c0 = typeset.GetCount(); - const Array& n = GetTypeItems(codebase, type); - LDUMP(type); - LDUMP(tparam); - - // STL/NTL is too much to parse for now, so until we have better expression resolver, let us play dirty - static Index std_container; - static Index std_pair_container; - static Index std_container_iterator; - static Index std_pair_container_iterator; - static Index upp_container; - static Index upp_container_iterator; - static Index upp_map_container; - static Index upp_map_container_iterator; - static Index upp_map_container_key_iterator; - ONCELOCK { - Vector a = Split("array;vector;deque;forward_list;list;stack;queue;priority_queue;" - "set;multiset;unordered_set;unordered_multiset", ';'); - for(int i = 0; i < a.GetCount(); i++) { - std_container.Add("std::" + a[i]); - std_container_iterator.Add("std::" + a[i] + "::iterator"); - } - a = Split("map;multimap;unordered_map;unordered_multimap", ';'); - for(int i = 0; i < a.GetCount(); i++) { - std_container.Add("std::" + a[i]); - std_pair_container_iterator.Add("std::" + a[i] + "::iterator"); - } - a = Split("VectorMap;ArrayMap;SortedVectorMap;SortedArrayMap", ';'); - for(int i = 0; i < a.GetCount(); i++) { - upp_map_container.Add("Upp::" + a[i]); - upp_map_container_iterator.Add("Upp::" + a[i] + "::iterator"); - upp_map_container_iterator.Add("Upp::" + a[i] + "::Iterator"); - upp_map_container_key_iterator.Add("Upp::" + a[i] + "::KeyIterator"); - } - a = Split("Index;ArrayIndex;InVector;InArray;SortedIndex", ';'); - for(int i = 0; i < a.GetCount(); i++) { - upp_container.Add("Upp::" + a[i]); - upp_container_iterator.Add("Upp::" + a[i] + "::iterator"); - upp_container_iterator.Add("Upp::" + a[i] + "::Iterator"); - } - } - if(tparam.GetCount() > 0 && std_container_iterator.Find(type) >= 0) { - LLOG("# nasty iterator"); - typeset.Clear(); - ExpressionType(false, tparam[0], ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(tparam.GetCount() > 1 && std_pair_container_iterator.Find(type) >= 0) { - LLOG("# nasty pair iterator"); - typeset.Clear(); - ExpressionType(false, "std::pair<" + tparam[0] + "," + tparam[1] + ">", - ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(tparam.GetCount() > 0 && upp_container_iterator.Find(type) >= 0) { - LLOG("# Upp nasty iterator"); - typeset.Clear(); - ExpressionType(false, tparam[0], ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(tparam.GetCount() > 1 && upp_map_container_iterator.Find(type) >= 0) { - LLOG("# Upp map nasty iterator"); - typeset.Clear(); - ExpressionType(false, tparam[1], ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(tparam.GetCount() > 1 && upp_map_container_key_iterator.Find(type) >= 0) { - LLOG("# Upp map nasty key iterator"); - typeset.Clear(); - ExpressionType(false, tparam[0], ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - - if(codebase.namespaces.Find(ttype) < 0 && ttype.GetCount()) // do not search for namespace typedefs - for(int i = 0; i < n.GetCount(); i++) - if(n[i].kind == TYPEDEF) { - LLOG("typedef -> " << n[i].qtype); - ExpressionType(false, AddTParams(ResolveTParam(codebase, n[i].qtype, tparam), ttype), ii, variable, can_shortcut_operator, visited_bases, lvl + 1); - return; - } - if(ii >= xp.GetCount()) { - LLOG("==== Final type: " << ttype); - typeset.FindAdd(ttype); - return; - } - String id = xp[ii]; - - // More nasty tricks to make things work with containers (hopefully temporary) - if((id == "begin" || id == "end") && std_container.Find(type) >= 0) { - LLOG("# nasty begin/end"); - typeset.Clear(); - ExpressionType(false, ttype + "::iterator", ii + 1, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(findarg(id, "begin", "end", "Begin", "End") >= 0 && - (upp_map_container.Find(type) >= 0 || upp_container.Find(type) >= 0)) { - LLOG("# nasty Upp begin/end"); - typeset.Clear(); - ExpressionType(false, ttype + "::Iterator", ii + 1, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - if(findarg(id, "KeyBegin", "KeyEnd") >= 0 && upp_map_container.Find(type) >= 0) { - LLOG("# nasty Upp KeyBegin/KeyEnd"); - typeset.Clear(); - ExpressionType(false, ttype + "::KeyIterator", ii + 1, variable, can_shortcut_operator, visited_bases, lvl + 1); - scan_counter = MAX_COUNT; - return; - } - - int q = id.ReverseFind(':'); - if(q > 0 && id[q - 1] == ':') { - type = ResolveTParam(codebase, Qualify(codebase, ttype, id.Mid(0, q - 1), usings), tparam); - id = id.Mid(q + 1); - } - if(id.Find('<') >= 0) // as in Single - id = ParseTemplatedType(id, tparam); - LLOG("ExpressionType " << type << " ii: " << ii << " id:" << id << " variable:" << variable); - - for(int i = 0; i < tparam.GetCount(); i++) // need to qualify template parameters - tparam[i] = Qualify(codebase, context_type, tparam[i], usings); - - bool shortcut_oper = false; - if(!iscid(*id) && *id != '.' && !isptr) { - shortcut_oper = can_shortcut_operator; - id = "operator" + id; - LLOG("id as: " << id); - } - if(*id == '.' || (!variable && !iscid(*id))) { - LLOG(". " << ttype); - ExpressionType(isptr, ttype, ii + 1, false, lvl + 1); - return; - } - LDUMP(id); - for(int i = 0; i < n.GetCount(); i++) { - const CppItem& m = n[i]; - if(m.name == id) { - String t = AddTParams(ResolveReturnType(m, tparam), ttype); - bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()"; - ExpressionType(m.isptr, ResolveTParam(codebase, t, tparam), ii + skipfnpars + 1, - m.IsData() && !m.isptr, lvl + 1); - } - } - - if(typeset.GetCount() == c0 && type.GetCount()) { // try to find id in type - Class::Method case - String type2 = ParseTemplatedType(type, tparam); - const Array& n = GetTypeItems(codebase, type2); - for(int i = 0; i < n.GetCount(); i++) { - const CppItem& m = n[i]; - if(m.name == id) { - String t = AddTParams(ResolveReturnType(m, tparam), type); - bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()"; - ExpressionType(m.isptr, ResolveTParam(codebase, t, tparam), ii + skipfnpars + 1, - m.IsData() && !m.isptr, lvl + 1); - } - } - } - - if(typeset.GetCount() != c0 || IsNull(type)) - return; - Vector base = GetTypeBases(type); - LDUMPC(base); - ResolveTParam(codebase, base, tparam); - LDUMPC(base); - for(int i = 0; i < base.GetCount(); i++) - if(visited_bases.Find(base[i]) < 0) { - visited_bases.Add(base[i]); - ExpressionType(isptr, base[i], ii, variable, false, visited_bases, lvl + 1); - if(typeset.GetCount() != c0) - return; - } - - if(shortcut_oper) { - LLOG("Shortcut " << xp[ii] << ", ttype " << ttype); - ExpressionType(false, ttype, ii + 1, false, lvl + 1); - } -} - -void ExpressionTyper::ExpressionType(bool isptr, const String& ttype, int ii, bool variable, int lvl) -{ - Index bases; - ExpressionType(isptr, ttype, ii, false, true, bases, 0); -} - -Index ExpressionTyper::ExpressionType() -{ - LLOG("------------------------------------------------------"); - LLOG("**** ExpressionType " << xp); - String type; - if(xp.GetCount() == 0) - return pick(typeset); - if(xp[0] == "this") { - LLOG("this: " << type); - ExpressionType(false, context_type, 1, false, 0); - return pick(typeset); - } - int q = parser.local.FindLast(xp[0]); - if(q >= 0) { - String type = Qualify(codebase, context_type, parser.local[q].type, parser.context.namespace_using); - LLOG("Found type local: " << type << " in scope: " << context_type << ", isptr: " << parser.local[q].isptr); - ExpressionType(parser.local[q].isptr, type, 1, !parser.local[q].isptr, 0); - return pick(typeset); - } - if(context_type.GetCount()) { - ExpressionType(false, context_type, 0, false, 0); - if(typeset.GetCount()) - return pick(typeset); - } - if(xp.GetCount() >= 2 && xp[1] == "()") { - Vector usings = Split(parser.context.namespace_using, ';'); - usings.Add(""); - for(int i = 0; i < usings.GetCount(); i++) { - String qtype = Qualify(codebase, context_type, Merge("::", usings[i], xp[0]), parser.context.namespace_using); - Vector tparam; - if(codebase.Find(ParseTemplatedType(qtype, tparam)) >= 0) { - LLOG("Is constructor " << qtype); - ExpressionType(false, qtype, 2, false, 0); - } - } - if(typeset.GetCount()) - return pick(typeset); - } - Vector ns = parser.GetNamespaces(); - for(int i = 0; i < ns.GetCount(); i++) - ExpressionType(false, ns[i], 0, false, 0); - return pick(typeset); -} - -Index GetExpressionType(const CppBase& codebase, const ParserContext& parser, const Vector& xp) -{ // xp is a list of meaningful parts like "foo", "." , "Fn", "()", "->", "m", "[]" - return ExpressionTyper(codebase, parser, xp).ExpressionType(); -} - -void SkipPars(CParser& p) -{ - int lvl = 1; - while(lvl && !p.IsEof()) - if(p.Char('(') || p.Char('[')) - lvl++; - else - if(p.Char(')') || p.Char(']')) - lvl--; - else - p.SkipTerm(); -} - -Vector MakeXP(const char *s) -{ - Vector xp; - try { - CParser p(s); - while(!p.IsChar2(':', ':') && !p.IsId() && !p.IsEof()) - p.SkipTerm(); - while(!p.IsEof()) { - String id; - if(p.IsChar2(':', ':') || p.IsId()) { - for(;;) - if(p.Char2(':', ':')) - id.Cat("::"); - else - if(p.IsId()) - id.Cat(p.ReadId()); - else - break; - const char *s = p.GetPtr(); - if(p.Char('<')) { - int lvl = 1; - while(lvl && !p.IsEof()) { - if(p.Char('<')) - lvl++; - else - if(p.Char('>')) - lvl--; - else - p.SkipTerm(); - } - while(s < p.GetPtr()) { - if((byte)*s > ' ') - id.Cat(*s); - s++; - } - } - xp.Add(id); - } - else - if(p.Char('(')) { - xp.Add("()"); - SkipPars(p); - } - else - if(p.Char('[')) { - xp.Add("[]"); - SkipPars(p); - } - else - if(p.Char2('-', '>')) - xp.Add("->"); - else - if(p.Char('.')) - xp.Add("."); - else - break; - } - } - catch(CParser::Error) {} - return xp; -} - -}; \ No newline at end of file diff --git a/uppsrc/CppBase/Iface.cpp b/uppsrc/CppBase/Iface.cpp deleted file mode 100644 index bc331940d..000000000 --- a/uppsrc/CppBase/Iface.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -bool HasCPPFileKeyword(const String& path, const String& id) -{ - const PPFile& f = GetPPFile(NormalizeSourcePath(path)); - return FindIndex(f.keywords, id) >= 0; -} - -String GetDependeciesMD5(const String& path, Index& visited) -{ - Cpp pp; - FileIn in(path); - String npath = NormalizeSourcePath(path); - pp.Preprocess(npath, in, GetMasterFile(npath), true); - String md5 = pp.GetDependeciesMd5(GetPPFile(path).keywords); - visited = pick(pp.visited); - return md5; -} - -String GetPPMD5(const String& fn) -{ - return GetPPFile(fn).md5sum; -} - -void Parse(CppBase& base, - const String& src, int file, int filetype, const String& path, - Event error, const Vector& namespace_stack, - const Index& namespace_using) -{ - StringStream pin(src); - Parser p; - p.Do(pin, base, file, filetype, GetFileName(path), error, Vector(), - namespace_stack, namespace_using); -} - -void PreprocessParse(CppBase& base, Stream& in, int file, const String& path, - Event error) -{ - Cpp cpp; - cpp.Preprocess(path, in, GetMasterFile(path)); - int filetype = decode(ToLower(GetFileExt(path)), ".h", FILE_H, ".hpp", FILE_HPP, - ".cpp", FILE_CPP, ".icpp", FILE_CPP, ".c", FILE_C, FILE_OTHER); - Parse(base, cpp.output, file, filetype, path, error, cpp.namespace_stack, cpp.namespace_using); -} - -String PreprocessCpp(const String& src, const String& path) -{ - Cpp cpp; - StringStream in(src); - String p = NormalizeSourcePath(path); - cpp.Preprocess(p, in, GetMasterFile(p)); - return cpp.output; -} - -ParserContext AssistParse(const String& src, const String& path_, Event error, - Function qualify) -{ - String path = NormalizeSourcePath(path_); - Cpp cpp; - StringStream ss(src); - cpp.Preprocess(path, ss, GetMasterFile(path)); - Parser parser; - parser.dobody = true; // will do bodies and not write anything to base - parser.qualify = qualify; - StringStream pin(cpp.output); - CppBase dummy; - parser.Do(pin, dummy, Null, Null, GetFileTitle(path), error, - Vector(), cpp.namespace_stack, cpp.namespace_using); // needs CodeBase to identify type names - return pick(parser); -} - -void SimpleParse(CppBase& cpp, const String& txt, const String& cls) -{ - Parser parser; // we do not need/want preprocessing here - StringStream ss(txt); - parser.Do(ss, cpp, Null, Null, Null, CNULL, Split(cls, ':'), - Vector(), Index()); -} - -}; \ No newline at end of file diff --git a/uppsrc/CppBase/Internal.h b/uppsrc/CppBase/Internal.h deleted file mode 100644 index 218a9d940..000000000 --- a/uppsrc/CppBase/Internal.h +++ /dev/null @@ -1,450 +0,0 @@ -#ifndef _CppBase_Internal_h_ -#define _CppBase_Internal_h_ - -namespace Upp { - -const char *SkipString(const char *s); - -void RemoveComments(String& l, bool& incomment); - -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() { segment_id = 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); - -String GetIncludePath(); - -String GetSegmentFile(int segment_id); - -void MakePP(const Index& paths); // this is the only place to change PPFile info, cannot be run concurrently with anything else - -const PPFile& GetPPFile(const char *path); // only returns information created by MakePP - -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 - -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, -}; - -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: - Event 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); - -String CppItemKindAsString(int kind); - -struct Parser : ParserContext { - struct Decla { - bool s_static = false; - bool s_extern = false; - bool s_register = false; - bool s_mutable = false; - bool s_explicit = false; - bool s_virtual = false; - String name; - bool function = false; - bool type_def = false; - bool isfriend = false; - bool istemplate = false; - bool istructor = false; - bool isdestructor = false; - bool isptr = false; - bool nofn = false; - bool oper = false; - bool castoper = false; - - String tnames; - String type; - String natural; - }; - - 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; } - }; - - SrcFile file; - Lex lex; - int filei; - byte filetype; - String title; - int struct_level; - - Event err; - - int lpos, line; - - CppBase *base; - - int RPtr(); - - bool Key(int code); - bool EatBody(); - String ResolveAutoType(); - void TryLambda(); - bool Skipars(int& q); - - void Cv(); - String TType(); - String ReadType(Decla& d, const String& tname, const String& tparam); - void Qualifier(bool override_final = false); - 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); - - void ClassEnum(const String& clss); - bool IsEnum(int i); - bool UsingNamespace(); - void SetScopeCurrent(); - void ScopeBody(); - void DoNamespace(); - void Do(); - String AnonymousName(); - String StructDeclaration(const String& tp, const String& tn); - void Enum(bool vars); - - 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); - bool IsNamespace(const String& scope); - - friend class Lex; // Fix to make Lex::ThrowError - - typedef Parser CLASSNAME; - -public: - void AddMacro(int lineno, const String& macro, int kind = MACRO); - - bool dobody; - Function qualify; // used to qualify local variable names (needs main codebase and its mutex) - int currentScopeDepth; - int maxScopeDepth; - - String namespace_info; - - const SrcFile &getPreprocessedFile() { return file; } - - void Do(Stream& in, CppBase& _base, int file, int filetype, - const String& title, Event _err, - const Vector& typenames, - const Vector& namespace_stack, - const Index& namespace_using); - - Parser() : dobody(false) { lex.WhenError = THISBACK(ThrowError); } -}; - -void QualifyTypes(CppBase& base, const String& scope, CppItem& m); -String QualifyKey(const CppBase& base, const String& scope, const String& type, const String& usings); - -const Array& GetTypeItems(const CppBase& codebase, const String& type); - -Vector MakeXP(const char *s); - -}; - -#endif diff --git a/uppsrc/CppBase/Parser.cpp b/uppsrc/CppBase/Parser.cpp deleted file mode 100644 index 98962b709..000000000 --- a/uppsrc/CppBase/Parser.cpp +++ /dev/null @@ -1,1796 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LLOG(x) // DLOG(x) -#define LTIMING(x) // DTIMING(x) - -void Parser::ThrowError(const String& e) -{ - err(GetLine(lex.Pos()), e); -#ifdef _DEBUG - int i = 0; - while(i < 40 && lex[i] != t_eof) - i++; - LLOG("ERROR: (" << GetLine(lex.Pos()) << ") " << e << ", scope: " << current_scope << - ", code: " << AsCString(String(lex.Pos(), lex.Pos(i)))); -#endif - throw Error(); -} - -inline const char *bew(const char *s, const char *t) -{ - while(*s) - if(*s++ != *t++) - return NULL; - return t; -} - -// String == String comparison is likely faster than String == const char * comparison -static String s_operator("operator"); -static String s_virtual("virtual"); -static String s_inline("inline"); -static String s_static("static"); - -static inline bool sSpaces(String& res, const char *& s) -{ - if((byte)*s <= ' ') { - char c = *s++; - if(c != '\2' && c != '\x1f') { - res.Cat(' '); - while((byte)*s <= ' ' && *s) - s++; - } - return true; - } - return false; -} - -String FnItem(const char *s, const char *pname, const char *qname, const String& name, bool oper) -{ // Converts function natural text to (unqualified) item - String res; - while(*s && (byte)*s <= ' ') s++; - while(*s) { // Get the name of function into res - while(*s && !iscid(*s) && *s != '~') - if(*s == '[') { // Skip MSVC attributes - while(*s) - if(*s++ == '[') - break; - } - else - s++; - int lvl = 0; - int plvl = 0; - for(;;) { - if(*s == '<' && plvl == 0 && !oper) { // resolve template params, like Fn - res.Cat(*s++); - lvl++; - } - if(*s == '>' && plvl == 0 && !oper) { - res.Cat(*s++); - lvl--; - } - if(*s == '(' && lvl) { - res.Cat(*s++); - plvl++; - } - if(*s == ')') { - res.Cat(*s++); - plvl--; - } - if(iscid(*s) || *s == '~' || *s && lvl) - res.Cat(*s++); - else - break; - } - if(res == s_operator) { - while(*s && *s != '(') { - if((byte)*s >= ' ') - res.Cat(*s); - s++; - } - break; - } - while(*s && (byte)*s <= ' ') - s++; - if(*s == '(' && (res == name || res == '~' + name)) - break; - res.Clear(); - } - bool wasid = false; - while(*s) { - const char *w = bew(qname, s); - byte c = *s; - if(w && w > s && !iscid(*w)) { - if(iscid(*res.Last())) - res.Cat(' '); - res.Cat(name); - s = w; - wasid = true; - } - else - if(iscid(c)) { - const char *b = s++; - while(iscid(*s)) s++; - String q(b, s); - if(q != s_virtual && q != s_inline && q != s_static && !InScList(q, pname)) { - if(iscid(*res.Last())) - res.Cat(' '); - res.Cat(q); - } - else - while((byte)*s <= ' ' && *s) s++; - wasid = true; - } - else - if(c == '=') { - s++; - int l = 0; - int tl = 0; - while(*s && !(l == 0 && (*s == ',' && tl == 0 || *s == ')'))) { - if(*s == '(' || *s == '[') - l++; - else - if(*s == ')' || *s == ']') - l--; - if(*s == '<') // we always consider < > to be template bracket, not operator here - tl++; - else - if(*s == '>') - tl--; - s++; - } - } - else - if((byte)*s <= ' ') { - s++; - while((byte)*s <= ' ' && *s) - s++; - } - else - if(c == '[' && !wasid) { // Skip MSVC attribute - while(*s) - if(*s++ == ']') - break; - } - else - if(c == '-' && s[1] == '>') - break; // trailing return type - else { - res.Cat(c); - if(c == ',') - wasid = false; - s++; - } - } - return res; -} - -String Purify(const char *s, const char *qname, const String& name) { - String res; - while(*s && (byte)*s <= ' ') s++; - bool wasid = false; - bool firstpar = true; - while(*s) { - const char *w = bew(qname, s); - if(w && w > s) { - res.Cat(name); - s = w; - wasid = true; - } - else - if(iscid(*s)) { - const char *b = s++; - while(iscid(*s)) s++; - String q(b, s); - if(q != s_virtual && q != s_inline && q != s_static) - res.Cat(q); - else - while((byte)*s <= ' ' && *s) s++; - wasid = true; - } - else - if(*s == '[' && !wasid) { // skip MSVC attribute - do { - while(*s) - if(*s++ == ']') - break; - while(*s == ' ' || *s == '\2' || *s == '\x1f') - s++; - } - while(*s == '['); - } - else - if(!sSpaces(res, s)) { - if(*s == ',') - wasid = false; - if(*s == '(' && firstpar) - wasid = firstpar = false; - res.Cat(*s++); - } - } - return TrimRight(res); -} - -String Purify(const char *s) { - String res; - while(*s && (byte)*s <= ' ') s++; - while(*s) { - if(iscid(*s)) { - const char *b = s++; - while(iscid(*s)) s++; - String q(b, s); - if(q != s_virtual && q != s_inline) - res.Cat(q); - else - while((byte)*s <= ' ' && *s) s++; - } - else - if(!sSpaces(res, s)) - res.Cat(*s++); - } - return TrimRight(res); -} - -String Gpurify(const char *s) -{ - String res; - while(*s) - if(!sSpaces(res, s)) - res.Cat(*s++); - return res; -} - -void ScAdd(String& s, const String& a) -{ - if(a.IsEmpty()) return; - if(!s.IsEmpty()) - s << ';'; - s << a; -} - - -void TpSkip(CParser& p) -{ - int lvl = 0; - for(;;) { - if(lvl == 0 && (p.IsChar(',') || p.IsChar('>')) || p.IsEof()) - break; - if(p.Char('<')) - lvl++; - else - if(p.Char('>')) - lvl--; - else - p.SkipTerm(); - } -} - -String Subst(const String& s, const Vector& tpar) -{ - if(tpar.GetCount() == 0) - return s; - String r; - CParser p(s); - while(!p.IsEof()) { - if(p.IsId()) { - String id = p.ReadId(); - int q = FindIndex(tpar, id); - if(q >= 0) - r << AsString(q); - else - r << id; - } - else - r << p.GetChar(); - } - return r; -} - -String CleanTp(const String& tp) -{ - int q = tp.Find('<'); - int w = tp.ReverseFind('>'); - if(q < 0 || w < 0) return tp; - String a = TrimLeft(TrimRight(tp.Mid(q + 1, w - q - 1))); - const char *s = a; - String r; - while(*s) { - if(*s == ',') { - r.Cat(';'); - s++; - while(*s && *s <= ' ') - s++; - } - else - r.Cat(*s++); - } - return r; -} - -String Parser::Context::Dump() const -{ - return "Scopeing: " + scope; -} - -static String s_dblcln("::"); - -inline void ScopeCat(String& scope, const String& s) -{ - if(scope.GetCount()) - scope << s_dblcln; - scope << s; -} - -void Parser::Context::operator<<=(const Context& t) -{ - ns = t.ns; - scope = t.scope; - typenames = clone(t.typenames); - tparam = clone(t.tparam); - access = t.access; - ctname = t.ctname; - namespace_using = t.namespace_using; -} - -bool Parser::IsNamespace(const String& scope) -{ - int l = scope.GetCount(); - return memcmp(~context.ns, ~scope, l) == 0 && findarg(context.ns[l], '\0', ':') >= 0; -} - -bool Parser::Key(int code) -{ - if(lex == code) { - ++lex; - return true; - } - return false; -} - -int Parser::GetLine(const char *p) -{ - int pos = int(p - ~file.text); - int l = 0; - int h = file.linepos.GetCount(); - while(l < h) { - int q = (l + h) / 2; - if(file.linepos[q] < pos) - l = q + 1; - else - h = q; - } - return l; -} - -void Parser::Line() -{ - int pos = int(lex.Pos() - ~file.text); - while(line + 1 < file.linepos.GetCount() && file.linepos[line + 1] <= pos) - line++; -} - -void Parser::Check(bool b, const char *err) -{ - if(!b) ThrowError(err); -} - -void Parser::CheckKey(int c) -{ - if(!Key(c)) ThrowError(Format("Missing %c", c)); -} - -String Parser::TemplateParams(String& param) -{ - String r; - do { - const char *pos = lex.Pos(); - CheckKey('<'); - int level = 1; - String id; - bool gp = true; - while(lex != t_eof) { - if(lex.IsId() && gp) - id = lex.GetId(); - else - if(Key(',')) { - ScAdd(param, id); - id.Clear(); - gp = true; - } - else - if(Key('=')) { - if(!id.IsEmpty()) { - ScAdd(param, id); - id.Clear(); - } - gp = false; - } - else - if(Key('>')) { - level--; - if(level <= 0) { - ScAdd(param, id); - break; - } - } - else - if(Key(t_shr) && level >= 2) { - level -= 2; - if(level <= 0) { - ScAdd(param, id); - break; - } - } - else - if(Key('<')) - level++; - else - if(Key('(')) - level++; - else - if(Key(')')) - level--; - else - ++lex; - } - MergeWith(r, ",", String(pos, lex.Pos())); - } - while(Key(tk_template)); - return r; -} - -String Parser::TemplateParams() -{ - String dummy; - return TemplateParams(dummy); -} - -String Parser::TemplatePnames() -{ - String pnames; - TemplateParams(pnames); - return pnames; -} - -String Parser::ReadOper(bool& castoper) { - const char *p = lex.Pos(); - Key(tk_operator); - int level = 0; - if(Key('(')) - level++; - for(;;) { - if(lex == t_eof || level <= 0 && lex == '(') break; - if(Key('(') || Key('[')) level++; - else - if(Key(')') || Key(']')) level--; - else - ++lex; - } - StringBuffer r; - bool spc = false; - while(p < lex.Pos()) { - if((byte)*p > ' ') { - if(spc && iscid(*p)) { - castoper = true; - r.Cat(' '); - } - r.Cat(*p); - spc = false; - } - else - spc = true; - p++; - } - return String(r); -} - -String Parser::Name(String& name, bool& castoper, bool& oper) -{ - String s; - if(Key(t_dblcolon)) { - s = "::"; - name = s; - } - Check(lex.IsId() || lex == tk_operator, "Name expected"); - for(;;) { - if(lex.IsId()) { - name << lex.Id(); - s << lex.GetId(); - } - else { - String h = ReadOper(castoper); - oper = true; - name << h; - s << h; - break; - } - if(lex == '<') // void Fn(); situation - s << TemplateParams(); - if(Key(t_dblcolon)) { - s << "::"; - name << "::"; - if(Key('~')) { - s << "~"; - name << "~"; - } - } - else - break; - } - return s; -} - -String Parser::Name(bool& castoper, bool& oper) -{ - String h; - return Name(h, castoper, oper); -} - -String Parser::Constant() -{ - const char *p = lex.Pos(); - const char *p1 = p; - int level = 0; - for(;;) { - p1 = lex.Pos(); - if(lex == t_eof) break; - if(level <= 0 && (lex == ',' || lex == ';' || lex == ')' || lex == '}' || lex == ']')) - break; - if(Key('(') || Key('[') || Key('{')) level++; - else - if(Key(')') || Key(']') || Key('}')) level--; - else - ++lex; - } - return String(p, p1); -} - -String Parser::TType() -{ - int q = FindIndex(context.tparam, lex[0]); - if(q >= 0) return AsString(q); - return lex.Id(); -} - -String Parser::StructDeclaration(const String& tn, const String& tp) -{ - int t = lex.GetCode(); // t is now struct/class/union - context.typenames.FindAdd(lex); - Context cc; - cc <<= context; - CParser p(tp); - Vector tpar; - if(p.Char('<')) { - while(!p.IsEof() && !p.Char('>')) { - if((p.Id("class") || p.Id("typename") || p.Id("struct")) && p.IsId()) { - tpar.Add(p.ReadId()); - context.tparam.Add(lex.Id(tpar.Top())); - } - else - context.tparam.Add(0); - TpSkip(p); - p.Char(','); - } - } - if(Key(t_dblcolon)) - context.scope = Null; - String name; - String new_scope = context.scope; - if(lex.IsId()) - do { - context.typenames.FindAdd(lex); - name = lex.GetId(); // name of structure - if(lex == '<') - name << TemplateParams(); - ScopeCat(new_scope, name); - } - while(Key(t_dblcolon)); - else { - name = AnonymousName(); - ScopeCat(new_scope, name); - } - if(lex.IsId() && findarg(lex.Id(), "override", "final") >= 0) - ++lex; - if(lex.IsId() || lex == '*') { // struct My { struct My *p; } - return name; - } - context.scope = new_scope; - context.access = t == tk_class ? PRIVATE : PUBLIC; - if(tn.GetCount()) { - if(context.ctname.GetCount()) - context.ctname << ';'; - context.ctname << tn; - } - String nn; - if(!tp.IsEmpty()) - nn = "template " + tp + " "; - String key = (t == tk_class ? "class" : t == tk_union ? "union" : "struct"); - nn << key << ' ' << name; - LLOG("Struct " << context.scope << " using " << context.namespace_using); - CppItem& im = Item(context.scope, context.namespace_using, key, name, lex != ';'); - im.kind = tp.IsEmpty() ? STRUCT : STRUCTTEMPLATE; - im.type = name; - im.access = cc.access; - im.tname = tn; - im.ctname = context.ctname; - im.tparam = CleanTp(tp); - im.ptype.Clear(); - im.pname.Clear(); - im.param.Clear(); - if(lex == ';') { // TODO: perhaps could be united with following code - context = pick(cc); - im.natural = Gpurify(nn); - SetScopeCurrent(); - return name; - } - if(Key(':')) { - nn << " : "; - bool c = false; - do { - String access = t == tk_class ? "private" : "public"; - bool virt = Key(tk_virtual); - if(Key(tk_public)) access = "public"; - else - if(Key(tk_protected)) access = "protected"; - else - if(Key(tk_private)) access = "private"; - if(Key(tk_virtual) || virt) access << " virtual"; - String h; - bool dummy; - String n = Name(h, dummy, dummy); - ScAdd(im.pname, h); - if(c) - im.ptype << ';'; - im.ptype << Subst(n, tpar); - ScAdd(im.param, access + ' ' + n); - if(c) - nn << ", "; - nn << access + ' ' + n; - c = true; - } - while(Key(',')); - } - if(Key('{')) { - struct_level++; - ScopeBody(); - struct_level--; - im.natural = Gpurify(nn); - im.decla = true; - } - else - if(IsNull(im.natural)) - im.natural = Gpurify(nn); - context = pick(cc); - SetScopeCurrent(); - return name; -} - -String Parser::ReadType(Decla& d, const String& tname, const String& tparam) -{ // returns the name of constructor - if(findarg((int)lex, tk_struct, tk_class, tk_union) >= 0 && !d.isfriend) { - d.type = StructDeclaration(tname, tparam); - return String(); - } - Key(tk_typename) || Key(tk_struct) || Key(tk_class) || Key(tk_union) || Key(tk_enum) || Key(tk_template); - if(Key(tk_bool) || Key(tk_float) || Key(tk_double) || Key(tk_void)) - return Null; - bool sgn = Key(tk_signed) || Key(tk_unsigned); - if(Key(tk_long)) { - Key(tk_long); - Key(tk_int) || Key(tk_double); - return Null; - } - if(Key(tk_short)) { - Key(tk_unsigned); - Key(tk_int); - return Null; - } - if(Key(tk_int) || Key(tk_char) || - Key(tk___int8) || Key(tk___int16) || Key(tk___int32) || Key(tk___int64) || Key(tk___int128) || - Key(tk_char16_t) || Key(tk_char32_t)) return Null; - if(sgn) return Null; - const char *p = lex.Pos(); - bool cs = false; - Index cix; - if(Key(tk_decltype) && Key('(')) { - const char *p = lex.Pos(); - int lvl = 1; - for(;;) { - if(lex == t_eof) - break; - if(lex == '(') - lvl++; - else - if(lex == ')' && --lvl == 0) { - d.type = "@" + String(p, lex.Pos()); - ++lex; - break; - } - ++lex; - } - } - else - if(Key(tk_auto)) - d.type = "*"; - else { - if(Key(t_dblcolon)) - d.type << "::"; - Key(tk_typename) || Key(tk_template); - Check(lex.IsId(), "Name expected"); - while(lex.IsId()) { - d.type << TType(); - if(cix.Find(lex) >= 0) - cs = true; - else - cix.Add(lex); - ++lex; - if(lex == '<') - d.type << TemplateParams(); - if(Key(t_dblcolon)) { - d.type << "::"; - if(Key('~')) - cs = true; - Key(tk_typename) || Key(tk_template); - } - else - break; - } - } - return cs ? String(p, lex.Pos()) : String(); -} - -void Parser::Qualifier(bool override_final) -{ - for(;;) - if(Key(tk_const) || Key(tk_volatile) || Key(tk_constexpr) || Key(tk_thread_local) || VCAttribute()) - ; - else - if(Key(tk_noexcept)) { - if(Key('(')) { - int lvl = 0; - while(lex != t_eof && lex != ';' && !(lvl == 0 && Key(')'))) - if(Key('(')) - lvl++; - else - if(Key(')')) - lvl--; - else - ++lex; - } - } - else - if(override_final && lex.IsId() && findarg(lex.Id(), "override", "final") >= 0) - ++lex; - else - if(Key(tk_throw) || Key(tk_alignas)) { - while(lex != t_eof && lex != ';' && !Key(')')) - ++lex; - } - else - if(lex[0] == '=' && findarg(lex[1], tk_delete, tk_default) >= 0) { - ++lex; - ++lex; - } - else - break; -} - -void Parser::Elipsis(Decl& d) -{ - Decl& q = d.param.Add(); - q.name = "..."; - if(lex.IsId()) // bool emplace(_Args&&... __args); - ++lex; - CheckKey(')'); -} - -void Parser::ParamList(Decl& d) { - if(!Key(')')) - for(;;) { - if(Key(t_elipsis)) { - Elipsis(d); - break; - } - else { - Array decl = Declaration(false, false, Null, Null); - if(decl.GetCount()) { - d.param.Add() = pick(decl.Top()); - if(dobody) { // put arguments to the list of local variables - Decl& p = d.param.Top(); - Local& l = local.Add(p.name); - l.type = p.type; - l.isptr = p.isptr; - l.line = line + 1; - } - } - } - if(Key(t_elipsis)) { - Elipsis(d); - break; - } - if(Key(')')) break; - CheckKey(','); - } -} - -int Parser::RPtr() -{ - int n = 0; - int tlevel = 0; - for(;;) { - int t = lex[n]; - if(t == '*') return n + 1; - if(t == '<') { - tlevel++; - n++; - } - else - if(t == '>') { - tlevel--; - n++; - } - else - if(t == t_shr && tlevel >= 2) { - tlevel -= 2; - n++; - } - else - if(t == t_dblcolon || lex.IsId(n) || t == ',' && tlevel > 0) - n++; - else - return 0; - } -} - -void Parser::EatInitializers() -{ - if(Key(':')) { - int lvl = 0; - for(;;) { - if(lex == t_eof) - break; - if(lvl == 0) { - Qualifier(false); - if(lex == '{') - break; - if(lex.IsId() && lex[1] == '{') { // : X{123} { case - lvl++; - ++lex; - ++lex; - } - } - else - if(lex == '{') - lvl++; - if(lex == '(') - lvl++; - if(lex == ')' || lex == '}') - lvl--; - ++lex; - } - } -} - -void Parser::Declarator(Decl& d, const char *p) -{ - int n = RPtr(); - if(n) { - while(n--) lex.Get(); - Declarator(d, p); - d.isptr = true; - return; - } - if(Key('&') || Key(t_and) || Key(tk_const) || Key(tk_volatile)) { // t_and is r-value here - Declarator(d, p); - return; - } - if(Key('(')) { - Declarator(d, p); - if(d.isptr) - d.nofn = true; - CheckKey(')'); - } -// if(lex == tk_operator) -// d.name = ReadOper(); -// else - if(lex.IsId() || lex == t_dblcolon || lex == tk_operator) { - d.name = Name(d.castoper, d.oper); - if(lex == ':' && lex[1] == t_integer) { // Bitfield, like 'unsigned x:5' - ++lex; - ++lex; - } - } - if(Key('(')) { - if(inbody || (lex < 256 || lex == tk_true || lex == tk_false) - && lex != ')' && lex != '[' && lex != t_dblcolon) { - int level = 0; - for(;;) { - if(lex == t_eof) break; - if(Key('(')) level++; - else - if(Key(')')) { - if(--level < 0) break; - } - else - ++lex; - } - return; - } - else { - d.function = !d.nofn; - ParamList(d); - p = lex.Pos(); - Qualifier(true); - - if(d.function && Key(t_arrow)) { // C++11 trailing return type - d.type.Clear(); - ReadType(d, Null, Null); - } - - if(filetype == FILE_C && lex != '{' && lex != ';') // K&R style function header - while(lex != '{' && lex != t_eof) - ++lex; - } - } - if(*d.type == '*') // C++11 auto declaration - d.type = ResolveAutoType(); - else - EatInitializers(); - while(Key('[')) { - d.isptr = true; - int level = 1; - while(level && lex != t_eof) { - if(Key('[')) level++; - else - if(Key(']')) level--; - else - ++lex; - } - } - if(Key('=') || (inbody && lex == '(')) { // TODO: Add C++11 initializers here (?) - int level = 0; - int tlevel = 0; - for(;;) { - TryLambda(); - if(lex == t_eof || lex == ';' - || level == 0 && ((lex == ',' && tlevel == 0) || lex == ')')) - break; - if(Key('<')) // we ignore < > as operators, always consider them template bracket - tlevel++; - else - if(Key('>')) - tlevel--; - else - if(Key('(') || Key('{')) - level++; - else - if(Key(')') || Key('}')) - level--; - else - ++lex; - } - } -} - -Parser::Decl& Parser::Finish(Decl& d, const char *s) -{ - d.natural = String(s, lex.Pos()); - return d; -} - -bool Parser::IsParamList(int q) -{ - return true; -} - -void Parser::ReadMods(Decla& d) -{ - for(;;) { - if(Key(tk_static)) - d.s_static = true; - else - if(Key(tk_extern)) - d.s_extern = true; - else - if(Key(tk_register)) - d.s_register = true; - else - if(Key(tk_mutable)) - d.s_mutable = true; - else - if(Key(tk_explicit)) - d.s_explicit = true; - else - if(Key(tk_virtual)) - d.s_virtual = true; - else - if(!(Key(tk_inline) || Key(tk_force_inline) || Key(tk_never_inline) || Key(tk___inline) || VCAttribute())) - break; - } -} - -Array Parser::Declaration0(bool l0, bool more, const String& tname, const String& tparam) -{ - Array r; - Decla d; - const char *p = lex.Pos(); - if(Key(tk_friend)) - d.isfriend = true; - ReadMods(d); - Qualifier(); - if(l0) { - if(lex == tk_SKYLARK && lex[1] == '(' && lex.IsId(2)) { - ++lex; - ++lex; - Decl& a = r.Add(); - a.name = lex.GetId(); - a.function = true; - a.natural = String().Cat() << "void " << a.name << "(Http& http)"; - Decl& p = a.param.Add(); - p.name = "http"; - p.type = "Http"; - p.natural = "Http& http"; - Key(','); - lex.GetText(); - Key(')'); - return r; - } - else - if((lex == tk_RPC_METHOD || lex == tk_RPC_GMETHOD) && lex[1] == '(' && lex.IsId(2)) { - ++lex; - ++lex; - Decl& a = r.Add(); - a.name = lex.GetId(); - a.function = true; - a.natural = String().Cat() << "void " << a.name << "(RpcData& rpc)"; - Decl& p = a.param.Add(); - p.name = "rpc"; - p.type = "RpcData"; - p.natural = "RpcData& rpc"; - if (Key(',')) - lex.GetText(); - Key(')'); - return r; - } - } - bool isdestructor = Key('~'); - if(l0 && context.typenames.Find(lex) >= 0 && lex[1] == '(' && lex.IsId()) { - Decl& a = r.Add(); - a.name = lex.GetId(); - a.isdestructor = isdestructor; - a.function = true; - a.istructor = true; - ++lex; - ParamList(a); - Qualifier(); - a.natural = String(p, lex.Pos()); - EatInitializers(); - return r; - } - if(lex == tk_operator) { - Decl& a = r.Add(); - (Decla&)a = d; - a.name = ReadOper(a.castoper); - Key('('); - ParamList(a); - Qualifier(); - a.function = true; - a.natural = String(p, lex.Pos()); - a.oper = true; - return r; - } - String st = ReadType(d, tname, tparam); - if(!lex.IsGrounded()) // 'static' etc.. can be after type too... (but not allow it on start of line) - ReadMods(d); - if(!st.IsEmpty()) { - Decl& a = r.Add(); - int q = st.Find('~'); - if(q >= 0) - st.Remove(q, 1); - a.name = st; - a.isdestructor = q >= 0; - a.function = true; - a.istructor = true; - if(Key('(')) - ParamList(a); - Qualifier(); - a.natural = String(p, lex.Pos()); - EatInitializers(); - return r; - } - String natural1 = String(p, lex.Pos()); - if(lex != ';') // struct/class declaration without defining variable - do { - const char *p1 = lex.Pos(); - Decl& a = r.Add(); - (Decla&)a = d; - Declarator(a, p); - if(a.castoper) - a.name = Filter(natural1, CharFilterNotWhitespace) + a.name; - a.natural = natural1 + String(p1, lex.Pos()); - p = lex.Pos(); - } - while(more && Key(',')); - return r; -} - -Array Parser::Declaration(bool l0, bool more, const String& tname, const String& tparam) -{ - if(Key(tk_typedef)) { - Array r = Declaration0(false, true, tname, tparam); - for(int i = 0; i < r.GetCount(); i++) { - r[i].type_def = true; - r[i].natural = "typedef " + r[i].natural; - } - return r; - } - const char *b = lex.Pos(); - if(Key(tk_using) && lex.IsId()) { - String name = lex.GetId(); - Key('='); - Array r; - Decl& d = r.Add(); - ReadType(d, tname, tparam); - while(Key('*') || Key(tk_volatile) || Key(tk_const)); - d.name = name; - d.natural = String(b, lex.Pos()); - d.type_def = true; - return r; - } - return Declaration0(l0, more, tname, tparam); -} - -String Parser::Tparam(int& q) -{ - if(lex[q] != '<') - return Null; - const char *p = lex.Pos(q); - int level = 1; - q++; - while(lex[q] != t_eof && level) { - if(lex[q] == '<') - level++; - if(lex[q] == '>') - level--; - else - if(lex[q] == t_shr && level >= 2) - level -= 2; - q++; - } - return String(p, lex.Pos(q)); -} - -String NoTemplatePars(const String& s) -{ - int q = s.Find('<'); - return q >= 0 ? s.Mid(0, q) : s; -} - -bool Parser::VCAttribute() -{ - if(lex[0] == '[') // Skip Visual C++ attribute - for(;;) { - if(lex[0] == ']') { - ++lex; - return true; - } - if(lex[0] == t_eof) - return false; - ++lex; - } - return false; -} - -void Parser::SetScopeCurrent() -{ - current_scope = context.scope; -} - -CppItem& Parser::Item(const String& scope, const String& using_namespace, const String& item, - const String& name, bool impl) -{ - current_scope = scope; - if(dobody) - current = CppItem(); - current_key = item; - current_name = name; - CppItem& im = dobody ? current : base->GetAdd(current_scope).Add(); - im.item = item; - im.name = name; - im.file = filei; - im.line = line + 1; - im.impl = impl; - im.filetype = filetype; - im.using_namespaces = using_namespace; - LLOG("New item " << line + 1 << " " << scope << "::" << item); - return im; -} - -void Parser::AddMacro(int lineno, const String& macro, int kind) -{ - String name; - const char *s = macro; - while(*s && iscid(*s)) - name.Cat(*s++); - CppItem& im = Item("", "", macro, name); - im.kind = kind; - im.line = lineno; - im.access = PUBLIC; -} - -CppItem& Parser::Item(const String& scope, const String& using_namespace, const String& item, - const String& name) -{ - String h = Purify(item); - CppItem& im = Item(scope, using_namespace, h, name, false); - im.natural = h; - return im; -} - -void Parser::Resume(int bl) -{ - for(;;) { - if(lex == t_eof || lex.GetBracesLevel() == bl && lex == ';') - break; - ++lex; - } -} - -void Parser::ScopeBody() -{ - int bl = lex.GetBracesLevel(); - while(!Key('}')) { - if(lex == t_eof) - ThrowError("Unexpected end of file"); - try { - Do(); - } - catch(Error) { - Resume(bl); - Key(';'); - } - } -} - -String Parser::AnonymousName() -{ - int lvl = 0; - for(int i = 0; lex[i] != t_eof; i++) { - if(lex[i] == '{') lvl++; - else - if(lex[i] == '}') - if(--lvl == 0) { - if(lex.IsId(i + 1)) - return "." + lex.Id(i + 1); - break; - } - } - - dword x[4]; - x[0] = Random(); - x[1] = Random(); - x[2] = Random(); - x[3] = Random(); - - return "@" + Base64Encode(String((const char *)&x, sizeof(x))) + "/" + title; -} - -void Parser::AddNamespace(const String& n, const String& name) -{ - String h = "namespace " + n; - CppItem& m = Item(n, Null, h, name); - m.kind = NAMESPACE; - m.natural = h; -} - -bool Parser::Scope(const String& tp, const String& tn) { - if(Key(tk_namespace)) { - Check(lex.IsId(), "Expected name of namespace"); - String name = lex.GetId(); - LLOG("namespace " << name); - namespace_info << ';' << name; - Context c0; - c0 <<= context; - int struct_level0 = struct_level; - ScopeCat(context.scope, name); - ScopeCat(context.ns, name); - AddNamespace(context.scope, name); - if(Key('{')) { - Context cc; - cc <<= context; - while(!Key('}')) { - if(lex == t_eof) - ThrowError("Unexpected end of file"); - try { - Do(); - } - catch(Error) { - if(struct_level0) - throw; - context <<= cc; - struct_level = struct_level0; - LLOG("---- Recovery to namespace level"); - ++lex; - lex.SkipToGrounding(); - lex.ClearBracesLevel(); - LLOG("Grounding skipped to " << GetLine(lex.Pos())); - } - catch(Lex::Grounding) { - LLOG("---- Grounding to namespace level"); - context <<= cc; - struct_level = struct_level0; - lex.ClearBracesLevel(); - lex.ClearBody(); - } - } - } - LLOG("End namespace"); - Key(';'); - context <<= c0; - SetScopeCurrent(); - namespace_info << ";}"; - return true; - } - return false; -} - -CppItem& Parser::Fn(const Decl& d, const String& templ, bool body, - const String& tname, const String& tparam) -{ - String param; - String pname; - String ptype; - for(int i = 0; i < d.param.GetCount(); i++) { - const Decla& p = d.param[i]; - ScAdd(param, p.natural); - if(i) - ptype << ';'; - ptype << p.type; - ScAdd(pname, p.name); - } - String nn0; - String nm = d.name; - int q; - if(d.castoper) { - q = d.name.ReverseFind(' '); - q = q > 0 ? d.name.ReverseFind(':', q) : d.name.ReverseFind(':'); - } - else - q = d.name.ReverseFind(':'); - if(q >= 0) { - nm = d.name.Mid(q + 1); - if(q > 0) - nn0 = d.name.Mid(0, q - 1); - } - String item = FnItem(d.natural, pname, d.name, nm, d.oper); - String scope = context.scope; - String nn; - const char *s = nn0; - int l = 0; - while(*s) { - if(*s == '<') - l++; - else - if(*s == '>') - l--; - else - if(l == 0) - nn.Cat(*s); - s++; - } - s = nn; - while(*s == ':') s++; - if(*s) - ScopeCat(scope, s); - CppItem& im = Item(scope, context.namespace_using, item, nm, body); - im.natural.Clear(); - if(!IsNull(templ)) { - im.natural = TrimRight(Gpurify(templ)) + ' '; - im.at = im.natural.GetLength(); - } - im.natural << Purify(d.natural, d.name, nm); - im.kind = templ.GetCount() ? IsNamespace(scope) ? FUNCTIONTEMPLATE - : d.s_static ? CLASSFUNCTIONTEMPLATE - : INSTANCEFUNCTIONTEMPLATE - : d.istructor ? (d.isdestructor ? DESTRUCTOR : CONSTRUCTOR) - : d.isfriend ? INLINEFRIEND - : IsNamespace(scope) ? FUNCTION - : d.s_static ? CLASSFUNCTION - : INSTANCEFUNCTION; - im.param = param; - im.pname = pname; - im.ptype = ptype; - im.access = context.access; - im.virt = d.s_virtual; - im.type = d.type; - im.decla = true; - im.tname = tname; - im.tparam = tparam; - im.ctname = context.ctname; - LLOG("FnItem: " << scope << "::" << item << ", natural: " << im.natural - << ", ctname: " << im.ctname); - return im; -} - -void Parser::Enum(bool vars) -{ - String name; - if(lex.IsId()) - name = lex.GetId(); - while(lex != '{' && lex != ';' && lex != t_eof) - ++lex; - if(Key('{')) { - for(;;) { - Line(); - String val; - Check(lex.IsId(), "Expected identifier"); - String id = lex.GetId(); - CppItem& im = Item(context.scope, context.namespace_using, id, id); - im.natural = "enum "; - if(!IsNull(name)) - im.natural << name << ' '; - im.natural << id; - if(Key('=')) - im.natural << " = " << Constant(); - im.kind = ENUM; - im.access = context.access; - Key(','); - if(Key('}')) break; - } - } - while(!Key(';')) { - if(lex.IsId()) { - if(vars) { // typedef name ignored here - String scope = context.scope; - String name = lex.GetId(); - CppItem& im = Item(scope, context.namespace_using, name, name); - im.natural = "enum " + name; - im.access = context.access; - im.kind = IsNamespace(scope) ? VARIABLE : INSTANCEVARIABLE; - } - ++lex; - } - else - if(lex == ',' || lex == '*') - ++lex; - else - break; - } - Key(';'); - SetScopeCurrent(); -} - -bool Parser::UsingNamespace() -{ - if(lex == tk_using && !(lex.IsId(1) && lex[2] == '=')) { - ++lex; - if(Key(tk_namespace)) - while(lex.IsId()) { - Vector h = Split(context.namespace_using, ';'); - String u; - do { - u << lex.GetId(); - if(Key(t_dblcolon)) - u << "::"; - } - while(lex.IsId()); - if(FindIndex(h, u) < 0) - h.Add(u); - context.namespace_using = Join(h, ";"); - Key(','); - } - while(!Key(';') && lex != t_eof) - ++lex; - namespace_info << ";using " << context.namespace_using; - return true; - } - return false; -} - -bool Parser::IsEnum(int i) -{ - for(;;) { - if(lex[i] == '{') - return true; - else - if(lex.IsId(i) || lex[i] == ':' || - findarg(lex[i], tk_bool, tk_signed, tk_unsigned, tk_long, tk_int, tk_short, - tk_char, tk___int8, tk___int16, tk___int32, tk___int64, - tk_char16_t, tk_char32_t) >= 0) - i++; - else - return false; - } -} - -void Parser::ClassEnum(const String& clss) -{ - context.typenames.FindAdd(lex); - Context cc; - cc <<= context; - String name = lex.GetId(); - String new_scope = context.scope; - ScopeCat(new_scope, name); - context.scope = new_scope; - context.access = PUBLIC; - String key = "class"; - LLOG("enum class " << context.scope << " using " << context.namespace_using); - CppItem& im = Item(context.scope, context.namespace_using, key, name, lex != ';'); - im.kind = STRUCT; - im.natural = clss + " enum " + name; - im.type = name; - im.access = cc.access; - im.tname.Clear(); - im.ctname.Clear(); - im.tparam.Clear(); - im.ptype.Clear(); - im.pname.Clear(); - im.param.Clear(); - Enum(true); - context = pick(cc); - SetScopeCurrent(); -} - -void Parser::DoNamespace() -{ - if(Key('{')) - while(!Key('}')) { - if(lex == t_eof) - ThrowError("Unexpected end of file"); - Do(); - } - Key(';'); -} - -void Parser::Do() -{ - LLOG("Do, scope: " << current_scope); - if(lex.IsGrounded() && struct_level) - throw Lex::Grounding(); - Line(); - if(UsingNamespace()) - ; - else - if(Key(tk_static_assert)) - while(lex != t_eof && lex != ';') - ++lex; - else - if(lex == tk_inline && lex[1] == tk_namespace) { // for now, inline namespace is simply ignored - while(lex != t_eof && lex != '{') - ++lex; - DoNamespace(); - } - else - if(Key(';')) // 'empty' declaration, result of some ignores - ; - else - if(lex == tk_extern && lex[1] == tk_template) { // skip 'extern template void Foo();' - while(lex != t_eof) { - if(lex == ';') { - ++lex; - break; - } - ++lex; - } - } - else - if(Key(tk_extern) && lex == t_string) { // extern "C++" kind - ++lex; - DoNamespace(); - } - else - if(Key(tk_template)) { - if(lex.IsId() || lex == tk_class && lex.IsId(1)) { - Key(tk_class); - for(;;) { - if(lex.IsId()) - lex.GetId(); - else - if(!Key(t_dblcolon)) - break; - } - TemplateParams(); - Key(';'); - } - else { - String tnames; - String tparam = TemplateParams(tnames); - if(lex == tk_using) { //C++11 template alias template <...> using ID = - Array r = Declaration(true, true, tnames, tparam); - for(int i = 0; i < r.GetCount(); i++) { - Decla& d = r[i]; - if(d.type_def) { - String scope = context.scope; - ScopeCat(scope, d.name); - CppItem& im = Item(scope, context.namespace_using, "typedef", d.name); - im.natural = Purify(d.natural); - im.type = d.type; - im.access = context.access; - im.kind = TYPEDEF; - } - } - } - else { - if(!Scope(tparam, tnames)) { - Array r = Declaration(true, true, tnames, tparam); - bool body = lex == '{'; - for(int i = 0; i < r.GetCount(); i++) { - Decl& d = r[i]; - if(!d.isfriend && d.function) - Fn(d, "template " + tparam + ' ', body, tnames, tparam); - } - EatBody(); - Key(';'); - } - EatBody(); - } - } - } - else - if(lex == tk_enum && IsEnum(1)) { - ++lex; - Enum(true); - } - else - if(lex == tk_enum && lex[1] == tk_class && IsEnum(2)) { - ++lex; - ++lex; - ClassEnum("class"); // like enum class Foo { A, B } - } - else - if(lex == tk_enum && lex[1] == tk_struct && IsEnum(2)) { - ++lex; - ++lex; - ClassEnum("struct"); // like enum struct Foo { A, B } - } - else - if(lex == tk_typedef && lex[1] == tk_enum && IsEnum(2)) { - ++lex; - ++lex; - Enum(false); - } - else - if(!Scope(String(), String())) { - if(Key(tk_public)) { - context.access = PUBLIC; - Key(':'); - } - else - if(Key(tk_private)) { - context.access = PRIVATE; - Key(':'); - } - else - if(Key(tk_protected)) { - context.access = PROTECTED; - Key(':'); - } - else { - Array r = Declaration(true, true, Null, Null); - bool body = lex == '{'; - for(int i = 0; i < r.GetCount(); i++) { - Decl& d = r[i]; - if(d.name.GetCount()) { - if(d.function) { - if(!d.isfriend) - Fn(d, Null, body, String(), String()); - } - else { - String h = d.natural; - int q = h.Find('='); - if(q >= 0) - h = TrimRight(h.Mid(0, q)); - String scope = context.scope; - if(d.type_def) - ScopeCat(scope, d.name); - String name = d.name; - int member_type = d.s_static ? CLASSVARIABLE : INSTANCEVARIABLE; - q = d.name.ReverseFind("::"); - if(q >= 0) { // class variable definition like: int Ctrl::EventLoop; - ScopeCat(scope, d.name.Mid(0, q)); - current_scope = scope; // temporary until ';' - name = d.name.Mid(q + 2); - member_type = CLASSVARIABLE; - } - CppItem& im = Item(scope, context.namespace_using, - d.isfriend ? "friend class" - : d.type_def ? "typedef" - : name, name); - im.natural = Purify(h); - im.type = d.type; - im.access = context.access; - im.kind = d.isfriend ? FRIENDCLASS : - d.type_def ? TYPEDEF : - IsNamespace(scope) ? VARIABLE : - member_type; - if(im.IsData()) - im.isptr = d.isptr; - } - } - } - EatBody(); - if(Key(';')) - SetScopeCurrent(); // need to be after ';' to make class variable definitions work - } - } -} - -void Parser::Do(Stream& in, CppBase& _base, int filei_, int filetype_, - const String& title_, Event _err, - const Vector& typenames, - const Vector& namespace_stack, - const Index& namespace_using) -{ - LTIMING("Parser::Do"); - LLOG("= C++ Parser ==================================== " << title_ << " " << namespace_stack << ", dobody: " << dobody); - base = &_base; - err = _err; - filei = filei_; - filetype = filetype_; - title = title_; - lpos = 0; - line = 0; - - context.namespace_using = Join(namespace_using.GetKeys(), ";"); - - String n; - for(int i = 0; i < namespace_stack.GetCount(); i++) { - MergeWith(n, "::", namespace_stack[i]); - AddNamespace(n, namespace_stack[i]); - } - - file = PreProcess(in, *this); - lex.Init(~file.text); - - while(lex != t_eof) - try { - try { - current_scope.Clear(); - context.access = PUBLIC; - context.typenames.Clear(); - context.tparam.Clear(); - context.ns = context.scope = Join(namespace_stack, "::"); - inbody = false; - struct_level = 0; - for(int i = 0; i < typenames.GetCount(); i++) - context.typenames.Add(lex.Id(typenames[i])); - Do(); - } - catch(Error) { - if(lex.IsBody()) { - LLOG("---- Recovery to next ';'"); - Resume(lex.GetBracesLevel()); - Key(';'); - } - else { - LLOG("---- Recovery to file level"); - ++lex; - lex.SkipToGrounding(); - lex.ClearBracesLevel(); - LLOG("Grounding skipped to " << GetLine(lex.Pos())); - } - } - } - catch(Lex::Grounding) { - LLOG("---- Grounding to file level"); - lex.ClearBracesLevel(); - lex.ClearBody(); - } -} - -Vector ParserContext::GetNamespaces() const -{ - Vector ns; - Vector h = Split(current_scope, ':'); - while(h.GetCount()) { - ns.Add(Join(h, "::")); - h.Drop(); - } - ns.Append(Split(context.namespace_using, ';')); - ns.Add(""); // Add global namespace too - return ns; -} - -} diff --git a/uppsrc/CppBase/Pre.cpp b/uppsrc/CppBase/Pre.cpp deleted file mode 100644 index 8680381b4..000000000 --- a/uppsrc/CppBase/Pre.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -#define LTIMING(x) // DTIMING(x) - -namespace Upp { - -void SLPos(SrcFile& res) -{ - res.linepos.Add(res.text.GetLength()); -} - -SrcFile::SrcFile() : - preprocessorLinesRemoved(0), - blankLinesRemoved(0), - commentLinesRemoved(0) -{ -} - -SrcFile PreProcess(Stream& in, Parser& parser) // This is not really C preprocess, only removes (or processes) comments and directives -{ - SrcFile res; - bool include = true; - int lineno = 0; - while(!in.IsEof()) { - String ln = in.GetLine(); - lineno++; - SLPos(res); - while(*ln.Last() == '\\') { - ln.Trim(ln.GetLength() - 1); - ln.Cat(in.GetLine()); - SLPos(res); - } - const char *rm = ln; - if(IsAlNum(*rm)) { - const char *s = ln; - bool islbl = false; - bool wassemi = false; - while(*s && iscid(*s) || findarg(*s, '\t', ' ', ':') >= 0) { // check for label, labeled lines are not grounded - if(*s == ':' && !wassemi) { - islbl = true; - wassemi = true; // second ':' cancels label - } - else - if(*s != '\t' && *s != ' ') - islbl = false; // something was after the label, e.g. void Foo::Bar() - s++; - } - if(!islbl) - res.text << '\2'; - } - else - if(*rm == '\x1f') // line started with macro - res.text << '\2'; - while(*rm == ' ' || *rm == '\t') rm++; - if(*rm == '\0') - res.blankLinesRemoved++; - else - if(*rm == '#') { - const char *s = rm + 1; - while(*s == ' ' || *s == '\t') - s++; - if(s[0] == 'd' && s[1] == 'e' && s[2] == 'f' && - s[3] == 'i' && s[4] == 'n' && s[5] == 'e' && !iscid(s[6])) { - s += 6; - while(*s == ' ' || *s == '\t') s++; - const char *b = s; - while(iscid(*s)) - s++; - String macro(b, s); - if(*s == '(') { - b = s; - while(*s != ')' && *s) - s++; - macro.Cat(b, s); - macro << ')'; - } - if(include) - parser.AddMacro(lineno, macro); - } - else - if(s[0] == 'i' && s[1] == 'f') { - CParser p(s + 2); - try { - while(!p.IsEof()) { - if(p.IsId()) { - String id = p.ReadId(); - if(id.StartsWith("flag")) - parser.AddMacro(lineno, id, FLAGTEST); - } - else - p.SkipTerm(); - } - } - catch(CParser::Error) {} - } - res.preprocessorLinesRemoved++; - } - else { - bool lineContainsComment = false; - bool lineContainsNonComment = false; - String cmd; - while(*rm) { - if(*rm == '\"') { - lineContainsNonComment = true; - res.text << '\"'; - rm++; - while((byte)*rm && *rm != '\r' && *rm != '\n') { - if(*rm == '\"') { - res.text << '\"'; - rm++; - break; - } - if(*rm == '\\' && rm[1]) { - if(include) - res.text.Cat(*rm); - rm++; - } - if(include) - res.text.Cat(*rm); - rm++; - } - } - else - if(*rm == '\\' && rm[1]) { - lineContainsNonComment = true; - if(include) { - res.text.Cat(*rm++); - res.text.Cat(*rm++); - } - else - rm += 2; - } - else - if(rm[0] == '/' && rm[1] == '/') { - cmd = rm + 2; - if(!lineContainsNonComment) - res.commentLinesRemoved++; - break; - } - else - if(rm[0] == '/' && rm[1] == '*') { - lineContainsComment = true; - rm += 2; - for(;;) { - if(*rm == '\0') { - if(!lineContainsNonComment) - res.commentLinesRemoved++; - if(in.IsEof()) break; - SLPos(res); - ln = in.GetLine(); - rm = ~ln; - lineContainsNonComment = false; - } - if(rm[0] == '*' && rm[1] == '/') { - rm += 2; - break; - } - rm++; - } - if(include) - res.text.Cat(' '); - } - else { - lineContainsNonComment = true; - if(include) - res.text.Cat(*rm); - rm++; - } - } - if(include) - res.text << ' '; - if(cmd[0] == '$') { - if(cmd[1] == '-') include = false; - if(cmd[1] == '+') include = true; - if(cmd[1]) { - res.text.Cat(~cmd + 2); - res.text.Cat(' '); - } - } - if(lineContainsComment && !lineContainsNonComment) - res.commentLinesRemoved++; - } - } - return pick(res); -} - -} diff --git a/uppsrc/CppBase/Qualify.cpp b/uppsrc/CppBase/Qualify.cpp deleted file mode 100644 index 048ea42d2..000000000 --- a/uppsrc/CppBase/Qualify.cpp +++ /dev/null @@ -1,315 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LLOG(x) // DLOG(x) -#define LTIMING(x) // DTIMING(x) - -bool DoQualify(ScopeInfo& nf, const String& type, const String& usings, String& qt); - -bool Qualify0(ScopeInfo& nf, const String& type, const String& usings, String& qt) -{ // Qualify single type based on scoping information - const Vector& nd = nf.GetScopes(usings); - if(nd.GetCount()) { - LTIMING("First test"); - qt = nd[0] + type; - if(nf.base.Find(qt) >= 0) - return true; - } - if(nf.GetScope() >= 0) { - int q = type.ReverseFind(':'); - if(q > 0) { - LTIMING("Qualifying qualification"); - ScopeInfo hnf(nf); - hnf.NoBases(); - String qn; - String qs = type.Mid(0, q - 1); - if(IsDigit(*qs)) { - qt = type; - return true; - } - if(DoQualify(hnf, qs, usings, qn)) { - String tp = type.Mid(q + 1); - if(nf.base.Find(qn) >= 0) { - qt = qn + "::" + tp; - return true; - } - int scopei = nf.base.Find(qn); - if(scopei >= 0) { - ScopeInfo nnf(nf.base, scopei); - const Vector& bs = nnf.GetBases(); - for(int i = 0; i < bs.GetCount(); i++) { - qt = bs[i] + tp; - if(nf.base.Find(qt) >= 0) - return true; - } - } - } - if(nf.base.Find(qs) >= 0) { - qt = qs; - return true; - } - qt = type; - if(nf.base.Find(qt) >= 0) // e.g. std::string - return true; - qt = type.Mid(q + 1); - return true; - } - else { - LTIMING("Bases"); - const Vector& bs = nf.GetBases(); - for(int i = 0; i < bs.GetCount(); i++) { - qt = bs[i] + type; - if(nf.base.Find(qt) >= 0) - return true; - } - } - } - if(type[0] != ':') { - LTIMING("Testing scopes"); - for(int i = 1; i < nd.GetCount(); i++) { - qt = nd[i] + type; - if(nf.base.Find(qt) >= 0) - return true; - } - } - int q = type.Find(':'); - if(q < 0) - return false; - return Qualify0(nf, type.Mid(q + 1), usings, qt); -} - -bool DoQualify(ScopeInfo& nf, const String& type, const String& usings, String& qt) -{ - LTIMING("Qualify"); - int q = nf.cache.Find(type); - if(q >= 0) { - qt = nf.cache[q]; - return true; - } - LTIMING("Qualify0"); - if(!Qualify0(nf, type, usings, qt)) - return false; - nf.cache.Add(type, qt); - return true; -} - -String DoQualify(ScopeInfo& nf, const String& type, const String& usings) -{ - String qt; - return DoQualify(nf, type, usings, qt) ? qt : type; -} - -static String s_int("int"); -static String s_void("void"); -static String s_double("double"); -static String s_char("char"); -static String s_float("float"); -static String s_long("long"); -static String s_const("const"); -static String s_struct("struct"); -static String s_class("class"); -static String s_unsigned("unsigned"); - -inline void Qualify(String& r, ScopeInfo& nf, const char *b, const char *s, const String& usings) -{ - String type(b, s); - if(type.GetCount() == 0 || type == s_const || - type == s_int || type == s_double || type == s_char || - type == s_long || type == s_unsigned || type == s_struct || type == s_class || - type == s_float) { - r << type; - return; - } - r << DoQualify(nf, type, usings); -} - -String QualifyIds(ScopeInfo& nf, const String& k, const String& usings, bool all) -{ - LTIMING("QualifyIds"); - String r; - const char *s = k; - Vector empty; - while(*s) { - int c = *s; - if(c == ':') { - const char *b = s++; - while(*s == ':' || iscid(*s)) s++; -/* if(all) { - if(iscid(*r.Last())) - r << ' '; - ScopeInfo nnf(nf.GetScope(), nf.base); - Qualify(r, nnf, b, s, usings); - } - else*/ - r.Cat(b, s); - } - else - if(iscid(c)) { - if(iscid(*r.Last())) - r << ' '; - if(s[0] == 'c' && s[1] == 'o' && s[2] == 'n' && s[3] == 's' && s[4] == 't' && !iscid(s[5])) { - r << s_const; - s += 5; - } - else - if(s[0] == 'm' && s[1] == 'u' && s[2] == 't' && s[3] == 'a' && s[4] == 'b' && s[5] == 'l' && s[6] == 'e' && !iscid(s[7])) { - r << "mutable"; - s += 7; - } - else - if(s[0] == 'v' && s[1] == 'o' && s[2] == 'l' && s[3] == 'a' && s[4] == 't' && s[5] == 'i' && s[6] == 'l' && s[7] == 'e' && !iscid(s[8])) { - r << "volatile"; - s += 8; - } - else { - const char *b = s++; - while(*s == ':' || iscid(*s)) s++; - if(all) - Qualify(r, nf, b, s, usings); - else - r.Cat(b, s); - } - } - else { - if(c == '(') - all = true; - if(c != ' ') - r.Cat(c); - s++; - } - } - return r; -} - -String Qualify(const CppBase& base, const String& scope, const String& type, const String& usings) -{ - if(type.StartsWith("::")) - return type.Mid(2); - ScopeInfo nf(base, scope); - return QualifyIds(nf, type, usings, true); -} - -String QualifyKey(const CppBase& base, const String& scope, const String& type, const String& usings) -{ - ScopeInfo nf(base, scope); - return QualifyIds(nf, type, usings, false); -} - -void QualifyTypes(CppBase& base, const String& scope, CppItem& m) -{ - ScopeInfo nf(base, scope); - m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true); - m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true); -} - -void QualifyPass0(CppBase& base) -{ // Move scopes - solve: namespace X { struct C { void Foo(); }; using namespace X; void C::Foo() {} - Vector remove_scope; - for(int ni = 0; ni < base.GetCount(); ni++) { - Array& n = base[ni]; - ScopeInfo nf(base); - String scope = base.GetKey(ni); - String usings; - int toscopei = -1; - Vector remove_item; - for(int i = 0; i < n.GetCount(); i++) { - CppItem& m = n[i]; - if(m.qualify && m.impl) { - if(usings != m.using_namespaces) { - usings = m.using_namespaces; - toscopei = -1; - Vector h = Split(m.using_namespaces, ';'); - for(int i = 0; i < h.GetCount(); i++) { - String ns = h[i] + "::" + scope; - toscopei = base.Find(ns); - if(toscopei >= 0) - break; - } - } - if(toscopei >= 0 && toscopei != ni) { - base[toscopei].Add(m); - remove_item.Add(i); - } - } - } - n.Remove(remove_item); - if(scope.GetCount() && n.GetCount() == 0) - remove_scope.Add(ni); - } - base.Remove(remove_scope); -} - -void QualifyPass1(CppBase& base) -{ // Qualify types - LTIMING("QualifyPass1"); - for(int ni = 0; ni < base.GetCount(); ni++) { - Array& n = base[ni]; - ScopeInfo nf(base, ni); - for(int i = 0; i < n.GetCount(); i++) { - CppItem& m = n[i]; - if(m.kind == NAMESPACE) - base.namespaces.FindAdd(base.GetKey(ni)); - if(m.IsType() && m.qualify) { - m.qualify = false; - m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true); // type of item, now qualified (probaly already was) - m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true); // base classes - m.qitem = m.item; // name of type (struct) item is already qualified - } - } - } -} - -void QualifyPass2(CppBase& base) -{ // Qualify function parameters - LTIMING("QualifyPass2"); - for(int ni = 0; ni < base.GetCount(); ni++) { - Array& n = base[ni]; - ScopeInfo nf(base, ni); - for(int i = 0; i < n.GetCount(); i++) { - CppItem& m = n[i]; - if(m.uname.GetCount() == 0 && m.name.GetCount()) - m.uname = ToUpper(m.name); - if(!m.IsType() && m.qualify) { - m.qualify = false; - m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true); - m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true); - m.qitem = m.IsCode() ? QualifyIds(nf, m.item, m.using_namespaces, false) - : m.item; - } - } - } -} - -void Qualify(CppBase& base) -{ - Md5Stream md5; - Vector no = GetSortOrder(base.GetKeys()); - for(int q = 0; q < base.GetCount(); q++) { - int ni = no[q]; - md5 << base.GetKey(ni); - const Array& n = base[ni]; - for(int i = 0; i < n.GetCount(); i++) { - const CppItem& m = n[i]; - if(m.IsType()) - md5 << ';' << m.ptype; - } - md5 << '\n'; - } - String c5 = md5.FinishString(); - if(c5 != base.types_md5) { // set of types changed, requalify everything - base.types_md5 = c5; - for(int ni = 0; ni < base.GetCount(); ni++) { - Array& n = base[ni]; - for(int i = 0; i < n.GetCount(); i++) - n[i].qualify = true; - } - } - base.namespaces.Clear(); - QualifyPass0(base); - QualifyPass1(base); - QualifyPass2(base); -} - -} diff --git a/uppsrc/CppBase/ScopeInfo.cpp b/uppsrc/CppBase/ScopeInfo.cpp deleted file mode 100644 index c7eb570e7..000000000 --- a/uppsrc/CppBase/ScopeInfo.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LLOG(x) -#define LTIMING(x) // DTIMING(x) - -ScopeInfo::ScopeInfo(const CppBase& base, int scopei) - : scopei(scopei), base(base) -{ - LTIMING("ScopeInfo(const CppBase& base, int scopei)"); - Init(); -} - -ScopeInfo::ScopeInfo(int scopei, const CppBase& base) - : scopei(scopei), base(base) -{ - LTIMING("ScopeInfo(int scopei, const CppBase& base)"); - Init(); -} - -ScopeInfo::ScopeInfo(const CppBase& base, const String& scope) - : scopei(base.Find(scope)), base(base) -{ - LTIMING("ScopeInfo(const CppBase& base, const String& scope)"); - Init(); -} - -ScopeInfo::ScopeInfo(const ScopeInfo& f) - : base(f.base) -{ - LTIMING("ScopeInfo copy contructor"); - scopes <<= f.scopes; - bvalid = nvalid = false; - scopei = f.scopei; -} - -void ScopeInfo::Init() -{ - bvalid = nvalid = false; -} - -void ScopeInfo::Bases(int i, Vector& g) -{ // recursively retrieve all base classes - if(base.IsType(i)) { - const Array& n = base[i]; - for(int i = 0; i < n.GetCount(); i++) { - const CppItem& im = n[i]; - if(im.IsType()) { - const char *q = im.qptype; - const char *b = q; - for(;;) { - if(*q == ';' || *q == '\0') { - if(b < q) { - String h = String(b, q); - int q = h.Find('<'); - if(q >= 0) - h.Trim(q); - h = TrimBoth(h); - int nq = base.Find(h); - if(nq >= 0) - g.Add(nq); - } - if(*q == '\0') - break; - q++; - b = q; - } - else - q++; - } - } - } - } -} - -const Vector& ScopeInfo::GetBases() -{ - LTIMING("GetBases"); - if(!bvalid) { - bvalid = true; - baselist.Clear(); - if(scopei < 0) - return baselist; - Vector b; - Index bi; - Bases(scopei, b); - while(b.GetCount()) { - Vector bb; - for(int i = 0; i < b.GetCount(); i++) { - int q = b[i]; - if(bi.Find(q) < 0) { - bi.Add(q); - Bases(b[i], bb); - } - } - b = pick(bb); - } - for(int i = 0; i < bi.GetCount(); i++) - baselist.Add(base.GetKey(bi[i]) + "::"); - } - return baselist; -} - -const Vector& ScopeInfo::GetScopes(const String& usings_) -{ - LTIMING("GetScopes"); - if(!nvalid || usings != usings_) { - usings = usings_; - nvalid = true; - scopes.Clear(); - if(scopei >= 0) { - String nn = base.GetKey(scopei); - while(nn.GetCount()) { - if(nn[0] == ':' && nn.GetCount() == 2) { - scopes.Add(nn); - return scopes; - } - scopes.Add(nn + "::"); - int q = nn.ReverseFind(':'); - nn.Trim(max(0, q - 1)); - } - } - scopes.Add(""); - Vector h = Split(usings, ';'); - for(int i = 0; i < h.GetCount(); i++) - scopes.Add(h[i] + "::"); - } - return scopes; -} - -} diff --git a/uppsrc/CppBase/cpp.cpp b/uppsrc/CppBase/cpp.cpp deleted file mode 100644 index 0256101d0..000000000 --- a/uppsrc/CppBase/cpp.cpp +++ /dev/null @@ -1,391 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LTIMING(x) // DTIMING(x) -#define LLOG(x) // DLOG(x) - -void Cpp::ParamAdd(Vector& param, const char *s, const char *e) -{ - while(s < e && (byte)*s <= ' ') s++; - while(e > s && (byte)*(e - 1) <= ' ') e--; - String h; - while(s < e) { - if((byte)*s <= ' ') { - h.Cat(' '); - s++; - while(s < e && (byte)*s <= ' ') - s++; - } - else - if(*s == '\"' || *s == '\'') { - const char *q = SkipString(s); - h.Cat(String(s, q)); - s = q; - } - else - h.Cat(*s++); - } - param.Add(h); -} - -String Cpp::Expand(const char *s) -{ - StringBuffer r; - const char *l0 = s; - while(*s) { - if(incomment) { - if(s[0] == '*' && s[1] == '/') { - incomment = false; - s += 2; - r.Cat("*/"); - } - else - r.Cat(*s++); - } - else - if(iscib(*s)) { - LTIMING("Expand ID"); - const char *bid = s; - s++; - while(iscid(*s)) - s++; - String id(bid, s); - LTIMING("Expand ID2"); - if(notmacro.Find(id) < 0) { - const PPMacro *pp = macro.FindLastPtr(id); - int segmenti = pp ? segment_id.Find(pp->segment_id) : -1; - const CppMacro *m = FindMacro(id, segment_id, segmenti); - if(!m && pp) - m = &pp->macro; - if(m && m->IsUndef()) - m = NULL; - if(m) { - LTIMING("Expand macro"); - Vector param; - bool function_like = false; - const char *s0 = s; - if(m->param.GetCount()) { - while(*s && (byte)*s <= ' ') - s++; - if(*s == '(') { - function_like = true; - s++; - const char *b = s; - int level = 0; - for(;;) - if(*s == ',' && level == 0) { - ParamAdd(param, b, s); - s++; - b = s; - } - else - if(*s == ')') { - s++; - if(level == 0) { - ParamAdd(param, b, s - 1); - break; - } - level--; - } - else - if(*s == '(') { - s++; - level++; - } - else - if(*s == '\0') { // macro use spread into more lines - if(bid == l0) // begin of line - prefix_macro = bid; - else - prefix_macro = String(' ', 1) + bid; // do not want to emit grounding in body - return String(r); - } - else - if(*s == '\"' || *s == '\'') - s = SkipString(s); - else - s++; - } - } - if(!!m->param.GetCount() == function_like) { - int ti = notmacro.GetCount(); - Vector eparam; - eparam.SetCount(param.GetCount()); - for(int i = 0; i < param.GetCount(); i++) - eparam[i] = Expand(param[i]); - notmacro.Add(id); - id = '\x1f' + Expand(m->Expand(param, eparam)); // \x1f is info for Pre that there was a macro expansion - notmacro.Trim(ti); - } - else - s = s0; - } - else - notmacro.Add(id); - } - r.Cat(id); - } - else - if(*s == '\"') { - const char *e = SkipString(s); - r.Cat(s, e); - s = e; - } - else - if(s[0] == '/' && s[1] == '*') { - incomment = true; - s += 2; - r.Cat("/*"); - } - else - if(s[0] == '/' && s[1] == '/') { - r.Cat(s); - break; - } - else - r.Cat(*s++); - } - return String(r); -} - -void Cpp::DoFlatInclude(const String& header_path) -{ - LTIMING("DoFlatInclude"); - LLOG("Flat include " << header_path); - if(header_path.GetCount()) { - md5.Put(header_path); - const FlatPP& pp = GetFlatPPFile(header_path); - LLOG("DoFlatInclude " << header_path << ", " << pp.segment_id.GetCount() << " segments"); - for(int i = 0; i < pp.segment_id.GetCount(); i++) - segment_id.FindAdd(pp.segment_id[i]); - for(int i = 0; i < pp.usings.GetCount(); i++) { - namespace_using.FindAdd(pp.usings[i]); - LLOG(" Flat usings " << pp.usings[i]); - md5.Put('$'); - md5.Put(pp.usings[i]); - } - } -} - -#define IGNORE_ELSE - -void Cpp::Do(const String& sourcefile, Stream& in, const String& currentfile, bool get_macros) -{ - LLOG("Cpp::Do " << sourcefile << ", current: " << currentfile); - if(visited.Find(currentfile) >= 0 || visited.GetCount() > 20000) - return; - visited.Add(currentfile); - String current_folder = GetFileFolder(currentfile); - bool notthefile = sourcefile != currentfile; - if(notthefile || get_macros) { - LTIMING("DO2"); - const PPFile& pp = GetPPFile(currentfile); - for(int i = 0; i < pp.item.GetCount() && !done; i++) { - const PPItem& m = pp.item[i]; - if(m.type == PP_DEFINES) { - LTIMING("PP_DEFINES"); - if(notthefile) // if getting macros, we are interested in included macros only - segment_id.FindAdd(m.segment_id); - } - else - if(m.type == PP_INCLUDE) { - String s = GetIncludePath(m.text, current_folder); - if(s.GetCount()) { - if(notthefile && (s == sourcefile || IncludesFile(s, sourcefile))) { - LLOG("Include IN " << s); - md5.Put(s); - Do(sourcefile, in, s, get_macros); - } - else { - LLOG("Include FLAT " << s); - DoFlatInclude(s); - } - } - } - else - if(m.type == PP_NAMESPACE) { - namespace_stack.Add(m.text); - LLOG("pp namespace " << m.text << " " << namespace_stack); - } - else - if(m.type == PP_NAMESPACE_END && namespace_stack.GetCount()) { - namespace_stack.Drop(); - LLOG("pp end namespace " << namespace_stack); - } - else - if(m.type == PP_USING) { - namespace_using.FindAdd(m.text); - md5.Put('$'); - md5.Put(m.text); - } - } - if(sourcefile != currentfile) - return; - } - - md5.Put('@'); - md5.Put(Join(namespace_stack, ";")); - - done = true; - - if(get_macros) - return; - - if(in.Peek() == 0xef) { // Skip UTF-8 BOM - int64 pos = in.GetPos(); - in.Get(); - if(in.Get() != 0xbb || in.Get() != 0xbf) - in.Seek(pos); // Was not UTF-8 BOM after all - } - - LTIMING("Expand"); - incomment = false; - prefix_macro.Clear(); - StringBuffer result; - result.Clear(); - result.Reserve(16384); - int lineno = 0; - bool incomment = false; - bool do_pp = true; - int segment_serial = 0; - segment_id.Add(--segment_serial); -#ifdef IGNORE_ELSE - int ignore_else = 0; -#endif - while(!in.IsEof()) { - String l = prefix_macro + in.GetLine(); - String ll = TrimLeft(l); - if(ll.StartsWith("//$")) { // Do not remove assist++ parser directives - result.Cat(l + "\n"); - do_pp = decode(ll[3], '+', true, '-', false, do_pp); - continue; - } - prefix_macro.Clear(); - lineno++; - int el = 0; - while(*l.Last() == '\\' && !in.IsEof()) { - el++; - l.Trim(l.GetLength() - 1); - l.Cat(in.GetLine()); - } - RemoveComments(l, incomment); - CParser p(l); - if(p.Char('#')) { - if(do_pp) { - if(p.Id("define")) { - result.Cat(l + "\n"); - CppMacro m; - String id = m.Define(p.GetPtr()); - if(id.GetCount()) { - PPMacro& pp = macro.Add(id); - pp.macro = m; - pp.segment_id = segment_serial; - notmacro.Trim(kw.GetCount()); - } - } - else - if(p.Id("undef")) { - result.Cat(l + "\n"); - if(p.IsId()) { - segment_id.Add(--segment_serial); - PPMacro& m = macro.Add(p.ReadId()); - m.segment_id = segment_serial; - m.macro.SetUndef(); - notmacro.Trim(kw.GetCount()); - segment_id.Add(--segment_serial); - } - } - else - if(p.Id("if") || p.Id("ifdef") || p.Id("ifndef")) // FLAGTEST support - result.Cat(l + "\n"); - else { - result.Cat('\n'); - #ifdef IGNORE_ELSE - if(ignore_else) { - if(p.Id("if") || p.Id("ifdef") || p.Id("ifndef")) - ignore_else++; - else - if(p.Id("endif")) - ignore_else--; - } - else { - if(p.Id("else") || p.Id("elif")) - ignore_else = 1; - } - #endif - if(p.Id("include")) { - LTIMING("Expand include"); - String s = GetIncludePath(p.GetPtr(), current_folder); - DoFlatInclude(s); - segment_id.Add(--segment_serial); - } - } - } - else - result.Cat('\n'); - } - else { - LTIMING("Expand expand"); - #ifdef IGNORE_ELSE - if(ignore_else) - result.Cat('\n'); - else - #endif - result.Cat(Expand(l) + "\n"); - } - while(el--) - result.Cat("\n"); - } - output = result; -} - -Index Cpp::kw; - -bool Cpp::Preprocess(const String& sourcefile, Stream& in, const String& currentfile, - bool get_macros) -{ - LLOG("===== Preprocess " << sourcefile << " <- " << currentfile); - LTIMING("Cpp::Preprocess"); - macro.Clear(); - macro.Reserve(1000); - segment_id.Clear(); - segment_id.Add(0); - segment_id.Reserve(100); - - ONCELOCK { - const char **h = CppKeyword(); - while(*h) { - kw.Add(*h); - h++; - } - } - notmacro = clone(kw); - - done = false; - incomment = false; - output.Clear(); - visited.Clear(); - Do(NormalizePath(sourcefile), in, NormalizePath(currentfile), get_macros); - if(!done) - output.Clear(); - return done; -} - -void GetAllMacros(Md5Stream& md5, const String& id, Index& segment_id); - -String Cpp::GetDependeciesMd5(const Vector& m) -{ - String r; - Md5Stream md5; - md5.Put(Join(namespace_stack, ";")); - md5.Put('@'); - md5.Put(Join(namespace_using.GetKeys(), ";")); - md5.Put('@'); - for(int i = 0; i < m.GetCount(); i++) - GetAllMacros(md5, m[i], segment_id); - return md5.FinishString(); -} - -} diff --git a/uppsrc/CppBase/cpplex.cpp b/uppsrc/CppBase/cpplex.cpp deleted file mode 100644 index 7306767f8..000000000 --- a/uppsrc/CppBase/cpplex.cpp +++ /dev/null @@ -1,499 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -// #define LOGNEXT _DBG_ - -namespace Upp { - -#ifdef _MSC_VER -#pragma inline_depth(255) -#pragma optimize("t", on) -#endif - -#define case_id \ - case '_':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h': \ - case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q': \ - case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z': \ - case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I': \ - case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R': \ - case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case '$' - -#define case_nonzero_digit \ - case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9' - - -const char *_CppKeyword[] = { -#define CPPID(x) #x, -#include "keyword.i" -#undef CPPID - NULL -}; - -const char **CppKeyword() { return _CppKeyword; } - - -LexSymbolStat::LexSymbolStat() : - minSymbol(0) -{ -} - -void LexSymbolStat::Reset(int minSymbol, int maxSymbol) -{ - ASSERT(minSymbol <= maxSymbol); - v.Clear(); - this->minSymbol = minSymbol; - v.SetCount(maxSymbol - minSymbol + 1, 0); -} - -void LexSymbolStat::IncStat(int symbol) -{ - int symbolIndex = symbol - minSymbol; - if(symbolIndex >= 0 && symbolIndex < v.GetCount()) - v[symbolIndex]++; -} - -int LexSymbolStat::GetStat(int symbol) const -{ - int symbolIndex = symbol - minSymbol; - return (symbolIndex >= 0 && symbolIndex < v.GetCount()) ? - v[symbolIndex] : - 0; -} - -int LexSymbolStat::SumStat(const Vector & symbols) const -{ - int sum = 0; - for(int i = 0; i < symbols.GetCount(); i++) - sum += GetStat(symbols[i]); - return sum; -} - -void LexSymbolStat::Merge(const LexSymbolStat & other) -{ - if(v.GetCount() == 0) { - minSymbol = other.minSymbol; - v <<= other.v; - return; - } - ASSERT(other.minSymbol == minSymbol && other.v.GetCount() == v.GetCount()); - for(int i = 0; i < v.GetCount(); i++) - v[i] += other.v[i]; -} - - -Lex::Lex() -: statsCollected(false) -{ - const char **cppk = CppKeyword(); - for(int i = 0; cppk[i]; i++) - id.Add(cppk[i]); - endkey = id.GetCount(); - braceslevel = body = 0; -} - -void Lex::Init(const char *s) -{ - ptr = s; -} - -void Lex::StartStatCollection() -{ - symbolStat.Reset(-200, endkey+256); - statsCollected = true; -} - -const LexSymbolStat& Lex::FinishStatCollection() -{ - statsCollected = false; - return symbolStat; -} - -int Lex::GetCharacter() -{ - if(*ptr == '\0') return t_eof; - int c = *ptr++; - if(c == '\\') { - c = *ptr++; - switch(c) { - case 'a': return '\a'; - case 'b': return '\b'; - case 't': return '\t'; - case 'v': return '\v'; - case 'n': return '\n'; - case 'r': return '\r'; - case 'f': return '\f'; - case 'x': - c = 0; - if(isxdigit(*ptr)) { - c = (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); - ptr++; - if(isxdigit(*ptr)) { - c = 16 * c + (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); - ptr++; - } - } - break; - default: - if(c >= '0' && c <= '7') { - c -= '0'; - if(*ptr >= '0' && *ptr <= '7') - c = 8 * c + *ptr++ - '0'; - if(*ptr >= '0' && *ptr <= '7') - c = 8 * c + *ptr++ - '0'; - } - } - } - return (byte)c; -} - -void Lex::Next() -{ - grounding = false; - while((byte)*ptr <= ' ') { - if(*ptr == '\2') - grounding = true; - if(*ptr == '\0') return; - ptr++; - } - pos = ptr; - int c = (byte)*ptr++; - if(c == '\0') return; - switch(c) { - case_id: { - const char *b = ptr - 1; - while(iscid(*ptr)) - ptr++; - String x(b, ptr); - int q = id.FindAdd(x); - if(q == tk_rval_ - 256) { // simple hack for old rval macro - AddCode('&'); - AddCode('&'); - } - else - AddCode(q + 256); - break; - } - case ':': AddCode(Char(':') ? t_dblcolon : ':'); break; - case '*': AssOp('*', t_mulass); break; - case '/': AssOp('/', t_divass); break; - case '%': AssOp('%', t_modass); break; - case '^': AssOp('^', t_xorass); break; - case '!': AssOp('!', t_neq); break; - case '.': - if(Char('*')) AddCode(t_dot_asteriks); - else - if(*ptr == '.' && ptr[1] == '.') { - AddCode(t_elipsis); - ptr += 2; - } - else - AddCode('.'); - break; - case '+': - if(Char('+')) AddCode(t_inc); - else - AssOp('+', t_addass); - return; - case '-': - if(Char('-')) AddCode(t_dec); - else - if(Char('>')) - AddCode(Char('*') ? t_arrow_asteriks : t_arrow); - else - AssOp('-', t_subass); - break; - case '&': - if(Char('&')) - AddCode(t_and); - else - AssOp('&', t_andass); - break; - case '|': - if(Char('|')) - AddCode(t_or); - else - AssOp('|', t_orass); - break; - case '=': - AssOp('=', t_eq); - break; - case '<': - if(Char('<')) - AssOp(t_shl, t_shlass); - else - AssOp('<', t_le); - break; - case '>': - if(Char('>')) - AssOp(t_shr, t_shrass); - else - AssOp('>', t_ge); - break; - case '0': { - dword w = 0; - if(Char('x') || Char('X')) { - for(;;) { - int d; - if(*ptr >= '0' && *ptr <= '9') - d = *ptr - '0'; - else - if(*ptr >= 'A' && *ptr <= 'F') - d = *ptr - 'A' + 10; - else - if(*ptr >= 'a' && *ptr <= 'f') - d = *ptr - 'a' + 10; - else - break; - if(w >= 0x8000000u - d) { - AddCode(te_integeroverflow); - return; - } - w = w * 16 + d - '0'; - ptr++; - } - } - else - while(*ptr >= '0' && *ptr <= '7') { - int d = *ptr++ - '0'; - if(w >= 0x1000000u - d) { - AddCode(te_integeroverflow); - return; - } - w = w * 8 + d - '0'; - } - Term& tm = term.AddTail(); - tm.code = t_integer; - tm.ptr = pos; - tm.number = w; - } - break; - case_nonzero_digit: { - double w = c - '0'; - bool fp = false; - while(*ptr >= '0' && *ptr <= '9') - w = w * 10 + *ptr++ - '0'; - if(*ptr == '.') { //TODO TO BE Completed !!! - fp = true; - ptr++; - double x = 0.1; - while(*ptr >= '0' && *ptr <= '9') { - w += x * (*ptr++ - '0'); - x /= 10; - } - } - Term& tm = term.AddTail(); - if(fp || w < INT_MIN || w > INT_MAX) - tm.code = t_double; - else - tm.code = t_integer; - tm.ptr = pos; - tm.number = w; - } - break; - case '\'': { - Term& tm = term.AddTail(); - tm.code = t_character; - tm.ptr = pos; - tm.text = String(GetCharacter(), 1); - if(*ptr == '\'') - ptr++; - else - tm.code = te_badcharacter; - } - break; - case '\"': { - Term& tm = term.AddTail(); - tm.code = t_string; - tm.ptr = pos; - for(;;) { - while(*ptr != '\"') { - if((byte)*ptr < ' ' && *ptr != 9) { - tm.code = te_badstring; - return; - } - tm.text.Cat(GetCharacter()); - } - ptr++; - while(*ptr && (byte)*ptr <= ' ') ptr++; - if(*ptr != '\"') break; - ptr++; - } - } - break; - default: - AddCode(c); - return; - } -} - -bool Lex::Prepare(int pos) { - while(term.GetCount() <= pos) { - if(*ptr == '\0') return false; - Next(); - } -#ifdef _DEBUG - pp = term[0].ptr; -#endif - return true; -} - -int Lex::Code(int pos) -{ - if(!Prepare(pos)) return t_eof; - return term[pos].code; -} - -bool Lex::IsId(int pos) -{ - return Code(pos) >= endkey + 256; -} - -void Lex::ThrowError(const char *e) -{ - WhenError(e); - throw Parser::Error(); -} - -String Lex::Id(int pos) -{ - if(!IsId(pos)) - ThrowError("expected id"); - return id[Code(pos) - 256]; -} - -void Lex::Get(int n) -{ - while(n--) { - if(term.GetCount()) { - if(body && term.Head().grounding) - throw Grounding(); - int chr = term.Head().code; - if(statsCollected) - symbolStat.IncStat(chr); - if(chr == '{') - braceslevel++; - else - if(chr == '}') - braceslevel--; - term.DropHead(); - } - if(term.GetCount() == 0) - Next(); - if(term.GetCount() == 0) - break; - } -#ifdef LOGNEXT - Dump(0); -#endif -} - -void Lex::Dump(int pos) -{ -#ifdef LOGNEXT - int code = Code(pos); - switch(code) { - case t_string: LOG(AsCString(Text(pos))); break; - case t_double: LOG(Double(pos)); break; - case t_integer: LOG(Int(pos)); break; - case t_character: LOG("char " << AsCString(String(Chr(pos), 1))); break; - default: - if(code < 0) - LOG(decode(Code(), - 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, "", - "???")); - else - if(code < 256) - LOG((char)code); - else - LOG(id[code - 256]); - } -#endif -} - -void Lex::SkipToGrounding() -{ - for(;;) { - if(term.GetCount() == 0) - Next(); - if(term.GetCount() == 0) - break; - int chr = term.Head().code; - if(chr == t_eof) - return; - if(term.Head().grounding) - return; - if(chr == '{') - braceslevel++; - else - if(chr == '}') - braceslevel--; - term.DropHead(); - } -} - -int Lex::Int(int pos) -{ - Prepare(pos); - if(term[pos].code != t_integer) - ThrowError("expected integer literal"); - return (int)term[pos].number; -} - -double Lex::Double(int pos) -{ - Prepare(pos); - if(term[pos].code != t_double) - ThrowError("expected floating point literal"); - return term[pos].number; -} - -String Lex::Text(int pos) -{ - Prepare(pos); - if(term[pos].code != t_string) - ThrowError("expected string literal"); - return term[pos].text; -} - -int Lex::Chr(int pos) -{ - Prepare(pos); - if(term[pos].code != t_character) - ThrowError("expected character literal"); - return (byte)*term[pos].text; -} - -const char *Lex::Pos(int pos) -{ - Prepare(pos); - return pos < term.GetCount() ? term[pos].ptr : ptr; -} - -} diff --git a/uppsrc/CppBase/keyword.i b/uppsrc/CppBase/keyword.i deleted file mode 100644 index fee9b2459..000000000 --- a/uppsrc/CppBase/keyword.i +++ /dev/null @@ -1,101 +0,0 @@ -//#BLITZ_APPROVE - -CPPID(__asm) -CPPID(else) -CPPID(struct) -CPPID(enum) -CPPID(auto) -CPPID(__except) -CPPID(template) -CPPID(explicit) -CPPID(this) -CPPID(bool) -CPPID(extern) -CPPID(mutable) -CPPID(thread) -CPPID(break) -CPPID(false) -CPPID(throw) -CPPID(case) -//CPPID(__fastcall) -CPPID(namespace) -CPPID(true) -//CPPID(__finally) -CPPID(new) -//CPPID(__cdecl) -CPPID(float) -CPPID(__try) -CPPID(char) -CPPID(operator) -CPPID(typedef) -CPPID(class) -CPPID(friend) -CPPID(private) -CPPID(typeid) -CPPID(const) -CPPID(goto) -CPPID(protected) -CPPID(typename) -CPPID(const_cast) -CPPID(public) -CPPID(union) -CPPID(continue) -CPPID(inline) -CPPID(register) -CPPID(unsigned) -//CPPID(__declspec) -//CPPID(__inline) -CPPID(reinterpret_cast) -CPPID(using) -CPPID(default) -CPPID(int) -CPPID(return) -CPPID(delete) -CPPID(__int8) -CPPID(short) -CPPID(__uuidof) -CPPID(dllexport) -CPPID(__int16) -CPPID(signed) -CPPID(virtual) -CPPID(dllimport) -CPPID(__int32) -CPPID(sizeof) -CPPID(void) -CPPID(__int64) -CPPID(static) -CPPID(volatile) -CPPID(double) -CPPID(__leave) -CPPID(static_cast) -CPPID(dynamic_cast) -CPPID(long) -//CPPID(__stdcall) -CPPID(__inline) - -CPPID(if) -CPPID(while) -CPPID(switch) -CPPID(for) -CPPID(try) -CPPID(catch) -CPPID(do) - -CPPID(SKYLARK) - -CPPID(RPC_METHOD) -CPPID(RPC_GMETHOD) -CPPID(force_inline) -CPPID(never_inline) - -CPPID(rval_) - -CPPID(constexpr) -CPPID(noexcept) -CPPID(alignas) -CPPID(thread_local) -CPPID(char16_t) -CPPID(char32_t) -CPPID(static_assert) -CPPID(decltype) -CPPID(__int128) diff --git a/uppsrc/CppBase/macro.cpp b/uppsrc/CppBase/macro.cpp deleted file mode 100644 index 4198254ad..000000000 --- a/uppsrc/CppBase/macro.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -inline bool IsSpc(byte c) -{ - return c > 0 && c <= 32; -} - -String CppMacro::Define(const char *s) -{ - CParser p(s); - String id; - try { - if(!p.IsId()) - return Null; - p.NoSkipSpaces().NoSkipComments(); // '#define TEST(x)' is different form '#define TEST (x)' - later is parameterless - id = p.ReadId(); - param.Clear(); - if(p.Char('(')) { - p.SkipSpaces(); - p.Spaces(); - while(p.IsId()) { - if(param.GetCount()) - param << ","; - param << p.ReadId(); - p.Char(','); - } - if(p.Char3('.', '.', '.')) - param << '.'; - p.Char(')'); - if(param.GetCount() == 0) // #define foo() bar - need to 'eat' parenthesis, cheap way - param = "."; - } - const char *b = p.GetPtr(); - while(!p.IsEof() && !p.IsChar2('/', '/')) - p.SkipTerm(); - body = String(b, p.GetPtr()); - Md5Stream m; - m.Put(param); - m.Put(body); - m.Finish(md5); - } - catch(CParser::Error) { - return Null; - } - return id; -} - -String CppMacro::ToString() const -{ - String r; - if(param.GetCount()) { - String h = param; - h.Replace(".", "..."); - r << "(" << h << ")"; - } - if(IsUndef()) - r << " #undef"; - else - r << ' ' << body; - return r; -} - -void CppMacro::Serialize(Stream& s) -{ - s % param % body; - s.SerializeRaw(md5, 16); -} - -String CppMacro::Expand(const Vector& p, const Vector& ep) const -{ - String r; - const char *s = body; - String pp = param; - if(*pp.Last() == '.') - pp.Trim(pp.GetCount() - 1); - Index param(Split(pp, ',')); - static String VA_ARGS("__VA_ARGS__"); // static - Speed optimization - while(*s) { - if(IsAlpha(*s) || *s == '_') { - const char *b = s; - s++; - while(IsAlNum(*s) || *s == '_') - s++; - String id(b, s); - const char *ss = b; - bool cat = false; - while(ss > ~body && ss[-1] == ' ') - ss--; - if(ss >= ~body + 2 && ss[-1] == '#' && ss[-2] == '#') - cat = true; - ss = s; - while(*ss && *ss == ' ') - ss++; - if(ss[0] == '#' && ss[1] == '#') - cat = true; - if(id == VA_ARGS) { - bool next = false; - for(int i = param.GetCount(); i < ep.GetCount(); i++) { - if(next) - r.Cat(", "); - r.Cat((cat ? p : ep)[i]); - next = true; - } - } - else { - int q = param.Find(id); - if(q >= 0) { - if(q < ep.GetCount()) - r.Cat((cat ? p : ep)[q]); - } - else - r.Cat(id); - } - continue; - } - if(s[0] == '#' && s[1] == '#') { - int q = r.GetLength(); - while(q > 0 && IsSpc(r[q - 1])) - q--; - r.Trim(q); - s += 2; - while((byte)*s <= ' ') - s++; - continue; - } - if(*s == '#') { - const char *ss = s + 1; - while(IsSpc(*ss)) - ss++; - if(IsAlpha(*ss) || *ss == '_') { - const char *b = ss; - ss++; - while(IsAlNum(*ss) || *ss == '_') - ss++; - String id(b, ss); - int q = param.Find(id); - if(q >= 0) { - if(q <= p.GetCount()) { - if(q < p.GetCount()) - r.Cat(AsCString(p[q])); - s = ss; - continue; - } - } - r.Cat(String(s, ss)); - s = ss; - continue; - } - } - r.Cat(*s++); - } - return r; -} - -} diff --git a/uppsrc/CppBase/ppconfig.cpp b/uppsrc/CppBase/ppconfig.cpp deleted file mode 100644 index 3bd48bf52..000000000 --- a/uppsrc/CppBase/ppconfig.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -String GetStdDefs() -{ - static const char ns[] = "_STD_BEGIN:std;_C_STD_BEGIN:std;_STDEXT_BEGIN:stdext;NAMESPACE_UPP:Upp"; - static const char endns[] = "_STD_END;_STDEXT_END;_C_STD_END;END_UPP_NAMESPACE"; - static const char ignore[] = "__declspec(...);__cdecl;__attribute__(...);__stdcall;__forceinline;" - "__out;__in;__inout;__deref_in;__deref_inout;__deref_out;" - "__pragma(...);__pascal;_far;_pascal;_cdecl;" - "__AuToQuOtE;__xin;__xout;__export;" - "__clrcall;__alignof(...);" - - "__asm__(...);__asm(...);__restrict;__inline;__typeof;" - "_GLIBCXX_VISIBILITY(...);_GLIBCXX_BEGIN_NAMESPACE_VERSION;" - "_GLIBCXX_END_NAMESPACE_VERSION;_GLIBCXX_CONSTEXPR;" - "_GLIBCXX_HAS_NESTED_TYPE(...);" - "__inline__;" - "_GLIBCXX_CONST;" - "_GLIBCXX_ABI_TAG_CXX11;" - "__attribute(...);" - "__glibcxx_class_requires(...);" - "__glibcxx_class_requires2(...);" - "__glibcxx_class_requires3(...);" - "__glibcxx_class_requires4(...);" - "__glibcxx_class_requires5(...);" - ; - - String defs; - Vector h = Split(ns, ';'); - for(int i = 0; i < h.GetCount(); i++) { - String id, n; - SplitTo(h[i], ':', id, n); - ValueMap m; - m.Add(id, n); - defs << "#define " << id << " namespace " << n << " {\n"; - } - h = Split(endns, ';'); - for(int i = 0; i < h.GetCount(); i++) - defs << "#define " << h[i] << " };\r\n"; - h = Split(ignore, ';'); - for(int i = 0; i < h.GetCount(); i++) - defs << "#define " << h[i] << "\n"; - defs << "#define NULL NULL\n"; - defs << "#define DrawText DrawText\n"; // DrawTextA/DrawTextW fiasco... - defs << "#define __typeof__ decltype\n"; - return defs; -} - -}; \ No newline at end of file diff --git a/uppsrc/CppBase/ppfile.cpp b/uppsrc/CppBase/ppfile.cpp deleted file mode 100644 index 9f10b0f7b..000000000 --- a/uppsrc/CppBase/ppfile.cpp +++ /dev/null @@ -1,693 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LTIMING(x) // DTIMING(x) -#define LLOG(x) // DLOG(x) - -static std::atomic s_PPserial; -static VectorMap sAllMacros; // Only MakePP can write to this -static ArrayMap sPPfile; // Only MakePP can write to this - -static VectorMap s_PathFileTime; -static StaticMutex s_PathFileTimeMutex; - -static VectorMap s_IncludePath; -static String s_Include_Path; -static StaticMutex s_IncludePathMutex; - -static StaticMutex s_FlatPPMutex; -static ArrayMap s_FlatPP; // ArrayMap to allow read access - -int NextPPSerial() -{ - return ++s_PPserial; -} - -void SweepPPFiles(const Index& keep) -{ - Index pp_segment_id; - int unlinked_count = 0; - for(int i = 0; i < sPPfile.GetCount(); i++) - if(sPPfile.IsUnlinked(i)) - unlinked_count++; - else - if(keep.Find(sPPfile.GetKey(i)) < 0) { - unlinked_count++; - sPPfile.Unlink(i); - } - else { - const PPFile& p = sPPfile[i]; - for(int j = 0; j < p.item.GetCount(); j++) - pp_segment_id.FindAdd(p.item[j].segment_id); - } - if(unlinked_count > sPPfile.GetCount() / 2) { - CleanPP(); - return; - } - unlinked_count = 0; - for(int i = 0; i < sAllMacros.GetCount(); i++) { - if(sAllMacros.IsUnlinked(i)) - unlinked_count++; - else - if(sAllMacros[i].segment_id && pp_segment_id.Find(sAllMacros[i].segment_id) < 0) { - sAllMacros.Unlink(i); - unlinked_count++; - } - if(unlinked_count > sAllMacros.GetCount() / 2) { - CleanPP(); - return; - } - } -} - -String GetSegmentFile(int segment_id) -{ - for(int i = 0; i < sPPfile.GetCount(); i++) { - const Array& m = sPPfile[i].item; - for(int j = 0; j < m.GetCount(); j++) - if(m[j].type == PP_DEFINES && m[j].segment_id == segment_id) - return sPPfile.GetKey(i); - } - return ""; -} - -PPMacro *FindPPMacro(const String& id, Index& segment_id, int& segmenti) -{ - Index undef; - PPMacro *r; - int best; - for(int pass = 0; pass < 2; pass++) { - r = NULL; - best = segmenti; - int line = -1; - int q = sAllMacros.Find(id); - while(q >= 0) { - PPMacro& m = sAllMacros[q]; - if(m.macro.IsUndef()) { - if(pass == 0 && segment_id.Find(m.segment_id) >= 0) - undef.FindAdd(m.segment_id); // cancel out undefined macro... - } - else - if(pass == 0 || m.segment_id == 0 || undef.Find(m.undef_segment_id) < 0) { - int si = m.segment_id == 0 ? INT_MAX : segment_id.Find(m.segment_id); // defs macros always override - if(si > best || si >= 0 && si == best && m.line > line) { - best = si; - line = m.line; - r = &m; - } - } - q = sAllMacros.FindNext(q); - } - if(undef.GetCount() == 0) - break; - } - segmenti = best; - return r; -} - -const CppMacro *FindMacro(const String& id, Index& segment_id, int& segmenti) -{ - PPMacro *m = FindPPMacro(id, segment_id, segmenti); - return m ? &m->macro : NULL; -} - -void PPFile::CheckEndNamespace(Vector& namespace_block, int level, Md5Stream& md5) -{ - if(namespace_block.GetCount() && namespace_block.Top() == level) { - namespace_block.Drop(); - item.Add().type = PP_NAMESPACE_END; - md5.Put('.'); - } -} - -void PPFile::Parse(Stream& in) -{ - LTIMING("PPFile::Parse"); - for(int i = 0; i < ppmacro.GetCount(); i++) - sAllMacros.Unlink(ppmacro[i]); - ppmacro.Clear(); - item.Clear(); - includes.Clear(); - bool was_using = false; - bool was_namespace = false; - int level = 0; - bool incomment = false; - bool do_pp = true; - Vector namespace_block; - bool next_segment = true; - Index local_segments; - keywords.Clear(); - int linei = 0; - Md5Stream md5; - int current_serial = 0; - - VectorMap local_macro; // gather all macros first to reduce locking - - while(!in.IsEof()) { - String l = in.GetLine(); - const char *ll = l; - while(*ll == ' ' || *ll == '\t') - ll++; - if(ll[0] == '/' && ll[1] == '/' && ll[2] == '$') - do_pp = decode(ll[3], '+', true, '-', false, do_pp); - while(*l.Last() == '\\' && !in.IsEof()) { - l.Trim(l.GetLength() - 1); - l.Cat(in.GetLine()); - } - RemoveComments(l, incomment); - try { - CParser p(l); - if(p.Char('#')) { - if(do_pp) { - if(p.Id("define")) { - if(next_segment) { - PPItem& m = item.Add(); - m.type = PP_DEFINES; - m.segment_id = current_serial = NextPPSerial(); - next_segment = false; - local_segments.Add(current_serial); - } - CppMacro def; - String id = def.Define(p.GetPtr()); - if(id.GetCount()) { - PPMacro& l = local_macro.Add(id); - l.segment_id = current_serial; - l.line = linei; - l.macro = def; - /* - PPMacro m; - m.segment_id = current_serial; - m.line = linei; - m.macro = def; - ppmacro.Add(sAllMacros.Put(id, m)); - */ - md5.Put("#", 1); - md5.Put(id); - md5.Put(0); - md5.Put(l.macro.md5, 16); - } - } - else - if(p.Id("undef")) { - if(p.IsId()) { - String id = p.ReadId(); - if(id.GetCount()) { - md5.Put("#", 1); - md5.Put(id); - md5.Put(1); - int q = local_macro.FindLast(id); // heuristic: only local undefs are allowed - while(q >= 0) { - PPMacro& um = local_macro[q]; - if(!um.macro.IsUndef()) { // found corresponding macro to undef - PPItem& m = item.Add(); - m.type = PP_DEFINES; - m.segment_id = current_serial = NextPPSerial(); - um.undef_segment_id = m.segment_id; - next_segment = true; - local_segments.Add(current_serial); - PPMacro& l = local_macro.Add(id); - l.segment_id = current_serial; - l.line = linei; - l.macro.SetUndef(); - } - q = local_macro.FindPrev(q); - } - } - /* - int segmenti = -1; - PPMacro *um = FindPPMacro(id, local_segments, segmenti); - if(um && segmenti) { - PPItem& m = item.Add(); - m.type = PP_DEFINES; - m.segment_id = current_serial = NextPPSerial(); - um->undef_segment_id = m.segment_id; - next_segment = true; - local_segments.Add(current_serial); - if(id.GetCount()) { - PPMacro m; - m.segment_id = current_serial; - m.line = linei; - m.macro.SetUndef(); - ppmacro.Add(sAllMacros.Put(id, m)); - } - } - */ - } - } - else - if(p.Id("include")) { - PPItem& m = item.Add(); - next_segment = true; - m.type = PP_INCLUDE; - m.text = TrimBoth(p.GetPtr()); - if(IsNull(m.text)) - item.Drop(); - else - includes.FindAdd(m.text); - md5.Put('@'); - md5.Put(m.text); - } - } - } - else { - while(!p.IsEof()) { - if(was_namespace) { - int type = was_using ? PP_USING : PP_NAMESPACE; - String id; - while(p.Char2(':', ':')) - id = "::"; - if(p.IsId()) { - id << p.ReadId(); - while(p.Char2(':', ':') && p.IsId()) - id << "::" << p.ReadId(); - if(!was_using) - namespace_block.Add(level); - if(!was_using || level == 0) { - PPItem& m = item.Add(); - next_segment = true; - m.type = type; - m.text = id; - } - md5.Put('$'); - md5.Put(type); - md5.Put(id); - } - was_namespace = was_using = false; - } - else - if(p.Id("using")) - was_using = true; - else - if(p.Id("namespace")) - was_namespace = true; - else { - was_using = was_namespace = false; - if(p.IsId()) { - static const VectorMap& namespace_macro = GetNamespaceMacros(); - static const Index& namespace_end_macro = GetNamespaceEndMacros(); - - String id = p.ReadId(); - int q = namespace_macro.Find(id); - if(q > 0) { - PPItem& m = item.Add(); - next_segment = true; - m.type = PP_NAMESPACE; - m.text = namespace_macro[q]; - namespace_block.Add(level); - level++; - md5.Put('%'); - md5.Put(id); - } - else { - q = namespace_end_macro.Find(id); - if(q >= 0) { - level--; - CheckEndNamespace(namespace_block, level, md5); - } - } - keywords.Add(id); - } - else - if(p.Char('}')) { - if(level > 0) { - level--; - CheckEndNamespace(namespace_block, level, md5); - } - } - else - if(p.Char('{')) - level++; - else - p.SkipTerm(); - } - } - } - } - catch(...) {} - linei++; - } - md5sum = md5.FinishString(); - Sort(keywords); - Vector remove; - int i = 0; - while(i < keywords.GetCount()) { // Remove identical items - int ii = i; - i++; - while(i < keywords.GetCount() && keywords[ii] == keywords[i]) - remove.Add(i++); - } - keywords.Remove(remove); - INTERLOCKED { // this is the only place that is allowed to write to sAllMacros - for(int i = 0; i < local_macro.GetCount(); i++) - ppmacro.Add(sAllMacros.Put(local_macro.GetKey(i), local_macro[i])); - } -} - -void PPFile::Dump() const -{ - for(int i = 0; i < item.GetCount(); i++) { - const PPItem& m = item[i]; - String ll; - ll << decode(m.type, PP_DEFINES, "#defines ", PP_INCLUDE, "#include ", - PP_USING, "using namespace ", PP_NAMESPACE, "namespace ", - PP_NAMESPACE_END, "}", ""); - if(m.type == PP_DEFINES) - ll << m.segment_id; - else - ll << m.text; - if(m.type == PP_NAMESPACE) - ll << " {"; - LOG(ll); - } - LOG("----- includes:"); - DUMPC(includes); -} - -void InvalidatePPCache() -{ - { - Mutex::Lock __(s_IncludePathMutex); - s_IncludePath.Clear(); - } - { - Mutex::Lock __(s_FlatPPMutex); - s_FlatPP.Clear(); - } -} - -void PPSync(const String& include_path) -{ - LLOG("* PPSync"); - bool update = false; - { - Mutex::Lock __(s_IncludePathMutex); - if(s_Include_Path != include_path) { - s_IncludePath.Clear(); - s_Include_Path = include_path; - update = true; - } - } - if(update) { - Mutex::Lock __(s_FlatPPMutex); - s_FlatPP.Clear(); - } -} - -void InvalidateFileTimeCache() -{ - Mutex::Lock __(s_PathFileTimeMutex); - s_PathFileTime.Clear(); -} - -void InvalidateFileTimeCache(const String& path) -{ - LLOG("InvalidateFileTimeCache " << path); - Mutex::Lock __(s_PathFileTimeMutex); - s_PathFileTime.UnlinkKey(path); -} - -Time GetFileTimeCached(const String& p) -{ - LTIMING("GetFileTimeCached"); - { - Mutex::Lock __(s_PathFileTimeMutex); - int q = s_PathFileTime.Find(p); - if(q >= 0) - return s_PathFileTime[q]; - } - Time m = FileGetTime(p); - { - Mutex::Lock __(s_PathFileTimeMutex); - s_PathFileTime.Put(p, m); - } - return m; -} - -String GetIncludePath() -{ - Mutex::Lock __(s_IncludePathMutex); - return s_Include_Path; -} - -String GetIncludePath0(const char *s, const char *filedir) -{ - LTIMING("GetIncludePath0"); - while(IsSpace(*s)) - s++; - int type = *s; - if(type == '<' || type == '\"' || type == '?') { - s++; - String name; - if(type == '<') type = '>'; - while(*s != '\r' && *s != '\n' && *s) { - if(*s == type) { - if(type == '\"') { - String fn = NormalizeSourcePath(name, filedir); - if(FileExists(fn)) - return fn; - } - String p = GetFileOnPath(name, GetIncludePath(), false); - if(p.GetCount()) - return NormalizeSourcePath(p); - return Null; - } - name.Cat(*s++); - } - } - return Null; -} - -String GetIncludePath(const String& s, const String& filedir) -{ - LTIMING("GetIncludePath"); - Mutex::Lock __(s_IncludePathMutex); - String key; - key << s << "#" << filedir; - int q = s_IncludePath.Find(key); - if(q >= 0) - return s_IncludePath[q]; - LTIMING("GetIncludePath 2"); - String p = GetIncludePath0(s, filedir); - s_IncludePath.Add(key, p); - LLOG("GetIncludePath " << s << " " << filedir << ": " << p); - return p; -} - -void MakePP(const Index& paths) -{ - LLOG("MakePP " << paths); - Vector todo; - Vector pp; - for(int i = 0; i < paths.GetCount(); i++) { - String path = paths[i]; - PPFile& f = sPPfile.GetPut(path); - Time tm = GetFileTimeCached(path); - if(f.filetime != tm) { - f.filetime = tm; - pp.Add(&f); - todo.Add(path); - } - } - CoFor(todo.GetCount(), [&](int i) { - FileIn in(todo[i]); - pp[i]->Parse(in); - }); -} - -const PPFile& GetPPFile(const char *path) -{ - LTIMING("GetPPFile"); - LLOG("GetPPFile " << path); - static PPFile zero; - return sPPfile.Get(path, zero); -} - -bool IsSameFile(const String& f1, const String& f2) -{ - return NormalizePath(f1) == NormalizePath(f2); -} - -const FlatPP& GetFlatPPFile(const char *path, Index& visited) -{ - LTIMING("GetFlatPPFile"); - LLOG("GetFlatPPFile " << path); - Mutex::Lock __(s_FlatPPMutex); - int q = s_FlatPP.Find(path); - if(q >= 0) { - LLOG("From cache"); - return s_FlatPP[q]; - } - FlatPP& fp = s_FlatPP.Add(path); - const PPFile& pp = GetPPFile(path); - int n = visited.GetCount(); - visited.FindAdd(path); - for(int i = 0; i < pp.item.GetCount(); i++) { - const PPItem& m = pp.item[i]; - if(m.type == PP_INCLUDE) { - String s = GetIncludePath(m.text, GetFileFolder(path)); - LLOG("#include " << m.text << " -> " << s); - if(s.GetCount() && visited.Find(s) < 0) { - visited.Add(s); - const FlatPP& pp = GetFlatPPFile(s, visited); - for(int i = 0; i < pp.segment_id.GetCount(); i++) - fp.segment_id.FindAdd(pp.segment_id[i]); - for(int i = 0; i < pp.usings.GetCount(); i++) - fp.usings.FindAdd(pp.usings[i]); - } - } - else - if(m.type == PP_DEFINES) - fp.segment_id.FindAdd(m.segment_id); - else - if(m.type == PP_USING) - fp.usings.FindAdd(m.text); - } - visited.Trim(n); - return fp; -} - -const FlatPP& GetFlatPPFile(const char *path) -{ - Index visited; - visited.Add(path); - return GetFlatPPFile(path, visited); -} - -void GetAllMacros(Md5Stream& md5, const String& id, Index& segment_id) -{ - Vector< Tuple2 > pos; - Vector def; - String r; - int q = sAllMacros.Find(id); - while(q >= 0) { - const PPMacro& m = sAllMacros[q]; - int si = segment_id.Find(m.segment_id); - if(si >= 0) { - pos.Add(MakeTuple(si, m.line)); - def.Add(&m.macro); - } - q = sAllMacros.FindNext(q); - } - IndexSort(pos, def); - int n = def.GetCount(); - if(n) { - md5.Put(&n, sizeof(int)); - md5.Put(id); - for(int i = 0; i < n; i++) - md5.Put(def[i]->md5, 16); - } -} - -static VectorMap s_namespace_macro; -static Index s_namespace_end_macro; - -static String sDefs; - -void LoadPPConfig() -{ - for(int i = 0; i < sAllMacros.GetCount(); i++) - if(sAllMacros[i].segment_id == 0 && !sAllMacros.IsUnlinked(i)) - sAllMacros.Unlink(i); - - s_namespace_macro.Clear(); - s_namespace_end_macro.Clear(); - - StringStream ss(sDefs); - int linei = 0; - while(!ss.IsEof()) { - String l = ss.GetLine(); - try { - CParser p(l); - if(p.Char('#')) { - if(p.Id("define")) { - CppMacro def; - String id = def.Define(p.GetPtr()); - if(id.GetCount()) { - PPMacro m; - m.segment_id = 0; - m.line = linei; - m.macro = def; - sAllMacros.Put(id, m); - if(findarg(TrimBoth(def.body), "}", "};") >= 0) - s_namespace_end_macro.Add(id); - try { - CParser p(def.body); - if(p.Id("namespace") && p.IsId()) { - String n = p.ReadId(); - if(p.Char('{') && p.IsEof()) - s_namespace_macro.Add(id, n); - } - } - catch(CParser::Error) {} - } - } - } - } - catch(CParser::Error) {} - linei++; - } -} - -const VectorMap& GetNamespaceMacros() -{ - return s_namespace_macro; -} - -const Index& GetNamespaceEndMacros() -{ - return s_namespace_end_macro; -} - -void SetPPDefs(const String& defs) -{ - sDefs = defs; - LoadPPConfig(); -} - -void CleanPP() -{ - sAllMacros.Clear(); - sPPfile.Clear(); - s_PPserial = 0; - LoadPPConfig(); -} - -void SerializePPFiles(Stream& s) -{ - int sPPserial = s_PPserial; - s % sAllMacros % sPPfile % sPPserial; - s_PPserial = sPPserial; - if(s.IsLoading()) - LoadPPConfig(); - -#if 0 - if(s.IsLoading()) { _DBG_ - DDUMP(sPPfile.GetCount()); - DDUMP(sAllMacros.GetCount()); - DDUMP(sPPserial); - - Index psegment; - for(int i = 0; i < sPPfile.GetCount(); i++) { - const PPFile& p = sPPfile[i]; - for(int j = 0; j < p.item.GetCount(); j++) - psegment.FindAdd(p.item[j].segment_id); - } - DDUMP(psegment.GetCount()); - - int n = 0; _DBG_ - Index msegment; - for(int i = 0; i < sAllMacros.GetCount(); i++) { _DBG_ - if(sAllMacros.IsUnlinked(i)) - n++; - else - msegment.FindAdd(sAllMacros[i].segment_id); - } - DLOG("UNLINKED " << n); - DLOG("Segments " << msegment.GetCount()); - } -#endif -} - -} diff --git a/uppsrc/CppBase/srcfiles.cpp b/uppsrc/CppBase/srcfiles.cpp deleted file mode 100644 index fffccbbbb..000000000 --- a/uppsrc/CppBase/srcfiles.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -#define LTIMING(x) // DTIMING(x) -#define LLOG(x) // DLOG(x) - -static VectorMap sSrcFile; -static Index sIncludes; - -String NormalizeSourcePath(const String& path, const String& currdir) -{ - LTIMING("NormalizeSourcePath"); -#ifdef PLATFORM_WIN32 - return ToLower(NormalizePath(path, currdir)); -#else - return NormalizePath(path, currdir); -#endif -} - -String NormalizeSourcePath(const String& path) -{ - return NormalizeSourcePath(path, GetCurrentDirectory()); -} - -void ClearSources() -{ - sSrcFile.Clear(); - sIncludes.Clear(); -} - -const Index& GetAllSources() -{ - return sSrcFile.GetIndex(); -} - -const VectorMap& GetAllSourceMasters() -{ - return sSrcFile; -} - -void GatherSources(const String& master_path, const String& path_, Vector& parents) -{ - String path = NormalizeSourcePath(path_); - LLOG("--- GatherSources " << master_path << " " << path); - if(sSrcFile.Find(path) >= 0) - return; - int ii = sSrcFile.GetCount(); - for(int i = 0; i < parents.GetCount(); i++) - sIncludes.Add(MAKEQWORD(parents[i], ii)); - sSrcFile.Add(path, master_path); - parents.Add(ii); - const PPFile& f = GetPPFile(path); - Index todo; - for(String inc : f.includes) { - String p = GetIncludePath(inc, GetFileFolder(path)); - if(p.GetCount()) - todo.FindAdd(p); - } - MakePP(todo); // parse PP files in parallel to accelerate things... - for(String p : todo) - GatherSources(master_path, p, parents); - parents.Drop(); -} - -void GatherSources(const String& path) -{ - LTIMING("GatherSources"); - Vector parents; - LLOG("=== GatherSources " << path); - MakePP({ NormalizeSourcePath(path) }); - GatherSources(NormalizeSourcePath(path), path, parents); -} - -String GetMasterFile(const String& file) -{ - return sSrcFile.Get(file, Null); -} - -bool IncludesFile(const String& parent_path, const String& header_path) -{ - LTIMING("IncludesFile"); - int pi = sSrcFile.Find(parent_path); - int i = sSrcFile.Find(header_path); - return pi >= 0 && i >= 0 && sIncludes.Find(MAKEQWORD(pi, i)) >= 0; -} - -} diff --git a/uppsrc/CppBase/util.cpp b/uppsrc/CppBase/util.cpp deleted file mode 100644 index 3419d6404..000000000 --- a/uppsrc/CppBase/util.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "CppBase.h" -#include "Internal.h" - -namespace Upp { - -bool IsCPPFile(const String& path) -{ - return findarg(ToLower(GetFileExt(path)) , ".c", ".cpp", ".cc" , ".cxx", ".icpp") >= 0; -} - -bool IsHFile(const String& path) -{ - return findarg(ToLower(GetFileExt(path)) , ".h", ".hpp", ".hxx" , ".hh") >= 0; -} - -void SetSpaces(String& l, int pos, int count) -{ - StringBuffer s(l); - memset(~s + pos, ' ', count); - l = s; -} - -const char *SkipString(const char *s) -{ - CParser p(s); - try { - p.ReadOneString(*s); - } - catch(CParser::Error) {} - s = p.GetPtr(); - while((byte)*(s - 1) <= ' ') - s--; - return s; -} - -void RemoveComments(String& l, bool& incomment) -{ - int q = -1; - int w = -1; - if(incomment) - q = w = 0; - else { - const char *s = l; - while(*s) { - if(*s == '\"') - s = SkipString(s); - else - if(s[0] == '/' && s[1] == '/') { - q = int(s - ~l); - SetSpaces(l, q, l.GetCount() - q); - return; - } - else - if(s[0] == '/' && s[1] == '*') { - q = int(s - ~l); - break; - } - else - s++; - } - if(q >= 0) - w = q + 2; - } - while(q >= 0) { - int eq = l.Find("*/", w); - if(eq < 0) { - incomment = true; - SetSpaces(l, q, l.GetCount() - q); - return; - } - SetSpaces(l, q, eq + 2 - q); - incomment = false; - q = l.Find("/*"); - w = q + 2; - } -} - -}; \ No newline at end of file diff --git a/uppsrc/CtrlCore/CocoCtrl.h b/uppsrc/CtrlCore/CocoCtrl.h index 7288050fb..55603fdbc 100644 --- a/uppsrc/CtrlCore/CocoCtrl.h +++ b/uppsrc/CtrlCore/CocoCtrl.h @@ -1,4 +1,3 @@ -//$ class Upp::Ctrl { private: friend struct MMCtrl; friend struct MMImp; @@ -31,4 +30,3 @@ public: void RegisterCocoaDropFormats(); static Rect GetScreenArea(Point pt); -//$ }; diff --git a/uppsrc/CtrlCore/CocoTop.h b/uppsrc/CtrlCore/CocoTop.h index acbee0398..ff9a89d09 100644 --- a/uppsrc/CtrlCore/CocoTop.h +++ b/uppsrc/CtrlCore/CocoTop.h @@ -1,4 +1,3 @@ -//$ class Upp::TopWindow { protected: friend struct MMImp; @@ -22,4 +21,3 @@ public: Event WhenDockMenu; void SetMainMenu(Event menu); -//$ }; \ No newline at end of file diff --git a/uppsrc/CtrlCore/CtrlMt.cpp b/uppsrc/CtrlCore/CtrlMt.cpp index 3628b7e84..41748695f 100644 --- a/uppsrc/CtrlCore/CtrlMt.cpp +++ b/uppsrc/CtrlCore/CtrlMt.cpp @@ -110,8 +110,10 @@ void Ctrl::ShutdownThreads() { Thread::BeginShutdownThreads(); while(Thread::GetCount()) { + Thread::TryShutdownThreads(); ProcessEvents(); - Sleep(0); + GuiUnlock __; + Sleep(100); } Thread::EndShutdownThreads(); } diff --git a/uppsrc/CtrlCore/Gtk.h b/uppsrc/CtrlCore/Gtk.h index 3334cd3c3..48d73eb2f 100644 --- a/uppsrc/CtrlCore/Gtk.h +++ b/uppsrc/CtrlCore/Gtk.h @@ -179,7 +179,6 @@ Vector GetPropertyInts(GdkWindow *w, const char *property); #define GUIPLATFORM_KEYCODES_INCLUDE -//$ struct Ctrl::Top { #define GUIPLATFORM_CTRL_TOP_DECLS \ GtkWidget *window; \ GtkIMContext *im_context; \ @@ -187,7 +186,6 @@ Vector GetPropertyInts(GdkWindow *w, const char *property); GtkIMContext *im_context_multi; \ int64 cursor_id; \ int id; \ -//$ } #define GUIPLATFORM_CTRL_DECLS_INCLUDE diff --git a/uppsrc/CtrlCore/GtkApp.cpp b/uppsrc/CtrlCore/GtkApp.cpp index 0d2a7f992..a6d1ef4c7 100644 --- a/uppsrc/CtrlCore/GtkApp.cpp +++ b/uppsrc/CtrlCore/GtkApp.cpp @@ -2,6 +2,8 @@ #ifdef GUI_GTK +#include + #define CATCH_ERRORS 1 namespace Upp { @@ -55,6 +57,8 @@ int Ctrl::scale; void InitGtkApp(int argc, char **argv, const char **envptr) { LLOG(rmsecs() << " InitGtkApp"); + + XInitThreads(); // otherwise there are errors despide GuiLock #if GTK_CHECK_VERSION(3, 10, 0) gdk_set_allowed_backends("x11"); // this fixes wayland issues diff --git a/uppsrc/CtrlCore/GtkCtrl.h b/uppsrc/CtrlCore/GtkCtrl.h index 90b07762b..a796770c5 100644 --- a/uppsrc/CtrlCore/GtkCtrl.h +++ b/uppsrc/CtrlCore/GtkCtrl.h @@ -1,5 +1,3 @@ -//$ namespace Upp { -//$ class Ctrl { void Create(Ctrl *owner, bool popup); static gboolean GtkProc(GtkWidget *widget, GdkEvent *event, gpointer user_data); @@ -101,7 +99,7 @@ _DBG_ static Ptr activeCtrl; static bool invalids; // there are active invalid areas - static int FindId(int id); + static int FindGtkId(int id); static int FindCtrl(Ctrl *ctrl); static int FindGtkWindow(GtkWidget *gtk); static int FindGdkWindow(GdkWindow *gdk); @@ -213,5 +211,3 @@ public: GtkWindow *gtk() const; static GdkFilterReturn RootKeyFilter(GdkXEvent *xevent, GdkEvent *event, gpointer data); - -//$ }}; diff --git a/uppsrc/CtrlCore/GtkEvent.cpp b/uppsrc/CtrlCore/GtkEvent.cpp index 29cc1bebf..e535f3b64 100644 --- a/uppsrc/CtrlCore/GtkEvent.cpp +++ b/uppsrc/CtrlCore/GtkEvent.cpp @@ -69,7 +69,7 @@ Tuple2 xEvent[] = { Ctrl *Ctrl::GetTopCtrlFromId(int id) { - int q = FindId(id); + int q = FindGtkId(id); if(q >= 0) { Ctrl *p = wins[q].ctrl; if(p && p->top) diff --git a/uppsrc/CtrlCore/GtkTop.h b/uppsrc/CtrlCore/GtkTop.h index 66d47704b..cb44b5f6a 100644 --- a/uppsrc/CtrlCore/GtkTop.h +++ b/uppsrc/CtrlCore/GtkTop.h @@ -1,4 +1,3 @@ -//$ class Upp::TopWindow : Ctrl { ImageGdk gdk_icon; ImageGdk gdk_largeicon; bool topmost; @@ -12,4 +11,3 @@ static gboolean StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data); friend class Ctrl; -//$ }; diff --git a/uppsrc/CtrlCore/GtkWnd.cpp b/uppsrc/CtrlCore/GtkWnd.cpp index 6d85ccda3..202bc80d7 100644 --- a/uppsrc/CtrlCore/GtkWnd.cpp +++ b/uppsrc/CtrlCore/GtkWnd.cpp @@ -16,7 +16,7 @@ Ptr Ctrl::activeCtrl; bool Ctrl::invalids; -int Ctrl::FindId(int id) +int Ctrl::FindGtkId(int id) { for(int i = 0; i < wins.GetCount(); i++) if(wins[i].id == id) diff --git a/uppsrc/CtrlCore/Win32Ctrl.h b/uppsrc/CtrlCore/Win32Ctrl.h index 193050fa8..0cd15a4e2 100644 --- a/uppsrc/CtrlCore/Win32Ctrl.h +++ b/uppsrc/CtrlCore/Win32Ctrl.h @@ -1,5 +1,3 @@ -//$ namespace Upp { -//$ class Ctrl { private: bool activex:1; bool isdhctrl:1; @@ -74,5 +72,3 @@ public: static void InitWin32(HINSTANCE hinst); static void ExitWin32(); static void GuiFlush() { ::GdiFlush(); } -//$ }; -//$ }; \ No newline at end of file diff --git a/uppsrc/CtrlCore/Win32Top.h b/uppsrc/CtrlCore/Win32Top.h index bd28d9d3d..5d2cb43da 100644 --- a/uppsrc/CtrlCore/Win32Top.h +++ b/uppsrc/CtrlCore/Win32Top.h @@ -1,4 +1,3 @@ -//$ class Upp::TopWindow { public: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); @@ -16,4 +15,3 @@ public: dword GetStyle() const { return style; } TopWindow& ExStyle(dword _exstyle); dword GetExStyle() const { return exstyle; } -//$ }; \ No newline at end of file diff --git a/uppsrc/CtrlCore/X11Ctrl.h b/uppsrc/CtrlCore/X11Ctrl.h index 759bc4fd3..3ba866acf 100644 --- a/uppsrc/CtrlCore/X11Ctrl.h +++ b/uppsrc/CtrlCore/X11Ctrl.h @@ -1,5 +1,3 @@ -//$ namespace Upp { -//$ class Ctrl { bool ignoretakefocus:1; protected: struct XWindow { @@ -110,4 +108,3 @@ public: static void InitX11(const char *display); static void ExitX11(); static void GuiFlush() { XFlush(Xdisplay); } -//$ }}; diff --git a/uppsrc/CtrlCore/X11Top.h b/uppsrc/CtrlCore/X11Top.h index 78772790c..2c619fe50 100644 --- a/uppsrc/CtrlCore/X11Top.h +++ b/uppsrc/CtrlCore/X11Top.h @@ -1,4 +1,3 @@ -//$ class Upp::TopWindow { protected: virtual void EventProc(XWindow& w, XEvent *event); private: @@ -20,4 +19,4 @@ private: WString title2; static Rect windowFrameMargin; -//$ }; + diff --git a/uppsrc/CtrlCore/src.tpp/Ctrl_en-us.tpp b/uppsrc/CtrlCore/src.tpp/Ctrl_en-us.tpp index 3e6b851f9..6f9fe88e6 100644 --- a/uppsrc/CtrlCore/src.tpp/Ctrl_en-us.tpp +++ b/uppsrc/CtrlCore/src.tpp/Ctrl_en-us.tpp @@ -2742,7 +2742,8 @@ should terminate.&] s]()&] [s2; Similiar to Thread`::ShutdownThreads, but as part of waiting for threads to finish calls ProcessEvents so that any Call methods -can finish.&] +can finish and also periodically unlocks GuiLock so that threads +waiting on it can finish.&] [s3;%- &] [s4;%- &] [s5;:Ctrl`:`:GetEventId`(`):%- [@(0.0.255) static] [_^int64^ int64]_[* GetEventId]()&] diff --git a/uppsrc/CtrlLib/ArrayCtrl.cpp b/uppsrc/CtrlLib/ArrayCtrl.cpp index 83d681c3a..4f5f222be 100644 --- a/uppsrc/CtrlLib/ArrayCtrl.cpp +++ b/uppsrc/CtrlLib/ArrayCtrl.cpp @@ -2165,7 +2165,6 @@ void ArrayCtrl::AddHeading(const Value& v) DisableLine(ii); } -//$- #define E__Addv(I) Set0(q, I - 1, p##I) #define E__AddF(I) \ void ArrayCtrl::Add(__List##I(E__Value)) { \ @@ -2174,7 +2173,6 @@ void ArrayCtrl::Add(__List##I(E__Value)) { \ AfterSet(q); \ } __Expand(E__AddF) -//$+ void ArrayCtrl::Insert(int i, int count) { if(i < array.GetCount()) { diff --git a/uppsrc/CtrlLib/ArrayCtrl.h b/uppsrc/CtrlLib/ArrayCtrl.h index f8dd51c9c..a36f115d0 100644 --- a/uppsrc/CtrlLib/ArrayCtrl.h +++ b/uppsrc/CtrlLib/ArrayCtrl.h @@ -490,10 +490,8 @@ public: void Add(Vector&& v) { Set(array.GetCount(), pick(v)); } void Add(const Nuller& null) { Add((Value)Null); } void Add(const VectorMap& m); -//$-void Add(const Value& [, const Value& ]...); template void Add(const Args& ...args) { Add(gather>(args...)); } -//$+ void SetMap(int i, const ValueMap& m); void AddMap(const ValueMap& m); diff --git a/uppsrc/CtrlLib/EditCtrl.h b/uppsrc/CtrlLib/EditCtrl.h index a96a65aa6..c493012b6 100644 --- a/uppsrc/CtrlLib/EditCtrl.h +++ b/uppsrc/CtrlLib/EditCtrl.h @@ -97,6 +97,7 @@ protected: ATTR_NULLTEXT, ATTR_NULLINK, ATTR_NULLFONT, + ATTR_BACKGROUND, ATTR_LAST, }; @@ -238,6 +239,7 @@ public: EditField& SetCharset(byte cs) { charset = cs; return *this; } EditField& SetFont(Font _font); EditField& SetColor(Color c); + EditField& SetBackground(Color c); EditField& ClickSelect(bool b = true) { clickselect = b; return *this; } bool IsClickSelect() const { return clickselect; } EditField& InitCaps(bool b = true) { initcaps = b; return *this; } diff --git a/uppsrc/CtrlLib/EditField.cpp b/uppsrc/CtrlLib/EditField.cpp index a4fae995a..f816b9d16 100644 --- a/uppsrc/CtrlLib/EditField.cpp +++ b/uppsrc/CtrlLib/EditField.cpp @@ -295,8 +295,11 @@ void EditField::State(int) Color EditField::GetPaper() { bool enabled = IsShowEnabled(); - Color paper = enabled && !IsReadOnly() ? (HasFocus() ? style->focus : style->paper) - : style->disabled; + Color paper = GetColorAttr(ATTR_BACKGROUND); + if(IsNull(paper)) + paper = enabled && !IsReadOnly() ? (HasFocus() ? style->focus + : style->paper) + : style->disabled; if(nobg) paper = Null; if(enabled && (convert && convert->Scan(text).IsError() || errorbg)) @@ -1068,8 +1071,19 @@ EditField& EditField::SetFont(Font _font) EditField& EditField::SetColor(Color c) { - SetColorAttr(ATTR_TEXTCOLOR, c); - Refresh(); + if(GetColorAttr(ATTR_TEXTCOLOR) != c) { + SetColorAttr(ATTR_TEXTCOLOR, c); + Refresh(); + } + return *this; +} + +EditField& EditField::SetBackground(Color c) +{ + if(GetColorAttr(ATTR_BACKGROUND) != c) { + SetColorAttr(ATTR_BACKGROUND, c); + Refresh(); + } return *this; } diff --git a/uppsrc/CtrlLib/Help.cpp b/uppsrc/CtrlLib/Help.cpp index 67d6e128e..a3da30062 100644 --- a/uppsrc/CtrlLib/Help.cpp +++ b/uppsrc/CtrlLib/Help.cpp @@ -29,7 +29,12 @@ bool HelpWindow::GoTo0(const String& link) FinishText(txt); view.Pick(pick(txt), zoom); current_link = link; - return view.GotoLabel(label, true);; + if(WhenMatchLabel) { + WString lw = label.ToWString(); + return view.GotoLabel([=](const WString& data) { return WhenMatchLabel(data, lw); }, true); + } + else + return view.GotoLabel(label, true);; } return false; } diff --git a/uppsrc/CtrlLib/RichText.h b/uppsrc/CtrlLib/RichText.h index 434876c1b..fbe6811f0 100644 --- a/uppsrc/CtrlLib/RichText.h +++ b/uppsrc/CtrlLib/RichText.h @@ -75,6 +75,7 @@ public: Zoom GetZoom() const; Rect GetPage() const; + bool GotoLabel(Gate match, bool dohighlight = false); bool GotoLabel(const String& lbl, bool highlight = false); void ClearHighlight() { highlight = Null; Refresh(); } @@ -318,6 +319,8 @@ public: virtual Topic AcquireTopic(const String& topic); virtual void FinishText(RichText& text); virtual void BarEx(Bar& bar); + + Gate WhenMatchLabel; bool GoTo(const String& link); diff --git a/uppsrc/CtrlLib/RichTextView.cpp b/uppsrc/CtrlLib/RichTextView.cpp index 355869e0f..4725ed236 100644 --- a/uppsrc/CtrlLib/RichTextView.cpp +++ b/uppsrc/CtrlLib/RichTextView.cpp @@ -317,13 +317,12 @@ void RichTextView::Scroll() scroller.Scroll(*this, Rect(GetSize()).Deflated(margin), sb * GetZoom()); } -bool RichTextView::GotoLabel(const String& lbl, bool dohighlight) +bool RichTextView::GotoLabel(Gate match, bool dohighlight) { Vector f = text.GetValPos(GetPage(), RichText::LABELS); highlight = Null; - WString lw = lbl.ToWString(); for(int i = 0; i < f.GetCount(); i++) { - if(f[i].data == lw) { + if(match(f[i].data)) { sb = f[i].py.y; if(dohighlight) highlight = f[i].pos; @@ -334,6 +333,12 @@ bool RichTextView::GotoLabel(const String& lbl, bool dohighlight) return false; } +bool RichTextView::GotoLabel(const String& lbl, bool dohighlight) +{ + WString lw = lbl.ToWString(); + return GotoLabel([&](const WString& data) { return data == lw; }, dohighlight); +} + void RichTextView::Clear() { sb = 0; diff --git a/uppsrc/CtrlLib/src.tpp/EditField_en-us.tpp b/uppsrc/CtrlLib/src.tpp/EditField_en-us.tpp index e75b19c4c..5721f0d14 100644 --- a/uppsrc/CtrlLib/src.tpp/EditField_en-us.tpp +++ b/uppsrc/CtrlLib/src.tpp/EditField_en-us.tpp @@ -1,5 +1,4 @@ topic "EditField"; -[2 $$0,0#00000000000000000000000000000000:Default] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [l288;2 $$2,0#27521748481378242620020725143825:desc] [0 $$3,0#96390100711032703541132217272105:end] @@ -9,6 +8,7 @@ topic "EditField"; [l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [b42;2 $$9,9#13035079074754324216151401829390:normal] +[2 $$0,0#00000000000000000000000000000000:Default] [{_} [ {{10000@3 [s0;%% [*@(229)4 EditField]]}}&] [s3; &] @@ -279,6 +279,11 @@ olor]_[*@3 c])&] [s2;%% [%- Sets the color] of displayed text. Returns `*this.&] [s3;%% &] [s4; &] +[s5;:Upp`:`:EditField`:`:SetBackground`(Upp`:`:Color`): EditField[@(0.0.255) `&] +[* SetBackground](Color [*@3 c])&] +[s2;%% Sets the background color. Returns `*this.&] +[s3; &] +[s4; &] [s5;:EditField`:`:ClickSelect`(bool`): [_^EditField^ EditField][@(0.0.255) `&]_[* ClickSele ct]([@(0.0.255) bool]_[*@3 b]_`=_[@(0.0.255) true])&] [s2; In ClickSelect mode, all the text of EditField is select when diff --git a/uppsrc/Draw/iml_header.h b/uppsrc/Draw/iml_header.h index 1253ca825..3e13a8dc9 100644 --- a/uppsrc/Draw/iml_header.h +++ b/uppsrc/Draw/iml_header.h @@ -1,7 +1,5 @@ //#BLITZ_APPROVE -//$- - #define IMAGE_META(k, v) #define IMAGE_SCAN(s) #define IMAGE_PACKED(n, d) diff --git a/uppsrc/Draw/iml_source.h b/uppsrc/Draw/iml_source.h index 82c99d8dc..5ebc84247 100644 --- a/uppsrc/Draw/iml_source.h +++ b/uppsrc/Draw/iml_source.h @@ -1,7 +1,5 @@ //#BLITZ_APPROVE -//$ - #define IMAGE_META(k, v) #define PREMULTIPLIED diff --git a/uppsrc/IconDes/IconDes.key b/uppsrc/IconDes/IconDes.key index bbbba820b..d4c23166a 100644 --- a/uppsrc/IconDes/IconDes.key +++ b/uppsrc/IconDes/IconDes.key @@ -52,4 +52,5 @@ KEY(EMPTY_RECTANGLES, "Empty rectangles", K_T) KEY(HOTSPOTS, "Hotspots", K_H) KEY(RESIZE_SINGLE, "Resize", 0) KEY(TEXT, "Text", 0) +KEY(REFERENCES, "Find references..", K_ALT_U) KEY(SLICE, "Slice..", 0) \ No newline at end of file diff --git a/uppsrc/RichEdit/Cursor.cpp b/uppsrc/RichEdit/Cursor.cpp index cea3c4275..cb4c23ad2 100644 --- a/uppsrc/RichEdit/Cursor.cpp +++ b/uppsrc/RichEdit/Cursor.cpp @@ -443,17 +443,22 @@ void RichEdit::GotoEntry() GotoType(RichText::INDEXENTRIES, indexentry); } -bool RichEdit::GotoLabel(const String& lbl) +bool RichEdit::GotoLabel(Gate match) { Vector f = text.GetValPos(pagesz, RichText::LABELS); for(int i = 0; i < f.GetCount(); i++) - if(f[i].data == WString(lbl)) { + if(match(f[i].data)) { Move(f[i].pos); return true; } return false; } +bool RichEdit::GotoLabel(const String& lbl) +{ + return GotoLabel([=](const WString& data) { return data == WString(lbl); }); +} + void RichEdit::BeginPara() { RichPos pos = text.GetRichPos(anchor); diff --git a/uppsrc/RichEdit/RichEdit.h b/uppsrc/RichEdit/RichEdit.h index 502e4f66a..0ccc9627e 100644 --- a/uppsrc/RichEdit/RichEdit.h +++ b/uppsrc/RichEdit/RichEdit.h @@ -785,6 +785,7 @@ public: Value GetVar(const String& id) const { return vars.Get(id, Value()); } void EvaluateFields(); + bool GotoLabel(Gate match); bool GotoLabel(const String& lbl); void BeginPara(); void NextPara(); diff --git a/uppsrc/ide/About.cpp b/uppsrc/ide/About.cpp index 80d54d5a0..ac83f0552 100644 --- a/uppsrc/ide/About.cpp +++ b/uppsrc/ide/About.cpp @@ -74,11 +74,18 @@ Size SplashCtrl::MakeLogo(Ctrl& parent, Array& ctrl) Label& v1 = ctrl.Create