#include "Core.h" VectorMap& BuilderMap() { static VectorMap h; return h; } 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); String cd = UnixPath(GetCurrentDirectory()); int q = cd.GetCount(); if(fn.StartsWith(cd) && fn[q] == '/') { fn.Remove(0, q); fn.Insert(0, '.'); } return fn; } String AdjustMakePath(const char *fn) { String out; for(; *fn; fn++) if(*fn == '$') out << "$$"; else out << *fn; return out; } bool IsHeaderExt(const String& ext) { return findarg(ext, ".h", ".hpp", ".hh", ".hxx") >= 0; } bool SaveChangedFile(const char *path, String data, bool delete_empty) { if(LoadFile(path) == data && (FileExists(path) || delete_empty)) 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; } bool IsDoc(String s) { s = ToLower(s); if(s.Find("svn") >= 0) return false; return s.Find("readme") >= 0 || s.Find("copying") >= 0 || s.Find("license") >= 0 || s.Find("authors") >= 0; } static void WriteByteArray(StringBuffer& fo, const String& data) { int pos = 0; for(int p = 0; p < data.GetLength(); p++) { if(pos >= 70) { fo << '\n'; pos = 0; } if(pos == 0) fo << '\t'; String part = FormatInt((byte)data[p]); fo << part << ", "; pos += part.GetLength() + 2; } } String BrcToC(CParser& binscript, String basedir) { BinObjInfo info; info.Parse(binscript, basedir); StringBuffer fo; for(int i = 0; i < info.blocks.GetCount(); i++) { String ident = info.blocks.GetKey(i); ArrayMap& belem = info.blocks[i]; if(belem[0].flags & (BinObjInfo::Block::FLG_ARRAY | BinObjInfo::Block::FLG_MASK)) { int count = Max(belem.GetKeys()) + 1; Vector blockref; blockref.SetCount(count, 0); for(int a = 0; a < belem.GetCount(); a++) { BinObjInfo::Block& b = belem[a]; blockref[b.index] = &b; } for(int i = 0; i < blockref.GetCount(); i++) if(blockref[i]) { BinObjInfo::Block& b = *blockref[i]; fo << "static unsigned char " << ident << "_" << i << "[] = {\n"; String data = ::LoadFile(b.file); if(data.IsVoid()) throw Exc(Format("Error reading file '%s'", b.file)); if(data.GetLength() != b.length) throw Exc(Format("length of file '%s' changed (%d -> %d) during object creation", b.file, b.length, data.GetLength())); b.Compress(data); b.length = data.GetLength(); data.Cat('\0'); WriteByteArray(fo, data); fo << "\n};\n\n"; // fo << AsCString(data, 70, "\t", ASCSTRING_OCTALHI | ASCSTRING_SMART) << ";\n\n"; } fo << "int " << ident << "_count = " << blockref.GetCount() << ";\n\n" "int " << ident << "_length[] = {\n"; for(int i = 0; i < blockref.GetCount(); i++) fo << '\t' << (blockref[i] ? blockref[i]->length : -1) << ",\n"; fo << "};\n\n" "unsigned char *" << ident << "[] = {\n"; for(int i = 0; i < blockref.GetCount(); i++) if(blockref[i]) fo << '\t' << ident << '_' << i << ",\n"; else fo << "\t0,\n"; fo << "};\n\n"; if(belem[0].flags & BinObjInfo::Block::FLG_MASK) { fo << "char *" << ident << "_files[] = {\n"; for(int i = 0; i < blockref.GetCount(); i++) fo << '\t' << AsCString(blockref[i] ? GetFileName(blockref[i]->file) : String(Null)) << ",\n"; fo << "\n};\n\n"; } } else { BinObjInfo::Block& b = belem[0]; fo << "static unsigned char " << ident << "_[] = {\n"; String data = ::LoadFile(b.file); if(data.IsVoid()) throw Exc(Format("Error reading file '%s'", b.file)); if(data.GetLength() != b.length) throw Exc(Format("length of file '%s' changed (%d -> %d) during object creation", b.file, b.length, data.GetLength())); b.Compress(data); int b_length = data.GetLength(); data.Cat('\0'); WriteByteArray(fo, data); fo << "\n};\n\n" << "unsigned char *" << ident << " = " << ident << "_;\n\n" // fo << AsCString(data, 70) << ";\n\n" "int " << ident << "_length = " << b_length << ";\n\n"; } } return String(fo); } void CopyFile(const String& d, const String& s, bool brc) { FindFile ff(s); if(ff) { String ext = ToLower(GetFileExt(s)); if(brc && ext == ".brc") { try { String brcdata = LoadFile(s); if(brcdata.IsVoid()) throw Exc(Format("error reading file '%s'", s)); CParser parser(brcdata, s); Upp::SaveFile(d + "c", BrcToC(parser, GetFileDirectory(s))); } catch(Exc e) { PutConsole(e); } } SaveFile(d, LoadFile(s)); SetFileTime(d, ff.GetLastWriteTime()); } } void CopyFolder(const char *_dst, const char *_src, Index& used, bool all, bool brc) { if(GetFileName(_src) == ".svn") return; String dst = NativePath(_dst); String src = NativePath(_src); if(dst == src) return; FindFile ff(AppendFileName(src, "*")); bool realize = true; while(ff) { String s = AppendFileName(src, ff.GetName()); String d = AppendFileName(dst, ff.GetName()); if(ff.IsFolder()) CopyFolder(d, s, used, all, brc); else if(ff.IsFile() && (all || IsDoc(s) || used.Find(s) >= 0)) { if(realize) { RealizeDirectory(dst); realize = false; } CopyFile(d, s, brc); } ff.Next(); } } String Join(const String& a, const String& b, const char *sep) { String h = a; if(a.GetCount() && b.GetCount()) h << sep; h << b; return h; } String GetExeExt() { #if defined(PLATFORM_WIN32) || defined(PLATFORM_WIN64) return ".exe"; #else return ""; #endif } String NormalizeExePath(String exePath) { if(exePath.Find(" ") >= 0) { #if defined(PLATFORM_WIN32) || defined(PLATFORM_WIN64) exePath = "\"" + exePath + "\""; #else exePath.Replace(" ", "\\ "); #endif } return exePath; } String NormalizePathSeparator(String path) { #if defined(PLATFORM_WIN32) || defined(PLATFORM_WIN64) path.Replace("/", DIR_SEPS); #else path.Replace("\\", DIR_SEPS); #endif return path; } Index pch_files; void RegisterPCHFile(const String& pch_file) { pch_files.FindAdd(pch_file); } void DeletePCHFiles() { for(int i = 0; i < pch_files.GetCount(); i++) FileDelete(pch_files[i]); } String GetLineEndings(const String& data, const String& default_eol) { int q = data.ReverseFind("\n"); if(q >= 0) { if(data.Mid(q - 1, 1) == "\r") return "\r\n"; else return "\n"; } return default_eol; }