diff --git a/uppsrc/Common/Common.upp b/uppsrc/Common/Common.upp index 9a498b5a4..2c8a5544f 100644 --- a/uppsrc/Common/Common.upp +++ b/uppsrc/Common/Common.upp @@ -1,2 +1,3 @@ file TreeTypes.txt; + diff --git a/uppsrc/ide/Common/ComDlg.cpp b/uppsrc/ide/Common/ComDlg.cpp index 8cb35b464..0e5b0bfb5 100644 --- a/uppsrc/ide/Common/ComDlg.cpp +++ b/uppsrc/ide/Common/ComDlg.cpp @@ -1,5 +1,9 @@ #include "Common.h" +#define IMAGECLASS IdeCommonImg +#define IMAGEFILE +#include + void IdeFileIcon0(bool dir, const String& filename, Image& img, bool fast = false) { if(dir) return; diff --git a/uppsrc/ide/Common/Common.h b/uppsrc/ide/Common/Common.h index 706c3c2df..72d0e3858 100644 --- a/uppsrc/ide/Common/Common.h +++ b/uppsrc/ide/Common/Common.h @@ -1,119 +1,36 @@ -#ifndef COMMON_H -#define COMMON_H +#ifndef _ide_GuiCommon_GuiCommon_h_ +#define _ide_GuiCommon_GuiCommon_h_ +#include #include -#include -#include - -using namespace Upp; #define IMAGECLASS IdeCommonImg #define IMAGEFILE #include -int CharFilterCid(int c); +struct Debugger { + virtual void DebugBar(Bar& bar) = 0; + virtual bool SetBreakpoint(const String& filename, int line, const String& bp) = 0; + virtual bool RunTo() = 0; + virtual void Run() = 0; + virtual void Stop() = 0; + virtual bool IsFinished() = 0; -int ReadLNG(CParser& p); -String MakeLNG(int lang); - -bool OldLang(); - -String PrintTime(int msecs); -inline String GetPrintTime(dword time0) { return PrintTime(msecs(time0)); } - -bool SaveChangedFile(const char *path, String data, bool delete_empty = false); - -class Workspace; - -struct Ide; - -class IdeContext -{ -public: - virtual void PutConsole(const char *s) = 0; - virtual void PutVerbose(const char *s) = 0; - - virtual const Workspace& IdeWorkspace() const = 0; - virtual bool IdeIsBuilding() const = 0; - virtual String IdeGetOneFile() const = 0; - virtual int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false) = 0; - virtual int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) = 0; - virtual int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false) = 0; - virtual int IdeConsoleAllocSlot() = 0; - virtual bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; - virtual bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; - virtual void IdeConsoleFlush() = 0; - virtual void IdeConsoleBeginGroup(String group) = 0; - virtual void IdeConsoleEndGroup() = 0; - virtual bool IdeConsoleWait() = 0; - - virtual bool IdeIsDebug() const = 0; - virtual void IdeEndDebug() = 0; - virtual void IdeSetBottom(Ctrl& ctrl) = 0; - virtual void IdeActivateBottom() = 0; - virtual void IdeRemoveBottom(Ctrl& ctrl) = 0; - virtual void IdeSetRight(Ctrl& ctrl) = 0; - virtual void IdeRemoveRight(Ctrl& ctrl) = 0; - - virtual String IdeGetFileName() const = 0; - virtual int IdeGetFileLine() = 0; - virtual String IdeGetLine(int i) const = 0; - - virtual void IdeSetDebugPos(const String& fn, int line, const Image& img, int i) = 0; - virtual void IdeHidePtr() = 0; - virtual bool IdeDebugLock() = 0; - virtual bool IdeDebugUnLock() = 0; - virtual bool IdeIsDebugLock() const = 0; - virtual void IdeSetBar() = 0; - virtual void IdeGotoCodeRef(String link) = 0; - virtual void IdeOpenTopicFile(const String& file) = 0; - virtual void IdeFlushFile() = 0; - virtual String IdeGetFileName() = 0; - virtual String IdeGetNestFolder() = 0; - - virtual ~IdeContext() {} + virtual ~Debugger() {} }; -IdeContext *TheIde(); -void TheIde(IdeContext *context); +void SourceFs(FileSel& fsel); +FileSel& AnySourceFs(); +FileSel& AnyPackageFs(); +FileSel& BasedSourceFs(); +FileSel& OutputFs(); -void PutConsole(const char *s); -void PutVerbose(const char *s); +Image IdeFileImage(const String& filename, bool fast = false); -const Workspace& GetIdeWorkspace(); -bool IdeIsBuilding(); -String IdeGetOneFile(); -int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false); -int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet); -int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false); -int IdeConsoleAllocSlot(); -bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); -bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); -void IdeConsoleFlush(); -void IdeConsoleBeginGroup(String group); -void IdeConsoleEndGroup(); -bool IdeConsoleWait(); -void IdeGotoCodeRef(String s); - -bool IdeIsDebug(); -void IdeEndDebug(); -void IdeSetBottom(Ctrl& ctrl); -void IdeActivateBottom(); -void IdeRemoveBottom(Ctrl& ctrl); -void IdeSetRight(Ctrl& ctrl); -void IdeRemoveRight(Ctrl& ctrl); - -String IdeGetFileName(); -int IdeGetFileLine(); -String IdeGetLine(int i); - -void IdeSetDebugPos(const String& fn, int line, const Image& img, int i); -void IdeHidePtr(); -bool IdeDebugLock(); -bool IdeDebugUnLock(); -bool IdeIsDebugLock(); - -void IdeSetBar(); +bool FinishSave(String tmpfile, String outfile); +bool FinishSave(String outfile); +bool SaveFileFinish(const String& filename, const String& data); +bool SaveChangedFileFinish(const String& filename, const String& data); struct IdeDesigner { virtual String GetFileName() const = 0; @@ -143,312 +60,10 @@ void RegisterIdeModule(IdeModule& module); int GetIdeModuleCount(); IdeModule& GetIdeModule(int q); -struct IdeMacro { - IdeMacro(); - - int hotkey; - String menu; - String submenu; - EscValue code; -}; - -ArrayMap& UscGlobal(); -Array& UscMacros(); - -void CleanUsc(); -void ParseUscFile(const char *filename) throw(CParser::Error); - -Point ReadNums(CParser& p); -Point ReadPoint(CParser& p); - -struct SemiTextTest : public TextTest { - virtual const char *Accept(const char *s) const; -}; - -Vector SplitDirs(const char *s); - -String VarFilePath(); -String VarFilePath(String name); - -bool SaveVarFile(const char *filename, const VectorMap& var); -bool LoadVarFile(const char *name, VectorMap& var); -bool SaveVars(const char *name); -bool LoadVars(const char *name); -String GetVar(const String& var); -String GetVarsName(); -String VarFilePath(); -Vector GetUppDirs(); -String GetUppDir(); -void SetVar(const String& var, const String& value); - -String GetAnyFileName(const char *path); -String GetAnyFileTitle(const char *path); -String CatAnyPath(String path, const char *more); -String PackagePath(const String& name); -String SourcePath(const String& package, const String& name); -inline -String PackageDirectory(const String& name) { return GetFileDirectory(PackagePath(name)); } -bool IsNestReadOnly(const String& path); - -String GetLocalDir(); -String LocalPath(const String& filename); - -Vector IgnoreList(); - -bool IsFullDirectory(const String& d); -bool IsFolder(const String& path); - -bool IsCSourceFile(const char *path); -bool IsCHeaderFile(const char *path); - -String FollowCygwinSymlink(const String& filename); - -void SplitPathMap(const char *path_map, Vector& local, Vector& remote); -String JoinPathMap(const Vector& local, const Vector& remote); -void SplitHostName(const char *hostname, String& host, int& port); - -Vector SplitFlags0(const char *flags); -Vector SplitFlags(const char *flags, bool main = false); -Vector SplitFlags(const char *flags, bool main, const Vector& accepts); - -bool MatchWhen(const String& when, const Vector& flag); -String ReadWhen(CParser& p); -String AsStringWhen(const String& when); - -struct OptItem { - String when; - String text; -}; - -struct CustomStep { - String when; - String ext; - String command; - String output; - - void Load(CParser& p) throw(CParser::Error); - String AsString() const; - - String GetExt() const; - bool MatchExt(const char *fn) const; -}; - -Vector Combine(const Vector& conf, const char *flags); -String Gather(const Array& set, const Vector& conf, bool nospace = false); - -bool HasFlag(const Vector& conf, const char *flag); - -enum { - FLAG_MISMATCH = -2, - FLAG_UNDEFINED = -1, -}; - -int GetType(const Vector& conf, const char *flags); -int GetType(const Vector& conf, const char *flags, int def); -bool GetFlag(const Vector& conf, const char *flag); -String RemoveType(Vector& conf, const char *flags); - -class Package { -public: - struct File : public String { - Array option; - Array depends; - bool readonly; - bool separator; - int tabsize; - byte charset; - int font; - String highlight; - int optimize_speed; - - void operator=(const String& s) { String::operator=(s); readonly = separator = false; } - void Init() { readonly = separator = false; tabsize = Null; charset = 0; font = 0; - optimize_speed = false; } - - File() { Init(); } - File(const String& s) : String(s) { Init(); } - }; - struct Config { - String name; - String param; - }; - byte charset; - bool optimize_speed; - bool noblitz; - String description; - Vector accepts; - Array flag; - Array uses; - Array target; - Array library; - Array link; - Array option; - Array file; - Array config; - Array custom; - Time time; - - int GetCount() const { return file.GetCount(); } - File& operator[](int i) { return file[i]; } - const File& operator[](int i) const { return file[i]; } - - void Load(const char *file); - bool Save(const char *file) const; - - Package(); -}; - -class Workspace { - void AddUses(Package& p, bool match, const Vector& flag); - void AddLoad(const String& name, bool match, const Vector& flag); - -public: - ArrayMap package; - - void Clear() { package.Clear(); } - String operator[](int i) const { return package.GetKey(i); } - Package& GetPackage(int i) { return package[i]; } - const Package& GetPackage(int i) const { return package[i]; } - int GetCount() const { return package.GetCount(); } - - void Scan(const char *prjname); - void Scan(const char *prjname, const Vector& flag); - - Vector GetAllAccepts(int pk) const; - - void Dump(); -}; - -struct Ide; - -bool FinishSave(String tmpfile, String outfile); -bool FinishSave(String outfile); -bool SaveFileFinish(const String& filename, const String& data); -bool SaveChangedFileFinish(const String& filename, const String& data); - enum { DEBUG_NONE, DEBUG_MINIMAL, DEBUG_FULL }; -struct Host { - struct FileInfo : Time, Moveable { - int length; - }; - virtual String GetEnvironment() = 0; - virtual String GetHostPath(const String& path) = 0; - virtual String GetLocalPath(const String& path) = 0; - virtual String NormalizePath(const String& path) = 0; - virtual Vector GetFileInfo(const Vector& path) = 0; - virtual void DeleteFile(const Vector& path) = 0; - virtual void DeleteFolderDeep(const String& dir) = 0; - virtual void ChDir(const String& path) = 0; - virtual void RealizeDir(const String& path) = 0; - virtual void SaveFile(const String& path, const String& data) = 0; - virtual String LoadFile(const String& path) = 0; - virtual int Execute(const char *cmdline) = 0; - virtual int ExecuteWithInput(const char *cmdline) = 0; - virtual int Execute(const char *cmdline, Stream& out) = 0; - virtual int AllocSlot() = 0; - virtual bool Run(const char *cmdline, int slot, String key, int blitz_count) = 0; - virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) = 0; - virtual bool Wait() = 0; - virtual One StartProcess(const char *cmdline) = 0; - virtual void Launch(const char *cmdline, bool console = false) = 0; - virtual void AddFlags(Index& cfg) = 0; - - virtual ~Host() {} -}; - -String FindInDirs(const Vector& dir, const String& file); -String FindCommand(const Vector& exedir, const String& cmdline); - -struct MakeFile { - String outdir; - String outfile; - String output; - String config; - String install; - String rules; - String linkdep; - String linkfiles; - String linkfileend; -}; - -String GetMakePath(String fn, bool win32); -String AdjustMakePath(const char *fn); - -enum { - R_OPTIMAL, - R_SPEED, - R_SIZE -}; - -struct Builder { - Host *host; - Index config; - String compiler; - String method; - String outdir; - Vector include; - Vector libpath; - String target; - String debug_options; - String release_options; - String release_size_options; - String version; - String script; - bool doall; - - virtual bool BuildPackage(const String& package, Vector& linkfile, String& linkoptions, - const Vector& all_uses, const Vector& all_libraries, int optimize) - { return false; } - virtual bool Link(const Vector& linkfile, const String& linkoptions, bool createmap) - { return false; } - virtual bool Preprocess(const String& package, const String& file, const String& result, bool asmout) - { return false; } - virtual void AddFlags(Index& cfg) {} - virtual void AddMakeFile(MakeFile& mfinfo, String package, - const Vector& all_uses, const Vector& all_libraries, - const Index& common_config, bool exporting) {} - virtual String GetTargetExt() const = 0; - - Builder() { doall = false; } - virtual ~Builder() {} -}; - -VectorMap& BuilderMap(); -void RegisterBuilder(const char *name, Builder *(*create)()); - -struct Debugger { - virtual void DebugBar(Bar& bar) = 0; - virtual bool SetBreakpoint(const String& filename, int line, const String& bp) = 0; - virtual bool RunTo() = 0; - virtual void Run() = 0; - virtual void Stop() = 0; - virtual bool IsFinished() = 0; - - virtual ~Debugger() {} -}; - -void HdependSetDirs(pick_ Vector& id); -void HdependTimeDirty(); -void HdependClearDependencies(); -void HdependAddDependency(const String& file, const String& depends); -Time HdependFileTime(const String& path); -Vector HdependGetDependencies(const String& path); -String FindIncludeFile(const char *s, const String& filedir); -bool HdependBlitzApproved(const String& path); -const Vector& HdependGetDefines(const String& path); -const Vector& HdependGetAllFiles(); - -void SourceFs(FileSel& fsel); -FileSel& AnySourceFs(); -FileSel& AnyPackageFs(); -FileSel& BasedSourceFs(); -FileSel& OutputFs(); - -Image IdeFileImage(const String& filename, bool fast = false); - void RegisterWorkspaceConfig(const char *name); void RegisterNWorkspaceConfig(const char *name, Callback WhenFlush); String& WorkspaceConfigData(const char *name); diff --git a/uppsrc/ide/Common/Common.upp b/uppsrc/ide/Common/Common.upp index 86c9d49b4..eda388175 100644 --- a/uppsrc/ide/Common/Common.upp +++ b/uppsrc/ide/Common/Common.upp @@ -1,18 +1,10 @@ -description "TheIDE - common library"; - uses - CtrlLib, - Esc; + ide\Core; file Common.h, - Common.cpp, - Hdepend.cpp optimize_speed, - Package.cpp, - Workspace.cpp, - usc.cpp, ComDlg.cpp, - common.iml, - Info readonly separator, - Copying; + Module.cpp, + Util.cpp, + common.iml; diff --git a/uppsrc/ide/Common/Module.cpp b/uppsrc/ide/Common/Module.cpp new file mode 100644 index 000000000..b654bdf00 --- /dev/null +++ b/uppsrc/ide/Common/Module.cpp @@ -0,0 +1,22 @@ +#include "Common.h" + +static Vector& sM() +{ + static Vector m; + return m; +} + +void RegisterIdeModule(IdeModule& module) +{ + sM().Add(&module); +} + +int GetIdeModuleCount() +{ + return sM().GetCount(); +} + +IdeModule& GetIdeModule(int q) +{ + return *sM()[q]; +} diff --git a/uppsrc/ide/Common/Util.cpp b/uppsrc/ide/Common/Util.cpp new file mode 100644 index 000000000..e59537902 --- /dev/null +++ b/uppsrc/ide/Common/Util.cpp @@ -0,0 +1,190 @@ +#include "Common.h" + +bool FinishSave(String tmpfile, String outfile) +{ + Progress progress; + int time = GetTickCount(); + for(;;) { + progress.SetTotal(10000); + progress.SetText("Saving '" + GetFileName(outfile) + "'"); + if(!FileExists(tmpfile)) + return false; + FileDelete(outfile); + if(FileMove(tmpfile, outfile)) + return true; + IdeConsoleFlush(); + Sleep(200); + if(progress.SetPosCanceled((GetTickCount() - time) % progress.GetTotal())) { + int art = Prompt(Ctrl::GetAppName(), CtrlImg::exclamation(), + "Unable to save current file.&" + "Retry save, ignore it or save file to another location?", + "Save as...", "Retry", "Ignore"); + if(art < 0) + return false; + if(art && AnySourceFs().ExecuteSaveAs()) + outfile = AnySourceFs(); + progress.SetPos(0); + } + } +} + +bool FinishSave(String outfile) +{ + return FinishSave(outfile + ".$tmp", outfile); +} + +bool SaveFileFinish(const String& filename, const String& data) +{ + if(!SaveFile(filename + ".$tmp", data)) { + Exclamation("Error creating temporary file " + filename); + return false; + } + return FinishSave(filename); +} + +bool SaveChangedFileFinish(const String& filename, const String& data) +{ + if(data == LoadFile(filename)) + return true; + return SaveFileFinish(filename, data); +} + +typedef VectorMap StringMap; + +GLOBAL_VAR(StringMap, sWorkspaceCfg) +GLOBAL_VAR(Vector, sWorkspaceCfgFlush) + +void RegisterWorkspaceConfig(const char *name) +{ + ASSERT(sWorkspaceCfg().Find(name) < 0); + sWorkspaceCfg().Add(name); +} + +void RegisterWorkspaceConfig(const char *name, Callback WhenFlush) +{ + RegisterWorkspaceConfig(name); + sWorkspaceCfgFlush().Add(WhenFlush); +} + + +String& WorkspaceConfigData(const char *name) +{ + return sWorkspaceCfg().GetAdd(name); +} + +void SerializeWorkspaceConfigs(Stream& s) +{ + int i; + for(i = 0; i < sWorkspaceCfgFlush().GetCount(); i++) + sWorkspaceCfgFlush()[i](); + VectorMap& cfg = sWorkspaceCfg(); + int version = 0; + s / version; + int count = cfg.GetCount(); + s / count; + for(i = 0; i < count; i++) { + String name; + if(s.IsStoring()) + name = cfg.GetKey(i); + s % name; + int q = cfg.Find(name); + if(q >= 0) + s % cfg[q]; + else + { + String dummy; + s % dummy; + } + } + s.Magic(); +} + +bool GuiPackageResolver(const String& error, const String& path, int line) +{ +prompt: + switch(Prompt(Ctrl::GetAppName(), CtrlImg::exclamation(), + error + "&while parsing package " + DeQtf(path), + "Edit \\& Retry", "Ignore", "Stop")) { + case 0: + if(!PromptYesNo("Ignoring will damage package. Everything past the " + "point of error will be lost.&Do you want to continue ?")) + goto prompt; + return false; + case 1: { + TopWindow win; + LineEdit edit; + edit.Set(LoadFile(path)); + edit.SetCursor(edit.GetPos(line)); + win.Title(path); + win.Add(edit.SizePos()); + win.Run(); + SaveFile(path, edit.Get()); + } + return true;; + case -1: + exit(1); + } + return false; +} + +void CleanModules() +{ + for(int i = 0; i < GetIdeModuleCount(); i++) + GetIdeModule(i).CleanUsc(); +} + +bool IdeModuleUsc(CParser& p) +{ + for(int i = 0; i < GetIdeModuleCount(); i++) + if(GetIdeModule(i).ParseUsc(p)) + return true; + return false; +} + +static void ReadMacro(CParser& p) +{ + IdeMacro macro; + if(p.IsString()) { + macro.menu = p.ReadString(); + if(p.Char(':')) + macro.submenu = p.ReadString(); + } + if(!p.IsChar('{')) + macro.hotkey = ParseKeyDesc(p); + EscLambda& l = macro.code.CreateLambda(); + const char *t = p.GetPtr(); + l.filename = p.GetFileName(); + l.line = p.GetLine(); + if(!p.Char('{')) + p.ThrowError("missing '{'"); + SkipBlock(p); + l.code = String(t, p.GetPtr()); + Array& mlist = UscMacros(); + if(macro.hotkey) { + int f = FindFieldIndex(mlist, &IdeMacro::hotkey, macro.hotkey); + if(f >= 0) { + PutConsole(NFormat("%s(%d): duplicate macro hotkey %s\n", l.filename, l.line, GetKeyDesc(macro.hotkey))); + const EscLambda& lambda = UscMacros()[f].code.GetLambda(); + PutConsole(NFormat("%s(%d): previously defined here\n", lambda.filename, lambda.line)); + } + } + if(!IsNull(macro.menu)) { + for(int i = 0; i < mlist.GetCount(); i++) + if(mlist[i].menu == macro.menu && mlist[i].submenu == macro.submenu) { + PutConsole(NFormat("%s(%d): duplicate macro menu item (%s:%s)\n", + l.filename, l.line, macro.menu, macro.submenu)); + const EscLambda& lambda = UscMacros()[i].code.GetLambda(); + PutConsole(NFormat("%s(%d): previously defined here\n", lambda.filename, lambda.line)); + break; + } + } + mlist.Add(macro); +} + +INITBLOCK { + Package::SetPackageResolver(GuiPackageResolver); + UscSetCleanModules(CleanModules); + SetIdeModuleUsc(IdeModuleUsc); + UscSetReadMacro(ReadMacro); +} + diff --git a/uppsrc/ide/Common/init b/uppsrc/ide/Common/init index 64ab525dc..3b668aa69 100644 --- a/uppsrc/ide/Common/init +++ b/uppsrc/ide/Common/init @@ -1,5 +1,4 @@ #ifndef _ide_Common_icpp_init_stub #define _ide_Common_icpp_init_stub -#include "CtrlLib/init" -#include "Esc/init" +#include "ide\Core/init" #endif diff --git a/uppsrc/ide/Common/usc.cpp b/uppsrc/ide/Common/usc.cpp deleted file mode 100644 index be64cd540..000000000 --- a/uppsrc/ide/Common/usc.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "Common.h" - -ArrayMap& UscGlobal() -{ - static ArrayMap global; - return global; -} - -IdeMacro::IdeMacro() -{ - hotkey = 0; -} - -GLOBAL_VAR(Array, UscMacros) - -void ESC_cout(EscEscape& e) -{ - if(e[0].IsArray()) - PutConsole((String) e[0]); - else - if(e[0].IsNumber()) { - String str; - str << e[0].GetNumber(); - PutConsole(str); - } - else - if(!e[0].IsVoid()) - e.ThrowError("invalid argument to 'cout'" + e.DumpType(0)); -} - -void ESC_dump(EscEscape& e) -{ - PutConsole(e[0].ToString()); -} - -void CleanUsc() -{ - UscGlobal().Clear(); - UscMacros().Clear(); - for(int i = 0; i < GetIdeModuleCount(); i++) - GetIdeModule(i).CleanUsc(); - StdLib(UscGlobal()); - Escape(UscGlobal(), "cout(x)", ESC_cout); - Escape(UscGlobal(), "dump(x)", ESC_dump); -} - -bool IdeModuleUsc(CParser& p) -{ - for(int i = 0; i < GetIdeModuleCount(); i++) - if(GetIdeModule(i).ParseUsc(p)) - return true; - return false; -} - -static void ReadMacro(CParser& p) -{ - IdeMacro macro; - if(p.IsString()) { - macro.menu = p.ReadString(); - if(p.Char(':')) - macro.submenu = p.ReadString(); - } - if(!p.IsChar('{')) - macro.hotkey = ParseKeyDesc(p); - EscLambda& l = macro.code.CreateLambda(); - const char *t = p.GetPtr(); - l.filename = p.GetFileName(); - l.line = p.GetLine(); - if(!p.Char('{')) - p.ThrowError("missing '{'"); - SkipBlock(p); - l.code = String(t, p.GetPtr()); - Array& mlist = UscMacros(); - if(macro.hotkey) { - int f = FindFieldIndex(mlist, &IdeMacro::hotkey, macro.hotkey); - if(f >= 0) { - PutConsole(NFormat("%s(%d): duplicate macro hotkey %s\n", l.filename, l.line, GetKeyDesc(macro.hotkey))); - const EscLambda& lambda = UscMacros()[f].code.GetLambda(); - PutConsole(NFormat("%s(%d): previously defined here\n", lambda.filename, lambda.line)); - } - } - if(!IsNull(macro.menu)) { - for(int i = 0; i < mlist.GetCount(); i++) - if(mlist[i].menu == macro.menu && mlist[i].submenu == macro.submenu) { - PutConsole(NFormat("%s(%d): duplicate macro menu item (%s:%s)\n", - l.filename, l.line, macro.menu, macro.submenu)); - const EscLambda& lambda = UscMacros()[i].code.GetLambda(); - PutConsole(NFormat("%s(%d): previously defined here\n", lambda.filename, lambda.line)); - break; - } - } - mlist.Add(macro); -} - -void ParseUscFile(const char *filename) throw(CParser::Error) -{ - String d = LoadFile(filename); - CParser p(d, filename); - while(!p.IsEof()) { - if(p.Id("fn")) { - EscValue& v = UscGlobal().GetPut(p.ReadId()); - v = ReadLambda(p); - } - else - if(p.Id("macro")) - ReadMacro(p); - else - if(!IdeModuleUsc(p)) { - EscValue& v = UscGlobal().GetPut(p.ReadId()); - v = ReadLambda(p); - } - } -} diff --git a/uppsrc/ide/Common/Copying b/uppsrc/ide/Core/Copying similarity index 100% rename from uppsrc/ide/Common/Copying rename to uppsrc/ide/Core/Copying diff --git a/uppsrc/ide/Common/Common.cpp b/uppsrc/ide/Core/Core.cpp similarity index 72% rename from uppsrc/ide/Common/Common.cpp rename to uppsrc/ide/Core/Core.cpp index 2161c1e2d..332e78915 100644 --- a/uppsrc/ide/Common/Common.cpp +++ b/uppsrc/ide/Core/Core.cpp @@ -1,482 +1,358 @@ -#include "Common.h" - -#define IMAGECLASS IdeCommonImg -#define IMAGEFILE -#include - -typedef VectorMap BuilderMapType; -GLOBAL_VAR(BuilderMapType, BuilderMap) - -void RegisterBuilder(const char *name, Builder *(*create)()) -{ - ASSERT(BuilderMap().Find(name) < 0); - BuilderMap().Add(name, create); -} - -String FindInDirs(const Vector& dir, const String& file) -{ - if(!IsFullPath(file)) - for(int i = 0; i < dir.GetCount(); i++) { - String ef = CatAnyPath(dir[i], file); - if(FileExists(ef)) - return ef; - } - return file; -} - -String FindCommand(const Vector& exedir, const String& cmdline) -{ - String app; - const char *s = cmdline; - while(*s && (byte)*s <= ' ') - s++; - if(*s == '\"') - { - const char *b = ++s; - while(*s && *s != '\"') - s++; - app = String(b, s); - if(*s) - s++; - } - else - { - const char *b = s; - while(*s && (byte)*s > ' ') - s++; - app = String(b, s); - } - String tail = s; - String fn = FindInDirs(exedir, app); - if(!FileExists(fn)) -#ifdef PLATFORM_WIN32 - fn = FindInDirs(exedir, ForceExt(app, ".exe")); -#endif -#ifdef PLATFORM_POSIX - fn = FindInDirs(exedir, app); -#endif - if(fn.Find(' ') >= 0) - fn = '\"' + fn + '\"'; - return fn + tail; -} - -String GetMakePath(String fn, bool win32) -{ - fn = UnixPath(fn); - if(!win32) - return fn; - String out; - for(const char *p = fn; *p; p++) - if(*p == '/') - out << "\\\\"; - else - out.Cat(*p); - return out; -} - -String AdjustMakePath(const char *fn) -{ - String out; - for(; *fn; fn++) - if(*fn == '$') - out << '$' << '$'; - else - out << *fn; - return out; -} - -static IdeContext *the_ide; - -IdeContext *TheIde() { return the_ide; } -void TheIde(IdeContext *context) { the_ide = context; } - -void PutConsole(const char *s) { if(the_ide) the_ide->PutConsole(s); } -void PutVerbose(const char *s) { if(the_ide) the_ide->PutVerbose(s); } - -const Workspace& GetIdeWorkspace() -{ - if(the_ide) - return the_ide->IdeWorkspace(); - static Workspace x; - return x; -} - -bool IdeIsBuilding() -{ - return the_ide && the_ide->IdeIsBuilding(); -} - -void IdeSetBar() -{ - if(the_ide) - the_ide->IdeSetBar(); -} - -String IdeGetOneFile() -{ - return the_ide ? the_ide->IdeGetOneFile() : String(Null); -} - -int IdeConsoleExecute(const char *cmdline, Stream *out, const char *envptr, bool quiet) -{ - return the_ide ? the_ide->IdeConsoleExecute(cmdline, out, envptr, quiet) : -1; -} - -int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) -{ - return the_ide ? the_ide->IdeConsoleExecuteWithInput(cmdline, out, envptr, quiet) : -1; -} - -int IdeConsoleExecute(One process, const char *cmdline, Stream *out, bool quiet) -{ - return the_ide ? the_ide->IdeConsoleExecute(process, cmdline, out, quiet) : -1; -} - -int IdeConsoleAllocSlot() -{ - return the_ide ? the_ide->IdeConsoleAllocSlot() : 0; -} - -bool IdeConsoleRun(const char *cmdline, Stream *out, const char *envptr, bool quiet, int slot, String key, int blitz_count) -{ - return the_ide && the_ide->IdeConsoleRun(cmdline, out, envptr, quiet, slot, key, blitz_count); -} - -bool IdeConsoleRun(One process, const char *cmdline, Stream *out, bool quiet, int slot, String key, int blitz_count) -{ - return the_ide && the_ide->IdeConsoleRun(process, cmdline, out, quiet, slot, key, blitz_count); -} - -void IdeConsoleFlush() -{ - if(the_ide) the_ide->IdeConsoleFlush(); -} - -void IdeConsoleBeginGroup(String group) -{ - if(the_ide) the_ide->IdeConsoleBeginGroup(group); -} - -void IdeConsoleEndGroup() -{ - if(the_ide) the_ide->IdeConsoleEndGroup(); -} - -bool IdeConsoleWait() -{ - return the_ide && the_ide->IdeConsoleWait(); -} - -void IdeGotoCodeRef(String s) -{ - if(the_ide) the_ide->IdeGotoCodeRef(s); -} - -void IdeSetBottom(Ctrl& ctrl) -{ - if(the_ide) the_ide->IdeSetBottom(ctrl); -} - -void IdeActivateBottom() { - if(the_ide) the_ide->IdeActivateBottom(); -} - - -void IdeRemoveBottom(Ctrl& ctrl) -{ - if(the_ide) the_ide->IdeRemoveBottom(ctrl); -} - -void IdeSetRight(Ctrl& ctrl) -{ - if(the_ide) the_ide->IdeSetRight(ctrl); -} - -void IdeRemoveRight(Ctrl& ctrl) -{ - if(the_ide) the_ide->IdeRemoveRight(ctrl); -} - -bool IdeIsDebug() -{ - return the_ide && the_ide->IdeIsDebug(); -} - -void IdeEndDebug() -{ - if(the_ide) - the_ide->IdeEndDebug(); -} - -void IdeSetDebugPos(const String& file, int line, const Image& img, int i) -{ - if(the_ide) - the_ide->IdeSetDebugPos(file, line, img, i); -} - -void IdeHidePtr() -{ - if(the_ide) - the_ide->IdeHidePtr(); -} - -bool IdeDebugLock() -{ - return the_ide && the_ide->IdeDebugLock(); -} - -bool IdeDebugUnLock() -{ - return the_ide && the_ide->IdeDebugUnLock(); -} - -bool IdeIsDebugLock() -{ - return the_ide && the_ide->IdeIsDebugLock(); -} - -String IdeGetFileName() -{ - return the_ide ? the_ide->IdeGetFileName() : String(Null); -} - -int IdeGetFileLine() -{ - return the_ide ? the_ide->IdeGetFileLine() : 0; -} - -String IdeGetLine(int i) -{ - return the_ide ? the_ide->IdeGetLine(i) : String(Null); -} - -bool SaveChangedFile(const char *path, String data, bool delete_empty) -{ - if(LoadFile(path) == data) - return true; - if(delete_empty && IsNull(data)) - return FileDelete(path); - else - return SaveFile(path, data); -} - -static int sReadCharc(CParser& p) -{ - p.PassChar('\''); - if(!IsAlpha(p.PeekChar())) - p.ThrowError("language code alphabetic character expected"); - char c = p.GetChar(); - p.PassChar('\''); - return c; -} - -static void sReadLNG(CParser& p, char *c) -{ - p.PassChar('('); - c[0] = sReadCharc(p); - p.PassChar(','); - c[1] = sReadCharc(p); - p.PassChar(','); - c[2] = sReadCharc(p); - p.PassChar(','); - c[3] = sReadCharc(p); -} - -int ReadLNG(CParser& p) { - char c[4]; - if(p.Id("LNG_CZECH")) - return LNG_CZECH; - else - if(p.Id("LNG_ENGLISH")) - return LNG_ENGLISH; - else - if(p.Id("LNG_")) { - sReadLNG(p, c); - p.PassChar(')'); - return LNG_(c[0], c[1], c[2], c[3]); - } - else - if(p.Id("LNGC_")) { - sReadLNG(p, c); - p.PassChar(','); - dword l = LNGC_(c[0], c[1], c[2], c[3], p.ReadInt()); - p.PassChar(')'); - return l; - } - else - p.ThrowError("invalid language code"); - return 0; -} - -String MakeLNG(int lang) -{ - int cs = GetLNGCharset(lang); - String str; - if(cs) - return str << "LNGC_('" - << char(((lang >> 15) & 31) + 'A' - 1) << "', '" - << char(((lang >> 10) & 31) + 'A' - 1) << "', '" - << char(((lang >> 5) & 31) + 'A' - 1) << "', '" - << char((lang & 31) + 'A' - 1) << "', " << cs << ")"; - else - return str << "LNG_('" - << char(((lang >> 15) & 31) + 'A' - 1) << "', '" - << char(((lang >> 10) & 31) + 'A' - 1) << "', '" - << char(((lang >> 5) & 31)+ 'A' - 1) << "', '" - << char((lang & 31) + 'A' - 1) << "')"; -} - -String PrintTime(int time) { - int q = time % 1000 / 10; - time /= 1000; - return Format("(%d:%02d.%02d)", time / 60, time % 60, q); -} - -Point ReadNums(CParser& p) { - Point pt; - pt.x = p.ReadInt(); - p.PassChar(','); - pt.y = p.ReadInt(); - return pt; -} - -Point ReadPoint(CParser& p) -{ - Point pt; - p.PassChar('('); - pt = ReadNums(p); - p.PassChar(')'); - return pt; -} - -static Vector& sM() -{ - static Vector m; - return m; -} - -void RegisterIdeModule(IdeModule& module) -{ - sM().Add(&module); -} - -int GetIdeModuleCount() -{ - return sM().GetCount(); -} - -IdeModule& GetIdeModule(int q) -{ - return *sM()[q]; -} - -bool FinishSave(String tmpfile, String outfile) -{ - Progress progress; - int time = GetTickCount(); - for(;;) { - progress.SetTotal(10000); - progress.SetText("Saving '" + GetFileName(outfile) + "'"); - if(!FileExists(tmpfile)) - return false; - FileDelete(outfile); - if(FileMove(tmpfile, outfile)) - return true; - IdeConsoleFlush(); - Sleep(200); - if(progress.SetPosCanceled((GetTickCount() - time) % progress.GetTotal())) { - int art = Prompt(Ctrl::GetAppName(), CtrlImg::exclamation(), - "Unable to save current file.&" - "Retry save, ignore it or save file to another location?", - "Save as...", "Retry", "Ignore"); - if(art < 0) - return false; - if(art && AnySourceFs().ExecuteSaveAs()) - outfile = AnySourceFs(); - progress.SetPos(0); - } - } -} - -bool FinishSave(String outfile) -{ - return FinishSave(outfile + ".$tmp", outfile); -} - -bool SaveFileFinish(const String& filename, const String& data) -{ - if(!SaveFile(filename + ".$tmp", data)) { - Exclamation("Error creating temporary file " + filename); - return false; - } - return FinishSave(filename); -} - -bool SaveChangedFileFinish(const String& filename, const String& data) -{ - if(data == LoadFile(filename)) - return true; - return SaveFileFinish(filename, data); -} - -typedef VectorMap StringMap; - -GLOBAL_VAR(StringMap, sWorkspaceCfg) -GLOBAL_VAR(Vector, sWorkspaceCfgFlush) - -void RegisterWorkspaceConfig(const char *name) -{ - ASSERT(sWorkspaceCfg().Find(name) < 0); - sWorkspaceCfg().Add(name); -} - -void RegisterWorkspaceConfig(const char *name, Callback WhenFlush) -{ - RegisterWorkspaceConfig(name); - sWorkspaceCfgFlush().Add(WhenFlush); -} - - -String& WorkspaceConfigData(const char *name) -{ - return sWorkspaceCfg().GetAdd(name); -} - -void SerializeWorkspaceConfigs(Stream& s) -{ - int i; - for(i = 0; i < sWorkspaceCfgFlush().GetCount(); i++) - sWorkspaceCfgFlush()[i](); - VectorMap& cfg = sWorkspaceCfg(); - int version = 0; - s / version; - int count = cfg.GetCount(); - s / count; - for(i = 0; i < count; i++) { - String name; - if(s.IsStoring()) - name = cfg.GetKey(i); - s % name; - int q = cfg.Find(name); - if(q >= 0) - s % cfg[q]; - else - { - String dummy; - s % dummy; - } - } - s.Magic(); -} - -bool OldLang() { - static int q = -1; - if(q < 0) - q = FileExists(ConfigFile("oldlang")); - return q; -} - -int CharFilterCid(int c) -{ - return IsAlNum(c) || c == '_' ? c : 0; -} +#include "Core.h" + +typedef VectorMap BuilderMapType; +GLOBAL_VAR(BuilderMapType, BuilderMap) + +void RegisterBuilder(const char *name, Builder *(*create)()) +{ + ASSERT(BuilderMap().Find(name) < 0); + BuilderMap().Add(name, create); +} + +String FindInDirs(const Vector& dir, const String& file) +{ + if(!IsFullPath(file)) + for(int i = 0; i < dir.GetCount(); i++) { + String ef = CatAnyPath(dir[i], file); + if(FileExists(ef)) + return ef; + } + return file; +} + +String FindCommand(const Vector& exedir, const String& cmdline) +{ + String app; + const char *s = cmdline; + while(*s && (byte)*s <= ' ') + s++; + if(*s == '\"') + { + const char *b = ++s; + while(*s && *s != '\"') + s++; + app = String(b, s); + if(*s) + s++; + } + else + { + const char *b = s; + while(*s && (byte)*s > ' ') + s++; + app = String(b, s); + } + String tail = s; + String fn = FindInDirs(exedir, app); + if(!FileExists(fn)) +#ifdef PLATFORM_WIN32 + fn = FindInDirs(exedir, ForceExt(app, ".exe")); +#endif +#ifdef PLATFORM_POSIX + fn = FindInDirs(exedir, app); +#endif + if(fn.Find(' ') >= 0) + fn = '\"' + fn + '\"'; + return fn + tail; +} + +String GetMakePath(String fn, bool win32) +{ + fn = UnixPath(fn); + if(!win32) + return fn; + String out; + for(const char *p = fn; *p; p++) + if(*p == '/') + out << "\\\\"; + else + out.Cat(*p); + return out; +} + +String AdjustMakePath(const char *fn) +{ + String out; + for(; *fn; fn++) + if(*fn == '$') + out << '$' << '$'; + else + out << *fn; + return out; +} + +static IdeContext *the_ide; + +IdeContext *TheIde() { return the_ide; } +void TheIde(IdeContext *context) { the_ide = context; } + +void PutConsole(const char *s) { if(the_ide) the_ide->PutConsole(s); } +void PutVerbose(const char *s) { if(the_ide) the_ide->PutVerbose(s); } + +const Workspace& GetIdeWorkspace() +{ + if(the_ide) + return the_ide->IdeWorkspace(); + static Workspace x; + return x; +} + +bool IdeIsBuilding() +{ + return the_ide && the_ide->IdeIsBuilding(); +} + +void IdeSetBar() +{ + if(the_ide) + the_ide->IdeSetBar(); +} + +String IdeGetOneFile() +{ + return the_ide ? the_ide->IdeGetOneFile() : String(Null); +} + +int IdeConsoleExecute(const char *cmdline, Stream *out, const char *envptr, bool quiet) +{ + return the_ide ? the_ide->IdeConsoleExecute(cmdline, out, envptr, quiet) : -1; +} + +int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) +{ + return the_ide ? the_ide->IdeConsoleExecuteWithInput(cmdline, out, envptr, quiet) : -1; +} + +int IdeConsoleExecute(One process, const char *cmdline, Stream *out, bool quiet) +{ + return the_ide ? the_ide->IdeConsoleExecute(process, cmdline, out, quiet) : -1; +} + +int IdeConsoleAllocSlot() +{ + return the_ide ? the_ide->IdeConsoleAllocSlot() : 0; +} + +bool IdeConsoleRun(const char *cmdline, Stream *out, const char *envptr, bool quiet, int slot, String key, int blitz_count) +{ + return the_ide && the_ide->IdeConsoleRun(cmdline, out, envptr, quiet, slot, key, blitz_count); +} + +bool IdeConsoleRun(One process, const char *cmdline, Stream *out, bool quiet, int slot, String key, int blitz_count) +{ + return the_ide && the_ide->IdeConsoleRun(process, cmdline, out, quiet, slot, key, blitz_count); +} + +void IdeConsoleFlush() +{ + if(the_ide) the_ide->IdeConsoleFlush(); +} + +void IdeConsoleBeginGroup(String group) +{ + if(the_ide) the_ide->IdeConsoleBeginGroup(group); +} + +void IdeConsoleEndGroup() +{ + if(the_ide) the_ide->IdeConsoleEndGroup(); +} + +bool IdeConsoleWait() +{ + return the_ide && the_ide->IdeConsoleWait(); +} + +void IdeGotoCodeRef(String s) +{ + if(the_ide) the_ide->IdeGotoCodeRef(s); +} + +void IdeSetBottom(Ctrl& ctrl) +{ + if(the_ide) the_ide->IdeSetBottom(ctrl); +} + +void IdeActivateBottom() { + if(the_ide) the_ide->IdeActivateBottom(); +} + + +void IdeRemoveBottom(Ctrl& ctrl) +{ + if(the_ide) the_ide->IdeRemoveBottom(ctrl); +} + +void IdeSetRight(Ctrl& ctrl) +{ + if(the_ide) the_ide->IdeSetRight(ctrl); +} + +void IdeRemoveRight(Ctrl& ctrl) +{ + if(the_ide) the_ide->IdeRemoveRight(ctrl); +} + +bool IdeIsDebug() +{ + return the_ide && the_ide->IdeIsDebug(); +} + +void IdeEndDebug() +{ + if(the_ide) + the_ide->IdeEndDebug(); +} + +void IdeSetDebugPos(const String& file, int line, const Image& img, int i) +{ + if(the_ide) + the_ide->IdeSetDebugPos(file, line, img, i); +} + +void IdeHidePtr() +{ + if(the_ide) + the_ide->IdeHidePtr(); +} + +bool IdeDebugLock() +{ + return the_ide && the_ide->IdeDebugLock(); +} + +bool IdeDebugUnLock() +{ + return the_ide && the_ide->IdeDebugUnLock(); +} + +bool IdeIsDebugLock() +{ + return the_ide && the_ide->IdeIsDebugLock(); +} + +String IdeGetFileName() +{ + return the_ide ? the_ide->IdeGetFileName() : String(Null); +} + +int IdeGetFileLine() +{ + return the_ide ? the_ide->IdeGetFileLine() : 0; +} + +String IdeGetLine(int i) +{ + return the_ide ? the_ide->IdeGetLine(i) : String(Null); +} + +bool SaveChangedFile(const char *path, String data, bool delete_empty) +{ + if(LoadFile(path) == data) + return true; + if(delete_empty && IsNull(data)) + return FileDelete(path); + else + return SaveFile(path, data); +} + +static int sReadCharc(CParser& p) +{ + p.PassChar('\''); + if(!IsAlpha(p.PeekChar())) + p.ThrowError("language code alphabetic character expected"); + char c = p.GetChar(); + p.PassChar('\''); + return c; +} + +static void sReadLNG(CParser& p, char *c) +{ + p.PassChar('('); + c[0] = sReadCharc(p); + p.PassChar(','); + c[1] = sReadCharc(p); + p.PassChar(','); + c[2] = sReadCharc(p); + p.PassChar(','); + c[3] = sReadCharc(p); +} + +int ReadLNG(CParser& p) { + char c[4]; + if(p.Id("LNG_CZECH")) + return LNG_CZECH; + else + if(p.Id("LNG_ENGLISH")) + return LNG_ENGLISH; + else + if(p.Id("LNG_")) { + sReadLNG(p, c); + p.PassChar(')'); + return LNG_(c[0], c[1], c[2], c[3]); + } + else + if(p.Id("LNGC_")) { + sReadLNG(p, c); + p.PassChar(','); + dword l = LNGC_(c[0], c[1], c[2], c[3], p.ReadInt()); + p.PassChar(')'); + return l; + } + else + p.ThrowError("invalid language code"); + return 0; +} + +String MakeLNG(int lang) +{ + int cs = GetLNGCharset(lang); + String str; + if(cs) + return str << "LNGC_('" + << char(((lang >> 15) & 31) + 'A' - 1) << "', '" + << char(((lang >> 10) & 31) + 'A' - 1) << "', '" + << char(((lang >> 5) & 31) + 'A' - 1) << "', '" + << char((lang & 31) + 'A' - 1) << "', " << cs << ")"; + else + return str << "LNG_('" + << char(((lang >> 15) & 31) + 'A' - 1) << "', '" + << char(((lang >> 10) & 31) + 'A' - 1) << "', '" + << char(((lang >> 5) & 31)+ 'A' - 1) << "', '" + << char((lang & 31) + 'A' - 1) << "')"; +} + +String PrintTime(int time) { + int q = time % 1000 / 10; + time /= 1000; + return Format("(%d:%02d.%02d)", time / 60, time % 60, q); +} + +Point ReadNums(CParser& p) { + Point pt; + pt.x = p.ReadInt(); + p.PassChar(','); + pt.y = p.ReadInt(); + return pt; +} + +Point ReadPoint(CParser& p) +{ + Point pt; + p.PassChar('('); + pt = ReadNums(p); + p.PassChar(')'); + return pt; +} + +bool OldLang() { + static int q = -1; + if(q < 0) + q = FileExists(ConfigFile("oldlang")); + return q; +} + +int CharFilterCid(int c) +{ + return IsAlNum(c) || c == '_' ? c : 0; +} diff --git a/uppsrc/ide/Core/Core.h b/uppsrc/ide/Core/Core.h new file mode 100644 index 000000000..783e6b1b4 --- /dev/null +++ b/uppsrc/ide/Core/Core.h @@ -0,0 +1,375 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include + +using namespace Upp; + +int CharFilterCid(int c); + +int ReadLNG(CParser& p); +String MakeLNG(int lang); + +bool OldLang(); + +String PrintTime(int msecs); +inline String GetPrintTime(dword time0) { return PrintTime(msecs(time0)); } + +bool SaveChangedFile(const char *path, String data, bool delete_empty = false); + +class Workspace; + +struct Ide; + +namespace Upp { +class Ctrl; +class Image; +}; + +class IdeContext +{ +public: + virtual void PutConsole(const char *s) = 0; + virtual void PutVerbose(const char *s) = 0; + + virtual const Workspace& IdeWorkspace() const = 0; + virtual bool IdeIsBuilding() const = 0; + virtual String IdeGetOneFile() const = 0; + virtual int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false) = 0; + virtual int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet) = 0; + virtual int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false) = 0; + virtual int IdeConsoleAllocSlot() = 0; + virtual bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; + virtual bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1) = 0; + virtual void IdeConsoleFlush() = 0; + virtual void IdeConsoleBeginGroup(String group) = 0; + virtual void IdeConsoleEndGroup() = 0; + virtual bool IdeConsoleWait() = 0; + + virtual bool IdeIsDebug() const = 0; + virtual void IdeEndDebug() = 0; + virtual void IdeSetBottom(Ctrl& ctrl) = 0; + virtual void IdeActivateBottom() = 0; + virtual void IdeRemoveBottom(Ctrl& ctrl) = 0; + virtual void IdeSetRight(Ctrl& ctrl) = 0; + virtual void IdeRemoveRight(Ctrl& ctrl) = 0; + + virtual String IdeGetFileName() const = 0; + virtual int IdeGetFileLine() = 0; + virtual String IdeGetLine(int i) const = 0; + + virtual void IdeSetDebugPos(const String& fn, int line, const Image& img, int i) = 0; + virtual void IdeHidePtr() = 0; + virtual bool IdeDebugLock() = 0; + virtual bool IdeDebugUnLock() = 0; + virtual bool IdeIsDebugLock() const = 0; + virtual void IdeSetBar() = 0; + virtual void IdeGotoCodeRef(String link) = 0; + virtual void IdeOpenTopicFile(const String& file) = 0; + virtual void IdeFlushFile() = 0; + virtual String IdeGetFileName() = 0; + virtual String IdeGetNestFolder() = 0; + + virtual ~IdeContext() {} +}; + +IdeContext *TheIde(); +void TheIde(IdeContext *context); + +void PutConsole(const char *s); +void PutVerbose(const char *s); + +const Workspace& GetIdeWorkspace(); +bool IdeIsBuilding(); +String IdeGetOneFile(); +int IdeConsoleExecute(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false); +int IdeConsoleExecuteWithInput(const char *cmdline, Stream *out, const char *envptr, bool quiet); +int IdeConsoleExecute(One process, const char *cmdline, Stream *out = NULL, bool quiet = false); +int IdeConsoleAllocSlot(); +bool IdeConsoleRun(const char *cmdline, Stream *out = NULL, const char *envptr = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); +bool IdeConsoleRun(One process, const char *cmdline, Stream *out = NULL, bool quiet = false, int slot = 0, String key = Null, int blitz_count = 1); +void IdeConsoleFlush(); +void IdeConsoleBeginGroup(String group); +void IdeConsoleEndGroup(); +bool IdeConsoleWait(); +void IdeGotoCodeRef(String s); + +bool IdeIsDebug(); +void IdeEndDebug(); +void IdeSetBottom(Ctrl& ctrl); +void IdeActivateBottom(); +void IdeRemoveBottom(Ctrl& ctrl); +void IdeSetRight(Ctrl& ctrl); +void IdeRemoveRight(Ctrl& ctrl); + +String IdeGetFileName(); +int IdeGetFileLine(); +String IdeGetLine(int i); + +void IdeSetDebugPos(const String& fn, int line, const Image& img, int i); +void IdeHidePtr(); +bool IdeDebugLock(); +bool IdeDebugUnLock(); +bool IdeIsDebugLock(); + +void IdeSetBar(); + +#include "Host.h" + +struct IdeMacro { + IdeMacro(); + + int hotkey; + String menu; + String submenu; + EscValue code; +}; + +ArrayMap& UscGlobal(); +Array& UscMacros(); + +void UscSetCleanModules(void (*CleanModules)()); +void SetIdeModuleUsc(bool (*IdeModuleUsc)(CParser& p)); +void UscSetReadMacro(void (*ReadMacro)(CParser& p)); + +void CleanUsc(); +void ParseUscFile(const char *filename) throw(CParser::Error); + +Point ReadNums(CParser& p); +Point ReadPoint(CParser& p); + +struct SemiTextTest : public TextTest { + virtual const char *Accept(const char *s) const; +}; + +Vector SplitDirs(const char *s); + +String VarFilePath(); +String VarFilePath(String name); + +bool SaveVarFile(const char *filename, const VectorMap& var); +bool LoadVarFile(const char *name, VectorMap& var); +bool SaveVars(const char *name); +bool LoadVars(const char *name); +String GetVar(const String& var); +String GetVarsName(); +String VarFilePath(); +Vector GetUppDirs(); +String GetUppDir(); +void SetVar(const String& var, const String& value); + +String GetAnyFileName(const char *path); +String GetAnyFileTitle(const char *path); +String CatAnyPath(String path, const char *more); +String PackagePath(const String& name); +String SourcePath(const String& package, const String& name); +inline +String PackageDirectory(const String& name) { return GetFileDirectory(PackagePath(name)); } +bool IsNestReadOnly(const String& path); + +String GetLocalDir(); +String LocalPath(const String& filename); + +Vector IgnoreList(); + +bool IsFullDirectory(const String& d); +bool IsFolder(const String& path); + +bool IsCSourceFile(const char *path); +bool IsCHeaderFile(const char *path); + +String FollowCygwinSymlink(const String& filename); + +void SplitPathMap(const char *path_map, Vector& local, Vector& remote); +String JoinPathMap(const Vector& local, const Vector& remote); +void SplitHostName(const char *hostname, String& host, int& port); + +Vector SplitFlags0(const char *flags); +Vector SplitFlags(const char *flags, bool main = false); +Vector SplitFlags(const char *flags, bool main, const Vector& accepts); + +bool MatchWhen(const String& when, const Vector& flag); +String ReadWhen(CParser& p); +String AsStringWhen(const String& when); + +struct OptItem { + String when; + String text; +}; + +struct CustomStep { + String when; + String ext; + String command; + String output; + + void Load(CParser& p) throw(CParser::Error); + String AsString() const; + + String GetExt() const; + bool MatchExt(const char *fn) const; +}; + +Vector Combine(const Vector& conf, const char *flags); +String Gather(const Array& set, const Vector& conf, bool nospace = false); + +bool HasFlag(const Vector& conf, const char *flag); + +enum { + FLAG_MISMATCH = -2, + FLAG_UNDEFINED = -1, +}; + +int GetType(const Vector& conf, const char *flags); +int GetType(const Vector& conf, const char *flags, int def); +bool GetFlag(const Vector& conf, const char *flag); +String RemoveType(Vector& conf, const char *flags); + +class Package { +public: + struct File : public String { + Array option; + Array depends; + bool readonly; + bool separator; + int tabsize; + byte charset; + int font; + String highlight; + int optimize_speed; + + void operator=(const String& s) { String::operator=(s); readonly = separator = false; } + void Init() { readonly = separator = false; tabsize = Null; charset = 0; font = 0; + optimize_speed = false; } + + File() { Init(); } + File(const String& s) : String(s) { Init(); } + }; + struct Config { + String name; + String param; + }; + byte charset; + bool optimize_speed; + bool noblitz; + String description; + Vector accepts; + Array flag; + Array uses; + Array target; + Array library; + Array link; + Array option; + Array file; + Array config; + Array custom; + Time time; + + int GetCount() const { return file.GetCount(); } + File& operator[](int i) { return file[i]; } + const File& operator[](int i) const { return file[i]; } + + void Load(const char *path); + bool Save(const char *file) const; + + static void SetPackageResolver(bool (*Resolve)(const String& error, const String& path, int line)); + + Package(); +}; + +class Workspace { + void AddUses(Package& p, bool match, const Vector& flag); + void AddLoad(const String& name, bool match, const Vector& flag); + +public: + ArrayMap package; + + void Clear() { package.Clear(); } + String operator[](int i) const { return package.GetKey(i); } + Package& GetPackage(int i) { return package[i]; } + const Package& GetPackage(int i) const { return package[i]; } + int GetCount() const { return package.GetCount(); } + + void Scan(const char *prjname); + void Scan(const char *prjname, const Vector& flag); + + Vector GetAllAccepts(int pk) const; + + void Dump(); +}; + +struct Ide; + +String FindInDirs(const Vector& dir, const String& file); +String FindCommand(const Vector& exedir, const String& cmdline); + +struct MakeFile { + String outdir; + String outfile; + String output; + String config; + String install; + String rules; + String linkdep; + String linkfiles; + String linkfileend; +}; + +String GetMakePath(String fn, bool win32); +String AdjustMakePath(const char *fn); + +enum { + R_OPTIMAL, + R_SPEED, + R_SIZE +}; + +struct Builder { + Host *host; + Index config; + String compiler; + String method; + String outdir; + Vector include; + Vector libpath; + String target; + String debug_options; + String release_options; + String release_size_options; + String version; + String script; + bool doall; + + virtual bool BuildPackage(const String& package, Vector& linkfile, String& linkoptions, + const Vector& all_uses, const Vector& all_libraries, int optimize) + { return false; } + virtual bool Link(const Vector& linkfile, const String& linkoptions, bool createmap) + { return false; } + virtual bool Preprocess(const String& package, const String& file, const String& result, bool asmout) + { return false; } + virtual void AddFlags(Index& cfg) {} + virtual void AddMakeFile(MakeFile& mfinfo, String package, + const Vector& all_uses, const Vector& all_libraries, + const Index& common_config, bool exporting) {} + virtual String GetTargetExt() const = 0; + + Builder() { doall = false; } + virtual ~Builder() {} +}; + +VectorMap& BuilderMap(); +void RegisterBuilder(const char *name, Builder *(*create)()); + +void HdependSetDirs(pick_ Vector& id); +void HdependTimeDirty(); +void HdependClearDependencies(); +void HdependAddDependency(const String& file, const String& depends); +Time HdependFileTime(const String& path); +Vector HdependGetDependencies(const String& path); +String FindIncludeFile(const char *s, const String& filedir); +bool HdependBlitzApproved(const String& path); +const Vector& HdependGetDefines(const String& path); +const Vector& HdependGetAllFiles(); + +#endif diff --git a/uppsrc/ide/Core/Core.upp b/uppsrc/ide/Core/Core.upp new file mode 100644 index 000000000..17cbde86e --- /dev/null +++ b/uppsrc/ide/Core/Core.upp @@ -0,0 +1,19 @@ +description "TheIDE - common library"; + +uses + CtrlLib, + Esc; + +file + Core.h, + Core.cpp, + Hdepend.cpp optimize_speed, + Package.cpp, + Workspace.cpp, + usc.cpp, + Host.h, + Host.cpp, + common.iml, + Info readonly separator, + Copying; + diff --git a/uppsrc/ide/Common/Hdepend.cpp b/uppsrc/ide/Core/Hdepend.cpp similarity index 95% rename from uppsrc/ide/Common/Hdepend.cpp rename to uppsrc/ide/Core/Hdepend.cpp index bdfa97cb2..cbad3ff39 100644 --- a/uppsrc/ide/Common/Hdepend.cpp +++ b/uppsrc/ide/Core/Hdepend.cpp @@ -1,489 +1,489 @@ -#include "Common.h" - -class Hdepend { - struct Info { - Time time; - Vector depend; - Vector bydefine; - Index macroinclude; - Vector define; - bool flag; - bool macroflag; - bool timedirty; - bool guarded; - bool blitzprohibit; - - bool CanBlitz() { return guarded && !blitzprohibit; } - - Info() { time = Null; flag = false; timedirty = true; guarded = false; } - }; - - ArrayMap map; - Vector incdir; - VectorMap > depends; - - void Include(const char *trm, Info& info, const String& filedir, bool bydefine); - void ScanFile(const String& path, int map_index); - int File(const String& path); - Time FileTime(int i); - void ClearFlag(); - void ClearMacroFlag(); - void GetMacroIndex(Index& dest, int ix); - -public: - void SetDirs(pick_ Vector& id) { incdir = id; map.Clear(); } - void TimeDirty(); - - void ClearDependencies() { depends.Clear(); } - void AddDependency(const String& file, const String& depends); - - Time FileTime(const String& path); - bool BlitzApproved(const String& path); - String FindIncludeFile(const char *s, const String& filedir); - const Vector& GetDefines(const String& path); - Vector GetDependencies(const String& path); - const Vector& GetAllFiles() { return map.GetKeys(); } -}; - -void Hdepend::AddDependency(const String& file, const String& dep) -{ - depends.GetAdd(NormalizePath(file)).FindAdd(NormalizePath(dep)); -} - -const char *SkipSpc(const char *term) { - while(*term == '\t' || *term == ' ') - term++; - return term; -} - -const char *RestOfLine(const char *term, String& val) { - while(*term && *term != '\r' && *term != '\n') - val.Cat(*term++); - return term; -} - -String Hdepend::FindIncludeFile(const char *s, const String& filedir) -{ - s = SkipSpc(s); - int type = *s; - if(type == '<' || type == '\"' || type == '?') { - s++; - String name; - if(type == '<') type = '>'; - while(*s != '\r' && *s != '\n') { - if(*s == type) { - if(type == '\"') { - String fn = NormalizePath(name, filedir); - if(FileExists(fn)) - return fn; - FindFile ff(fn); - } - for(int i = 0; i < incdir.GetCount(); i++) { - String fn = CatAnyPath(incdir[i], name); - if(FileExists(fn)) - return fn; - } - break; - } - name.Cat(*s++); - } - } - return String(); -} - -void Hdepend::Include(const char *s, Hdepend::Info& info, const String& filedir, bool bydefine) { - s = SkipSpc(s); - if(IsAlpha(*s) || *s == '_') { - const char *macid = s; - while(IsAlNum(*++s) || *s == '_') - ; - info.macroinclude.FindAdd(String(macid, s)); - } - else { - String fn = FindIncludeFile(s, filedir); - if(!IsNull(fn)) { - info.depend.Add(File(fn)); - info.bydefine.Add(bydefine); - } - } -} - -static const char *SkipComment(const char *s) { - if(*s == '/') - if(s[1] == '/') - for(s += 2; *s && *s != '\n';) - s++; - else if(s[1] == '*') - { - for(s += 2; *s && (*s != '*' || s[1] != '/'); s++) - ; - if(*s) - s += 2; - } - return s; -} - -void Hdepend::ScanFile(const String& path, int map_index) { - Info& info = map[map_index]; - String src = LoadFile(path); - const char *term = src; - info.depend.Clear(); - info.bydefine.Clear(); - info.macroinclude.Clear();; - info.define.Clear();; - info.guarded = false; - info.blitzprohibit = false; - String filedir = GetFileDirectory(path); - bool testg = true; - bool defines = IsCSourceFile(path); - goto begin; - while(*term) { - if(term[0] == '/' && term[1] == '*') { - while(*term) { - if(term[0] == '*' && term[1] == '/') { - term += 2; - break; - } - term++; - } - } - else - if(term[0] == '/' && term[1] == '/') { - if(term[2] == '#') { - CParser p(term + 3); - if(p.Id("BLITZ_APPROVE") || p.Id("once")) - info.guarded = true; - else - if(p.Id("BLITZ_PROHIBIT")) - info.blitzprohibit = true; - } - while(*term) { - if(*term == '\n') break; - term++; - } - } - else - if(*term == '\n') { - term++; - begin: - while(*term == '\r' || *term == ' ' || *term == '\t') term++; - if(*term == '#') { - term++; - while(*term == ' ' || *term == '\t') term++; - if(term[0] == 'i' && term[1] == 'n' && term[2] == 'c' && term[3] == 'l' && - term[4] == 'u' && term[5] == 'd' && term[6] == 'e' && - (term[7] == ' ' || term[7] == '\t')) { - term = SkipSpc(term + 7); - String val; - term = RestOfLine(term, val); - val = TrimRight(val); - Include(val, info, filedir, false); - } - else - if(testg && term[0] == 'i' && term[1] == 'f' && term[2] == 'n' && - term[3] == 'd' && term[4] == 'e' && term[5] == 'f' && - (term[6] == ' ' || term[6] == '\t')) { - testg = false; - CParser p(term + 6); - if(p.IsId()) { - String id = p.ReadId(); - if(p.Char('#') && p.Id("define") && p.IsId() && id == p.ReadId()) - info.guarded = true; - } - } - else - if(defines && term[0] == 'd' && term[1] == 'e' && term[2] == 'f' && - term[3] == 'i' && term[4] == 'n' && term[5] == 'e' && - (term[6] == ' ' || term[6] == '\t')) { - CParser p(term + 6); - if(p.IsId()) - info.define.Add(p.ReadId()); - term = p.GetPtr(); - } - else - if(term[0] == 'p' && term[1] == 'r' && term[2] == 'a' && - term[3] == 'g' && term[4] == 'm' && term[5] == 'a' && - (term[6] == ' ' || term[6] == '\t')) { - CParser p(term + 6); - if(p.Id("BLITZ_APPROVE") || p.Id("once")) - info.guarded = true; - else - if(p.Id("BLITZ_PROHIBIT")) - info.blitzprohibit = true; - term = p.GetPtr(); - } - } - else if(IsAlpha(*term) || *term == '_') { - const char *id = term; - while(IsAlNum(*++term) || *term == '_') - ; - bool is_bin = (term - id == 6 && !memcmp(id, "BINARY", 6)); - bool is_mask = (term - id == 11 && !memcmp(id, "BINARY_MASK", 11)); - bool is_array = (term - id == 12 && !memcmp(id, "BINARY_ARRAY", 12)); - if(is_bin || is_mask || is_array) { - while(*term && (byte)*term <= ' ') - term++; - if(*term == '(') { - while(*term && *term != ')' && *term != ',') - term++; - if(is_array && *term == ',') { - while(*++term && *term != ')' && *term != ',') - ; - } - if(*term == ',') { - while(*++term && *term != ')' && (byte)*term <= ' ') - ; - if(*term == '\"') - Include(term, info, filedir, false); - } - } - } - } - } - else { - if((byte)*term > ' ') - testg = false; - term++; - } - } - Index minc; - for(;;) { - ClearMacroFlag(); - Index new_minc; - GetMacroIndex(new_minc, map_index); - if(new_minc.GetCount() <= minc.GetCount()) - return; - minc = new_minc; - term = src; - while(*term) { - while(*term && (byte)*term <= ' ') - term++; - if(*term == '#') { - term++; - while(*term && *term != '\n' && (byte)*term <= ' ') - term++; - if(Peek32le(term) == 'd' + ('e' << 8) + ('f' << 16) + ('i' << 24) - && Peek16le(term + 4) == 'n' + ('e' << 8)) { - term += 6; - while(*term && *term != '\n' && (byte)*term <= ' ') - term++; - const char *id = term; - if(IsAlpha(*term) || *term == '_') - while(IsAlNum(*++term) || *term == '_') - ; - String ident(id, term); - if(minc.Find(ident) >= 0) { - term = SkipSpc(term); - String incfn; - id = term; - while(*term && *term != '\n') - term++; - const char *e = term; - while(e > id && (byte)e[-1] <= ' ') - e--; - Include(String(id, e), info, filedir, true); - } - } - } - while(*term && *term != '\n') - if(*term == '/' && (term[1] == '*' || term[1] == '/')) - term = SkipComment(term); - else - term++; - if(*term) - term++; - } - } -} - -int Hdepend::File(const String& f) { - String path = NormalizePath(f); - int ii = map.FindAdd(path); - Info& info = map[ii]; - if(info.flag) return ii; - info.flag = true; - FindFile ff(path); - if(!ff || ff.GetLastWriteTime() == info.time) { - if(info.timedirty) { - for(int i = 0; i < info.depend.GetCount(); i++) - File(map.GetKey(info.depend[i])); - info.timedirty = false; - } - } - else { - info.time = ff.GetLastWriteTime(); - if(info.time > GetSysTime() + 10) - PutConsole(String().Cat() << "WARNING: " << path << " has invalid (future) time " << info.time); - ScanFile(path, ii); - } - return ii; -} - -void Hdepend::GetMacroIndex(Index& dest, int ix) { - Info& info = map[ix]; - if(!info.macroflag) { - info.macroflag = true; - int i; - for(i = 0; i < info.macroinclude.GetCount(); i++) - dest.FindAdd(info.macroinclude[i]); - for(i = 0; i < info.depend.GetCount(); i++) - GetMacroIndex(dest, info.depend[i]); - } -} - -Time Hdepend::FileTime(int ii) -{ -// LOG("FileTime " << map.GetKey(ii)); -// LOGBEGIN(); - Info& info = map[ii]; -// DUMP(info.time); - Time time = info.time; - if(!info.flag) { - info.flag = true; - for(int i = 0; i < info.depend.GetCount(); i++) - time = max(time, FileTime(info.depend[i])); - } -// LOGEND(); - return time; -} - -Vector Hdepend::GetDependencies(const String& path) -{ - ClearFlag(); - Index out; - out.Add(File(path)); - for(int i = 0; i < out.GetCount(); i++) - if(out[i] >= 0) - FindAppend(out, map[out[i]].depend); - Vector outnames; - for(int i = 1; i < out.GetCount(); i++) - if(out[i] >= 0) - outnames.Add(map.GetKey(out[i])); - return outnames; -} - -void Hdepend::ClearFlag() -{ - for(int i = 0; i < map.GetCount(); i++) - map[i].flag = false; -} - -void Hdepend::ClearMacroFlag() -{ - for(int i = 0; i < map.GetCount(); i++) - map[i].macroflag = false; -} - -void Hdepend::TimeDirty() -{ - for(int i = 0; i < map.GetCount(); i++) - map[i].timedirty = true; -} - - -Time Hdepend::FileTime(const String& path) -{ - String p = NormalizePath(path); - ClearFlag(); - int d = File(p); - ClearFlag(); - Time h = FileTime(d); - d = depends.Find(p); - if(d >= 0) { - const Index& dep = depends[d]; - for(int i = 0; i < dep.GetCount(); i++) { - FindFile ff(dep[i]); - if(ff) { - Time tm = ff.GetLastWriteTime(); - if(tm > GetSysTime() + 10) - PutConsole(String().Cat() << "WARNING: " << dep[i] << " has invalid (future) time " << tm); - if(tm > h) - h = tm; - } - } - } - return h; -} - -bool Hdepend::BlitzApproved(const String& path) -{ - ClearFlag(); - int d = File(path); - ClearFlag(); - Info& info = map[d]; - if(info.blitzprohibit) - return false; - if(info.guarded) - return true; - if(info.guarded) - return true; - for(int i = 0; i < info.depend.GetCount(); i++) - if(!info.bydefine[i] && !map[info.depend[i]].CanBlitz()) { - PutVerbose(String().Cat() << map.GetKey(info.depend[i]) - << "(1) : blocks BLITZ of " << path); - return false; - } - return true; -} - -const Vector& Hdepend::GetDefines(const String& path) -{ - ClearFlag(); - int d = File(path); - ClearFlag(); - return map[d].define; -} - -void HdependSetDirs(pick_ Vector& id) -{ - Single().SetDirs(id); -} - -void HdependTimeDirty() -{ - Single().TimeDirty(); -} - -Time HdependFileTime(const String& path) -{ - String of = IdeGetOneFile(); - if(IsNull(of)) - return Single().FileTime(path); - else - return of == path ? GetSysTime() : Time::Low(); -} - -String FindIncludeFile(const char *s, const String& filedir) -{ - return Single().FindIncludeFile(s, filedir); -} - -bool HdependBlitzApproved(const String& path) -{ - return Single().BlitzApproved(path); -} - -const Vector& HdependGetDefines(const String& path) -{ - return Single().GetDefines(path); -} - -Vector HdependGetDependencies(const String& file) -{ - return Single().GetDependencies(file); -} - -void HdependClearDependencies() -{ - Single().ClearDependencies(); -} - -void HdependAddDependency(const String& file, const String& depends) -{ - Single().AddDependency(file, depends); -} - -const Vector& HdependGetAllFiles() -{ - return Single().GetAllFiles(); -} +#include "Core.h" + +class Hdepend { + struct Info { + Time time; + Vector depend; + Vector bydefine; + Index macroinclude; + Vector define; + bool flag; + bool macroflag; + bool timedirty; + bool guarded; + bool blitzprohibit; + + bool CanBlitz() { return guarded && !blitzprohibit; } + + Info() { time = Null; flag = false; timedirty = true; guarded = false; } + }; + + ArrayMap map; + Vector incdir; + VectorMap > depends; + + void Include(const char *trm, Info& info, const String& filedir, bool bydefine); + void ScanFile(const String& path, int map_index); + int File(const String& path); + Time FileTime(int i); + void ClearFlag(); + void ClearMacroFlag(); + void GetMacroIndex(Index& dest, int ix); + +public: + void SetDirs(pick_ Vector& id) { incdir = id; map.Clear(); } + void TimeDirty(); + + void ClearDependencies() { depends.Clear(); } + void AddDependency(const String& file, const String& depends); + + Time FileTime(const String& path); + bool BlitzApproved(const String& path); + String FindIncludeFile(const char *s, const String& filedir); + const Vector& GetDefines(const String& path); + Vector GetDependencies(const String& path); + const Vector& GetAllFiles() { return map.GetKeys(); } +}; + +void Hdepend::AddDependency(const String& file, const String& dep) +{ + depends.GetAdd(NormalizePath(file)).FindAdd(NormalizePath(dep)); +} + +const char *SkipSpc(const char *term) { + while(*term == '\t' || *term == ' ') + term++; + return term; +} + +const char *RestOfLine(const char *term, String& val) { + while(*term && *term != '\r' && *term != '\n') + val.Cat(*term++); + return term; +} + +String Hdepend::FindIncludeFile(const char *s, const String& filedir) +{ + s = SkipSpc(s); + int type = *s; + if(type == '<' || type == '\"' || type == '?') { + s++; + String name; + if(type == '<') type = '>'; + while(*s != '\r' && *s != '\n') { + if(*s == type) { + if(type == '\"') { + String fn = NormalizePath(name, filedir); + if(FileExists(fn)) + return fn; + FindFile ff(fn); + } + for(int i = 0; i < incdir.GetCount(); i++) { + String fn = CatAnyPath(incdir[i], name); + if(FileExists(fn)) + return fn; + } + break; + } + name.Cat(*s++); + } + } + return String(); +} + +void Hdepend::Include(const char *s, Hdepend::Info& info, const String& filedir, bool bydefine) { + s = SkipSpc(s); + if(IsAlpha(*s) || *s == '_') { + const char *macid = s; + while(IsAlNum(*++s) || *s == '_') + ; + info.macroinclude.FindAdd(String(macid, s)); + } + else { + String fn = FindIncludeFile(s, filedir); + if(!IsNull(fn)) { + info.depend.Add(File(fn)); + info.bydefine.Add(bydefine); + } + } +} + +static const char *SkipComment(const char *s) { + if(*s == '/') + if(s[1] == '/') + for(s += 2; *s && *s != '\n';) + s++; + else if(s[1] == '*') + { + for(s += 2; *s && (*s != '*' || s[1] != '/'); s++) + ; + if(*s) + s += 2; + } + return s; +} + +void Hdepend::ScanFile(const String& path, int map_index) { + Info& info = map[map_index]; + String src = LoadFile(path); + const char *term = src; + info.depend.Clear(); + info.bydefine.Clear(); + info.macroinclude.Clear();; + info.define.Clear();; + info.guarded = false; + info.blitzprohibit = false; + String filedir = GetFileDirectory(path); + bool testg = true; + bool defines = IsCSourceFile(path); + goto begin; + while(*term) { + if(term[0] == '/' && term[1] == '*') { + while(*term) { + if(term[0] == '*' && term[1] == '/') { + term += 2; + break; + } + term++; + } + } + else + if(term[0] == '/' && term[1] == '/') { + if(term[2] == '#') { + CParser p(term + 3); + if(p.Id("BLITZ_APPROVE") || p.Id("once")) + info.guarded = true; + else + if(p.Id("BLITZ_PROHIBIT")) + info.blitzprohibit = true; + } + while(*term) { + if(*term == '\n') break; + term++; + } + } + else + if(*term == '\n') { + term++; + begin: + while(*term == '\r' || *term == ' ' || *term == '\t') term++; + if(*term == '#') { + term++; + while(*term == ' ' || *term == '\t') term++; + if(term[0] == 'i' && term[1] == 'n' && term[2] == 'c' && term[3] == 'l' && + term[4] == 'u' && term[5] == 'd' && term[6] == 'e' && + (term[7] == ' ' || term[7] == '\t')) { + term = SkipSpc(term + 7); + String val; + term = RestOfLine(term, val); + val = TrimRight(val); + Include(val, info, filedir, false); + } + else + if(testg && term[0] == 'i' && term[1] == 'f' && term[2] == 'n' && + term[3] == 'd' && term[4] == 'e' && term[5] == 'f' && + (term[6] == ' ' || term[6] == '\t')) { + testg = false; + CParser p(term + 6); + if(p.IsId()) { + String id = p.ReadId(); + if(p.Char('#') && p.Id("define") && p.IsId() && id == p.ReadId()) + info.guarded = true; + } + } + else + if(defines && term[0] == 'd' && term[1] == 'e' && term[2] == 'f' && + term[3] == 'i' && term[4] == 'n' && term[5] == 'e' && + (term[6] == ' ' || term[6] == '\t')) { + CParser p(term + 6); + if(p.IsId()) + info.define.Add(p.ReadId()); + term = p.GetPtr(); + } + else + if(term[0] == 'p' && term[1] == 'r' && term[2] == 'a' && + term[3] == 'g' && term[4] == 'm' && term[5] == 'a' && + (term[6] == ' ' || term[6] == '\t')) { + CParser p(term + 6); + if(p.Id("BLITZ_APPROVE") || p.Id("once")) + info.guarded = true; + else + if(p.Id("BLITZ_PROHIBIT")) + info.blitzprohibit = true; + term = p.GetPtr(); + } + } + else if(IsAlpha(*term) || *term == '_') { + const char *id = term; + while(IsAlNum(*++term) || *term == '_') + ; + bool is_bin = (term - id == 6 && !memcmp(id, "BINARY", 6)); + bool is_mask = (term - id == 11 && !memcmp(id, "BINARY_MASK", 11)); + bool is_array = (term - id == 12 && !memcmp(id, "BINARY_ARRAY", 12)); + if(is_bin || is_mask || is_array) { + while(*term && (byte)*term <= ' ') + term++; + if(*term == '(') { + while(*term && *term != ')' && *term != ',') + term++; + if(is_array && *term == ',') { + while(*++term && *term != ')' && *term != ',') + ; + } + if(*term == ',') { + while(*++term && *term != ')' && (byte)*term <= ' ') + ; + if(*term == '\"') + Include(term, info, filedir, false); + } + } + } + } + } + else { + if((byte)*term > ' ') + testg = false; + term++; + } + } + Index minc; + for(;;) { + ClearMacroFlag(); + Index new_minc; + GetMacroIndex(new_minc, map_index); + if(new_minc.GetCount() <= minc.GetCount()) + return; + minc = new_minc; + term = src; + while(*term) { + while(*term && (byte)*term <= ' ') + term++; + if(*term == '#') { + term++; + while(*term && *term != '\n' && (byte)*term <= ' ') + term++; + if(Peek32le(term) == 'd' + ('e' << 8) + ('f' << 16) + ('i' << 24) + && Peek16le(term + 4) == 'n' + ('e' << 8)) { + term += 6; + while(*term && *term != '\n' && (byte)*term <= ' ') + term++; + const char *id = term; + if(IsAlpha(*term) || *term == '_') + while(IsAlNum(*++term) || *term == '_') + ; + String ident(id, term); + if(minc.Find(ident) >= 0) { + term = SkipSpc(term); + String incfn; + id = term; + while(*term && *term != '\n') + term++; + const char *e = term; + while(e > id && (byte)e[-1] <= ' ') + e--; + Include(String(id, e), info, filedir, true); + } + } + } + while(*term && *term != '\n') + if(*term == '/' && (term[1] == '*' || term[1] == '/')) + term = SkipComment(term); + else + term++; + if(*term) + term++; + } + } +} + +int Hdepend::File(const String& f) { + String path = NormalizePath(f); + int ii = map.FindAdd(path); + Info& info = map[ii]; + if(info.flag) return ii; + info.flag = true; + FindFile ff(path); + if(!ff || ff.GetLastWriteTime() == info.time) { + if(info.timedirty) { + for(int i = 0; i < info.depend.GetCount(); i++) + File(map.GetKey(info.depend[i])); + info.timedirty = false; + } + } + else { + info.time = ff.GetLastWriteTime(); + if(info.time > GetSysTime() + 10) + PutConsole(String().Cat() << "WARNING: " << path << " has invalid (future) time " << info.time); + ScanFile(path, ii); + } + return ii; +} + +void Hdepend::GetMacroIndex(Index& dest, int ix) { + Info& info = map[ix]; + if(!info.macroflag) { + info.macroflag = true; + int i; + for(i = 0; i < info.macroinclude.GetCount(); i++) + dest.FindAdd(info.macroinclude[i]); + for(i = 0; i < info.depend.GetCount(); i++) + GetMacroIndex(dest, info.depend[i]); + } +} + +Time Hdepend::FileTime(int ii) +{ +// LOG("FileTime " << map.GetKey(ii)); +// LOGBEGIN(); + Info& info = map[ii]; +// DUMP(info.time); + Time time = info.time; + if(!info.flag) { + info.flag = true; + for(int i = 0; i < info.depend.GetCount(); i++) + time = max(time, FileTime(info.depend[i])); + } +// LOGEND(); + return time; +} + +Vector Hdepend::GetDependencies(const String& path) +{ + ClearFlag(); + Index out; + out.Add(File(path)); + for(int i = 0; i < out.GetCount(); i++) + if(out[i] >= 0) + FindAppend(out, map[out[i]].depend); + Vector outnames; + for(int i = 1; i < out.GetCount(); i++) + if(out[i] >= 0) + outnames.Add(map.GetKey(out[i])); + return outnames; +} + +void Hdepend::ClearFlag() +{ + for(int i = 0; i < map.GetCount(); i++) + map[i].flag = false; +} + +void Hdepend::ClearMacroFlag() +{ + for(int i = 0; i < map.GetCount(); i++) + map[i].macroflag = false; +} + +void Hdepend::TimeDirty() +{ + for(int i = 0; i < map.GetCount(); i++) + map[i].timedirty = true; +} + + +Time Hdepend::FileTime(const String& path) +{ + String p = NormalizePath(path); + ClearFlag(); + int d = File(p); + ClearFlag(); + Time h = FileTime(d); + d = depends.Find(p); + if(d >= 0) { + const Index& dep = depends[d]; + for(int i = 0; i < dep.GetCount(); i++) { + FindFile ff(dep[i]); + if(ff) { + Time tm = ff.GetLastWriteTime(); + if(tm > GetSysTime() + 10) + PutConsole(String().Cat() << "WARNING: " << dep[i] << " has invalid (future) time " << tm); + if(tm > h) + h = tm; + } + } + } + return h; +} + +bool Hdepend::BlitzApproved(const String& path) +{ + ClearFlag(); + int d = File(path); + ClearFlag(); + Info& info = map[d]; + if(info.blitzprohibit) + return false; + if(info.guarded) + return true; + if(info.guarded) + return true; + for(int i = 0; i < info.depend.GetCount(); i++) + if(!info.bydefine[i] && !map[info.depend[i]].CanBlitz()) { + PutVerbose(String().Cat() << map.GetKey(info.depend[i]) + << "(1) : blocks BLITZ of " << path); + return false; + } + return true; +} + +const Vector& Hdepend::GetDefines(const String& path) +{ + ClearFlag(); + int d = File(path); + ClearFlag(); + return map[d].define; +} + +void HdependSetDirs(pick_ Vector& id) +{ + Single().SetDirs(id); +} + +void HdependTimeDirty() +{ + Single().TimeDirty(); +} + +Time HdependFileTime(const String& path) +{ + String of = IdeGetOneFile(); + if(IsNull(of)) + return Single().FileTime(path); + else + return of == path ? GetSysTime() : Time::Low(); +} + +String FindIncludeFile(const char *s, const String& filedir) +{ + return Single().FindIncludeFile(s, filedir); +} + +bool HdependBlitzApproved(const String& path) +{ + return Single().BlitzApproved(path); +} + +const Vector& HdependGetDefines(const String& path) +{ + return Single().GetDefines(path); +} + +Vector HdependGetDependencies(const String& file) +{ + return Single().GetDependencies(file); +} + +void HdependClearDependencies() +{ + Single().ClearDependencies(); +} + +void HdependAddDependency(const String& file, const String& depends) +{ + Single().AddDependency(file, depends); +} + +const Vector& HdependGetAllFiles() +{ + return Single().GetAllFiles(); +} diff --git a/uppsrc/ide/Host.cpp b/uppsrc/ide/Core/Host.cpp similarity index 95% rename from uppsrc/ide/Host.cpp rename to uppsrc/ide/Core/Host.cpp index 4bd5f2722..f8be0dfea 100644 --- a/uppsrc/ide/Host.cpp +++ b/uppsrc/ide/Core/Host.cpp @@ -1,542 +1,542 @@ -#include "ide.h" - -#define LLOG(x) - -#include - -String LocalHost::GetEnvironment() -{ - return environment; -} - -String LocalHost::GetHostPath(const String& path) -{ - return path; -} - -String LocalHost::GetLocalPath(const String& path) -{ - return path; -} - -String LocalHost::NormalizePath(const String& path) -{ - return ::NormalizePath(path); -} - -Vector LocalHost::GetFileInfo(const Vector& path) -{ - Vector fi; - for(int i = 0; i < path.GetCount(); i++) { - FindFile ff(path[i]); - FileInfo& f = fi.Add(); - if(ff) { - (Time&)f = ff.GetLastWriteTime(); -#ifdef PLATFORM_WIN32 - f.second = f.second & ~1; // FAT vs NTFS accuracy fix -#endif - f.length = ff.IsFile() ? (int)ff.GetLength() : -1; - } - else { - (Time&)f = Time::Low(); - f.length = Null; - } - } - return fi; -} - -void LocalHost::DeleteFile(const Vector& path) -{ - for(int i = 0; i < path.GetCount(); i++) - ::DeleteFile(path[i]); -} - -void LocalHost::DeleteFolderDeep(const String& folder) -{ - ::DeleteFolderDeep(folder); -} - -void LocalHost::ChDir(const String& path) -{ -#ifdef PLATFORM_WIN32 - SetCurrentDirectory(path); -#endif -#ifdef PLATFORM_POSIX - chdir(path); -#endif - if(cmdout) - *cmdout << "cd \"" << GetHostPath(path) << "\"\n"; -} - -void LocalHost::DoDir(const String& dir) -{ - if(dir.GetLength() > 3) { - DoDir(GetFileFolder(dir)); - *cmdout << "mkdir \"" << dir << "\"\n"; - } -} - -void LocalHost::RealizeDir(const String& path) -{ - RealizeDirectory(path); - if(cmdout) - DoDir(path); -} - -void LocalHost::SaveFile(const String& path, const String& data) -{ - ::SaveFile(path, data); -} - -String LocalHost::LoadFile(const String& path) -{ - return ::LoadFile(path); -} - -int LocalHost::Execute(const char *cmdline) -{ - if(cmdout) - *cmdout << cmdline << '\n'; - PutVerbose(cmdline); - int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), NULL, environment, false); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int LocalHost::ExecuteWithInput(const char *cmdline) -{ - if(cmdout) - *cmdout << cmdline << '\n'; - PutVerbose(cmdline); - int q = IdeConsoleExecuteWithInput(FindCommand(exedirs, cmdline), NULL, environment, false); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int LocalHost::Execute(const char *cmdline, Stream& out) -{ - PutVerbose(cmdline); - int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), &out, environment, true); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int LocalHost::AllocSlot() -{ - return IdeConsoleAllocSlot(); -} - -bool LocalHost::Run(const char *cmdline, int slot, String key, int blitz_count) -{ - return IdeConsoleRun(FindCommand(exedirs, cmdline), NULL, environment, false, slot, key, blitz_count); -} - -bool LocalHost::Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) -{ - return IdeConsoleRun(FindCommand(exedirs, cmdline), &out, environment, true, slot, key, blitz_count); -} - -bool LocalHost::Wait() -{ - return IdeConsoleWait(); -} - -One LocalHost::StartProcess(const char *cmdline) -{ - try { - PutVerbose(cmdline); - return ::StartProcess(FindCommand(exedirs, cmdline), environment, REMOTE_TIMEOUT); - } - catch(...) { - return NULL; - } -} - -#ifdef PLATFORM_POSIX -//#BLITZ_APPROVE -#include -#include -#include - -static Vector& sPid() -{ - static Vector q; - return q; -} - -void sCleanZombies(int signal_number) -{ - Vector& pid = sPid(); - int i = 0; - while(i < pid.GetCount()) - if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0) - pid.Remove(i); - else - i++; -} -#endif - -String LinuxHostConsole = "/usr/bin/xterm -e"; - -void LocalHost::Launch(const char *_cmdline, bool console) -{ - String cmdline = FindCommand(exedirs, _cmdline); - PutVerbose(cmdline); -#ifdef PLATFORM_WIN32 - if(console) - cmdline = GetExeFilePath() + " ! " + cmdline; - int n = cmdline.GetLength() + 1; - Buffer cmd(n); - memcpy(cmd, cmdline, n); - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - PROCESS_INFORMATION pi; - STARTUPINFO si; - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - Buffer env(environment.GetCount() + 1); - memcpy(env, environment, environment.GetCount() + 1); - if(CreateProcess(NULL, cmd, &sa, &sa, TRUE, - NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE, - ~env, NULL, &si, &pi)) { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - else - PutConsole("Unable to launch " + String(_cmdline)); -#endif -#ifdef PLATFORM_POSIX - String script = ConfigFile("console-script-" + AsString(getpid()) + ".tmp"); - if(console) { - FileStream out(script, FileStream::CREATE, 0777); - out << "#!/bin/sh\n" - << cmdline << '\n' - << "echo \"<--- Finished, press any key to close the window --->\"\nread\n"; - cmdline = LinuxHostConsole + " bash " + script; - } - Buffer cmd_buf(strlen(cmdline) + 1); - char *cmd_out = cmd_buf; - Vector args; - const char *p = cmdline; - const char *b = p; - while(*p && (byte)*p > ' ') - if(*p++ == '\"') - while(*p && *p++ != '\"') - ; - args.Add(cmd_out); - memcpy(cmd_out, b, p - b); - cmd_out += p - b; - *cmd_out++ = '\0'; - - while(*p) - if((byte)*p <= ' ') - p++; - else { - args.Add(cmd_out); - b = p; - while(*p && (byte)*p > ' ') - if(*p++ == '\"') - { - memcpy(cmd_out, b, p - b - 1); - cmd_out += p - b - 1; - b = p; - while(*p && *p != '\"') - p++; - memcpy(cmd_out, b, p - b); - cmd_out += p - b; - if(*p == '\"') - p++; - b = p; - } - memcpy(cmd_out, b, p - b); - cmd_out += p - b; - *cmd_out++ = '\0'; - } - - args.Add(NULL); - - ONCELOCK { - struct sigaction sigchld_action; - memset(&sigchld_action, 0, sizeof(sigchld_action)); - sigchld_action.sa_handler = sCleanZombies; - sigaction(SIGCHLD, &sigchld_action, NULL); - } - - pid_t pid = fork(); - if(pid == 0) - { - const char *from = environment; - Vector env; - while(*from) - { - env.Add(from); - from += strlen(from) + 1; - } - env.Add(NULL); - const char **envp = env.Begin(); - execve(args[0], args, (char *const *)envp); - abort(); - } - LLOG("Launch pid: " << pid); - sPid().Add(pid); -#endif -} - -void LocalHost::AddFlags(Index& cfg) -{ -#if defined(PLATFORM_WIN32) - cfg.Add("WIN32"); -#endif -#ifdef PLATFORM_LINUX - cfg.Add("LINUX"); -#elif defined(PLATFORM_FREEBSD) - cfg.Add("FREEBSD"); -#elif defined(PLATFORM_SOLARIS) - cfg.Add("SOLARIS"); -#elif defined(PLATFORM_OSX11) - cfg.Add("OSX11"); -#endif -} - -static bool IsSamePath(const char *a, const char *b, int count) { - for(; --count >= 0; a++, b++) - if(a != b && ToLower(*a) != ToLower(*b) && !((*a == '\\' || *a == '/') && (*b == '\\' || *b == '/'))) - return false; - return true; -} - -String RemoteHost::GetEnvironment() -{ - return environment; -} - -String RemoteHost::GetHostPath(const String& path) -{ - bool slash = (os_type != "WINDOWS"); - for(int i = 0; i < path_map_local.GetCount(); i++) { - String lc = path_map_local[i]; - if(path.GetLength() >= lc.GetLength() && IsSamePath(path, lc, lc.GetLength())) - { - String r = CatAnyPath(path_map_remote[i], path.Mid(lc.GetLength())); - return slash ? UnixPath(r) : WinPath(r); - } - } - return slash ? UnixPath(path) : WinPath(path); -} - -String RemoteHost::GetLocalPath(const String& path) -{ - for(int i = 0; i < path_map_remote.GetCount(); i++) { - String rc = path_map_remote[i]; - if(path.GetLength() >= rc.GetLength() && IsSamePath(path, rc, rc.GetLength())) - return path_map_local[i] + path.Mid(rc.GetLength()); - } - if(!memcmp(path, "/cygdrive/", 10)) - { - const char *s = path.Begin() + 10; - String out; - if(*s) - out << *s++ << ':'; - out << s; - return out; - } - return NativePath(path); -} - -String RemoteHost::NormalizePath(const String& path) -{ - return path; -} - -String RemoteHost::RemoteExec(String cmd) -{ - Socket socket; - String sockerr; -/* - String hostname = host; - int port = 2346; - int ppos = hostname.Find(':'); - if(ppos >= 0) - { - port = atoi(host.GetIter(ppos + 1)); - hostname.Trim(ppos); - } -*/ - if(!ClientSocket(socket, host, port, true, NULL, 2000)) { - PutConsole(NFormat("Error connecting to '%s', port %d: %s", host, port, Socket::GetErrorText())); - return String::GetVoid(); - } - socket.Write(cmd); - socket.Write("\0", 1); - return socket.ReadUntil('\0', Null, 10000000); -} - -Vector RemoteHost::GetFileInfo(const Vector& path) -{ - VectorMap out; - out.Reserve(path.GetCount()); - String request; - request << "@" << (int)(GetSysTime() - TimeBase()) << ":"; - for(int i = 0; i < path.GetCount(); i++) - { - String hp = GetHostPath(path[i]); - request << hp << "\n"; - FileInfo& fi = out.Add(hp); - (Time&)fi = Time::Low(); - fi.length = Null; - } - String result = RemoteExec(request); - const char *p = result; - while(*p) - { - const char *b = p; - while(*p && *p != '\n' && *p != '\t') - p++; - String fn(b, p); - Time time = Time::Low(); - int size = Null; - if(*p == '\t') - { - int t = ScanInt(p + 1, &p); - if(!IsNull(t)) - time = TimeBase() + t; - if(*p == '\t') - size = ScanInt(p + 1, &p); - } - int ifn = out.Find(fn); - if(ifn >= 0) - { - (Time&)out[ifn] = time; - out[ifn].length = size; - } - while(*p && *p++ != '\n') - ; - } - return out.PickValues(); -} - -void RemoteHost::DeleteFile(const Vector& path) -{ - String request = "-"; - for(int i = 0; i < path.GetCount(); i++) - request << GetHostPath(path[i]) << "\n"; - String out = RemoteExec(request); - if(!IsNull(out) && out != "OK") - PutVerbose(out); -} - -void RemoteHost::DeleteFolderDeep(const String& folder) -{ - String out = RemoteExec("~" + GetHostPath(folder)); - if(out != "OK") - PutConsole(out); -} - -void RemoteHost::ChDir(const String& path) -{ - chdir_path = GetHostPath(path); -} - -void RemoteHost::RealizeDir(const String& path) -{ - RemoteExec("*" + GetHostPath(path)); -} - -void RemoteHost::SaveFile(const String& path, const String& data) -{ - String request; - request << ">" << GetHostPath(path) - << "\t" << int(GetSysTime() - TimeBase()) - << "\t" << data.GetLength() - << "\t" << ASCII85Encode(BZ2Compress(data)) - << "\n"; - String out = RemoteExec(request); - if(out != "OK") - PutConsole(out); -} - -String RemoteHost::LoadFile(const String& path) -{ - String hpath = GetHostPath(path); - String request = "^" + hpath; - String out = RemoteExec(request); - const char *p = out; - while(*p && *p != '\n' && *p != '\t') - p++; - if(*p++ != '\t') - return String::GetVoid(); - int len = ScanInt(p, &p); - if(IsNull(len) || len <= 0 || *p++ != '\t') - return String::GetVoid(); - String data = BZ2Decompress(ASCII85Decode(p)); - if(data.GetLength() != len) - { - PutConsole(NFormat("%s: decompressed length (%d) doesn't match length in header (%d)", - hpath, data.GetLength(), len)); - return String::GetVoid(); - } - return data; -} - -int RemoteHost::Execute(const char *cmdline) -{ - int q = IdeConsoleExecute(StartProcess(cmdline), cmdline); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int RemoteHost::ExecuteWithInput(const char *cmdline) -{ - int q = IdeConsoleExecute(StartProcess(cmdline), cmdline); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int RemoteHost::Execute(const char *cmdline, Stream& out) -{ - int q = IdeConsoleExecute(StartProcess(cmdline), cmdline, &out, true); - PutVerbose(Format("Exitcode: %d", q)); - return q; -} - -int RemoteHost::AllocSlot() -{ - return IdeConsoleAllocSlot(); -} - -bool RemoteHost::Run(const char *cmdline, int slot, String key, int blitz_count) -{ - return IdeConsoleRun(StartProcess(cmdline), cmdline, NULL, false, slot, key, blitz_count); -} - -bool RemoteHost::Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) -{ - return IdeConsoleRun(StartProcess(cmdline), cmdline, &out, false, slot, key, blitz_count); -} - -bool RemoteHost::Wait() -{ - return IdeConsoleWait(); -} - -One RemoteHost::StartProcess(const char *cmdline) -{ - try { - PutVerbose(cmdline); - return StartRemoteProcess(host, port, cmdline, environment, REMOTE_TIMEOUT); - } - catch(...) { - return NULL; - } -} - -void RemoteHost::Launch(const char *_cmdline, bool) -{ -} - -void RemoteHost::AddFlags(Index& cfg) -{ - cfg.Add(os_type); -} +#include "Core.h" + +#define LLOG(x) + +#include + +String LocalHost::GetEnvironment() +{ + return environment; +} + +String LocalHost::GetHostPath(const String& path) +{ + return path; +} + +String LocalHost::GetLocalPath(const String& path) +{ + return path; +} + +String LocalHost::NormalizePath(const String& path) +{ + return ::NormalizePath(path); +} + +Vector LocalHost::GetFileInfo(const Vector& path) +{ + Vector fi; + for(int i = 0; i < path.GetCount(); i++) { + FindFile ff(path[i]); + FileInfo& f = fi.Add(); + if(ff) { + (Time&)f = ff.GetLastWriteTime(); +#ifdef PLATFORM_WIN32 + f.second = f.second & ~1; // FAT vs NTFS accuracy fix +#endif + f.length = ff.IsFile() ? (int)ff.GetLength() : -1; + } + else { + (Time&)f = Time::Low(); + f.length = Null; + } + } + return fi; +} + +void LocalHost::DeleteFile(const Vector& path) +{ + for(int i = 0; i < path.GetCount(); i++) + ::DeleteFile(path[i]); +} + +void LocalHost::DeleteFolderDeep(const String& folder) +{ + ::DeleteFolderDeep(folder); +} + +void LocalHost::ChDir(const String& path) +{ +#ifdef PLATFORM_WIN32 + SetCurrentDirectory(path); +#endif +#ifdef PLATFORM_POSIX + chdir(path); +#endif + if(cmdout) + *cmdout << "cd \"" << GetHostPath(path) << "\"\n"; +} + +void LocalHost::DoDir(const String& dir) +{ + if(dir.GetLength() > 3) { + DoDir(GetFileFolder(dir)); + *cmdout << "mkdir \"" << dir << "\"\n"; + } +} + +void LocalHost::RealizeDir(const String& path) +{ + RealizeDirectory(path); + if(cmdout) + DoDir(path); +} + +void LocalHost::SaveFile(const String& path, const String& data) +{ + ::SaveFile(path, data); +} + +String LocalHost::LoadFile(const String& path) +{ + return ::LoadFile(path); +} + +int LocalHost::Execute(const char *cmdline) +{ + if(cmdout) + *cmdout << cmdline << '\n'; + PutVerbose(cmdline); + int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), NULL, environment, false); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int LocalHost::ExecuteWithInput(const char *cmdline) +{ + if(cmdout) + *cmdout << cmdline << '\n'; + PutVerbose(cmdline); + int q = IdeConsoleExecuteWithInput(FindCommand(exedirs, cmdline), NULL, environment, false); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int LocalHost::Execute(const char *cmdline, Stream& out) +{ + PutVerbose(cmdline); + int q = IdeConsoleExecute(FindCommand(exedirs, cmdline), &out, environment, true); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int LocalHost::AllocSlot() +{ + return IdeConsoleAllocSlot(); +} + +bool LocalHost::Run(const char *cmdline, int slot, String key, int blitz_count) +{ + return IdeConsoleRun(FindCommand(exedirs, cmdline), NULL, environment, false, slot, key, blitz_count); +} + +bool LocalHost::Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) +{ + return IdeConsoleRun(FindCommand(exedirs, cmdline), &out, environment, true, slot, key, blitz_count); +} + +bool LocalHost::Wait() +{ + return IdeConsoleWait(); +} + +One LocalHost::StartProcess(const char *cmdline) +{ + try { + PutVerbose(cmdline); + return ::StartProcess(FindCommand(exedirs, cmdline), environment, REMOTE_TIMEOUT); + } + catch(...) { + return NULL; + } +} + +#ifdef PLATFORM_POSIX +//#BLITZ_APPROVE +#include +#include +#include + +static Vector& sPid() +{ + static Vector q; + return q; +} + +void sCleanZombies(int signal_number) +{ + Vector& pid = sPid(); + int i = 0; + while(i < pid.GetCount()) + if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0) + pid.Remove(i); + else + i++; +} +#endif + +String LinuxHostConsole = "/usr/bin/xterm -e"; + +void LocalHost::Launch(const char *_cmdline, bool console) +{ + String cmdline = FindCommand(exedirs, _cmdline); + PutVerbose(cmdline); +#ifdef PLATFORM_WIN32 + if(console) + cmdline = GetExeFilePath() + " ! " + cmdline; + int n = cmdline.GetLength() + 1; + Buffer cmd(n); + memcpy(cmd, cmdline, n); + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + PROCESS_INFORMATION pi; + STARTUPINFO si; + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + Buffer env(environment.GetCount() + 1); + memcpy(env, environment, environment.GetCount() + 1); + if(CreateProcess(NULL, cmd, &sa, &sa, TRUE, + NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE, + ~env, NULL, &si, &pi)) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + else + PutConsole("Unable to launch " + String(_cmdline)); +#endif +#ifdef PLATFORM_POSIX + String script = ConfigFile("console-script-" + AsString(getpid()) + ".tmp"); + if(console) { + FileStream out(script, FileStream::CREATE, 0777); + out << "#!/bin/sh\n" + << cmdline << '\n' + << "echo \"<--- Finished, press any key to close the window --->\"\nread\n"; + cmdline = LinuxHostConsole + " bash " + script; + } + Buffer cmd_buf(strlen(cmdline) + 1); + char *cmd_out = cmd_buf; + Vector args; + const char *p = cmdline; + const char *b = p; + while(*p && (byte)*p > ' ') + if(*p++ == '\"') + while(*p && *p++ != '\"') + ; + args.Add(cmd_out); + memcpy(cmd_out, b, p - b); + cmd_out += p - b; + *cmd_out++ = '\0'; + + while(*p) + if((byte)*p <= ' ') + p++; + else { + args.Add(cmd_out); + b = p; + while(*p && (byte)*p > ' ') + if(*p++ == '\"') + { + memcpy(cmd_out, b, p - b - 1); + cmd_out += p - b - 1; + b = p; + while(*p && *p != '\"') + p++; + memcpy(cmd_out, b, p - b); + cmd_out += p - b; + if(*p == '\"') + p++; + b = p; + } + memcpy(cmd_out, b, p - b); + cmd_out += p - b; + *cmd_out++ = '\0'; + } + + args.Add(NULL); + + ONCELOCK { + struct sigaction sigchld_action; + memset(&sigchld_action, 0, sizeof(sigchld_action)); + sigchld_action.sa_handler = sCleanZombies; + sigaction(SIGCHLD, &sigchld_action, NULL); + } + + pid_t pid = fork(); + if(pid == 0) + { + const char *from = environment; + Vector env; + while(*from) + { + env.Add(from); + from += strlen(from) + 1; + } + env.Add(NULL); + const char **envp = env.Begin(); + execve(args[0], args, (char *const *)envp); + abort(); + } + LLOG("Launch pid: " << pid); + sPid().Add(pid); +#endif +} + +void LocalHost::AddFlags(Index& cfg) +{ +#if defined(PLATFORM_WIN32) + cfg.Add("WIN32"); +#endif +#ifdef PLATFORM_LINUX + cfg.Add("LINUX"); +#elif defined(PLATFORM_FREEBSD) + cfg.Add("FREEBSD"); +#elif defined(PLATFORM_SOLARIS) + cfg.Add("SOLARIS"); +#elif defined(PLATFORM_OSX11) + cfg.Add("OSX11"); +#endif +} + +static bool IsSamePath(const char *a, const char *b, int count) { + for(; --count >= 0; a++, b++) + if(a != b && ToLower(*a) != ToLower(*b) && !((*a == '\\' || *a == '/') && (*b == '\\' || *b == '/'))) + return false; + return true; +} + +String RemoteHost::GetEnvironment() +{ + return environment; +} + +String RemoteHost::GetHostPath(const String& path) +{ + bool slash = (os_type != "WINDOWS"); + for(int i = 0; i < path_map_local.GetCount(); i++) { + String lc = path_map_local[i]; + if(path.GetLength() >= lc.GetLength() && IsSamePath(path, lc, lc.GetLength())) + { + String r = CatAnyPath(path_map_remote[i], path.Mid(lc.GetLength())); + return slash ? UnixPath(r) : WinPath(r); + } + } + return slash ? UnixPath(path) : WinPath(path); +} + +String RemoteHost::GetLocalPath(const String& path) +{ + for(int i = 0; i < path_map_remote.GetCount(); i++) { + String rc = path_map_remote[i]; + if(path.GetLength() >= rc.GetLength() && IsSamePath(path, rc, rc.GetLength())) + return path_map_local[i] + path.Mid(rc.GetLength()); + } + if(!memcmp(path, "/cygdrive/", 10)) + { + const char *s = path.Begin() + 10; + String out; + if(*s) + out << *s++ << ':'; + out << s; + return out; + } + return NativePath(path); +} + +String RemoteHost::NormalizePath(const String& path) +{ + return path; +} + +String RemoteHost::RemoteExec(String cmd) +{ + Socket socket; + String sockerr; +/* + String hostname = host; + int port = 2346; + int ppos = hostname.Find(':'); + if(ppos >= 0) + { + port = atoi(host.GetIter(ppos + 1)); + hostname.Trim(ppos); + } +*/ + if(!ClientSocket(socket, host, port, true, NULL, 2000)) { + PutConsole(NFormat("Error connecting to '%s', port %d: %s", host, port, Socket::GetErrorText())); + return String::GetVoid(); + } + socket.Write(cmd); + socket.Write("\0", 1); + return socket.ReadUntil('\0', Null, 10000000); +} + +Vector RemoteHost::GetFileInfo(const Vector& path) +{ + VectorMap out; + out.Reserve(path.GetCount()); + String request; + request << "@" << (int)(GetSysTime() - TimeBase()) << ":"; + for(int i = 0; i < path.GetCount(); i++) + { + String hp = GetHostPath(path[i]); + request << hp << "\n"; + FileInfo& fi = out.Add(hp); + (Time&)fi = Time::Low(); + fi.length = Null; + } + String result = RemoteExec(request); + const char *p = result; + while(*p) + { + const char *b = p; + while(*p && *p != '\n' && *p != '\t') + p++; + String fn(b, p); + Time time = Time::Low(); + int size = Null; + if(*p == '\t') + { + int t = ScanInt(p + 1, &p); + if(!IsNull(t)) + time = TimeBase() + t; + if(*p == '\t') + size = ScanInt(p + 1, &p); + } + int ifn = out.Find(fn); + if(ifn >= 0) + { + (Time&)out[ifn] = time; + out[ifn].length = size; + } + while(*p && *p++ != '\n') + ; + } + return out.PickValues(); +} + +void RemoteHost::DeleteFile(const Vector& path) +{ + String request = "-"; + for(int i = 0; i < path.GetCount(); i++) + request << GetHostPath(path[i]) << "\n"; + String out = RemoteExec(request); + if(!IsNull(out) && out != "OK") + PutVerbose(out); +} + +void RemoteHost::DeleteFolderDeep(const String& folder) +{ + String out = RemoteExec("~" + GetHostPath(folder)); + if(out != "OK") + PutConsole(out); +} + +void RemoteHost::ChDir(const String& path) +{ + chdir_path = GetHostPath(path); +} + +void RemoteHost::RealizeDir(const String& path) +{ + RemoteExec("*" + GetHostPath(path)); +} + +void RemoteHost::SaveFile(const String& path, const String& data) +{ + String request; + request << ">" << GetHostPath(path) + << "\t" << int(GetSysTime() - TimeBase()) + << "\t" << data.GetLength() + << "\t" << ASCII85Encode(BZ2Compress(data)) + << "\n"; + String out = RemoteExec(request); + if(out != "OK") + PutConsole(out); +} + +String RemoteHost::LoadFile(const String& path) +{ + String hpath = GetHostPath(path); + String request = "^" + hpath; + String out = RemoteExec(request); + const char *p = out; + while(*p && *p != '\n' && *p != '\t') + p++; + if(*p++ != '\t') + return String::GetVoid(); + int len = ScanInt(p, &p); + if(IsNull(len) || len <= 0 || *p++ != '\t') + return String::GetVoid(); + String data = BZ2Decompress(ASCII85Decode(p)); + if(data.GetLength() != len) + { + PutConsole(NFormat("%s: decompressed length (%d) doesn't match length in header (%d)", + hpath, data.GetLength(), len)); + return String::GetVoid(); + } + return data; +} + +int RemoteHost::Execute(const char *cmdline) +{ + int q = IdeConsoleExecute(StartProcess(cmdline), cmdline); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int RemoteHost::ExecuteWithInput(const char *cmdline) +{ + int q = IdeConsoleExecute(StartProcess(cmdline), cmdline); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int RemoteHost::Execute(const char *cmdline, Stream& out) +{ + int q = IdeConsoleExecute(StartProcess(cmdline), cmdline, &out, true); + PutVerbose(Format("Exitcode: %d", q)); + return q; +} + +int RemoteHost::AllocSlot() +{ + return IdeConsoleAllocSlot(); +} + +bool RemoteHost::Run(const char *cmdline, int slot, String key, int blitz_count) +{ + return IdeConsoleRun(StartProcess(cmdline), cmdline, NULL, false, slot, key, blitz_count); +} + +bool RemoteHost::Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) +{ + return IdeConsoleRun(StartProcess(cmdline), cmdline, &out, false, slot, key, blitz_count); +} + +bool RemoteHost::Wait() +{ + return IdeConsoleWait(); +} + +One RemoteHost::StartProcess(const char *cmdline) +{ + try { + PutVerbose(cmdline); + return StartRemoteProcess(host, port, cmdline, environment, REMOTE_TIMEOUT); + } + catch(...) { + return NULL; + } +} + +void RemoteHost::Launch(const char *_cmdline, bool) +{ +} + +void RemoteHost::AddFlags(Index& cfg) +{ + cfg.Add(os_type); +} diff --git a/uppsrc/ide/Core/Host.h b/uppsrc/ide/Core/Host.h new file mode 100644 index 000000000..090bebc4d --- /dev/null +++ b/uppsrc/ide/Core/Host.h @@ -0,0 +1,99 @@ +enum { REMOTE_TIMEOUT = 2000 }; + +extern String LinuxHostConsole; + +struct Host { + struct FileInfo : Time, Moveable { + int length; + }; + virtual String GetEnvironment() = 0; + virtual String GetHostPath(const String& path) = 0; + virtual String GetLocalPath(const String& path) = 0; + virtual String NormalizePath(const String& path) = 0; + virtual Vector GetFileInfo(const Vector& path) = 0; + virtual void DeleteFile(const Vector& path) = 0; + virtual void DeleteFolderDeep(const String& dir) = 0; + virtual void ChDir(const String& path) = 0; + virtual void RealizeDir(const String& path) = 0; + virtual void SaveFile(const String& path, const String& data) = 0; + virtual String LoadFile(const String& path) = 0; + virtual int Execute(const char *cmdline) = 0; + virtual int ExecuteWithInput(const char *cmdline) = 0; + virtual int Execute(const char *cmdline, Stream& out) = 0; + virtual int AllocSlot() = 0; + virtual bool Run(const char *cmdline, int slot, String key, int blitz_count) = 0; + virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count) = 0; + virtual bool Wait() = 0; + virtual One StartProcess(const char *cmdline) = 0; + virtual void Launch(const char *cmdline, bool console = false) = 0; + virtual void AddFlags(Index& cfg) = 0; + + virtual ~Host() {} +}; + +struct LocalHost : Host { + Vector exedirs; + String environment; + + String *cmdout; + void DoDir(const String& s); + + virtual String GetEnvironment(); + virtual String GetHostPath(const String& path); + virtual String GetLocalPath(const String& path); + virtual String NormalizePath(const String& path); + virtual Vector GetFileInfo(const Vector& path); + virtual void DeleteFile(const Vector& path); + virtual void DeleteFolderDeep(const String& dir); + virtual void ChDir(const String& path); + virtual void RealizeDir(const String& path); + virtual void SaveFile(const String& path, const String& data); + virtual String LoadFile(const String& path); + virtual int Execute(const char *cmdline); + virtual int ExecuteWithInput(const char *cmdline); + virtual int Execute(const char *cmdline, Stream& out); + virtual int AllocSlot(); + virtual bool Run(const char *cmdline, int slot, String key, int blitz_count); + virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count); + virtual bool Wait(); + virtual One StartProcess(const char *cmdline); + virtual void Launch(const char *cmdline, bool console); + virtual void AddFlags(Index& cfg); +}; + +struct RemoteHost : Host { + String host; + int port; + String os_type; +// bool transfer_files; + Vector path_map_local; + Vector path_map_remote; + String chdir_path; + String environment; + + static Time TimeBase() { return Time(2000, 1, 1); } + + virtual String GetEnvironment(); + virtual String GetHostPath(const String& path); + virtual String GetLocalPath(const String& path); + virtual String NormalizePath(const String& path); + virtual Vector GetFileInfo(const Vector& path); + virtual void DeleteFile(const Vector& path); + virtual void DeleteFolderDeep(const String& dir); + virtual void ChDir(const String& path); + virtual void RealizeDir(const String& path); + virtual void SaveFile(const String& path, const String& data); + virtual String LoadFile(const String& path); + virtual int Execute(const char *cmdline); + virtual int ExecuteWithInput(const char *cmdline); + virtual int Execute(const char *cmdline, Stream& out); + virtual int AllocSlot(); + virtual bool Run(const char *cmdline, int slot, String key, int blitz_count); + virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count); + virtual bool Wait(); + virtual One StartProcess(const char *cmdline); + virtual void Launch(const char *cmdline, bool console); + virtual void AddFlags(Index& cfg); + + String RemoteExec(String cmd); +}; diff --git a/uppsrc/ide/Common/Package.cpp b/uppsrc/ide/Core/Package.cpp similarity index 90% rename from uppsrc/ide/Common/Package.cpp rename to uppsrc/ide/Core/Package.cpp index 52ac2bcda..7fd6b5e46 100644 --- a/uppsrc/ide/Common/Package.cpp +++ b/uppsrc/ide/Core/Package.cpp @@ -1,401 +1,396 @@ -#include "Common.h" - -bool IsUppValueChar(int c) -{ - return c > ' ' && c != ',' && c != ';'; -} - -String ReadValue(CParser& p) -{ - p.Spaces(); - if(p.IsString()) - return p.ReadOneString(); - StringBuffer v; - while(IsUppValueChar(p.PeekChar())) - v.Cat(p.GetChar()); - p.Spaces(); - return v; -} - -static bool sMatchOr(CParser& p, const Vector& flag); - -static bool sMatchFlag(CParser& p, const Vector& flag) -{ - if(p.Char('!')) - return !sMatchFlag(p, flag); - if(p.Char('(')) { - bool b = sMatchOr(p, flag); - p.PassChar(')'); - return b; - } - if(p.IsEof()) - return true; - return FindIndex(flag, p.ReadId()) >= 0; -} - -static bool sMatchAnd(CParser& p, const Vector& flag) -{ - bool b = sMatchFlag(p, flag); - while(p.IsId() || p.IsChar('!') || p.IsChar('(') || p.Char2('&', '&') || p.Char('&')) - b = sMatchFlag(p, flag) && b; - return b; -} - -static bool sMatchOr(CParser& p, const Vector& flag) -{ - bool b = sMatchAnd(p, flag); - while(p.Char2('|', '|') || p.Char('|')) - b = sMatchFlag(p, flag) || b; - return b; -} - -bool MatchWhen_X(const String& when, const Vector& flag) -{ - CParser p(when); - bool b = sMatchOr(p, flag); - if(!p.IsEof()) - p.ThrowError("expected end of expression"); - return b; -} - -bool MatchWhen(const String& when, const Vector& flag) -{ - try { - return MatchWhen_X(when, flag); - } - catch(CParser::Error e) { - PutConsole(String().Cat() - << "Invalid When expression: " << AsCString(when) << ": " << e); - return false; - } -} - -String ReadWhen(CParser& p) { - String when; - if(p.Char('(')) - if(p.IsString()) - when = p.ReadString(); - else { - const char *b = p.GetPtr(); - int lvl = 0; - for(;;) { - if(p.IsEof() || lvl == 0 && p.IsChar(')')) - break; - if(p.Char('(')) - lvl++; - else - if(p.Char(')')) - lvl--; - else - p.SkipTerm(); - } - when = String(b, p.GetPtr()); - p.Char(')'); - } - return when; -} - -String AsStringWhen(const String& when) { - String out; - try { - Vector x; - MatchWhen_X(when, x); - out << '(' << when << ')'; - } - catch(CParser::Error) { - out << '(' << AsCString(when) << ')'; - } - return out; -} - -String CustomStep::AsString() const { - return "custom" + AsStringWhen(when) + ' ' + AsCString(ext) + ",\n\t" + - AsCString(command, 70, "\t") + ",\n\t" + - AsCString(output, 70, "\t") + ";\n\n"; -} - -void CustomStep::Load(CParser& p) throw(CParser::Error) { - when = ReadWhen(p); - ext = p.ReadString(); - p.PassChar(','); - command = p.ReadString(); - p.PassChar(','); - output = p.ReadString(); - p.PassChar(';'); -} - -String CustomStep::GetExt() const { - return ext[0] != '.' ? "." + ToLower(ext) : ToLower(ext); -} - -bool CustomStep::MatchExt(const char *fn) const { - return ToLower(GetFileExt(fn)) == GetExt(); -} - -bool LoadOpt(CParser& p, const char *key, Array& v) { - if(p.Id(key)) { - String when = ReadWhen(p); - do { - OptItem& m = v.Add(); - m.when = when; - m.text = ReadValue(p); - } - while(p.Char(',')); - return true; - } - return false; -} - -bool LoadFOpt(CParser& p, const char *key, Array& v) { - if(p.Id(key)) { - OptItem& m = v.Add(); - m.when = ReadWhen(p); - m.text = ReadValue(p); - return true; - } - return false; -} - -Package::Package() -{ - charset = 0; - optimize_speed = false; - noblitz = true; -} - -void Package::Load(const char *path) { - for(;;) { - charset = 0; - optimize_speed = false; - noblitz = false; - library.Clear(); - target.Clear(); - flag.Clear(); - option.Clear(); - link.Clear(); - uses.Clear(); - accepts.Clear(); - file.Clear(); - config.Clear(); - custom.Clear(); - description.Clear(); - String f = LoadFile(path); - time = FileGetTime(path); - CParser p(f); - try { - while(!p.IsEof()) { - if(!LoadOpt(p, "options", option) && - !LoadOpt(p, "link", link) && - !LoadOpt(p, "library", library) && - !LoadOpt(p, "flags", flag) && - !LoadOpt(p, "target", target) && - !LoadOpt(p, "uses", uses)) - if(p.Id("charset")) - charset = CharsetByName(p.ReadString()); - else - if(p.Id("description")) - description = p.ReadString(); - else - if(p.Id("acceptflags")) { - do - accepts.Add(ReadValue(p)); - while(p.Char(',')); - } - else - if(p.Id("noblitz")) - noblitz = true; - else - if(p.Id("optimize_speed")) - optimize_speed = true; - else - if(p.Id("optimize_size")) - optimize_speed = false; - else - if(p.Id("file")) { - do { - file.Add(ReadValue(p)); - while(!p.IsChar(',') && !p.IsChar(';')) { - if(!LoadFOpt(p, "options", file.Top().option) && - !LoadFOpt(p, "depends", file.Top().depends)) - if(p.Id("optimize_speed")) - file.Top().optimize_speed = true; - else - if(p.Id("optimize_size")) - file.Top().optimize_speed = false; - else - if(p.Id("readonly")) - file.Top().readonly = true; - else - if(p.Id("separator")) - file.Top().separator = true; - else - if(p.Id("charset")) - file.Top().charset = CharsetByName(p.ReadString()); - else - if(p.Id("tabsize")) - file.Top().tabsize = minmax(p.ReadInt(), 1, 20); - else - if(p.Id("font")) - file.Top().font = minmax(p.ReadInt(), 0, 3); - else - if(p.Id("highlight")) - file.Top().highlight = p.ReadId(); - else - p.ThrowError("invalid keyword"); - } - } - while(p.Char(',')); - } - else - if(p.Id("mainconfig")) { - do { - String c = p.ReadString(); - p.Char('='); - p.Id("external"); // Backward compatibility... - p.Id("console"); - p.Id("remotelinux"); - p.Id("normal"); - String f = p.ReadString(); - Config& cf = config.Add(); - cf.name = c; - cf.param = f; - } - while(p.Char(',')); - } - else - if(p.Id("custom")) - custom.Add().Load(p); - else - p.ThrowError("invalid keyword"); - p.Char(';'); - } - return; - } - catch(CParser::Error error) { - prompt: - switch(Prompt(Ctrl::GetAppName(), CtrlImg::exclamation(), - error + "&while parsing package " + DeQtf(path), - "Edit \\& Retry", "Ignore", "Stop")) { - case 0: - if(!PromptYesNo("Ignoring will damage package. Everything past the " - "point of error will be lost.&Do you want to continue ?")) - goto prompt; - Save(path); - return; - case 1: { - TopWindow win; - LineEdit edit; - edit.Set(f); - edit.SetCursor(edit.GetPos(p.GetLine() - 1)); - win.Title(path); - win.Add(edit.SizePos()); - win.Run(); - SaveFile(path, edit.Get()); - } - break; - case -1: - exit(1); - } - } - } -} - -String WriteValue(const String& x) { - for(const char *s = x; s < x.End(); s++) - if(!IsUppValueChar(*s)) - return AsCString(x); - return x; -} - -void putopt(Stream& out, const char *key, const Array& m) { - bool was = false; - for(int i = 0; i < m.GetCount(); i++) - if(IsNull(m[i].when)) { - if(was) - out << ",\n\t"; - else - out << key << "\n\t"; - out << WriteValue(m[i].text); - was = true; - } - if(was) - out << ";\n\n"; - for(int i = 0; i < m.GetCount(); i++) - if(!IsNull(m[i].when)) - out << key << AsStringWhen(m[i].when) << ' ' << WriteValue(m[i].text) << ";\n\n"; -} - -void putp(Stream& out, const char *key, const Vector& v) -{ - if(v.GetCount()) { - out << key << "\n"; - for(int i = 0; i < v.GetCount(); i++) { - if(i) out << ",\n"; - out << '\t' << WriteValue(v[i]); - } - out << ";\n\n"; - } -} - -void putfopt(Stream& out, const char *key, const Array& m) -{ - for(int i = 0; i < m.GetCount(); i++) - out << "\n\t\t" << key << AsStringWhen(m[i].when) << ' ' << WriteValue(m[i].text); -} - -bool Package::Save(const char *path) const { - StringStream out; - if(description.GetCount()) - out << "description " << AsCString(description) << ";\n\n"; - if(charset > 0 && charset < CharsetCount() || charset == CHARSET_UTF8) - out << "charset " << AsCString(CharsetName(charset)) << ";\n\n"; - if(optimize_speed) - out << "optimize_speed;\n\n"; - if(noblitz) - out << "noblitz;\n\n"; - putp(out, "acceptflags", accepts); - putopt(out, "flags", flag); - putopt(out, "uses", uses); - putopt(out, "target", target); - putopt(out, "library", library); - putopt(out, "options", option); - putopt(out, "link", link); - if(file.GetCount()) { - out << "file\n"; - int i; - for(i = 0; i < file.GetCount(); i++) { - if(i) out << ",\n"; - const File& f = file[i]; - out << '\t' << WriteValue(f); - if(f.readonly) - out << " readonly"; - if(f.separator) - out << " separator"; - if(f.tabsize > 0) - out << " tabsize " << f.tabsize; - if(f.font > 0) - out << " font " << f.font; - if(f.optimize_speed) - out << " optimize_speed"; - if(f.charset > 0 && f.charset < CharsetCount() || f.charset == CHARSET_UTF8) - out << " charset " << AsCString(CharsetName(f.charset)); - if(!IsNull(f.highlight)) - out << " highlight " << f.highlight; - putfopt(out, "options", f.option); - putfopt(out, "depends", f.depends); - } - out << ";\n\n"; - } - if(config.GetCount()) { - out << "mainconfig\n"; - for(int i = 0; i < config.GetCount(); i++) { - const Config& f = config[i]; - if(i) out << ",\n"; - out << '\t' << AsCString(f.name) << " = " << AsCString(f.param); - } - out << ";\n\n"; - } - for(int i = 0; i < custom.GetCount(); i++) - out << custom[i].AsString(); - return SaveChangedFile(path, out.GetResult()); -} +#include "Core.h" + +bool IsUppValueChar(int c) +{ + return c > ' ' && c != ',' && c != ';'; +} + +String ReadValue(CParser& p) +{ + p.Spaces(); + if(p.IsString()) + return p.ReadOneString(); + StringBuffer v; + while(IsUppValueChar(p.PeekChar())) + v.Cat(p.GetChar()); + p.Spaces(); + return v; +} + +static bool sMatchOr(CParser& p, const Vector& flag); + +static bool sMatchFlag(CParser& p, const Vector& flag) +{ + if(p.Char('!')) + return !sMatchFlag(p, flag); + if(p.Char('(')) { + bool b = sMatchOr(p, flag); + p.PassChar(')'); + return b; + } + if(p.IsEof()) + return true; + return FindIndex(flag, p.ReadId()) >= 0; +} + +static bool sMatchAnd(CParser& p, const Vector& flag) +{ + bool b = sMatchFlag(p, flag); + while(p.IsId() || p.IsChar('!') || p.IsChar('(') || p.Char2('&', '&') || p.Char('&')) + b = sMatchFlag(p, flag) && b; + return b; +} + +static bool sMatchOr(CParser& p, const Vector& flag) +{ + bool b = sMatchAnd(p, flag); + while(p.Char2('|', '|') || p.Char('|')) + b = sMatchFlag(p, flag) || b; + return b; +} + +bool MatchWhen_X(const String& when, const Vector& flag) +{ + CParser p(when); + bool b = sMatchOr(p, flag); + if(!p.IsEof()) + p.ThrowError("expected end of expression"); + return b; +} + +bool MatchWhen(const String& when, const Vector& flag) +{ + try { + return MatchWhen_X(when, flag); + } + catch(CParser::Error e) { + PutConsole(String().Cat() + << "Invalid When expression: " << AsCString(when) << ": " << e); + return false; + } +} + +String ReadWhen(CParser& p) { + String when; + if(p.Char('(')) + if(p.IsString()) + when = p.ReadString(); + else { + const char *b = p.GetPtr(); + int lvl = 0; + for(;;) { + if(p.IsEof() || lvl == 0 && p.IsChar(')')) + break; + if(p.Char('(')) + lvl++; + else + if(p.Char(')')) + lvl--; + else + p.SkipTerm(); + } + when = String(b, p.GetPtr()); + p.Char(')'); + } + return when; +} + +String AsStringWhen(const String& when) { + String out; + try { + Vector x; + MatchWhen_X(when, x); + out << '(' << when << ')'; + } + catch(CParser::Error) { + out << '(' << AsCString(when) << ')'; + } + return out; +} + +String CustomStep::AsString() const { + return "custom" + AsStringWhen(when) + ' ' + AsCString(ext) + ",\n\t" + + AsCString(command, 70, "\t") + ",\n\t" + + AsCString(output, 70, "\t") + ";\n\n"; +} + +void CustomStep::Load(CParser& p) throw(CParser::Error) { + when = ReadWhen(p); + ext = p.ReadString(); + p.PassChar(','); + command = p.ReadString(); + p.PassChar(','); + output = p.ReadString(); + p.PassChar(';'); +} + +String CustomStep::GetExt() const { + return ext[0] != '.' ? "." + ToLower(ext) : ToLower(ext); +} + +bool CustomStep::MatchExt(const char *fn) const { + return ToLower(GetFileExt(fn)) == GetExt(); +} + +bool LoadOpt(CParser& p, const char *key, Array& v) { + if(p.Id(key)) { + String when = ReadWhen(p); + do { + OptItem& m = v.Add(); + m.when = when; + m.text = ReadValue(p); + } + while(p.Char(',')); + return true; + } + return false; +} + +bool LoadFOpt(CParser& p, const char *key, Array& v) { + if(p.Id(key)) { + OptItem& m = v.Add(); + m.when = ReadWhen(p); + m.text = ReadValue(p); + return true; + } + return false; +} + +Package::Package() +{ + charset = 0; + optimize_speed = false; + noblitz = true; +} + +bool StdResolver(const String& error, const String& path, int line) +{ + PutConsole("Invalid package: " + path); + exit(1); + return false; +} + +static bool (*sResolve)(const String& error, const String& path, int line) = StdResolver; + +void Package::SetPackageResolver(bool (*Resolve)(const String& error, const String& path, int line)) +{ + sResolve = Resolve; +} + +void Package::Load(const char *path) +{ + for(;;) { + charset = 0; + optimize_speed = false; + noblitz = false; + library.Clear(); + target.Clear(); + flag.Clear(); + option.Clear(); + link.Clear(); + uses.Clear(); + accepts.Clear(); + file.Clear(); + config.Clear(); + custom.Clear(); + description.Clear(); + String f = LoadFile(path); + time = FileGetTime(path); + CParser p(f); + try { + while(!p.IsEof()) { + if(!LoadOpt(p, "options", option) && + !LoadOpt(p, "link", link) && + !LoadOpt(p, "library", library) && + !LoadOpt(p, "flags", flag) && + !LoadOpt(p, "target", target) && + !LoadOpt(p, "uses", uses)) + if(p.Id("charset")) + charset = CharsetByName(p.ReadString()); + else + if(p.Id("description")) + description = p.ReadString(); + else + if(p.Id("acceptflags")) { + do + accepts.Add(ReadValue(p)); + while(p.Char(',')); + } + else + if(p.Id("noblitz")) + noblitz = true; + else + if(p.Id("optimize_speed")) + optimize_speed = true; + else + if(p.Id("optimize_size")) + optimize_speed = false; + else + if(p.Id("file")) { + do { + file.Add(ReadValue(p)); + while(!p.IsChar(',') && !p.IsChar(';')) { + if(!LoadFOpt(p, "options", file.Top().option) && + !LoadFOpt(p, "depends", file.Top().depends)) + if(p.Id("optimize_speed")) + file.Top().optimize_speed = true; + else + if(p.Id("optimize_size")) + file.Top().optimize_speed = false; + else + if(p.Id("readonly")) + file.Top().readonly = true; + else + if(p.Id("separator")) + file.Top().separator = true; + else + if(p.Id("charset")) + file.Top().charset = CharsetByName(p.ReadString()); + else + if(p.Id("tabsize")) + file.Top().tabsize = minmax(p.ReadInt(), 1, 20); + else + if(p.Id("font")) + file.Top().font = minmax(p.ReadInt(), 0, 3); + else + if(p.Id("highlight")) + file.Top().highlight = p.ReadId(); + else + p.ThrowError("invalid keyword"); + } + } + while(p.Char(',')); + } + else + if(p.Id("mainconfig")) { + do { + String c = p.ReadString(); + p.Char('='); + p.Id("external"); // Backward compatibility... + p.Id("console"); + p.Id("remotelinux"); + p.Id("normal"); + String f = p.ReadString(); + Config& cf = config.Add(); + cf.name = c; + cf.param = f; + } + while(p.Char(',')); + } + else + if(p.Id("custom")) + custom.Add().Load(p); + else + p.ThrowError("invalid keyword"); + p.Char(';'); + } + return; + } + catch(CParser::Error error) { + if(sResolve(error, path, p.GetLine() - 1)) + break; + Save(path); + return; + } + } +} + +String WriteValue(const String& x) { + for(const char *s = x; s < x.End(); s++) + if(!IsUppValueChar(*s)) + return AsCString(x); + return x; +} + +void putopt(Stream& out, const char *key, const Array& m) { + bool was = false; + for(int i = 0; i < m.GetCount(); i++) + if(IsNull(m[i].when)) { + if(was) + out << ",\n\t"; + else + out << key << "\n\t"; + out << WriteValue(m[i].text); + was = true; + } + if(was) + out << ";\n\n"; + for(int i = 0; i < m.GetCount(); i++) + if(!IsNull(m[i].when)) + out << key << AsStringWhen(m[i].when) << ' ' << WriteValue(m[i].text) << ";\n\n"; +} + +void putp(Stream& out, const char *key, const Vector& v) +{ + if(v.GetCount()) { + out << key << "\n"; + for(int i = 0; i < v.GetCount(); i++) { + if(i) out << ",\n"; + out << '\t' << WriteValue(v[i]); + } + out << ";\n\n"; + } +} + +void putfopt(Stream& out, const char *key, const Array& m) +{ + for(int i = 0; i < m.GetCount(); i++) + out << "\n\t\t" << key << AsStringWhen(m[i].when) << ' ' << WriteValue(m[i].text); +} + +bool Package::Save(const char *path) const { + StringStream out; + if(description.GetCount()) + out << "description " << AsCString(description) << ";\n\n"; + if(charset > 0 && charset < CharsetCount() || charset == CHARSET_UTF8) + out << "charset " << AsCString(CharsetName(charset)) << ";\n\n"; + if(optimize_speed) + out << "optimize_speed;\n\n"; + if(noblitz) + out << "noblitz;\n\n"; + putp(out, "acceptflags", accepts); + putopt(out, "flags", flag); + putopt(out, "uses", uses); + putopt(out, "target", target); + putopt(out, "library", library); + putopt(out, "options", option); + putopt(out, "link", link); + if(file.GetCount()) { + out << "file\n"; + int i; + for(i = 0; i < file.GetCount(); i++) { + if(i) out << ",\n"; + const File& f = file[i]; + out << '\t' << WriteValue(f); + if(f.readonly) + out << " readonly"; + if(f.separator) + out << " separator"; + if(f.tabsize > 0) + out << " tabsize " << f.tabsize; + if(f.font > 0) + out << " font " << f.font; + if(f.optimize_speed) + out << " optimize_speed"; + if(f.charset > 0 && f.charset < CharsetCount() || f.charset == CHARSET_UTF8) + out << " charset " << AsCString(CharsetName(f.charset)); + if(!IsNull(f.highlight)) + out << " highlight " << f.highlight; + putfopt(out, "options", f.option); + putfopt(out, "depends", f.depends); + } + out << ";\n\n"; + } + if(config.GetCount()) { + out << "mainconfig\n"; + for(int i = 0; i < config.GetCount(); i++) { + const Config& f = config[i]; + if(i) out << ",\n"; + out << '\t' << AsCString(f.name) << " = " << AsCString(f.param); + } + out << ";\n\n"; + } + for(int i = 0; i < custom.GetCount(); i++) + out << custom[i].AsString(); + return SaveChangedFile(path, out.GetResult()); +} diff --git a/uppsrc/ide/Common/Workspace.cpp b/uppsrc/ide/Core/Workspace.cpp similarity index 95% rename from uppsrc/ide/Common/Workspace.cpp rename to uppsrc/ide/Core/Workspace.cpp index f3ea28e0d..c56b0724d 100644 --- a/uppsrc/ide/Common/Workspace.cpp +++ b/uppsrc/ide/Core/Workspace.cpp @@ -1,395 +1,395 @@ -#include "Common.h" - -String GetLocalDir() -{ - return ConfigFile("UppLocal"); -} - -String LocalPath(const String& filename) -{ - return AppendFileName(GetLocalDir(), filename); -} - -Vector IgnoreList() -{ - Vector ignore; - const Workspace& wspc = GetIdeWorkspace(); - for(int i = 0; i < wspc.GetCount(); i++) { - const Package& pk = wspc.GetPackage(i); - for(int j = 0; j < pk.GetCount(); j++) - if(!pk[j].separator && pk[j] == "ignorelist") { - FileIn in(SourcePath(wspc[i], pk[j])); - while(in && !in.IsEof()) { - String s = in.GetLine(); - if(!s.IsEmpty()) - ignore.Add(s); - } - } - } - return ignore; -} - -String FollowCygwinSymlink(const String& file) { - for(String fn = file;;) { - if(fn.IsEmpty()) - return fn; - FileIn fi(fn); - if(!fi.IsOpen()) - return fn; - char buffer[10]; - if(!fi.GetAll(buffer, 10) || memcmp(buffer, "!", 10)) - return fn; - fn = NormalizePath(LoadStream(fi), GetFileDirectory(fn)); - } -} - -const char *SemiTextTest::Accept(const char *s) const { - if(*s != ';') return NULL; - s++; - while(*s == ' ') s++; - return s; -}; - -Vector SplitDirs(const char *s) { - return Split(s, Single()); -} - -static GLOBAL_VARP(String, varsname, ("default")); -typedef VectorMap sHT; -static GLOBAL_VAR(sHT, sVar); - -String GetVarsName() { - return varsname(); -} - -String VarFilePath(String name) { - return ConfigFile(name + ".var"); -} - -String VarFilePath() { - return VarFilePath(GetVarsName()); -} - -bool SaveVarFile(const char *filename, const VectorMap& var) -{ - FileOut out(filename); - for(int i = 0; i < var.GetCount(); i++) - out << var.GetKey(i) << " = " << AsCString(var[i]) << ";\n"; - out.Close(); - return !out.IsError(); -} - -bool SaveVars(const char *name) -{ - if(!SaveVarFile(VarFilePath(name), sVar())) - return false; - varsname() = name; - return true; -} - -bool LoadVarFile(const char *name, VectorMap& _var) -{ - try { - VectorMap var; - String env = LoadFile(name); - CParser p(env); - while(!p.IsEof()) { - String v = p.ReadId(); - p.Char('='); - if(p.IsString()) - var.GetAdd(v) = p.ReadString(); - else { - String ln; - while(p.PeekChar() != '\r' && p.PeekChar() != '\n' && p.PeekChar() != ';') - ln.Cat(p.GetChar()); - var.GetAdd(v) = ln; - p.Spaces(); - } - p.Char(';'); - } - _var = var; - return true; - } - catch(...) { - return false; - } -} - -bool LoadVars(const char *name) { - varsname() = (name && *name ? name : "default"); - return LoadVarFile(VarFilePath(), sVar()); -} - -String GetVar(const String& var) { - return sVar().Get(var, Null); -} - -void SetVar(const String& var, const String& val) { - sVar().GetAdd(var) = val; - SaveVars(GetVarsName()); -} - -Vector GetUppDirs() { - return SplitDirs(GetVar("UPP")); -} - -String GetUppDir() { - Vector s = GetUppDirs(); -#ifdef PLATFORM_WIN32 - return s.GetCount() == 0 ? GetFileFolder(GetExeFilePath()) : s[0]; -#endif -#ifdef PLATFORM_POSIX - return s.GetCount() == 0 ? GetHomeDirectory() : s[0]; -#endif -} - -bool IsCSourceFile(const char *path) -{ - String ext = ToLower(GetFileExt(path)); - return ext == ".cpp" || ext == ".c" || ext == ".cc" || ext == ".cxx" || ext == ".icpp"; -} - -bool IsCHeaderFile(const char *path) -{ - String ext = ToLower(GetFileExt(path)); - return ext == ".h" || ext == ".hpp" || ext == ".hh" || ext == ".hxx"; -} - -bool IsFullDirectory(const String& d) { - if(IsFullPath(d)) { - FindFile ff(d); - if(ff) return ff.IsDirectory(); - } - return false; -} - -bool IsFolder(const String& path) -{ - if(IsNull(path) || *path.Last() == '\\' || *path.Last() == '/' || *path.Last() == ':') - return true; - if(path.Find('?') >= 0 || path.Find('*') >= 0) - return false; - FindFile ff(path); - return ff && ff.IsDirectory(); -} - -String PackagePath(const String& name) { - String uppfile = NativePath(name); - if(IsFullPath(uppfile)) return NormalizePath(uppfile); - Vector d = GetUppDirs(); - String p; - for(int i = 0; i < d.GetCount(); i++) { - p = NormalizePath(AppendFileName(AppendFileName(d[i], uppfile), - GetFileName(uppfile)) + ".upp"); - if(FileExists(p)) return p; - } - return d.GetCount() ? NormalizePath(AppendFileName(AppendFileName(d[0], uppfile), - GetFileName(uppfile)) + ".upp") : ""; -} - -String SourcePath(const String& package, const String& file) { - if(IsFullPath(file)) return NativePath(file); - return NormalizePath(AppendFileName(GetFileFolder(PackagePath(package)), file)); -} - -bool IsNestReadOnly(const String& path) -{ - Vector d = GetUppDirs(); - for(int i = 0; i < d.GetCount(); i++) - if(path.StartsWith(d[i]) && FileExists(AppendFileName(d[i], "readonly"))) - return true; - return false; -} - -String GetAnyFileName(const char *path) -{ - const char *p = path; - for(char c; (c = *path++) != 0;) - if(c == '\\' || c == '/' || c == ':') - p = path; - return p; -} - -String GetAnyFileTitle(const char *path) -{ - String fn = GetAnyFileName(path); - const char *p = fn; - const char *e = p; - while(*e && *e != '.') - e++; - return String(p, e); -} - -String CatAnyPath(String path, const char *more) -{ - if(!more || !*more) - return path; - if(!path.IsEmpty() && *path.Last() != '\\' && *path.Last() != '/' && - *more != '\\' && *more != '/') -#ifdef PLATFORM_WIN32 - path.Cat('\\'); -#else - path.Cat('/'); -#endif - path.Cat(more); - return path; -} - - -void SplitHostName(const char *hostname, String& host, int& port) { - enum { DEFAULT_REMOTE_PORT = 2346 }; - const char *p = hostname; - while(p && *p != ':') - p++; - host = String(hostname, p); - if(*p++ == ':' && IsDigit(*p)) - port = stou(p); - else - port = DEFAULT_REMOTE_PORT; -} - -Vector SplitFlags0(const char *flags) { - return Split(flags, CharFilterTextTest(CharFilterWhitespace)); -} - -Vector SplitFlags(const char *flags, bool main, const Vector& accepts) -{ - Vector v = SplitFlags0(flags); - Vector h; - for(int i = 0; i < v.GetCount(); i++) - if(v[i][0] == '.') { - String f = v[i].Mid(1); - if(main || FindIndex(accepts, f) >= 0) - h.Add(v[i].Mid(1)); - } - else - h.Add(v[i]); - if(main) - h.Add("MAIN"); - return h; -} - -Vector SplitFlags(const char *flags, bool main) -{ - Vector dummy; - return SplitFlags(flags, main, dummy); -} - -bool HasFlag(const Vector& conf, const char *flag) { - return FindIndex(conf, flag) >= 0; -} - -Vector Combine(const Vector& conf, const char *flags) { - Vector cfg(conf, 1); - CParser p(flags); - while(!p.IsEof()) { - bool isnot = p.Char('!'); - if(!p.IsId()) break; - String flg = p.ReadId(); - int i = FindIndex(cfg, flg); - if(isnot) { - if(i >= 0) cfg.Remove(i); - } - else - if(i < 0) cfg.Add(flg); - } - return cfg; -} - -String Gather(const Array& set, const Vector& conf, bool nospace) { - String s; - for(int i = 0; i < set.GetCount(); i++) - if(MatchWhen(set[i].when, conf)) { - if(!nospace && !s.IsEmpty()) s.Cat(' '); - s.Cat(set[i].text); - } - return s; -} - -int GetType(const Vector& conf, const char *flags) { - Vector f = SplitFlags(flags); - int q = FLAG_UNDEFINED; - for(int i = 0; i < f.GetCount(); i++) - if(HasFlag(conf, f[i])) - if(q == FLAG_UNDEFINED) - q = i; - else - q = FLAG_MISMATCH; - return q; -} - -String RemoveType(Vector& conf, const char *flags) -{ - String old; - Index f = SplitFlags(flags); - for(int i = conf.GetCount(); --i >= 0;) - if(f.Find(conf[i]) >= 0) - { - old = conf[i]; - conf.Remove(i); - } - return old; -} - -int GetType(const Vector& conf, const char *flags, int def) { - int q = GetType(conf, flags); - return q == FLAG_UNDEFINED ? def : q; -} - -bool GetFlag(const Vector& conf, const char *flag) { - return FindIndex(conf, flag) >= 0; -} - -void Workspace::AddLoad(const String& name, bool match, const Vector& flag) -{ - package.Add(name).Load(PackagePath(name)); -} - -void Workspace::AddUses(Package& p, bool match, const Vector& flag) -{ - int q = package.GetCount(); - for(int i = 0; i < p.uses.GetCount(); i++) - if((!match || MatchWhen(p.uses[i].when, flag)) && package.Find(p.uses[i].text) < 0) - AddLoad(p.uses[i].text, match, flag); - for(int i = q; i < package.GetCount(); i++) - AddUses(package[i], match, flag); -} - -void Workspace::Scan(const char *prjname) { - package.Clear(); - AddLoad(prjname, false, Vector()); - AddUses(package[0], false, Vector()); -} - -void Workspace::Scan(const char *prjname, const Vector& flag) { - package.Clear(); - AddLoad(prjname, true, flag); - AddUses(package[0], true, flag); -} - -void Workspace::Dump() { - for(int i = 0; i < package.GetCount(); i++) { - Package& prj = package[i]; - LOG("Package " << package.GetKey(i)); - LOG(" file "); - for(int i = 0; i < prj.file.GetCount(); i++) - LOG("\t" << prj.file[i]); - } -} - -Vector Workspace::GetAllAccepts(int pk) const -{ - Index accepts; - Index pkg; - pkg.Add(pk); - for(int i = 0; i < pkg.GetCount(); i++) { - const Package& p = package[pkg[i]]; - FindAppend(accepts, p.accepts); - for(int u = 0; u < p.uses.GetCount(); u++) { - int f = package.Find(p.uses[u].text); - if(f >= 0) - pkg.FindAdd(f); - } - } - return accepts.PickKeys(); -} +#include "Core.h" + +String GetLocalDir() +{ + return ConfigFile("UppLocal"); +} + +String LocalPath(const String& filename) +{ + return AppendFileName(GetLocalDir(), filename); +} + +Vector IgnoreList() +{ + Vector ignore; + const Workspace& wspc = GetIdeWorkspace(); + for(int i = 0; i < wspc.GetCount(); i++) { + const Package& pk = wspc.GetPackage(i); + for(int j = 0; j < pk.GetCount(); j++) + if(!pk[j].separator && pk[j] == "ignorelist") { + FileIn in(SourcePath(wspc[i], pk[j])); + while(in && !in.IsEof()) { + String s = in.GetLine(); + if(!s.IsEmpty()) + ignore.Add(s); + } + } + } + return ignore; +} + +String FollowCygwinSymlink(const String& file) { + for(String fn = file;;) { + if(fn.IsEmpty()) + return fn; + FileIn fi(fn); + if(!fi.IsOpen()) + return fn; + char buffer[10]; + if(!fi.GetAll(buffer, 10) || memcmp(buffer, "!", 10)) + return fn; + fn = NormalizePath(LoadStream(fi), GetFileDirectory(fn)); + } +} + +const char *SemiTextTest::Accept(const char *s) const { + if(*s != ';') return NULL; + s++; + while(*s == ' ') s++; + return s; +}; + +Vector SplitDirs(const char *s) { + return Split(s, Single()); +} + +static GLOBAL_VARP(String, varsname, ("default")); +typedef VectorMap sHT; +static GLOBAL_VAR(sHT, sVar); + +String GetVarsName() { + return varsname(); +} + +String VarFilePath(String name) { + return ConfigFile(name + ".var"); +} + +String VarFilePath() { + return VarFilePath(GetVarsName()); +} + +bool SaveVarFile(const char *filename, const VectorMap& var) +{ + FileOut out(filename); + for(int i = 0; i < var.GetCount(); i++) + out << var.GetKey(i) << " = " << AsCString(var[i]) << ";\n"; + out.Close(); + return !out.IsError(); +} + +bool SaveVars(const char *name) +{ + if(!SaveVarFile(VarFilePath(name), sVar())) + return false; + varsname() = name; + return true; +} + +bool LoadVarFile(const char *name, VectorMap& _var) +{ + try { + VectorMap var; + String env = LoadFile(name); + CParser p(env); + while(!p.IsEof()) { + String v = p.ReadId(); + p.Char('='); + if(p.IsString()) + var.GetAdd(v) = p.ReadString(); + else { + String ln; + while(p.PeekChar() != '\r' && p.PeekChar() != '\n' && p.PeekChar() != ';') + ln.Cat(p.GetChar()); + var.GetAdd(v) = ln; + p.Spaces(); + } + p.Char(';'); + } + _var = var; + return true; + } + catch(...) { + return false; + } +} + +bool LoadVars(const char *name) { + varsname() = (name && *name ? name : "default"); + return LoadVarFile(VarFilePath(), sVar()); +} + +String GetVar(const String& var) { + return sVar().Get(var, Null); +} + +void SetVar(const String& var, const String& val) { + sVar().GetAdd(var) = val; + SaveVars(GetVarsName()); +} + +Vector GetUppDirs() { + return SplitDirs(GetVar("UPP")); +} + +String GetUppDir() { + Vector s = GetUppDirs(); +#ifdef PLATFORM_WIN32 + return s.GetCount() == 0 ? GetFileFolder(GetExeFilePath()) : s[0]; +#endif +#ifdef PLATFORM_POSIX + return s.GetCount() == 0 ? GetHomeDirectory() : s[0]; +#endif +} + +bool IsCSourceFile(const char *path) +{ + String ext = ToLower(GetFileExt(path)); + return ext == ".cpp" || ext == ".c" || ext == ".cc" || ext == ".cxx" || ext == ".icpp"; +} + +bool IsCHeaderFile(const char *path) +{ + String ext = ToLower(GetFileExt(path)); + return ext == ".h" || ext == ".hpp" || ext == ".hh" || ext == ".hxx"; +} + +bool IsFullDirectory(const String& d) { + if(IsFullPath(d)) { + FindFile ff(d); + if(ff) return ff.IsDirectory(); + } + return false; +} + +bool IsFolder(const String& path) +{ + if(IsNull(path) || *path.Last() == '\\' || *path.Last() == '/' || *path.Last() == ':') + return true; + if(path.Find('?') >= 0 || path.Find('*') >= 0) + return false; + FindFile ff(path); + return ff && ff.IsDirectory(); +} + +String PackagePath(const String& name) { + String uppfile = NativePath(name); + if(IsFullPath(uppfile)) return NormalizePath(uppfile); + Vector d = GetUppDirs(); + String p; + for(int i = 0; i < d.GetCount(); i++) { + p = NormalizePath(AppendFileName(AppendFileName(d[i], uppfile), + GetFileName(uppfile)) + ".upp"); + if(FileExists(p)) return p; + } + return d.GetCount() ? NormalizePath(AppendFileName(AppendFileName(d[0], uppfile), + GetFileName(uppfile)) + ".upp") : ""; +} + +String SourcePath(const String& package, const String& file) { + if(IsFullPath(file)) return NativePath(file); + return NormalizePath(AppendFileName(GetFileFolder(PackagePath(package)), file)); +} + +bool IsNestReadOnly(const String& path) +{ + Vector d = GetUppDirs(); + for(int i = 0; i < d.GetCount(); i++) + if(path.StartsWith(d[i]) && FileExists(AppendFileName(d[i], "readonly"))) + return true; + return false; +} + +String GetAnyFileName(const char *path) +{ + const char *p = path; + for(char c; (c = *path++) != 0;) + if(c == '\\' || c == '/' || c == ':') + p = path; + return p; +} + +String GetAnyFileTitle(const char *path) +{ + String fn = GetAnyFileName(path); + const char *p = fn; + const char *e = p; + while(*e && *e != '.') + e++; + return String(p, e); +} + +String CatAnyPath(String path, const char *more) +{ + if(!more || !*more) + return path; + if(!path.IsEmpty() && *path.Last() != '\\' && *path.Last() != '/' && + *more != '\\' && *more != '/') +#ifdef PLATFORM_WIN32 + path.Cat('\\'); +#else + path.Cat('/'); +#endif + path.Cat(more); + return path; +} + + +void SplitHostName(const char *hostname, String& host, int& port) { + enum { DEFAULT_REMOTE_PORT = 2346 }; + const char *p = hostname; + while(p && *p != ':') + p++; + host = String(hostname, p); + if(*p++ == ':' && IsDigit(*p)) + port = stou(p); + else + port = DEFAULT_REMOTE_PORT; +} + +Vector SplitFlags0(const char *flags) { + return Split(flags, CharFilterTextTest(CharFilterWhitespace)); +} + +Vector SplitFlags(const char *flags, bool main, const Vector& accepts) +{ + Vector v = SplitFlags0(flags); + Vector h; + for(int i = 0; i < v.GetCount(); i++) + if(v[i][0] == '.') { + String f = v[i].Mid(1); + if(main || FindIndex(accepts, f) >= 0) + h.Add(v[i].Mid(1)); + } + else + h.Add(v[i]); + if(main) + h.Add("MAIN"); + return h; +} + +Vector SplitFlags(const char *flags, bool main) +{ + Vector dummy; + return SplitFlags(flags, main, dummy); +} + +bool HasFlag(const Vector& conf, const char *flag) { + return FindIndex(conf, flag) >= 0; +} + +Vector Combine(const Vector& conf, const char *flags) { + Vector cfg(conf, 1); + CParser p(flags); + while(!p.IsEof()) { + bool isnot = p.Char('!'); + if(!p.IsId()) break; + String flg = p.ReadId(); + int i = FindIndex(cfg, flg); + if(isnot) { + if(i >= 0) cfg.Remove(i); + } + else + if(i < 0) cfg.Add(flg); + } + return cfg; +} + +String Gather(const Array& set, const Vector& conf, bool nospace) { + String s; + for(int i = 0; i < set.GetCount(); i++) + if(MatchWhen(set[i].when, conf)) { + if(!nospace && !s.IsEmpty()) s.Cat(' '); + s.Cat(set[i].text); + } + return s; +} + +int GetType(const Vector& conf, const char *flags) { + Vector f = SplitFlags(flags); + int q = FLAG_UNDEFINED; + for(int i = 0; i < f.GetCount(); i++) + if(HasFlag(conf, f[i])) + if(q == FLAG_UNDEFINED) + q = i; + else + q = FLAG_MISMATCH; + return q; +} + +String RemoveType(Vector& conf, const char *flags) +{ + String old; + Index f = SplitFlags(flags); + for(int i = conf.GetCount(); --i >= 0;) + if(f.Find(conf[i]) >= 0) + { + old = conf[i]; + conf.Remove(i); + } + return old; +} + +int GetType(const Vector& conf, const char *flags, int def) { + int q = GetType(conf, flags); + return q == FLAG_UNDEFINED ? def : q; +} + +bool GetFlag(const Vector& conf, const char *flag) { + return FindIndex(conf, flag) >= 0; +} + +void Workspace::AddLoad(const String& name, bool match, const Vector& flag) +{ + package.Add(name).Load(PackagePath(name)); +} + +void Workspace::AddUses(Package& p, bool match, const Vector& flag) +{ + int q = package.GetCount(); + for(int i = 0; i < p.uses.GetCount(); i++) + if((!match || MatchWhen(p.uses[i].when, flag)) && package.Find(p.uses[i].text) < 0) + AddLoad(p.uses[i].text, match, flag); + for(int i = q; i < package.GetCount(); i++) + AddUses(package[i], match, flag); +} + +void Workspace::Scan(const char *prjname) { + package.Clear(); + AddLoad(prjname, false, Vector()); + AddUses(package[0], false, Vector()); +} + +void Workspace::Scan(const char *prjname, const Vector& flag) { + package.Clear(); + AddLoad(prjname, true, flag); + AddUses(package[0], true, flag); +} + +void Workspace::Dump() { + for(int i = 0; i < package.GetCount(); i++) { + Package& prj = package[i]; + LOG("Package " << package.GetKey(i)); + LOG(" file "); + for(int i = 0; i < prj.file.GetCount(); i++) + LOG("\t" << prj.file[i]); + } +} + +Vector Workspace::GetAllAccepts(int pk) const +{ + Index accepts; + Index pkg; + pkg.Add(pk); + for(int i = 0; i < pkg.GetCount(); i++) { + const Package& p = package[pkg[i]]; + FindAppend(accepts, p.accepts); + for(int u = 0; u < p.uses.GetCount(); u++) { + int f = package.Find(p.uses[u].text); + if(f >= 0) + pkg.FindAdd(f); + } + } + return accepts.PickKeys(); +} diff --git a/uppsrc/ide/Core/init b/uppsrc/ide/Core/init new file mode 100644 index 000000000..d60feb1cc --- /dev/null +++ b/uppsrc/ide/Core/init @@ -0,0 +1,5 @@ +#ifndef _ide_Core_icpp_init_stub +#define _ide_Core_icpp_init_stub +#include "CtrlLib/init" +#include "Esc/init" +#endif diff --git a/uppsrc/ide/Core/usc.cpp b/uppsrc/ide/Core/usc.cpp new file mode 100644 index 000000000..a3301527a --- /dev/null +++ b/uppsrc/ide/Core/usc.cpp @@ -0,0 +1,85 @@ +#include "Core.h" + +ArrayMap& UscGlobal() +{ + static ArrayMap global; + return global; +} + +IdeMacro::IdeMacro() +{ + hotkey = 0; +} + +GLOBAL_VAR(Array, UscMacros) + +void ESC_cout(EscEscape& e) +{ + if(e[0].IsArray()) + PutConsole((String) e[0]); + else + if(e[0].IsNumber()) { + String str; + str << e[0].GetNumber(); + PutConsole(str); + } + else + if(!e[0].IsVoid()) + e.ThrowError("invalid argument to 'cout'" + e.DumpType(0)); +} + +void ESC_dump(EscEscape& e) +{ + PutConsole(e[0].ToString()); +} + +static void (*sCleanModules)(); + +void UscSetCleanModules(void (*CleanModules)()) +{ + sCleanModules = CleanModules; +} + +void CleanUsc() +{ + UscGlobal().Clear(); + UscMacros().Clear(); + if(sCleanModules) + sCleanModules(); + StdLib(UscGlobal()); + Escape(UscGlobal(), "cout(x)", ESC_cout); + Escape(UscGlobal(), "dump(x)", ESC_dump); +} + +static bool (*sIdeModuleUsc)(CParser& p); +static void (*sReadMacro)(CParser& p); + +void SetIdeModuleUsc(bool (*IdeModuleUsc)(CParser& p)) +{ + sIdeModuleUsc = IdeModuleUsc; +} + +void UscSetReadMacro(void (*ReadMacro)(CParser& p)) +{ + sReadMacro = ReadMacro; +} + +void ParseUscFile(const char *filename) throw(CParser::Error) +{ + String d = LoadFile(filename); + CParser p(d, filename); + while(!p.IsEof()) { + if(p.Id("fn")) { + EscValue& v = UscGlobal().GetPut(p.ReadId()); + v = ReadLambda(p); + } + else + if(p.Id("macro") && sReadMacro) + sReadMacro(p); + else + if(!sIdeModuleUsc || !sIdeModuleUsc(p)) { + EscValue& v = UscGlobal().GetPut(p.ReadId()); + v = ReadLambda(p); + } + } +} diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index fafdb04f1..70befe169 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -32,8 +32,6 @@ #include -enum { REMOTE_TIMEOUT = 2000 }; - const char *FindTag(const char *txt, const char *tag); const char *FindAfter(const char *txt, const char *tag); int IdeLocateLine(String old_file, int old_line, String new_file); @@ -144,75 +142,6 @@ public: Console(); }; -extern String LinuxHostConsole; - -struct LocalHost : Host { - Vector exedirs; - String environment; - - String *cmdout; - void DoDir(const String& s); - - virtual String GetEnvironment(); - virtual String GetHostPath(const String& path); - virtual String GetLocalPath(const String& path); - virtual String NormalizePath(const String& path); - virtual Vector GetFileInfo(const Vector& path); - virtual void DeleteFile(const Vector& path); - virtual void DeleteFolderDeep(const String& dir); - virtual void ChDir(const String& path); - virtual void RealizeDir(const String& path); - virtual void SaveFile(const String& path, const String& data); - virtual String LoadFile(const String& path); - virtual int Execute(const char *cmdline); - virtual int ExecuteWithInput(const char *cmdline); - virtual int Execute(const char *cmdline, Stream& out); - virtual int AllocSlot(); - virtual bool Run(const char *cmdline, int slot, String key, int blitz_count); - virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count); - virtual bool Wait(); - virtual One StartProcess(const char *cmdline); - virtual void Launch(const char *cmdline, bool console); - virtual void AddFlags(Index& cfg); -}; - -struct RemoteHost : Host { - String host; - int port; - String os_type; -// bool transfer_files; - Vector path_map_local; - Vector path_map_remote; - String chdir_path; - String environment; - - static Time TimeBase() { return Time(2000, 1, 1); } - - virtual String GetEnvironment(); - virtual String GetHostPath(const String& path); - virtual String GetLocalPath(const String& path); - virtual String NormalizePath(const String& path); - virtual Vector GetFileInfo(const Vector& path); - virtual void DeleteFile(const Vector& path); - virtual void DeleteFolderDeep(const String& dir); - virtual void ChDir(const String& path); - virtual void RealizeDir(const String& path); - virtual void SaveFile(const String& path, const String& data); - virtual String LoadFile(const String& path); - virtual int Execute(const char *cmdline); - virtual int ExecuteWithInput(const char *cmdline); - virtual int Execute(const char *cmdline, Stream& out); - virtual int AllocSlot(); - virtual bool Run(const char *cmdline, int slot, String key, int blitz_count); - virtual bool Run(const char *cmdline, Stream& out, int slot, String key, int blitz_count); - virtual bool Wait(); - virtual One StartProcess(const char *cmdline); - virtual void Launch(const char *cmdline, bool console); - virtual void AddFlags(Index& cfg); - - String RemoteExec(String cmd); -}; - VectorMap& BuilderMap(); String SelectAnyPackage(); diff --git a/uppsrc/ide/ide.upp b/uppsrc/ide/ide.upp index bfdd505e1..19a0cd341 100644 --- a/uppsrc/ide/ide.upp +++ b/uppsrc/ide/ide.upp @@ -2,6 +2,7 @@ description "TheIDE main package"; uses ide\Common, + ide\Core, ide\LayDes, ide\IconDes, ide\Builders, @@ -64,7 +65,6 @@ file Methods.cpp, AutoSetup.cpp, OutputMode.cpp, - Host.cpp, Build.cpp, Debug.cpp, Valgrind.cpp, diff --git a/uppsrc/ide/init b/uppsrc/ide/init index 9bc471689..3857bfa1c 100644 --- a/uppsrc/ide/init +++ b/uppsrc/ide/init @@ -1,6 +1,7 @@ #ifndef _ide_icpp_init_stub #define _ide_icpp_init_stub #include "ide\Common/init" +#include "ide\Core/init" #include "ide\LayDes/init" #include "ide\IconDes/init" #include "ide\Builders/init"