void SerializePPFiles(Stream& s) { s % sAllMacros % sPPfile % sPPserial; if(s.IsLoading()) LoadPPConfig(); #if 0 if(s.IsLoading()) { _DBG_ DDUMP(sPPfile.GetCount()); DDUMP(sAllMacros.GetCount()); DDUMP(sPPserial); Index<int> psegment; for(int i = 0; i < sPPfile.GetCount(); i++) { const PPFile& p = sPPfile[i]; for(int j = 0; j < p.item.GetCount(); j++) psegment.FindAdd(p.item[j].segment_id); } DDUMP(psegment.GetCount()); int n = 0; _DBG_ Index<int> msegment; for(int i = 0; i < sAllMacros.GetCount(); i++) { _DBG_ if(sAllMacros.IsUnlinked(i)) n++; else msegment.FindAdd(sAllMacros[i].segment_id); } DLOG("UNLINKED " << n); DLOG("Segments " << msegment.GetCount()); }
static bool sIsEqual(const Index<Value>& a, const Index<Value>& b) { if(&a == &b) return true; if(a.GetCount() != b.GetCount()) return false; for(int i = 0; i < a.GetCount(); i++) { if(a[i] != b[i]) return false; } return true; }
PPMacro *FindPPMacro(const String& id, Index<int>& segment_id, int& segmenti) { Index<int> undef; PPMacro *r; int best; for(int pass = 0; pass < 2; pass++) { r = NULL; best = segmenti; int line = -1; int q = sAllMacros.Find(id); while(q >= 0) { PPMacro& m = sAllMacros[q]; if(m.macro.IsUndef()) { if(pass == 0 && segment_id.Find(m.segment_id) >= 0) undef.FindAdd(m.segment_id); // cancel out undefined macro... } else if(pass == 0 || m.segment_id == 0 || undef.Find(m.undef_segment_id) < 0) { int si = m.segment_id == 0 ? INT_MAX : segment_id.Find(m.segment_id); // defs macros always override if(si > best || si >= 0 && si == best && m.line > line) { best = si; line = m.line; r = &m; } } q = sAllMacros.FindNext(q); } if(undef.GetCount() == 0) break; } segmenti = best; return r; }
String MakeBuild::OutDir(const Index<String>& cfg, const String& package, const VectorMap<String, String>& bm, bool use_target) { Index<String> excl; excl.Add(bm.Get("BUILDER", "GCC")); excl.Add("MSC"); LocalHost().AddFlags(excl); Vector<String> x; bool dbg = cfg.Find("DEBUG_FULL") >= 0 || cfg.Find("DEBUG_MINIMAL") >= 0; if(cfg.Find("DEBUG") >= 0) { excl.Add("BLITZ"); if(cfg.Find("BLITZ") < 0) x.Add("NOBLITZ"); } else if(dbg) x.Add("RELEASE"); if(use_target) excl.Add("MAIN"); for(int i = 0; i < cfg.GetCount(); i++) if(excl.Find(cfg[i]) < 0) x.Add(cfg[i]); Sort(x); for(int i = 0; i < x.GetCount(); i++) x[i] = InitCaps(x[i]); String outdir = GetVar("OUTPUT"); if(output_per_assembly) outdir = AppendFileName(outdir, GetVarsName()); if(!use_target) outdir = AppendFileName(outdir, package); outdir = AppendFileName(outdir, GetFileTitle(method) + "." + Join(x, ".")); outdir = Filter(outdir, CharFilterSlash); return outdir; }
void RichQtfParser::FinishOldTable() { FinishCell(); Index<int> pos; Vector<int> srow; RichTable& t = Table(); Tab& b = table.Top(); for(int i = 0; i < t.GetRows(); i++) { int& s = srow.Add(); s = 0; int nx = b.rown[i]; for(int j = 0; j < nx; j++) s += t.GetSpan(i, j).cx; int xn = 0; for(int j = 0; j < nx; j++) { pos.FindAdd(xn * 10000 / s); xn += t.GetSpan(i, j).cx; } } Vector<int> h = pos.PickKeys(); if(h.GetCount() == 0) Error("table"); Sort(h); pos = pick(h); pos.Add(10000); RichTable tab; tab.SetFormat(t.GetFormat()); for(int i = 0; i < pos.GetCount() - 1; i++) { tab.AddColumn(pos[i + 1] - pos[i]); } for(int i = 0; i < t.GetRows(); i++) { int s = srow[i]; int nx = b.rown[i]; int xn = 0; int xi = 0; for(int j = 0; j < nx; j++) { Size span = t.GetSpan(i, j); xn += span.cx; int nxi = pos.Find(xn * 10000 / s); tab.SetPick(i, xi, t.GetPick(i, j)); tab.SetFormat(i, xi, t.GetFormat(i, j)); tab.SetSpan(i, xi, max(span.cy - 1, 0), nxi - xi - 1); xi = nxi; } } table.Drop(); if(table.GetCount()) table.Top().text.CatPick(pick(tab)); else target.CatPick(pick(tab)); oldtab = false; }
void ExtExclude(CParser& p, Index<String>& x) { Vector<String> e = ReadPatterns(p); Vector<int> remove; for(int i = 0; i < x.GetCount(); i++) for(int j = 0; j < e.GetCount(); j++) { if(PatternMatch(e[j], x[i])) { remove.Add(i); break; } } x.Remove(remove); }
Vector<String> Workspace::GetAllAccepts(int pk) const { Index<String> accepts; Index<int> 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(); }
// fill a pane with data from a couple of arrays without erasing it first // (avoid re-painting and resetting scroll if not needed) void Gdb_MI2::FillPane(ArrayCtrl &pane, Index<String> const &nam, Vector<String> const &val) { GuiLock __; int oldCount = pane.GetCount(); int newCount = nam.GetCount(); if(newCount < oldCount) for(int i = oldCount - 1; i >= newCount; i--) pane.Remove(i); for(int i = 0; i < min(oldCount, newCount); i++) { pane.Set(i, 0, nam[i]); pane.Set(i, 1, val[i]); } for(int i = oldCount; i < newCount; i++) pane.Add(nam[i], val[i]); SyncWidth(pane); }
void DocDir::Refresh(const String& package) { FindFile ff(DocFile(package, "dir.h")); if(!ff) { RebuildDir(package); return; } FileTime dirtime = ff.GetLastWriteTime(); ff.Search(DocFile(package, "links")); if(ff && ff.GetLastWriteTime() > dirtime) { RebuildDir(package); return; } const ArrayMap<DocKey, Entry>& p = dir.GetAdd(package); Index<String> dfn; for(int i = 0; i < p.GetCount(); i++) if(p[i].type == NORMAL || p[i].type == EXTERNAL) dfn.Add(p[i].text); ff.Search(DocFile(package, "*.dpp")); int count = 0; while(ff) { DocKey key; if(dfn.Find(ff.GetName()) >= 0) if(ff.GetLastWriteTime() > dirtime) { RebuildDir(package); return; } else count++; else if(ReadDocHeader(DocFile(package, ff.GetName()), key) >= 0) { RebuildDir(package); return; } ff.Next(); } if(count != dfn.GetCount()) RebuildDir(package); }
void Ide::DoDirDiff() { Index<String> dir; Vector<String> d = GetUppDirs(); for(int i = 0; i < d.GetCount(); i++) dir.FindAdd(d[i]); FindFile ff(ConfigFile("*.bm")); while(ff) { VectorMap<String, String> var; LoadVarFile(ff.GetPath(), var); Vector<String> p = Split(var.Get("UPP", String()), ';'); for(int i = 0; i < p.GetCount(); i++) dir.FindAdd(p[i]); ff.Next(); } String n = GetFileFolder(editfile); if(n.GetCount()) dir.FindAdd(n); SortIndex(dir); static DirDiffDlg dlg; dlg.diff.WhenLeftLine = THISBACK1(GotoDirDiffLeft, &dlg); dlg.diff.WhenRightLine = THISBACK1(GotoDirDiffRight, &dlg); for(int i = 0; i < dir.GetCount(); i++) { dlg.Dir1AddList(dir[i]); dlg.Dir2AddList(dir[i]); } if(d.GetCount()) dlg.Dir1(d[0]); if(!dlg.IsOpen()) { dlg.SetFont(veditorfont); dlg.Maximize(); dlg.Title("Compare directories"); dlg.OpenMain(); } else dlg.SetFocus(); }
void MakeBuild::SaveMakeFile(const String& fn, bool exporting) { BeginBuilding(false, true); VectorMap<String, String> bm = GetMethodVars(method); One<Host> host = CreateHost(false); One<Builder> b = CreateBuilder(~host); if(!b) return; const TargetMode& tm = GetTargetMode(); String makefile; Vector<String> uppdirs = GetUppDirs(); String uppout = exporting ? host->GetHostPath(GetVar("OUTPUT")) : "_out/"; String inclist; Index<String> allconfig = PackageConfig(GetIdeWorkspace(), 0, bm, mainconfigparam, *host, *b); bool win32 = allconfig.Find("WIN32") >= 0; Workspace wspc; wspc.Scan(GetMain(), allconfig.GetKeys()); for(int i = 1; i < wspc.GetCount(); i++) { Index<String> modconfig = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); for(int a = allconfig.GetCount(); --a >= 0;) if(modconfig.Find(allconfig[a]) < 0) allconfig.Remove(a); } if(!exporting) for(int i = 0; i < uppdirs.GetCount(); i++) { String srcdir = GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppdirs[i], ""))), win32); makefile << "UPPDIR" << (i + 1) << " = " << srcdir << "\n"; inclist << " -I$(UPPDIR" << (i + 1) << ")"; } else inclist << "-I./"; Vector<String> includes = SplitDirs(bm.Get("INCLUDE","")); for(int i = 0; i < includes.GetCount(); i++) inclist << " -I" << includes[i]; makefile << "\n" "UPPOUT = " << (exporting ? "_out/" : GetMakePath(AdjustMakePath(host->GetHostPath(AppendFileName(uppout, ""))), win32)) << "\n" "CINC = " << inclist << "\n" "Macro = "; for(int i = 0; i < allconfig.GetCount(); i++) makefile << " -Dflag" << allconfig[i]; makefile << "\n"; String output, config, install, rules, linkdep, linkfiles, linkfileend; for(int i = 0; i < wspc.GetCount(); i++) { b->config = PackageConfig(wspc, i, bm, mainconfigparam, *host, *b); b->version = tm.version; b->method = method; MakeFile mf; b->AddMakeFile(mf, wspc[i], GetAllUses(wspc, i), GetAllLibraries(wspc, i, bm, mainconfigparam, *host, *b), allconfig, exporting); if(!i) { String tdir = mf.outdir; String trg; if(tm.target_override) { trg = GetMakePath(AdjustMakePath(tm.target), win32); if(!trg.IsEmpty() && *trg.Last() == (win32 ? '\\' : '/')) trg << mf.outfile; else if(trg.Find(win32 ? '\\' : '/') < 0) trg.Insert(0, "$(OutDir)"); } output = Nvl(trg, mf.output); if(exporting) output = wspc[i] + ".out"; install << "\n" "OutDir = " << tdir << "\n" "OutFile = " << output << "\n" "\n" ".PHONY: all\n" "all: prepare $(OutFile)\n" "\n" ".PHONY: prepare\n" "prepare:\n"; } config << mf.config; install << mf.install; rules << mf.rules; linkdep << mf.linkdep; linkfiles << mf.linkfiles; linkfileend << mf.linkfileend; } makefile << config << install << "\n" "$(OutFile): " << linkdep << "\n\t" << linkfiles << linkfileend << " -Wl,--end-group\n\n" << rules << ".PHONY: clean\n" << "clean:\n" << "\tif [ -d $(UPPOUT) ]; then rm -rf $(UPPOUT); fi;\n"; bool sv = ::SaveFile(fn, makefile); if(!exporting) if(sv) PutConsole(NFormat("%s(1): makefile generation complete", fn)); else PutConsole(NFormat("%s: error writing makefile", fn)); EndBuilding(true); }
bool MakeBuild::Build(const Workspace& wspc, String mainparam, String outfile, bool clear_console) { String hfile = outfile + ".xxx"; SaveFile(hfile, ""); FileTime start_time = GetFileTime(hfile); // Defensive way to get correct filetime of start DeleteFile(hfile); ClearErrorEditor(); BeginBuilding(true, clear_console); bool ok = true; if(wspc.GetCount()) { for(int i = 0; i < wspc.GetCount(); i++) { const Package& pk = wspc.package[i]; for(int j = 0; j < pk.GetCount(); j++) if(pk[j] == "main.conf") { String pn = wspc[i]; String p = SourcePath(pn, "main.conf"); main_conf << "// " << pn << "\r\n" << LoadFile(p) << "\r\n"; PutConsole("Found " + p); } } if(main_conf.GetCount()) { VectorMap<String, String> bm = GetMethodVars(method); One<Host> host = CreateHost(false); One<Builder> b = CreateBuilder(~host); if(b) { Index<String> mcfg = PackageConfig(wspc, 0, bm, mainparam, *host, *b, NULL); String outdir = OutDir(mcfg, wspc[0], bm, false); String path = AppendFileName(outdir, "main.conf.h"); RealizePath(path); SaveChangedFile(path, main_conf); PutConsole("Saving " + path); add_includes << outdir << ';'; } } Vector<int> build_order; if(GetTargetMode().linkmode != 2) { for(int i = 1; i < wspc.GetCount(); i++) build_order.Add(i); } else { Index<int> remaining; for(int i = 1; i < wspc.GetCount(); i++) remaining.Add(i); while(!remaining.IsEmpty()) { int t; for(t = 0; t < remaining.GetCount(); t++) { const Package& pk = wspc.package[remaining[t]]; bool delay = false; for(int u = 0; u < pk.uses.GetCount(); u++) if(remaining.Find(wspc.package.Find(pk.uses[u].text)) >= 0) { delay = true; break; } if(!delay) break; } if(t >= remaining.GetCount()) t = 0; build_order.Add(remaining[t]); remaining.Remove(t); } } String mainpackage = wspc[0]; Vector<String> linkfile; String linkopt = GetMethodVars(method).Get(targetmode ? "RELEASE_LINK" : "DEBUG_LINK", Null); if(linkopt.GetCount()) linkopt << ' '; ok = true; int ms = msecs(); for(int i = 0; i < build_order.GetCount() && (ok || !stoponerrors); i++) { int px = build_order[i]; ok = BuildPackage(wspc, px, i, build_order.GetCount() + 1, mainparam, Null, linkfile, linkopt) && ok; if(msecs() - ms >= 200) { DoProcessEvents(); ms = msecs(); } } if(ok || !stoponerrors) { ok = BuildPackage(wspc, 0, build_order.GetCount(), build_order.GetCount() + 1, mainparam, outfile, linkfile, linkopt, ok) && ok; // Set the time of target to start-time, so that if any file changes during // compilation, it is recompiled during next build SetFileTime(target, start_time); } } EndBuilding(ok); ReQualifyCodeBase(); SetErrorEditor(); return ok; }
Vector<String> CppBuilder::CustomStep(const String& pf, const String& package_, bool& error) { String package = Nvl(package_, mainpackage); String path = (*pf == '.' && pf[1] != '.') ? target : SourcePath(package, pf); String file = GetHostPath(path); String ext = ToLower(GetFileExt(pf)); if(ext == ".ext") { Vector<String> files; Vector<String> dirs; sGatherAllExt(files, dirs, GetFileFolder(path), ""); Index<String> pkg_files; Package pkg; pkg.Load(PackagePath(package)); for(int i = 0; i < pkg.GetCount(); i++) pkg_files.Add(pkg[i]); Index<String> out; Index<String> include_path; String f = LoadFile(path); try { CParser p(f); while(!p.IsEof()) { if(p.Id("files")) { Vector<String> e = ReadPatterns(p); for(int i = 0; i < files.GetCount(); i++) for(int j = 0; j < e.GetCount(); j++) { String f = files[i]; if(PatternMatch(e[j], f) && pkg_files.Find(f) < 0) out.FindAdd(f); } } if(p.Id("exclude")) { ExtExclude(p, out); } if(p.Id("include_path")) { Vector<String> e = ReadPatterns(p); for(int j = 0; j < e.GetCount(); j++) { String ee = e[j]; if(ee.Find('*') >= 0) for(int i = 0; i < dirs.GetCount(); i++) { String d = dirs[i]; if(PatternMatch(e[j], d)) { include_path.FindAdd(d); } } else include_path.Add(ee); } } if(p.Id("exclude_path")) { ExtExclude(p, include_path); } if(p.Id("includes")) { Vector<String> e = ReadPatterns(p); for(int i = 0; i < files.GetCount(); i++) for(int j = 0; j < e.GetCount(); j++) { String f = files[i]; if(PatternMatch(e[j], f) && pkg_files.Find(f) < 0) include_path.FindAdd(GetFileFolder(f)); } } } } catch(CParser::Error) { PutConsole("Invalid .ext file"); error = true; return Vector<String>(); } for(int i = 0; i < include_path.GetCount(); i++) include.Add(NormalizePath(include_path[i], GetFileFolder(path))); Vector<String> o; for(int i = 0; i < out.GetCount(); i++) o.Add(SourcePath(package, out[i])); return o; } for(int i = 0; i < wspc.GetCount(); i++) { const Array< ::CustomStep >& mv = wspc.GetPackage(i).custom; for(int j = 0; j < mv.GetCount(); j++) { const ::CustomStep& m = mv[j]; if(MatchWhen(m.when, config.GetKeys()) && m.MatchExt(ext)) { VectorMap<String, String> mac; AddPath(mac, "PATH", file); AddPath(mac, "RELPATH", pf); AddPath(mac, "DIR", GetFileFolder(PackagePath(package))); AddPath(mac, "FILEDIR", GetFileFolder(file)); AddPath(mac, "PACKAGE", package); mac.Add("FILE", GetFileName(file)); mac.Add("TITLE", GetFileTitle(file)); AddPath(mac, "EXEPATH", GetHostPath(target)); AddPath(mac, "EXEDIR", GetHostPath(GetFileFolder(target))); mac.Add("EXEFILE", GetFileName(target)); mac.Add("EXETITLE", GetFileTitle(target)); AddPath(mac, "OUTDIR", GetHostPath(outdir)); //BW AddPath(mac, "OUTDIR", GetHostPath(GetFileFolder(target))); AddPath(mac, "OUTFILE", GetHostPath(GetFileName(target))); AddPath(mac, "OUTTITLE", GetHostPath(GetFileTitle(target))); mac.Add("INCLUDE", Join(include, ";")); Vector<String> out = Cuprep(m.output, mac, include); bool dirty = out.IsEmpty(); for(int i = 0; !dirty && i < out.GetCount(); i++) dirty = (GetFileTime(file) > GetFileTime(out[i])); if(dirty) { HdependTimeDirty(); PutConsole(GetFileName(file)); Vector<String> cmd = Cuprep(m.command, mac, include); String cmdtext; for(int c = 0; c < cmd.GetCount(); c++) { PutVerbose(cmd[c]); if(!Cd(cmd[c]) && !Cp(cmd[c], package, error)) { String ctext = cmd[c]; const char *cm = ctext; if(*cm == '?') cm++; if(*ctext != '?' && Execute(cm)) { for(int t = 0; t < out.GetCount(); t++) DeleteFile(out[t]); PutConsole("FAILED: " + ctext); error = true; return Vector<String>(); } } } } return out; } } } Vector<String> out; out.Add(path); return out; }
void Ide::FindInFiles(bool replace) { CodeEditor::FindReplaceData d = editor.GetFindReplaceData(); CtrlRetriever rf; rf(ff.find, d.find) (ff.replace, d.replace) (ff.ignorecase, d.ignorecase) (ff.samecase, d.samecase) (ff.wholeword, d.wholeword) (ff.wildcards, d.wildcards) (ff.regexp, d.regexp) ; WriteList(ff.find, d.find_list); WriteList(ff.replace, d.replace_list); ff.Sync(); if(IsNull(~ff.folder)) ff.folder <<= GetUppDir(); ff.style <<= STYLE_NO_REPLACE; ff.Sync(); ff.itext = editor.GetI(); ff.Setup(replace); int c = ff.Execute(); ff.find.AddHistory(); ff.replace.AddHistory(); rf.Retrieve(); d.find_list = ReadList(ff.find); d.replace_list = ReadList(ff.replace); editor.SetFindReplaceData(d); if(c == IDOK) { ffound.HeaderTab(2).SetText("Source line"); Renumber(); ff.find.AddHistory(); ff.files.AddHistory(); ff.folder.AddHistory(); ff.replace.AddHistory(); Progress pi("Found %d files to search."); pi.AlignText(ALIGN_LEFT); Index<String> files; if(ff.workspace) { const Workspace& wspc = GetIdeWorkspace(); for(int i = 0; i < wspc.GetCount(); i++) SearchForFiles(files, GetFileFolder(PackagePath(wspc[i])), ~ff.files, ~ff.readonly, pi); } else SearchForFiles(files, NormalizePath(~~ff.folder, GetUppDir()), ~ff.files, ~ff.readonly, pi); if(!pi.Canceled()) { String pattern; RegExp rx, *regexp = NULL; if(ff.regexp) { rx.SetPattern(~ff.find); regexp = ℞ pattern = "dummy"; } else if(ff.wildcards) { String q = ~ff.find; for(const char *s = q; *s; s++) if(*s == '\\') { s++; if(*s == '\0') break; pattern.Cat(*s); } else switch(*s) { case '*': pattern.Cat(WILDANY); break; case '?': pattern.Cat(WILDONE); break; case '%': pattern.Cat(WILDSPACE); break; case '#': pattern.Cat(WILDNUMBER); break; case '$': pattern.Cat(WILDID); break; default: pattern.Cat(*s); } } else pattern = ~ff.find; pi.SetTotal(files.GetCount()); ShowConsole2(); ffound.Clear(); pi.SetPos(0); int n = 0; for(int i = 0; i < files.GetCount(); i++) { pi.SetText(files[i]); if(pi.StepCanceled()) break; if(!IsNull(pattern)) { if(!SearchInFile(files[i], pattern, ff.wholeword, ff.ignorecase, n, regexp)) break; } else { ErrorInfo f; f.file = files[i]; f.lineno = 1; f.linepos = 0; f.kind = 0; f.message = files[i]; ffound.Add(f.file, 1, f.message, RawToValue(f)); ffound.Sync(); n++; } } if(!IsNull(pattern)) ffound.Add(Null, Null, AsString(n) + " occurrence(s) have been found."); else ffound.Add(Null, Null, AsString(n) + " matching file(s) have been found."); ffound.HeaderTab(2).SetText(Format("Source line (%d)", ffound.GetCount())); } } }
void HelpTopicLoad(String text_module, String data, Index<String> *topics_loaded) { const int *x = GetAllLanguages(); Vector<int> llist; while(*x) llist.Add(*x++); Index<String> lnames; while(lnames.GetCount() < llist.GetCount()) lnames.Add(GetLangIdent(llist[lnames.GetCount()])); int language = 0; CParser parser(data); while(!parser.IsEof()) { parser.Spaces(); if(parser.IsId()) { String id = parser.ReadId(); enum { DECL_NONE, DECL_HTB, DECL_HT, DECL_I } decl = DECL_NONE; if(id == "HELP_TOPIC_BEGIN") decl = DECL_HTB; else if(id == "HELP_TOPIC") decl = DECL_HT; else if(id == "ITEM") decl = DECL_I; if(decl != DECL_NONE) { parser.PassChar('('); String space = "AppDoc", nesting, topic; if(decl != DECL_HTB) { space = parser.ReadOneString(); parser.PassChar(','); nesting = parser.ReadOneString(); parser.PassChar(','); } topic = parser.ReadOneString(); parser.PassChar(','); if(decl == DECL_HTB) { String langid = parser.ReadId(); int lx = lnames.Find(langid); if(lx < 0) parser.ThrowError(NFormat("invalid language code: %d", language)); language = llist[lx]; } else { String lang = parser.ReadOneString(); language = LNGFromText(lang); } String title; if(decl != DECL_I) { parser.PassChar(','); title = parser.ReadOneString(); } parser.PassChar(')'); parser.Id("EXTERNAL"); String text; while(parser.IsId() && ((id = parser.ReadId()) == "HELP_TOPIC_TEXT" || id == "HELP_TEXT" || id == "TEXT")) { parser.PassChar('('); text.Cat(parser.ReadString()); parser.PassChar(')'); } if(id == "HELP_TOPIC_END") { parser.PassChar('('); parser.PassChar(')'); } else if(id == "END_ITEM" || id == "HELP_END") ; else parser.ThrowError(NFormat("HELP_TOPIC_END/END_ITEM expected, found: %s", StringSample(parser.GetPtr(), 10))); String drl = HelpFormatDPP(space, nesting, topic); HelpTopicSet(drl, text_module, language, title, text); if(topics_loaded) topics_loaded->FindAdd(drl); } else parser.ThrowError(NFormat("HELP_TOPIC_BEGIN/HELP_TOPIC/ITEM expected, found: %s", id)); } else parser.ThrowError(NFormat("identifier expected, found: %s", StringSample(parser.GetPtr(), 20))); } }