osgDB::ReaderWriter::ReadResult readNodeFromArchive(osgDB::Archive& archive, const osgDB::ReaderWriter::Options* options) const { osgDB::ReaderWriter::ReadResult result(osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND); if (!archive.getMasterFileName().empty()) { result = archive.readNode(archive.getMasterFileName(), options); } else { osgDB::Archive::FileNameList fileNameList; if (archive.getFileNames(fileNameList)) { typedef std::list< osg::ref_ptr<osg::Node> > Nodes; Nodes nodes; for(osgDB::Archive::FileNameList::iterator itr = fileNameList.begin(); itr != fileNameList.end(); ++itr) { result = archive.readNode(*itr, options); if (result.validNode()) nodes.push_back(result.getNode()); } if (!nodes.empty()) { if (nodes.size()==1) { result = osgDB::ReaderWriter::ReadResult(nodes.front().get()); } else { osg::ref_ptr<osg::Group> group = new osg::Group; for(Nodes::iterator itr = nodes.begin(); itr != nodes.end(); ++itr) { group->addChild(itr->get()); } result = osgDB::ReaderWriter::ReadResult(group.get()); } } } } return result; }
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 }