void CMacroList::DeleteMacro(int nMacro) { ASSERT(nMacro < Macros()); if (nMacro < Macros()) { delete Macro(nMacro); RemoveAt(nMacro); } }
void CMacroList::DeleteAll(void) { while (Macros() != 0) { DeleteMacro(0); } }
BOOL CMacroList::SetMacroValue(int nMacro, const CString& csNewValue) { if (nMacro < Macros()) { CMacro* pMacro = Macro(nMacro); if (pMacro != NULL) { pMacro->Value(csNewValue); return TRUE; } } ASSERT(FALSE); return FALSE; }
CMacro* CMacroList::FindMacro(LPCSTR pName) { int nMacros = Macros(); for (int nMacro = 0; nMacro < nMacros; nMacro++) { CMacro* pMacro = Macro(nMacro); if (pMacro->Name() == pName) { return pMacro; } } return NULL; }
CMacro* CMacroList::FindMacro(WORD wID) { int nMacros = Macros(); for (int nMacro = 0; nMacro < nMacros; nMacro++) { CMacro* pMacro = Macro(nMacro); if (pMacro->Id() == wID) { return pMacro; } } return NULL; }
void CMacroList::DeleteMacro(LPCSTR pName) { int nMacros = Macros(); for (int nMacro = 0; nMacro < nMacros; nMacro++) { CMacro* pMacro = Macro(nMacro); if (pMacro->Name() == pName) { DeleteMacro(nMacro); return; } } }
BOOL CMacroList::GetMacroValue(int nMacro, CString& csValue) { /* In case of error. */ csValue.Empty(); if (nMacro < Macros()) { CMacro* pMacro = Macro(nMacro); if (pMacro != NULL) { csValue = pMacro->Value(); return TRUE; } } ASSERT(FALSE); return FALSE; }
void Evaluator::subst_macros() { int cntr = 0; Token gtok(0, 0); while (1) { if (++cntr > MAX_SUBST) throw Err("Too many macro substitutions: " + bug::to_string(MAX_SUBST) + ", possible recursion", gtok); bool weresubs = false; Nodes old = root->children; root->children.clear(); Nodes leftovers; for (auto i : old) { Instruction * pin = get<Instruction>(NOTHR, i); if (pin) { for (auto j : leftovers) i->children[0]->children[1]->children.push_back(j); leftovers.clear(); root->addChild(i); continue; } Macuse * u = get<Macuse>(LNFUN, i); gtok = u->tok(); if (u->name() == "@end") { for (auto j : u->children[0]->children) leftovers.push_back(j); continue; } Nodes inject = Macros(root).process_macuse(*u); if (!inject.empty()) { Pnode pn = inject.front(); Instruction * pin = get<Instruction>(NOTHR, pn); if (pin) { for (auto j : leftovers) pn->children[0]->children[1]->children.push_back(j); } else { Macuse * pu = get<Macuse>(LNFUN, pn); for (auto j : leftovers) pu->children[0]->children.push_back(j); } leftovers.clear(); } for (auto j : inject) root->addChild(j); weresubs = true; } if (!weresubs) { if (leftovers.empty()) break; if (root->children.empty()) throw Err("Labels used in empty program"); throw Err("Program finishes with label (see macro definition)", root->children.back()->tok()); } // this can be improved later (one extra loop) // when expanding macro we can detect that no new macro introduced } // while }