#include "Core.h" void InvalidatePackageCache() { MainNest().InvalidatePackageCache(); } String PackageDirectory(const String& name) { return MainNest().PackageDirectory(name); } String GetPathNest(const String& path) { if(IsExternalMode()) return Null; String h = UnixPath(NormalizePath(path)); for(auto dir : GetUppDirs()) if(h.StartsWith(UnixPath(NormalizePath(dir)) + '/')) return dir; return Null; } String SourcePath(const String& package, const String& file) { if(IsFullPath(file)) return NativePath(file); return NormalizePath(AppendFileName(PackageDirectory(package), file)); } bool IsDirectoryExternalPackage(const String& dir) { String source_masks = GetVar("SOURCE_MASKS"); for(FindFile ff(dir + "/*.*"); ff; ff.Next()) if(ff.IsFile() && PatternMatchMulti(source_masks, ff.GetName())) return true; return false; } bool IsDirectoryPackage(const String& path) { if(IsExternalMode()) return DirectoryExists(path); return FileExists(AppendFileName(path, GetFileTitle(path) + ".upp")); } String EncodePathAsFileName(const String& path) { String p = UnixPath(path); p.Replace("/", "[sLash]"); p.Replace(":", "[cOlon]"); return p; } String DecodePathFromFileName(const String& n) { String p = n; p.Replace("[sLash]", "/"); p.Replace("[cOlon]", ":"); return p; } String PackageFile(const String& package) { // in external mode we are storing packages into .config if(IsExternalMode()) { String p = ConfigFile("external") + "/" + EncodePathAsFileName(package); RealizePath(p); return p; } return AppendFileName(PackageDirectory(package), GetFileTitle(package) + ".upp"); } 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; } 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, 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); try { 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); } } catch(CParser::Error) {} 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; } Vector GatherV(const Array& set, const Vector& conf) { Vector s; for(int i = 0; i < set.GetCount(); i++) if(MatchWhen(set[i].when, conf)) s << 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) { package.Add(name).Load(PackageFile(name)); } void Workspace::AddUses(Package& p, const Vector *flag) { int q = package.GetCount(); for(int i = 0; i < p.uses.GetCount(); i++) { String uses = UnixPath(p.uses[i].text); if((!flag || MatchWhen(p.uses[i].when, *flag)) && package.Find(uses) < 0) AddLoad(uses); } int n = package.GetCount(); for(int i = q; i < package.GetCount(); i++) AddUses(package[i], flag); for(int i = q; i < n; i++) use_order.Add(i); } void Workspace::Scan(const char *prjname, const Vector *flag) { package.Clear(); use_order.Clear(); AddLoad(prjname); AddUses(package[0], flag); use_order.Add(0); } 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(UnixPath(p.uses[u].text)); if(f >= 0) pkg.FindAdd(f); } } return accepts.PickKeys(); }