diff --git a/uppsrc/RichText/EncodeHTML.cpp b/uppsrc/RichText/EncodeHTML.cpp index 3e77ee02e..009567bf9 100644 --- a/uppsrc/RichText/EncodeHTML.cpp +++ b/uppsrc/RichText/EncodeHTML.cpp @@ -106,13 +106,11 @@ void TabBorder(String& style, const char *txt, int border, Color bordercolor, co << ColorToHtml(border ? bordercolor : tf.gridcolor) << ';'; } - String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, const VectorMap& links, const VectorMap& labels, - const String& outdir, const String& namebase, Zoom z, int& im, - const VectorMap& escape, - int imtolerance) + Zoom z, const VectorMap& escape, + HtmlObjectSaver& object_saver) { String html; for(int i = 0; i < text.GetPartCount(); i++) @@ -171,8 +169,7 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, if(c.vspan) html << " rowspan=" << c.vspan + 1; html << '>'; - html << AsHtml(c.text, styles, css, links, labels, outdir, namebase, z, - im, escape, imtolerance); + html << AsHtml(c.text, styles, css, links, labels, z, escape, object_saver); html << "\r\n"; } } @@ -221,26 +218,8 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, for(int i = 0; i < p.part.GetCount(); i++) { const RichPara::Part& part = p.part[i]; int q; - if(part.object) { - String name; - name << namebase << "_" << im++ << ".png"; - Size psz = part.object.GetPixelSize(); - String lname; - lname << "L$" << name; - Size sz = z * part.object.GetSize(); - if(abs(100 * (psz.cx - sz.cx) / sz.cx) < imtolerance) - sz = psz; - PNGEncoder png; - png.SaveFile(AppendFileName(outdir, name), part.object.ToImage(sz)); - if(psz.cx * psz.cy) - html << ""; - html << "\"\""; - if(psz.cx * psz.cy) { - html << ""; - PNGEncoder png; - png.SaveFile(AppendFileName(outdir, lname), part.object.ToImage(psz)); - } - } + if(part.object) + html << object_saver.GetHtml(part.object); else if(part.format.indexentry.GetCount() && (q = escape.Find(part.format.indexentry.ToString())) >= 0) @@ -342,14 +321,63 @@ String AsHtml(const RichTxt& text, const RichStyles& styles, Index& css, return html; } +class DefaultHtmlObjectSaver : public HtmlObjectSaver +{ +public: + DefaultHtmlObjectSaver(const String& outdir_, const String& namebase_, int imtolerance_, Zoom z_) + : outdir(outdir_), namebase(namebase_), imtolerance(imtolerance_), z(z_), im(0) {} + + virtual String GetHtml(const RichObject& object); + +private: + String outdir; + String namebase; + Zoom z; + int imtolerance; + int im; +}; + +String DefaultHtmlObjectSaver::GetHtml(const RichObject& object) +{ + StringBuffer html; + String name; + name << namebase << "_" << im++ << ".png"; + Size psz = object.GetPixelSize(); + String lname; + lname << "L$" << name; + Size sz = z * object.GetSize(); + if(abs(100 * (psz.cx - sz.cx) / sz.cx) < imtolerance) + sz = psz; + PNGEncoder png; + png.SaveFile(AppendFileName(outdir, name), object.ToImage(sz)); + if(psz.cx * psz.cy) + html << ""; + html << "\"\""; + if(psz.cx * psz.cy) { + html << ""; + PNGEncoder png; + png.SaveFile(AppendFileName(outdir, lname), object.ToImage(psz)); + } + return html; +} + String EncodeHtml(const RichText& text, Index& css, const VectorMap& links, const VectorMap& labels, const String& outdir, const String& namebase, Zoom z, const VectorMap& escape, int imt) { - int im = 0; - return AsHtml(text, text.GetStyles(), css, links, labels, outdir, namebase, z, im, escape, imt); + DefaultHtmlObjectSaver default_saver(outdir, namebase, imt, z); + return AsHtml(text, text.GetStyles(), css, links, labels, z, escape, default_saver); +} + +String EncodeHtml(const RichText& text, Index& css, + const VectorMap& links, + const VectorMap& labels, + HtmlObjectSaver& object_saver, Zoom z, + const VectorMap& escape) +{ + return AsHtml(text, text.GetStyles(), css, links, labels, z, escape, object_saver); } String AsCss(Index& ss) diff --git a/uppsrc/RichText/RichText.h b/uppsrc/RichText/RichText.h index 08f85172d..11e96ec1e 100644 --- a/uppsrc/RichText/RichText.h +++ b/uppsrc/RichText/RichText.h @@ -455,12 +455,25 @@ Zoom GetRichTextStdScreenZoom(); const Display& QTFDisplay(); const Display& QTFDisplayVCenter(); +class HtmlObjectSaver +{ +public: + virtual ~HtmlObjectSaver() {} + + virtual String GetHtml(const RichObject& object) = 0; +}; + String EncodeHtml(const RichText& text, Index& css, const VectorMap& links, const VectorMap& labels, const String& path, const String& base = Null, Zoom z = Zoom(8, 40), const VectorMap& escape = VectorMap(), int imtolerance = 0); +String EncodeHtml(const RichText& text, Index& css, + const VectorMap& links, + const VectorMap& labels, + HtmlObjectSaver& object_saver, Zoom z = Zoom(8, 40), + const VectorMap& escape = VectorMap()); String AsCss(Index& ss); inline //BW - no labels diff --git a/uppsrc/ide/Builders/MscBuilder.icpp b/uppsrc/ide/Builders/MscBuilder.icpp index 44a579219..62a616bb0 100644 --- a/uppsrc/ide/Builders/MscBuilder.icpp +++ b/uppsrc/ide/Builders/MscBuilder.icpp @@ -1,614 +1,614 @@ -#include "Builders.h" - -#include - -#ifdef PLATFORM_WIN32 -static bool HasTail(String s, const char *tail) -{ - int tl = (int)strlen(tail); - int sl = s.GetLength(); - if(sl < tl) - return false; - for(const char *p = s.GetIter(sl - tl); *p; p++, tail++) - if(*tail != '*' && *tail != *p) - return false; - return *tail == 0; -} -#endif - -static void AddObjectExports(const char *path, Index& out) -{ -#ifdef PLATFORM_WIN32 - FileMapping mapping; - if(!mapping.Open(path)) - return; - const byte *begin = mapping.Begin(); - const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)begin; - if(hdr->Machine != COFF_IMAGE_FILE_MACHINE_I386) - return; - const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)(begin - + sizeof(COFF_IMAGE_FILE_HEADER) + hdr->SizeOfOptionalHeader); - Index code_sections; - for(int i = 0; i < hdr->NumberOfSections; i++) - if(sechdr[i].Characteristics & COFF_IMAGE_SCN_CNT_CODE) - code_sections.Add(i + 1); - const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + hdr->PointerToSymbolTable); - const char *strtbl = (const char *)(symtbl + hdr->NumberOfSymbols); - for(int i = 0; i < (int)hdr->NumberOfSymbols; i++) - { - const COFF_IMAGE_SYMBOL& sym = symtbl[i]; - if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL && code_sections.Find(sym.SectionNumber) >= 0) - { - String name = COFFSymbolName(sym, strtbl); - if(!HasTail(name, "AEPAXI@Z")) - { - if(*name == '_' && name.Find('@') < 0) - name.Remove(0, 1); - out.FindAdd(name); - } - } - i += sym.NumberOfAuxSymbols; - } -#endif -} - -void MscBuilder::AddFlags(Index& cfg) -{ - cfg.FindAdd("MSC"); -} - -String MscBuilder::CmdLine(const String& package, const Package& pkg) -{ - String cc; - if(HasFlag("ARM")) - cc = "clarm"; - else - if(HasFlag("MIPS")) - cc = "clmips"; - else - if(HasFlag("SH3")) - cc = "shcl /Qsh3"; - else - if(HasFlag("SH4")) - cc = "shcl /Qsh4"; - else - if(HasFlag("MSC8ARM")) - cc = "cl -GS- "; - else - cc = HasFlag("INTEL") ? "icl" : "cl"; -// TRC 080605-documentation says Wp64 works in 32-bit compilation only -// cc << (IsMsc64() ? " -nologo -Wp64 -W3 -GR -c" : " -nologo -W3 -GR -c"); - cc << " -nologo -W3 -GR -c"; - cc << IncludesDefinesTargetTime(package, pkg); - - return cc; -} - -String MscBuilder::MachineName() const -{ - if(HasFlag("ARM")) return "ARM"; - if(HasFlag("MIPS")) return "MIPS"; - if(HasFlag("SH3")) return "SH3"; - if(HasFlag("SH4")) return "SH4"; - if(IsMscArm()) return "ARM"; - if(IsMsc64()) return "x64"; - if(HasFlag("WIN32")) return "I386"; - return "IX86"; -} - -bool MscBuilder::IsMsc89() const -{ - return IsMsc86() || IsMsc64() || IsMscArm(); -} - -bool MscBuilder::IsMsc86() const -{ - return HasFlag("MSC8") || HasFlag("MSC9") || HasFlag("MSC10"); -} - -bool MscBuilder::IsMscArm() const -{ - return HasFlag("MSC8ARM") || HasFlag("MSC9ARM"); -} - -bool MscBuilder::IsMsc64() const -{ - return HasFlag("MSC8X64") || HasFlag("MSC9X64") || HasFlag("MSC10X64"); -} - -String MscBuilder::LinkerName() const -{ - if(HasFlag("ULD")) return "uld"; - if(HasFlag("INTEL")) return "xilink"; - return "link"; -} - -static bool sContainsPchOptions(const String& x) -{ - Index a(Split(x, ' ')); - return a.Find("-GL") >= 0 || a.Find("/GL") >= 0 || a.Find("-Y-") >= 0 || a.Find("/Y-") >= 0 - || a.Find("-Yc") >= 0 || a.Find("/Yc") >= 0 || a.Find("-Yd") >= 0 || a.Find("/Yd") >= 0 - || a.Find("-Yl") >= 0 || a.Find("/Yl") >= 0 || a.Find("-Yu") >= 0 || a.Find("/Yu") >= 0 - || a.Find("-YX") >= 0 || a.Find("/YX") >= 0; -} - -bool MscBuilder::HasAnyDebug() const -{ - return HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL"); -} - -String MscBuilder::PdbPch(String package, int slot, bool do_pch) const -{ - String pkg_slot = NFormat("%s-%d", GetAnyFileName(package), slot + 1); - String pdb = GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pdb")); - String cc; - cc << " -Gy -Fd" << pdb; - if(do_pch && !IsMsc89()) // MSC8/9 does not support automatic precompiled headers... - cc << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pch")) << ' '; - return cc; -} - -bool MscBuilder::BuildPackage(const String& package, Vector& linkfile, String& linkoptions, - const Vector& all_uses, const Vector& all_libraries, int opt) -{ - int i; - String packagepath = PackagePath(package); - Package pkg; - pkg.Load(packagepath); - String packagedir = GetFileFolder(packagepath); - ChDir(packagedir); - PutVerbose("cd " + packagedir); - IdeConsoleBeginGroup(package); - Vector obj; - - bool is_shared = HasFlag("SO"), - is_clr = HasFlag("CLR"); - - String cc = CmdLine(package, pkg); - if(HasFlag("EVC")) { - if(!HasFlag("SH3") && !HasFlag("SH4")) - cc << " -Gs8192"; // disable stack checking - cc << " -GF" // read-only string pooling - " -GX-"; // turn off exception handling - } - else - if(is_clr) - cc << " -EHac"; - else - if(IsMsc89()) - cc << " -EHsc"; - else - cc << " -GX"; -// String pdb = GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pdb")); -// String pch; -// if(!HasFlag("MSC8")) // MSC8 does not support automatic precompiled headers... -// pch << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pch")) << ' '; -// cc << " -Gy -Fd" << pdb; - if(HasFlag("SSE2") && !IsMsc64()) - cc << " /arch:SSE2"; - if(HasFlag("DEBUG_MINIMAL")) - cc << " -Zd"; - if(HasFlag("DEBUG_FULL")) - cc << " -Zi"; - cc << ' ' << Gather(pkg.option, config.GetKeys()); - cc << (HasFlag("SHARED") || is_shared || is_clr ? " -MD" - : (HasFlag("MT") || IsMsc89()) ? " -MT" : " -ML"); - - String cc_size = cc; - String cc_speed = cc; - bool release = false; - - if(HasFlag("DEBUG")) - cc << "d " << debug_options; - else { - release = true; - cc << ' ' << release_size_options; - cc_speed << ' ' << release_options; - if(opt == R_SPEED || pkg.optimize_speed) - cc = cc_speed; - } - - - Vector sfile, isfile; - Vector soptions, isoptions; - Vector optimize, ioptimize; - Vector sobjfile; - bool error = false; - - for(i = 0; i < pkg.GetCount(); i++) { - if(!IdeIsBuilding()) - return false; - if(!pkg[i].separator) { - String gop = Gather(pkg[i].option, config.GetKeys()); - Vector srcfile = CustomStep(pkg[i], package, error); - if(srcfile.GetCount() == 0) - error = true; - for(int j = 0; j < srcfile.GetCount(); j++) { - String fn = srcfile[j]; - String ext = ToLower(GetFileExt(fn)); - if(ext == ".c" || ext == ".cpp" || ext == ".cc" || ext == ".cxx" || ext == ".rc" || ext == ".brc") { - sfile.Add(fn); - soptions.Add(gop); - optimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL); - } - else - if(ext == ".icpp") { - isfile.Add(fn); - isoptions.Add(gop); - ioptimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL); - } - else - if(ext == ".obj") - obj.Add(fn); - else - if(ext == ".lib") - linkfile.Add(fn); - } - } - } - - if(HasFlag("BLITZ")) { - Blitz b = BlitzStep(sfile, soptions, obj, ".obj", optimize); - if(b.build) { - PutConsole("BLITZ:" + b.info); - int slot = AllocSlot(); - if(slot < 0 || ! Run(cc + PdbPch(package, slot, false) - + " -Tp " + GetHostPathQ(b.path) + " -Fo" + GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count)) - error = true; - } - } - - int first_ifile = sfile.GetCount(); - sfile.AppendPick(isfile); - soptions.AppendPick(isoptions); - optimize.AppendPick(ioptimize); - - int ccount = 0; - -// if(sContainsPchOptions(cc)) -// pch = Null; - - for(i = 0; i < sfile.GetCount(); i++) { - if(!IdeIsBuilding()) - return false; - String fn = sfile[i]; - String ext = ToLower(GetFileExt(fn)); - bool rc = (ext == ".rc"); - bool brc = (ext == ".brc"); - bool init = (i >= first_ifile); - String objfile = CatAnyPath(outdir, GetFileTitle(fn) + (rc ? "$rc.obj" : brc ? "$brc.obj" : ".obj")); - if(HdependFileTime(fn) > GetFileTime(objfile)) { - int time = GetTickCount(); - bool execerr = false; - if(rc) { - PutConsole(GetFileNamePos(fn)); - int slot = AllocSlot(); - if(slot < 0 || !Run("rc /fo" + GetHostPathQ(objfile) + Includes(" /i", package, pkg) - + ' ' + GetHostPathQ(fn), slot, GetHostPath(objfile), 1)) - execerr = true; - } - else - if(brc) { - try { -// String hfn = GetHostPath(fn); - String brcdata = LoadFile(fn); - if(brcdata.IsVoid()) - throw Exc(NFormat("error reading file '%s'", fn)); - CParser parser(brcdata, fn); - String fo = BrcToC(parser, GetFileDirectory(fn)); - String tmpfile = ForceExt(objfile, ".c"); - SaveFile(tmpfile, fo); - int slot = AllocSlot(); - StringBuffer cmdline; - cmdline << cc << PdbPch(package, slot, false) - << " -Tc " << GetHostPathQ(tmpfile) << " -Fo" << GetHostPathQ(objfile); - if(slot < 0 || !Run(String(cmdline), slot, GetHostPath(objfile), 1)) - throw Exc(NFormat("Error compiling binary object '%s'.", objfile)); - } - catch(Exc e) { - PutConsole(e); - execerr = true; - } - } - else { - String c = cc; - if(optimize[i]) - c = cc_speed; - int slot = AllocSlot(); - if(slot < 0 || !Run(c + PdbPch(package, slot, !sContainsPchOptions(cc) && !sContainsPchOptions(soptions[i])) - + " " + soptions[i] + (ext == ".c" ? " -Tc " : " -Tp ") - + GetHostPathQ(fn) + " -Fo" + GetHostPathQ(objfile), slot, GetHostPath(objfile), 1)) - execerr = true; - } - if(execerr) - DeleteFile(objfile); - error |= execerr; - PutVerbose("compiled in " + GetPrintTime(time)); - ccount++; - } - if(init) - linkfile.Add(objfile); - else - obj.Add(objfile); - } - if(error) { - IdeConsoleEndGroup(); - return false; - } - - Vector pkglibs = Split(Gather(pkg.library, config.GetKeys()), ' '); - for(int i = 0; i < pkglibs.GetCount(); i++) { - String libfile = AppendExt(pkglibs[i], ".lib"); - if(!IsFullPath(libfile)) { - for(int p = 0; p < libpath.GetCount(); p++) { - String nf = NormalizePath(libfile, libpath[p]); - if(FileExists(nf)) { - libfile = nf; - break; - } - } - } - linkfile.Add(libfile); - } - linkoptions << ' ' << Gather(pkg.link, config.GetKeys()); - - int linktime = GetTickCount(); - if(!HasFlag("MAIN")) { - if(HasFlag("BLITZ") || HasFlag("NOLIB")) { - linkfile.Append(obj); -// ShowTime(ccount, time); - IdeConsoleEndGroup(); - return true; - } - String product; - if(is_shared) - product = GetSharedLibPath(package); - else - product = CatAnyPath(outdir, GetAnyFileName(package) + ".lib"); - Time producttime = GetFileTime(product); - if(obj.GetCount()) - linkfile.Add(ForceExt(product, ".lib")); - if(!Wait()) { - IdeConsoleEndGroup(); - return false; - } - Vector objinfo = host->GetFileInfo(obj); - for(int i = 0; i < obj.GetCount(); i++) - if(objinfo[i] > producttime) { - String linker, lib; - if(is_shared) { - linker << LinkerName() << "-dll -nologo "; - lib << "-machine:" << MachineName() - << " -pdb:" << GetHostPathQ(ForceExt(product, ".pdb")) - << " -out:" << GetHostPathQ(product); - if(!HasFlag("MSC10") && !HasFlag("MSC10X64")) - lib << " -incremental:no"; - if(HasFlag("FORCE_SIZE")){ - if(sContainsPchOptions(release_size_options)) - lib << " -ltcg"; - } - else - if(HasFlag("FORCE_SPEED")) - if(sContainsPchOptions(release_options)) - lib << " -ltcg"; - if(HasAnyDebug()) - lib << " -debug -OPT:NOREF"; - else - lib << " -release -OPT:REF,ICF"; - if(IsMscArm()) - lib << " -subsystem:windowsce,4.20 /ARMPADCODE"; - else - if(HasFlag("GUI")) - lib << (HasFlag("WIN32") ? " -subsystem:windows" - : " -subsystem:windowsce"); - else - lib << " -subsystem:console"; - Index exports; - for(int o = 0; o < obj.GetCount(); o++) - AddObjectExports(obj[o], exports); - String def; - def << "LIBRARY " << AsCString(GetFileName(product)) << "\n\n" - "EXPORTS\n"; - for(int o = 0; o < exports.GetCount(); o++) - def << '\t' << exports[o] << "\n"; //" @" << (o + 1) << "\n"; - String deffile = ForceExt(product, ".def"); - if(!SaveChangedFile(deffile, def)) - { - PutConsole(NFormat("%s: error saving file", deffile)); - return false; - } - lib << " -def:" << GetHostPathQ(deffile); - for(int i = 0; i < libpath.GetCount(); i++) - lib << " -LIBPATH:" << GetHostPathQ(libpath[i]); - lib << ' ' << Gather(pkg.link, config.GetKeys()); - for(int i = 0; i < all_uses.GetCount(); i++) - lib << ' ' << GetHostPathQ(ForceExt(GetSharedLibPath(all_uses[i]), ".lib")); - for(int i = 0; i < all_libraries.GetCount(); i++) { - String libfile = AppendExt(all_libraries[i], ".lib"); - if(!IsFullPath(libfile)) { - for(int p = 0; p < libpath.GetCount(); p++) { - String nf = NormalizePath(libfile, libpath[p]); - if(FileExists(nf)) { - libfile = nf; - break; - } - } - } - lib << ' ' << GetHostPathQ(libfile); - } - } - else{ - linker << (HasFlag("INTEL") ? "xilib" : "link /lib") << " -nologo "; - if(HasFlag("FORCE_SIZE")){ - if(sContainsPchOptions(release_size_options)) - lib << " -ltcg"; - } - else - if(HasFlag("FORCE_SPEED")) - if(sContainsPchOptions(release_options)) - lib << " -ltcg"; - lib << " -out:" << GetHostPathQ(product) << ' ' << Gather(pkg.link, config.GetKeys()); - } - for(int i = 0; i < obj.GetCount(); i++) - lib << ' ' << GetHostPathQ(obj[i]); - PutConsole("Creating library..."); - IdeConsoleEndGroup(); - DeleteFile(product); - String tmpFileName; - if(linker.GetCount() + lib.GetCount() >= 8192) - { - tmpFileName = GetTempFileName(); - // we can't simply put all data on a single line - // as it has a limit of around 130000 chars too, so we split - // in multiple lines - FileOut f(tmpFileName); - while(lib != "") - { - int found = 0; - bool quotes = false; - int lim = min(8192, lib.GetCount()); - for(int i = 0; i < lim; i++) - { - char c = lib[i]; - if(isspace(c) && !quotes) - found = i; - else if(c == '"') - quotes = !quotes; - } - if(!found) - found = lib.GetCount(); - f.PutLine(lib.Left(found)); - lib.Remove(0, found); - } - f.Close(); - linker << "@" << tmpFileName; - } - else - linker << lib; - bool res = Execute(linker); - if(tmpFileName != "") - FileDelete(tmpFileName); - if(res) { - DeleteFile(product); - return false; - } - else - if((IsMsc86() || IsMsc64()) && is_shared) { - String mt("mt -nologo -manifest "); - mt << GetHostPathQ(product) << ".manifest -outputresource:" << GetHostPathQ(product) << ";2"; - Execute(mt); - } - PutConsole(String().Cat() << product << " (" << GetFileInfo(product).length - << " B) created in " << GetPrintTime(linktime)); - break; - } - return true; - } - - IdeConsoleEndGroup(); - obj.Append(linkfile); - linkfile = obj; - return true; -} - -bool MscBuilder::Link(const Vector& linkfile, const String& linkoptions, bool createmap) -{ - int time = GetTickCount(); - if(!Wait()) - return false; - for(int i = 0; i < linkfile.GetCount(); i++) - if(GetFileTime(linkfile[i]) >= targettime) { - String link; - link << LinkerName() << " -nologo -machine:" << MachineName() - << " -pdb:" << GetHostPathQ(ForceExt(target, ".pdb")) - << " -out:" << GetHostPathQ(target); - if(HasFlag("FORCE_SIZE")){ - if(sContainsPchOptions(release_size_options)) - link << " -ltcg"; - } - else - if(HasFlag("FORCE_SPEED")) - if(sContainsPchOptions(release_options)) - link << " -ltcg"; - if(!HasFlag("MSC10") && !HasFlag("MSC10X64")) - if(HasAnyDebug()) - link << " -incremental:yes -debug -OPT:NOREF"; - else - link << " -incremental:no -release -OPT:REF,ICF"; - else - if(HasAnyDebug()) - link << " -debug -OPT:NOREF"; - else - link << " -release -OPT:REF,ICF"; - if(IsMscArm()) - link << " -subsystem:windowsce,4.20 /ARMPADCODE -NODEFAULTLIB:\"oldnames.lib\" "; - else - if(HasFlag("GUI") || IsMscArm()) - link << (HasFlag("WIN32") ? " -subsystem:windows" : " -subsystem:windowsce"); - else - link << " -subsystem:console"; - if(createmap) - link << " -MAP"; - if(HasFlag("DLL")) - link << " -DLL"; - for(i = 0; i < libpath.GetCount(); i++) - link << " -LIBPATH:\"" << libpath[i] << '\"'; - link << ' ' << linkoptions << ' '; - for(i = 0; i < linkfile.GetCount(); i++) - link << ' ' << GetHostPathQ(AppendExt(linkfile[i], ".lib")); - PutConsole("Linking..."); - bool error = false; - CustomStep(".pre-link", Null, error); - if(!error && Execute(link) == 0) { - CustomStep(".post-link", Null, error); - if((IsMsc86() || IsMsc64()) && HasFlag("SHARED")) { - String mt("mt -nologo -manifest "); - mt << GetHostPathQ(target) << ".manifest -outputresource:" << GetHostPathQ(target) - << (HasFlag("DLL") ? ";2" : ";1"); - Execute(mt); - } - PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length - << " B) linked in " << GetPrintTime(time)); - return !error; - } - else { - DeleteFile(target); - return false; - } - } - PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length - << " B) is up to date."); - return true; -} - -bool MscBuilder::Preprocess(const String& package, const String& file, const String& target, bool) -{ - FileOut out(target); - String packagepath = PackagePath(package); - Package pkg; - pkg.Load(packagepath); - return Execute(CmdLine(package, pkg) + " -E " + file, out); -} - -Builder *CreateMscBuilder() -{ - return new MscBuilder; -} - -INITBLOCK -{ - RegisterBuilder("MSC71", CreateMscBuilder); - RegisterBuilder("MSC8", CreateMscBuilder); - RegisterBuilder("MSC8X64", CreateMscBuilder); - RegisterBuilder("MSC8ARM", CreateMscBuilder); - RegisterBuilder("MSC9", CreateMscBuilder); - RegisterBuilder("MSC9X64", CreateMscBuilder); - RegisterBuilder("MSC10", CreateMscBuilder); - RegisterBuilder("MSC10X64", CreateMscBuilder); - RegisterBuilder("MSC9ARM", CreateMscBuilder); - RegisterBuilder("EVC_ARM", CreateMscBuilder); - RegisterBuilder("EVC_MIPS", CreateMscBuilder); - RegisterBuilder("EVC_SH3", CreateMscBuilder); - RegisterBuilder("EVC_SH4", CreateMscBuilder); - RegisterBuilder("INTEL", CreateMscBuilder); -} +#include "Builders.h" + +#include + +#ifdef PLATFORM_WIN32 +static bool HasTail(String s, const char *tail) +{ + int tl = (int)strlen(tail); + int sl = s.GetLength(); + if(sl < tl) + return false; + for(const char *p = s.GetIter(sl - tl); *p; p++, tail++) + if(*tail != '*' && *tail != *p) + return false; + return *tail == 0; +} +#endif + +static void AddObjectExports(const char *path, Index& out) +{ +#ifdef PLATFORM_WIN32 + FileMapping mapping; + if(!mapping.Open(path)) + return; + const byte *begin = mapping.Begin(); + const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)begin; + if(hdr->Machine != COFF_IMAGE_FILE_MACHINE_I386) + return; + const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)(begin + + sizeof(COFF_IMAGE_FILE_HEADER) + hdr->SizeOfOptionalHeader); + Index code_sections; + for(int i = 0; i < hdr->NumberOfSections; i++) + if(sechdr[i].Characteristics & COFF_IMAGE_SCN_CNT_CODE) + code_sections.Add(i + 1); + const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + hdr->PointerToSymbolTable); + const char *strtbl = (const char *)(symtbl + hdr->NumberOfSymbols); + for(int i = 0; i < (int)hdr->NumberOfSymbols; i++) + { + const COFF_IMAGE_SYMBOL& sym = symtbl[i]; + if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL && code_sections.Find(sym.SectionNumber) >= 0) + { + String name = COFFSymbolName(sym, strtbl); + if(!HasTail(name, "AEPAXI@Z")) + { + if(*name == '_' && name.Find('@') < 0) + name.Remove(0, 1); + out.FindAdd(name); + } + } + i += sym.NumberOfAuxSymbols; + } +#endif +} + +void MscBuilder::AddFlags(Index& cfg) +{ + cfg.FindAdd("MSC"); +} + +String MscBuilder::CmdLine(const String& package, const Package& pkg) +{ + String cc; + if(HasFlag("ARM")) + cc = "clarm"; + else + if(HasFlag("MIPS")) + cc = "clmips"; + else + if(HasFlag("SH3")) + cc = "shcl /Qsh3"; + else + if(HasFlag("SH4")) + cc = "shcl /Qsh4"; + else + if(HasFlag("MSC8ARM")) + cc = "cl -GS- "; + else + cc = HasFlag("INTEL") ? "icl" : "cl"; +// TRC 080605-documentation says Wp64 works in 32-bit compilation only +// cc << (IsMsc64() ? " -nologo -Wp64 -W3 -GR -c" : " -nologo -W3 -GR -c"); + cc << " -nologo -W3 -GR -c"; + cc << IncludesDefinesTargetTime(package, pkg); + + return cc; +} + +String MscBuilder::MachineName() const +{ + if(HasFlag("ARM")) return "ARM"; + if(HasFlag("MIPS")) return "MIPS"; + if(HasFlag("SH3")) return "SH3"; + if(HasFlag("SH4")) return "SH4"; + if(IsMscArm()) return "ARM"; + if(IsMsc64()) return "x64"; + if(HasFlag("WIN32")) return "I386"; + return "IX86"; +} + +bool MscBuilder::IsMsc89() const +{ + return IsMsc86() || IsMsc64() || IsMscArm(); +} + +bool MscBuilder::IsMsc86() const +{ + return HasFlag("MSC8") || HasFlag("MSC9") || HasFlag("MSC10"); +} + +bool MscBuilder::IsMscArm() const +{ + return HasFlag("MSC8ARM") || HasFlag("MSC9ARM"); +} + +bool MscBuilder::IsMsc64() const +{ + return HasFlag("MSC8X64") || HasFlag("MSC9X64") || HasFlag("MSC10X64"); +} + +String MscBuilder::LinkerName() const +{ + if(HasFlag("ULD")) return "uld"; + if(HasFlag("INTEL")) return "xilink"; + return "link"; +} + +static bool sContainsPchOptions(const String& x) +{ + Index a(Split(x, ' ')); + return a.Find("-GL") >= 0 || a.Find("/GL") >= 0 || a.Find("-Y-") >= 0 || a.Find("/Y-") >= 0 + || a.Find("-Yc") >= 0 || a.Find("/Yc") >= 0 || a.Find("-Yd") >= 0 || a.Find("/Yd") >= 0 + || a.Find("-Yl") >= 0 || a.Find("/Yl") >= 0 || a.Find("-Yu") >= 0 || a.Find("/Yu") >= 0 + || a.Find("-YX") >= 0 || a.Find("/YX") >= 0; +} + +bool MscBuilder::HasAnyDebug() const +{ + return HasFlag("DEBUG") || HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL"); +} + +String MscBuilder::PdbPch(String package, int slot, bool do_pch) const +{ + String pkg_slot = NFormat("%s-%d", GetAnyFileName(package), slot + 1); + String pdb = GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pdb")); + String cc; + cc << " -Gy -Fd" << pdb << ' '; + if(do_pch && !IsMsc89()) // MSC8/9 does not support automatic precompiled headers... + cc << "-YX -Fp" << GetHostPathQ(CatAnyPath(outdir, pkg_slot + ".pch")) << ' '; + return cc; +} + +bool MscBuilder::BuildPackage(const String& package, Vector& linkfile, String& linkoptions, + const Vector& all_uses, const Vector& all_libraries, int opt) +{ + int i; + String packagepath = PackagePath(package); + Package pkg; + pkg.Load(packagepath); + String packagedir = GetFileFolder(packagepath); + ChDir(packagedir); + PutVerbose("cd " + packagedir); + IdeConsoleBeginGroup(package); + Vector obj; + + bool is_shared = HasFlag("SO"), + is_clr = HasFlag("CLR"); + + String cc = CmdLine(package, pkg); + if(HasFlag("EVC")) { + if(!HasFlag("SH3") && !HasFlag("SH4")) + cc << " -Gs8192"; // disable stack checking + cc << " -GF" // read-only string pooling + " -GX-"; // turn off exception handling + } + else + if(is_clr) + cc << " -EHac"; + else + if(IsMsc89()) + cc << " -EHsc"; + else + cc << " -GX"; +// String pdb = GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pdb")); +// String pch; +// if(!HasFlag("MSC8")) // MSC8 does not support automatic precompiled headers... +// pch << " -YX -Fp" << GetHostPathQ(CatAnyPath(outdir, GetAnyFileName(package) + ".pch")) << ' '; +// cc << " -Gy -Fd" << pdb; + if(HasFlag("SSE2") && !IsMsc64()) + cc << " /arch:SSE2"; + if(HasFlag("DEBUG_MINIMAL")) + cc << " -Zd"; + if(HasFlag("DEBUG_FULL")) + cc << " -Zi"; + cc << ' ' << Gather(pkg.option, config.GetKeys()); + cc << (HasFlag("SHARED") || is_shared || is_clr ? " -MD" + : (HasFlag("MT") || IsMsc89()) ? " -MT" : " -ML"); + + String cc_size = cc; + String cc_speed = cc; + bool release = false; + + if(HasFlag("DEBUG")) + cc << "d " << debug_options; + else { + release = true; + cc << ' ' << release_size_options; + cc_speed << ' ' << release_options; + if(opt == R_SPEED || pkg.optimize_speed) + cc = cc_speed; + } + + + Vector sfile, isfile; + Vector soptions, isoptions; + Vector optimize, ioptimize; + Vector sobjfile; + bool error = false; + + for(i = 0; i < pkg.GetCount(); i++) { + if(!IdeIsBuilding()) + return false; + if(!pkg[i].separator) { + String gop = Gather(pkg[i].option, config.GetKeys()); + Vector srcfile = CustomStep(pkg[i], package, error); + if(srcfile.GetCount() == 0) + error = true; + for(int j = 0; j < srcfile.GetCount(); j++) { + String fn = srcfile[j]; + String ext = ToLower(GetFileExt(fn)); + if(ext == ".c" || ext == ".cpp" || ext == ".cc" || ext == ".cxx" || ext == ".rc" || ext == ".brc") { + sfile.Add(fn); + soptions.Add(gop); + optimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL); + } + else + if(ext == ".icpp") { + isfile.Add(fn); + isoptions.Add(gop); + ioptimize.Add(release && pkg[i].optimize_speed && opt == R_OPTIMAL); + } + else + if(ext == ".obj") + obj.Add(fn); + else + if(ext == ".lib") + linkfile.Add(fn); + } + } + } + + if(HasFlag("BLITZ")) { + Blitz b = BlitzStep(sfile, soptions, obj, ".obj", optimize); + if(b.build) { + PutConsole("BLITZ:" + b.info); + int slot = AllocSlot(); + if(slot < 0 || ! Run(cc + PdbPch(package, slot, false) + + " -Tp " + GetHostPathQ(b.path) + " -Fo" + GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count)) + error = true; + } + } + + int first_ifile = sfile.GetCount(); + sfile.AppendPick(isfile); + soptions.AppendPick(isoptions); + optimize.AppendPick(ioptimize); + + int ccount = 0; + +// if(sContainsPchOptions(cc)) +// pch = Null; + + for(i = 0; i < sfile.GetCount(); i++) { + if(!IdeIsBuilding()) + return false; + String fn = sfile[i]; + String ext = ToLower(GetFileExt(fn)); + bool rc = (ext == ".rc"); + bool brc = (ext == ".brc"); + bool init = (i >= first_ifile); + String objfile = CatAnyPath(outdir, GetFileTitle(fn) + (rc ? "$rc.obj" : brc ? "$brc.obj" : ".obj")); + if(HdependFileTime(fn) > GetFileTime(objfile)) { + int time = GetTickCount(); + bool execerr = false; + if(rc) { + PutConsole(GetFileNamePos(fn)); + int slot = AllocSlot(); + if(slot < 0 || !Run("rc /fo" + GetHostPathQ(objfile) + Includes(" /i", package, pkg) + + ' ' + GetHostPathQ(fn), slot, GetHostPath(objfile), 1)) + execerr = true; + } + else + if(brc) { + try { +// String hfn = GetHostPath(fn); + String brcdata = LoadFile(fn); + if(brcdata.IsVoid()) + throw Exc(NFormat("error reading file '%s'", fn)); + CParser parser(brcdata, fn); + String fo = BrcToC(parser, GetFileDirectory(fn)); + String tmpfile = ForceExt(objfile, ".c"); + SaveFile(tmpfile, fo); + int slot = AllocSlot(); + StringBuffer cmdline; + cmdline << cc << PdbPch(package, slot, false) + << " -Tc " << GetHostPathQ(tmpfile) << " -Fo" << GetHostPathQ(objfile); + if(slot < 0 || !Run(String(cmdline), slot, GetHostPath(objfile), 1)) + throw Exc(NFormat("Error compiling binary object '%s'.", objfile)); + } + catch(Exc e) { + PutConsole(e); + execerr = true; + } + } + else { + String c = cc; + if(optimize[i]) + c = cc_speed; + int slot = AllocSlot(); + if(slot < 0 || !Run(c + PdbPch(package, slot, !sContainsPchOptions(cc) && !sContainsPchOptions(soptions[i])) + + " " + soptions[i] + (ext == ".c" ? " -Tc " : " -Tp ") + + GetHostPathQ(fn) + " -Fo" + GetHostPathQ(objfile), slot, GetHostPath(objfile), 1)) + execerr = true; + } + if(execerr) + DeleteFile(objfile); + error |= execerr; + PutVerbose("compiled in " + GetPrintTime(time)); + ccount++; + } + if(init) + linkfile.Add(objfile); + else + obj.Add(objfile); + } + if(error) { + IdeConsoleEndGroup(); + return false; + } + + Vector pkglibs = Split(Gather(pkg.library, config.GetKeys()), ' '); + for(int i = 0; i < pkglibs.GetCount(); i++) { + String libfile = AppendExt(pkglibs[i], ".lib"); + if(!IsFullPath(libfile)) { + for(int p = 0; p < libpath.GetCount(); p++) { + String nf = NormalizePath(libfile, libpath[p]); + if(FileExists(nf)) { + libfile = nf; + break; + } + } + } + linkfile.Add(libfile); + } + linkoptions << ' ' << Gather(pkg.link, config.GetKeys()); + + int linktime = GetTickCount(); + if(!HasFlag("MAIN")) { + if(HasFlag("BLITZ") || HasFlag("NOLIB")) { + linkfile.Append(obj); +// ShowTime(ccount, time); + IdeConsoleEndGroup(); + return true; + } + String product; + if(is_shared) + product = GetSharedLibPath(package); + else + product = CatAnyPath(outdir, GetAnyFileName(package) + ".lib"); + Time producttime = GetFileTime(product); + if(obj.GetCount()) + linkfile.Add(ForceExt(product, ".lib")); + if(!Wait()) { + IdeConsoleEndGroup(); + return false; + } + Vector objinfo = host->GetFileInfo(obj); + for(int i = 0; i < obj.GetCount(); i++) + if(objinfo[i] > producttime) { + String linker, lib; + if(is_shared) { + linker << LinkerName() << "-dll -nologo "; + lib << "-machine:" << MachineName() + << " -pdb:" << GetHostPathQ(ForceExt(product, ".pdb")) + << " -out:" << GetHostPathQ(product); + if(!HasFlag("MSC10") && !HasFlag("MSC10X64")) + lib << " -incremental:no"; + if(HasFlag("FORCE_SIZE")){ + if(sContainsPchOptions(release_size_options)) + lib << " -ltcg"; + } + else + if(HasFlag("FORCE_SPEED")) + if(sContainsPchOptions(release_options)) + lib << " -ltcg"; + if(HasAnyDebug()) + lib << " -debug -OPT:NOREF"; + else + lib << " -release -OPT:REF,ICF"; + if(IsMscArm()) + lib << " -subsystem:windowsce,4.20 /ARMPADCODE"; + else + if(HasFlag("GUI")) + lib << (HasFlag("WIN32") ? " -subsystem:windows" + : " -subsystem:windowsce"); + else + lib << " -subsystem:console"; + Index exports; + for(int o = 0; o < obj.GetCount(); o++) + AddObjectExports(obj[o], exports); + String def; + def << "LIBRARY " << AsCString(GetFileName(product)) << "\n\n" + "EXPORTS\n"; + for(int o = 0; o < exports.GetCount(); o++) + def << '\t' << exports[o] << "\n"; //" @" << (o + 1) << "\n"; + String deffile = ForceExt(product, ".def"); + if(!SaveChangedFile(deffile, def)) + { + PutConsole(NFormat("%s: error saving file", deffile)); + return false; + } + lib << " -def:" << GetHostPathQ(deffile); + for(int i = 0; i < libpath.GetCount(); i++) + lib << " -LIBPATH:" << GetHostPathQ(libpath[i]); + lib << ' ' << Gather(pkg.link, config.GetKeys()); + for(int i = 0; i < all_uses.GetCount(); i++) + lib << ' ' << GetHostPathQ(ForceExt(GetSharedLibPath(all_uses[i]), ".lib")); + for(int i = 0; i < all_libraries.GetCount(); i++) { + String libfile = AppendExt(all_libraries[i], ".lib"); + if(!IsFullPath(libfile)) { + for(int p = 0; p < libpath.GetCount(); p++) { + String nf = NormalizePath(libfile, libpath[p]); + if(FileExists(nf)) { + libfile = nf; + break; + } + } + } + lib << ' ' << GetHostPathQ(libfile); + } + } + else{ + linker << (HasFlag("INTEL") ? "xilib" : "link /lib") << " -nologo "; + if(HasFlag("FORCE_SIZE")){ + if(sContainsPchOptions(release_size_options)) + lib << " -ltcg"; + } + else + if(HasFlag("FORCE_SPEED")) + if(sContainsPchOptions(release_options)) + lib << " -ltcg"; + lib << " -out:" << GetHostPathQ(product) << ' ' << Gather(pkg.link, config.GetKeys()); + } + for(int i = 0; i < obj.GetCount(); i++) + lib << ' ' << GetHostPathQ(obj[i]); + PutConsole("Creating library..."); + IdeConsoleEndGroup(); + DeleteFile(product); + String tmpFileName; + if(linker.GetCount() + lib.GetCount() >= 8192) + { + tmpFileName = GetTempFileName(); + // we can't simply put all data on a single line + // as it has a limit of around 130000 chars too, so we split + // in multiple lines + FileOut f(tmpFileName); + while(lib != "") + { + int found = 0; + bool quotes = false; + int lim = min(8192, lib.GetCount()); + for(int i = 0; i < lim; i++) + { + char c = lib[i]; + if(isspace(c) && !quotes) + found = i; + else if(c == '"') + quotes = !quotes; + } + if(!found) + found = lib.GetCount(); + f.PutLine(lib.Left(found)); + lib.Remove(0, found); + } + f.Close(); + linker << "@" << tmpFileName; + } + else + linker << lib; + bool res = Execute(linker); + if(tmpFileName != "") + FileDelete(tmpFileName); + if(res) { + DeleteFile(product); + return false; + } + else + if((IsMsc86() || IsMsc64()) && is_shared) { + String mt("mt -nologo -manifest "); + mt << GetHostPathQ(product) << ".manifest -outputresource:" << GetHostPathQ(product) << ";2"; + Execute(mt); + } + PutConsole(String().Cat() << product << " (" << GetFileInfo(product).length + << " B) created in " << GetPrintTime(linktime)); + break; + } + return true; + } + + IdeConsoleEndGroup(); + obj.Append(linkfile); + linkfile = obj; + return true; +} + +bool MscBuilder::Link(const Vector& linkfile, const String& linkoptions, bool createmap) +{ + int time = GetTickCount(); + if(!Wait()) + return false; + for(int i = 0; i < linkfile.GetCount(); i++) + if(GetFileTime(linkfile[i]) >= targettime) { + String link; + link << LinkerName() << " -nologo -machine:" << MachineName() + << " -pdb:" << GetHostPathQ(ForceExt(target, ".pdb")) + << " -out:" << GetHostPathQ(target); + if(HasFlag("FORCE_SIZE")){ + if(sContainsPchOptions(release_size_options)) + link << " -ltcg"; + } + else + if(HasFlag("FORCE_SPEED")) + if(sContainsPchOptions(release_options)) + link << " -ltcg"; + if(!HasFlag("MSC10") && !HasFlag("MSC10X64")) + if(HasAnyDebug()) + link << " -incremental:yes -debug -OPT:NOREF"; + else + link << " -incremental:no -release -OPT:REF,ICF"; + else + if(HasAnyDebug()) + link << " -debug -OPT:NOREF"; + else + link << " -release -OPT:REF,ICF"; + if(IsMscArm()) + link << " -subsystem:windowsce,4.20 /ARMPADCODE -NODEFAULTLIB:\"oldnames.lib\" "; + else + if(HasFlag("GUI") || IsMscArm()) + link << (HasFlag("WIN32") ? " -subsystem:windows" : " -subsystem:windowsce"); + else + link << " -subsystem:console"; + if(createmap) + link << " -MAP"; + if(HasFlag("DLL")) + link << " -DLL"; + for(i = 0; i < libpath.GetCount(); i++) + link << " -LIBPATH:\"" << libpath[i] << '\"'; + link << ' ' << linkoptions << ' '; + for(i = 0; i < linkfile.GetCount(); i++) + link << ' ' << GetHostPathQ(AppendExt(linkfile[i], ".lib")); + PutConsole("Linking..."); + bool error = false; + CustomStep(".pre-link", Null, error); + if(!error && Execute(link) == 0) { + CustomStep(".post-link", Null, error); + if((IsMsc86() || IsMsc64()) && HasFlag("SHARED")) { + String mt("mt -nologo -manifest "); + mt << GetHostPathQ(target) << ".manifest -outputresource:" << GetHostPathQ(target) + << (HasFlag("DLL") ? ";2" : ";1"); + Execute(mt); + } + PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length + << " B) linked in " << GetPrintTime(time)); + return !error; + } + else { + DeleteFile(target); + return false; + } + } + PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length + << " B) is up to date."); + return true; +} + +bool MscBuilder::Preprocess(const String& package, const String& file, const String& target, bool) +{ + FileOut out(target); + String packagepath = PackagePath(package); + Package pkg; + pkg.Load(packagepath); + return Execute(CmdLine(package, pkg) + " -E " + file, out); +} + +Builder *CreateMscBuilder() +{ + return new MscBuilder; +} + +INITBLOCK +{ + RegisterBuilder("MSC71", CreateMscBuilder); + RegisterBuilder("MSC8", CreateMscBuilder); + RegisterBuilder("MSC8X64", CreateMscBuilder); + RegisterBuilder("MSC8ARM", CreateMscBuilder); + RegisterBuilder("MSC9", CreateMscBuilder); + RegisterBuilder("MSC9X64", CreateMscBuilder); + RegisterBuilder("MSC10", CreateMscBuilder); + RegisterBuilder("MSC10X64", CreateMscBuilder); + RegisterBuilder("MSC9ARM", CreateMscBuilder); + RegisterBuilder("EVC_ARM", CreateMscBuilder); + RegisterBuilder("EVC_MIPS", CreateMscBuilder); + RegisterBuilder("EVC_SH3", CreateMscBuilder); + RegisterBuilder("EVC_SH4", CreateMscBuilder); + RegisterBuilder("INTEL", CreateMscBuilder); +}