00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <csignal>
00020 #include <algorithm>
00021 #include <set>
00022 #include <fstream>
00023 #include <climits>
00024 #include <sstream>
00025 #include "ncl/nxsreader.h"
00026 #include "ncl/nxsdefs.h"
00027
00028 #include "ncl/nxscharactersblock.h"
00029 #include "ncl/nxstaxablock.h"
00030 #include "ncl/nxstreesblock.h"
00031
00032 using namespace std;
00033
00034 #if defined(NCL_CONST_FUNCS) && NCL_CONST_FUNCS
00035 int onlyDefinedInCouldBeConst()
00036 {
00037 return 1;
00038 }
00039
00040 #endif
00041
00042
00043 static void NxsHandleSignalCallback(int);
00044
00045 NxsReader::SignalHandlerFuncPtr NxsReader::prevSignalCatcher = 0L;
00046 bool NxsReader::nclCatchesSignals = false;
00047 unsigned NxsReader::numSigIntsCaught = 0;
00048 bool NxsReader::prevSignalStored = true;
00049
00050 unsigned NxsReader::getNumSignalIntsCaught()
00051 {
00052 return NxsReader::numSigIntsCaught;
00053 }
00054
00055 void NxsReader::setNumSignalsIntsCaught(unsigned n)
00056 {
00057 NxsReader::numSigIntsCaught = n;
00058 }
00059
00060 void NxsReader::setNCLCatchesSignals(bool v)
00061 {
00062 NxsReader::nclCatchesSignals = v;
00063 }
00064
00065 bool NxsReader::getNCLCatchesSignals()
00066 {
00067 return NxsReader::nclCatchesSignals;
00068 }
00069
00070
00071 void NxsHandleSignalCallback(int)
00072 {
00073 unsigned nc = NxsReader::getNumSignalIntsCaught();
00074 NxsReader::setNumSignalsIntsCaught(1 + nc);
00075 }
00076
00077 void NxsReader::installNCLSignalHandler()
00078 {
00079 NxsReader::SignalHandlerFuncPtr prev = std::signal(SIGINT, SIG_IGN);
00080 if (prev != SIG_IGN)
00081 {
00082 NxsReader::prevSignalCatcher = prev;
00083 NxsReader::prevSignalStored = true;
00084 std::signal(SIGINT, NxsHandleSignalCallback);
00085 }
00086 }
00087
00088 void NxsReader::uninstallNCLSignalHandler()
00089 {
00090 if (prevSignalStored)
00091 {
00092 std::signal(SIGINT, NxsReader::prevSignalCatcher);
00093 NxsReader::prevSignalCatcher = 0L;
00094 NxsReader::prevSignalStored = false;
00095 }
00096 }
00097
00098
00099
00101 void NxsReader::ReadFilepath(const char *filename)
00102 {
00103 std::ifstream inf;
00104 try{
00105 inf.open(filename, ios::binary);
00106 if (!inf.good())
00107 {
00108 NxsString err;
00109 err << "Could not open the file \"" << filename <<"\"";
00110 this->NexusError(err, 0, -1, -1);
00111 }
00112 }
00113 catch (...)
00114 {
00115 NxsString err;
00116 err << '\"' << filename <<"\" does not refer to a valid file." ;
00117 this->NexusError(err, 0, -1, -1);
00118 }
00119 this->ReadFilestream(inf);
00120 }
00121
00122
00124 void NxsReader::ReadStringAsNexusContent(const std::string & s)
00125 {
00126 std::istringstream inf(s);
00127 this->ReadFilestream(inf);
00128 }
00129
00131 void NxsReader::ReadFilestream(std::istream & inf)
00132 {
00133 NxsToken token(inf);
00134 this->Execute(token);
00135 }
00136
00140 std::set<NxsBlock *> NxsReader::RemoveBlocksFromFactoriesFromUsedBlockLists()
00141 {
00142 std::set<NxsBlock *> todel;
00143 BlockReaderList saved;
00144 for (BlockReaderList::iterator bIt = blocksInOrder.begin(); bIt != blocksInOrder.end(); ++bIt)
00145 {
00146 NxsBlock * b = *bIt;
00147 if (BlockIsASingeltonReader(b))
00148 saved.push_back(b);
00149 else
00150 {
00151 todel.insert(b);
00152 }
00153 }
00154 for (std::set<NxsBlock *>::iterator d = todel.begin(); d != todel.end(); ++d)
00155 {
00156 RemoveBlockFromUsedBlockList(*d);
00157 }
00158 return todel;
00159 }
00160
00164 void NxsReader::DeleteBlocksFromFactories()
00165 {
00166 std::set<NxsBlock *> todel = RemoveBlocksFromFactoriesFromUsedBlockLists();
00167 for (std::set<NxsBlock *>::iterator d = todel.begin(); d != todel.end(); ++d)
00168 delete *d;
00169 }
00170
00174 bool NxsReader::BlockIsASingeltonReader(NxsBlock *b) const
00175 {
00176 NxsBlock * sb = blockList;
00177 while (sb)
00178 {
00179 if (b == sb)
00180 return true;
00181 sb = sb->next;
00182 }
00183 return false;
00184 }
00185
00192 NxsBlock *NxsReader::FindBlockByTitle(const BlockReaderList & chosenBlockList, const char *title, unsigned *nMatches)
00193 {
00194 BlockReaderList found = FindAllBlocksByTitle(chosenBlockList, title);
00195
00196 if (found.empty())
00197 {
00198 if (nMatches)
00199 *nMatches = 0;
00200 return NULL;
00201 }
00202 if (nMatches)
00203 *nMatches = (unsigned)found.size();
00204 return (NxsBlock *) found.front();
00205 }
00206
00207
00208
00209 BlockReaderList NxsReader::FindAllBlocksByTitle(const BlockReaderList & chosenBlockList, const char *title)
00210 {
00211 BlockReaderList found = FindAllBlocksByTitleNoPrioritization(chosenBlockList, title);
00212 if (found.empty())
00213 return found;
00214 map<int, BlockReaderList> byPriority;
00215 for (BlockReaderList::const_iterator fIt = found.begin(); fIt != found.end(); ++fIt)
00216 {
00217 NxsBlock * b = *fIt;
00218 int priority = GetBlockPriority(b);
00219 byPriority[priority].push_back(b);
00220 }
00221 NCL_ASSERT(!byPriority.empty());
00222 return byPriority.rbegin()->second;
00223 }
00224
00225 BlockReaderList NxsReader::FindAllBlocksByTitleNoPrioritization(const BlockReaderList & chosenBlockList, const char *title)
00226 {
00227 BlockReaderList found;
00228 if (chosenBlockList.empty() || title == NULL)
00229 {
00230 found = chosenBlockList;
00231 }
00232 else
00233 {
00234 bool emptyTitle = strlen(title) == 0;
00235 for (BlockReaderList::const_iterator cblIt = chosenBlockList.begin(); cblIt != chosenBlockList.end(); ++cblIt)
00236 {
00237 NxsBlock * b = *cblIt;
00238 std::vector<std::string> v = this->GetAllTitlesForBlock(b);
00239 for (std::vector<std::string>::const_iterator vIt = v.begin(); vIt != v.end(); ++vIt)
00240 {
00241 const std::string & n = *vIt;
00242 if ((emptyTitle && n.empty()) || (NxsString::case_insensitive_equals(title, n.c_str())))
00243 {
00244 found.push_back(b);
00245 break;
00246 }
00247 }
00248 }
00249 }
00250 return found;
00251
00252 }
00253
00261 std::vector<std::string> NxsReader::GetAllTitlesForBlock(const NxsBlock *b) const
00262 {
00263 std::vector<std::string> v;
00264 v.push_back(b->GetTitle());
00265 std::map<const NxsBlock *, std::list<std::string> >::const_iterator a = blockTitleAliases.find(b);
00266 if (a != blockTitleAliases.end())
00267 std::copy(a->second.begin(), a->second.end(), back_inserter(v));
00268 return v;
00269 }
00270
00272 void NxsReader::RegisterAltTitle(const NxsBlock * b, std::string t)
00273 {
00274 std::list<std::string> & v = blockTitleAliases[b];
00275 v.push_back(t);
00276 }
00277
00283 NxsBlock *NxsReader::FindBlockOfTypeByTitle(const std::string &btype, const char *title, unsigned *nMatches)
00284 {
00285 BlockTypeToBlockList::const_iterator btblIt = blockTypeToBlockList.find(btype);
00286 if (btblIt == blockTypeToBlockList.end())
00287 {
00288 if (nMatches)
00289 *nMatches = 0;
00290 return NULL;
00291 }
00292 const BlockReaderList & chosenBlockList = btblIt->second;
00293 return FindBlockByTitle(chosenBlockList, title, nMatches);
00294 }
00295
00302 NxsTaxaBlockAPI *NxsReader::GetTaxaBlockByTitle(const char *title, unsigned *nMatches)
00303 {
00304 const std::string btype("TAXA");
00305 return static_cast<NxsTaxaBlockAPI *>(FindBlockOfTypeByTitle(btype, title, nMatches));
00306 }
00307
00313 NxsCharactersBlockAPI *NxsReader::GetCharBlockByTitle(const char *title, unsigned *nMatches)
00314 {
00315 const std::string btype("CHARACTERS");
00316 return static_cast<NxsCharactersBlockAPI *>(FindBlockOfTypeByTitle(btype, title, nMatches));
00317 }
00323 NxsTreesBlockAPI *NxsReader::GetTreesBlockByTitle(const char *title, unsigned *nMatches)
00324 {
00325 const std::string btype("TREES");
00326 return static_cast<NxsTreesBlockAPI *>(FindBlockOfTypeByTitle(btype, title, nMatches));
00327 }
00328
00331 NxsReader::NxsReader() : currentWarningLevel(UNCOMMON_SYNTAX_WARNING), alwaysReportStatusMessages(false)
00332 {
00333 blockList = NULL;
00334 currBlock = NULL;
00335 taxaBlockFactory = NULL;
00336 destroyRepeatedTaxaBlocks = false;
00337 }
00338
00339 NxsReader::~NxsReader()
00340 {
00341 NxsBlock *curr;
00342 for (curr = blockList; curr;)
00343 {
00344 if (curr->GetNexus() == this)
00345 curr->SetNexus(NULL);
00346 curr = curr->next;
00347 }
00348 for (BlockReaderList::iterator b = blocksInOrder.begin(); b != blocksInOrder.end(); ++b)
00349 {
00350 if ((*b)->GetNexus() == this)
00351 (*b)->SetNexus(NULL);
00352 }
00353
00354 }
00355
00359 void NxsReader::AddFactory(NxsBlockFactory *f)
00360 {
00361 if (f)
00362 factories.push_front(f);
00363 }
00367 void NxsReader::RemoveFactory(NxsBlockFactory *f)
00368 {
00369 factories.remove(f);
00370 }
00371
00372
00380 void NxsReader::Add(
00381 NxsBlock *newBlock)
00382 {
00383 NCL_ASSERT(newBlock != NULL);
00384
00385 newBlock->SetNexus(this);
00386
00387 if (!blockList)
00388 blockList = newBlock;
00389 else
00390 {
00391
00392
00393 NxsBlock *curr;
00394 for (curr = blockList; curr && curr->next;)
00395 curr = curr->next;
00396 NCL_ASSERT(curr && !curr->next);
00397 curr->next = newBlock;
00398 }
00399 }
00400
00406 unsigned NxsReader::PositionInBlockList(
00407 NxsBlock *b)
00408 {
00409 unsigned pos = 0;
00410 NxsBlock *curr = blockList;
00411
00412 for (;;)
00413 {
00414 if (curr == NULL || curr == b)
00415 break;
00416 pos++;
00417 curr = curr->next;
00418 }
00419
00420 if (curr == NULL)
00421 pos = UINT_MAX;
00422
00423 return pos;
00424 }
00425
00434 void NxsReader::Reassign(
00435 NxsBlock *oldb,
00436 NxsBlock *newb)
00437 {
00438 NxsBlock *prev = NULL;
00439 NxsBlock *curr = blockList;
00440 newb->SetNexus(this);
00441
00442 for (;;)
00443 {
00444 if (curr == NULL || curr == oldb)
00445 break;
00446 prev = curr;
00447 curr = curr->next;
00448 }
00449
00450 NCL_ASSERT(curr != NULL);
00451
00452 newb->next = curr->next;
00453 if (prev == NULL)
00454 blockList = newb;
00455 else
00456 prev->next = newb;
00457 curr->next = NULL;
00458 curr->SetNexus(NULL);
00459 }
00460
00461 bool NxsReader::BlockListEmpty()
00462 {
00463 return (blockList == NULL ? true : false);
00464 }
00465
00478 void NxsReader::DebugReportBlock(
00479 NxsBlock &)
00480 {
00481 }
00482
00491 void NxsReader::Detach(
00492 NxsBlock *oldBlock)
00493 {
00494 NCL_ASSERT(oldBlock != NULL);
00495 RemoveBlockFromUsedBlockList(oldBlock);
00496
00497
00498 if (blockList == NULL)
00499 return;
00500
00501 if (blockList == oldBlock)
00502 {
00503 blockList = oldBlock->next;
00504 oldBlock->SetNexus(NULL);
00505 }
00506 else
00507 {
00508
00509
00510 NxsBlock *curr = blockList;
00511 for (; curr->next != NULL && curr->next != oldBlock;)
00512 curr = curr->next;
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 if (curr->next == oldBlock)
00523 {
00524 curr->next = oldBlock->next;
00525 oldBlock->SetNexus(NULL);
00526 }
00527 }
00528 }
00529
00537 bool NxsReader::EnteringBlock(
00538 NxsString )
00539 {
00540 return true;
00541 }
00542
00547 void NxsReader::ExitingBlock(
00548 NxsString )
00549 {
00550 }
00551
00555 void NxsReader::PostBlockReadingHook(
00556 NxsBlock & )
00557 {
00558 }
00559
00564 NxsBlock *NxsReader::CreateBlockFromFactories(const std::string & currBlockName, NxsToken &token, NxsBlockFactory **sourceOfBlock)
00565 {
00566 for (BlockFactoryList::iterator fIt = factories.begin(); currBlock == NULL && fIt != factories.end(); ++fIt)
00567 {
00568 NxsBlock *b = (*fIt)->GetBlockReaderForID(currBlockName, this, &token);
00569 if (b)
00570 {
00571 if (b->CanReadBlockType(token))
00572 {
00573 if (sourceOfBlock)
00574 *sourceOfBlock = *fIt;
00575 b->SetNexus(this);
00576 return b;
00577 }
00578 (*fIt)->BlockError(b);
00579 }
00580 }
00581 return NULL;
00582 }
00583
00608 void NxsReader::Execute(
00609 NxsToken &token,
00610 bool notifyStartStop)
00611 {
00612 bool signalHandlerInstalled = false;
00613 unsigned numSigInts = 0;
00614 if (NxsReader::nclCatchesSignals)
00615 {
00616 numSigInts = getNumSignalIntsCaught();
00617 installNCLSignalHandler();
00618 signalHandlerInstalled = true;
00619 }
00620 try {
00621 CoreExecutionTasks(token, notifyStartStop);
00622 }
00623 catch (...)
00624 {
00625 if (signalHandlerInstalled)
00626 uninstallNCLSignalHandler();
00627 throw;
00628 }
00629 if (signalHandlerInstalled)
00630 {
00631 uninstallNCLSignalHandler();
00632 if (numSigInts != getNumSignalIntsCaught())
00633 throw NxsSignalCanceledParseException("Reading NEXUS content");
00634 }
00635 }
00636
00638 void NxsReader::CoreExecutionTasks(
00639 NxsToken &token,
00640 bool notifyStartStop)
00641 {
00642 unsigned numSigInts = NxsReader::getNumSignalIntsCaught();
00643 const bool checkingSignals = NxsReader::getNCLCatchesSignals();
00644
00645 lastExecuteBlocksInOrder.clear();
00646 currBlock = NULL;
00647
00648 NxsString errormsg;
00649 token.SetEOFAllowed(true);
00650
00651 try
00652 {
00653 token.SetLabileFlagBit(NxsToken::saveCommandComments);
00654 token.GetNextToken();
00655 }
00656 catch (NxsException x)
00657 {
00658 NexusError(token.errormsg, 0, 0, 0);
00659 return;
00660 }
00661
00662 if (token.Equals("#NEXUS"))
00663 {
00664 token.SetLabileFlagBit(NxsToken::saveCommandComments);
00665 token.GetNextToken();
00666 }
00667 else
00668 {
00669 errormsg = "Expecting #NEXUS to be the first token in the file, but found ";
00670 errormsg += token.GetToken();
00671 errormsg += " instead";
00672
00673
00674
00675 NexusWarn(errormsg, NxsReader::AMBIGUOUS_CONTENT_WARNING, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
00676 }
00677
00678 if (notifyStartStop)
00679 ExecuteStarting();
00680 bool keepReading = true;
00681 for (;keepReading && !token.AtEOF();)
00682 {
00683 if (checkingSignals && NxsReader::getNumSignalIntsCaught() != numSigInts)
00684 {
00685 throw NxsSignalCanceledParseException("Reading NEXUS content");
00686 }
00687 if (token.Equals("BEGIN"))
00688 {
00689 token.SetEOFAllowed(false);
00690 token.GetNextToken();
00691 token.SetBlockName(token.GetTokenReference().c_str());
00692 for (currBlock = blockList; currBlock != NULL; currBlock = currBlock->next)
00693 {
00694 if (currBlock->CanReadBlockType(token))
00695 break;
00696 }
00697 NxsString currBlockName = token.GetToken();
00698 currBlockName.ToUpper();
00699 NxsBlockFactory * sourceOfBlock = NULL;
00700 if (currBlock == NULL)
00701 {
00702 try
00703 {
00704 currBlock = CreateBlockFromFactories(currBlockName, token, &sourceOfBlock);
00705 }
00706 catch (NxsException x)
00707 {
00708 NexusError(x.msg, x.pos, x.line, x.col);
00709 token.SetBlockName(0L);
00710 token.SetEOFAllowed(true);
00711 return;
00712 }
00713 }
00714 if (currBlock == NULL)
00715 {
00716 SkippingBlock(currBlockName);
00717 if (!ReadUntilEndblock(token, currBlockName))
00718 {
00719 token.SetBlockName(0L);
00720 token.SetEOFAllowed(true);
00721 return;
00722 }
00723 }
00724 else if (currBlock->IsEnabled())
00725 keepReading = ExecuteBlock(token, currBlockName, currBlock, sourceOfBlock);
00726 else
00727 {
00728 SkippingDisabledBlock(token.GetToken());
00729 if (sourceOfBlock)
00730 sourceOfBlock->BlockSkipped(currBlock);
00731 if (!ReadUntilEndblock(token, currBlockName))
00732 {
00733 token.SetBlockName(0L);
00734 token.SetEOFAllowed(true);
00735 return;
00736 }
00737 }
00738 currBlock = NULL;
00739 token.SetEOFAllowed(true);
00740 token.SetBlockName(0L);
00741 }
00742 else if (token.Equals("&SHOWALL"))
00743 {
00744 for (NxsBlock* showBlock = blockList; showBlock != NULL; showBlock = showBlock->next)
00745 DebugReportBlock(*showBlock);
00746 }
00747 else if (token.Equals("&LEAVE"))
00748 break;
00749 if (keepReading)
00750 {
00751 token.SetLabileFlagBit(NxsToken::saveCommandComments);
00752 token.GetNextToken();
00753 }
00754 }
00755 if (notifyStartStop)
00756 ExecuteStopping();
00757
00758 currBlock = NULL;
00759 }
00760
00761 void NxsReader::ClearContent()
00762 {
00763 for (currBlock = blockList; currBlock;)
00764 {
00765 currBlock->Reset();
00766 currBlock = currBlock->next;
00767 }
00768 currBlock = blockList;
00769 blocksInOrder.clear();
00770 blockPriorities.clear();
00771 lastExecuteBlocksInOrder.clear();
00772 blockTypeToBlockList.clear();
00773 blockTitleHistoryMap.clear();
00774 blockTitleAliases.clear();
00775 }
00776
00777
00792 NxsTaxaBlockAPI * NxsReader::GetOriginalTaxaBlock(const NxsTaxaBlockAPI * testB) const
00793 {
00794 if (!testB)
00795 return 0L;
00796 const std::string idstring("TAXA");
00797 BlockTypeToBlockList::const_iterator bttblIt = blockTypeToBlockList.find(idstring);
00798 if (bttblIt == blockTypeToBlockList.end())
00799 return 0L;
00800 const BlockReaderList & brl = bttblIt->second;
00801 const unsigned ntt = testB->GetNumTaxonLabels();
00802 const std::vector<std::string> testL = testB->GetAllLabels();
00803 for (BlockReaderList::const_iterator bIt = brl.begin(); bIt != brl.end(); ++bIt)
00804 {
00805 const NxsBlock * nb = *bIt;
00806 const NxsTaxaBlockAPI * prev = (const NxsTaxaBlockAPI *) nb;
00807 if (prev->GetNumTaxonLabels() == ntt)
00808 {
00809 const std::vector<std::string> prevL = prev->GetAllLabels();
00810 std::vector<std::string>::const_iterator pIt = prevL.begin();
00811 std::vector<std::string>::const_iterator testIt = testL.begin();
00812
00813 for (; (testIt != testL.end()) && (pIt != prevL.end()) ; ++testIt, ++pIt)
00814 {
00815 if (!NxsString::case_insensitive_equals(testIt->c_str(), pIt->c_str()))
00816 break;
00817 }
00818 if (testIt == testL.end())
00819 return const_cast<NxsTaxaBlockAPI *>(prev);
00820 }
00821 }
00822
00823 return 0L;
00824 }
00825
00826
00860 bool NxsReader::ExecuteBlock(NxsToken &token, const NxsString &currBlockName, NxsBlock *currentBlock, NxsBlockFactory * sourceOfBlock)
00861 {
00862 if (!EnteringBlock(currBlockName))
00863 {
00864 SkippingBlock(currBlockName);
00865 if (sourceOfBlock)
00866 sourceOfBlock->BlockSkipped(currentBlock);
00867 if (!ReadUntilEndblock(token, currBlockName))
00868 {
00869 token.SetBlockName(0L);
00870 token.SetEOFAllowed(true);
00871 return false;
00872 }
00873 return true;
00874 }
00875 this->RemoveBlockFromUsedBlockList(currentBlock);
00876 currentBlock->Reset();
00877
00878
00879
00880
00881
00882 bool eofFound = false;
00883 try
00884 {
00885 try
00886 {
00887 currentBlock->Read(token);
00888 }
00889 catch (NxsX_UnexpectedEOF &eofx)
00890 {
00891 if (!currentBlock->TolerateEOFInBlock())
00892 throw eofx;
00893 NxsString m;
00894 m << "Unexpected End of file in " << currBlockName << "block";
00895 currentBlock->WarnDangerousContent(m, token);
00896 eofFound = true;
00897 }
00898 if (destroyRepeatedTaxaBlocks && currBlockName.EqualsCaseInsensitive("TAXA"))
00899 {
00900 NxsTaxaBlockAPI * oldTB = this->GetOriginalTaxaBlock((NxsTaxaBlockAPI *) currentBlock);
00901 if (oldTB)
00902 {
00903 const std::string altTitle = currentBlock->GetTitle();
00904 this->RegisterAltTitle(oldTB, altTitle);
00905 if (sourceOfBlock)
00906 sourceOfBlock->BlockError(currentBlock);
00907 return true;
00908 }
00909 }
00910 BlockReadHook(currBlockName, currentBlock, &token);
00911 }
00912 catch (NxsException &x)
00913 {
00914 NxsString m;
00915 if (currentBlock->errormsg.length() > 0)
00916 m = currentBlock->errormsg;
00917 else
00918 m = x.msg;
00919 currentBlock->Reset();
00920 if (sourceOfBlock != 0)
00921 {
00922
00923 sourceOfBlock->BlockError(currentBlock);
00924 }
00925 else
00926
00927 token.SetBlockName(0L);
00928 token.SetEOFAllowed(true);
00929 currentBlock = NULL;
00930 NexusError(m, x.pos, x.line, x.col);
00931 return false;
00932 }
00933 ExitingBlock(currBlockName);
00934 PostBlockReadingHook(*currentBlock);
00935 return !eofFound;
00936 }
00937
00939 void NxsReader::BlockReadHook(const NxsString &currBlockName, NxsBlock *currentBlock, NxsToken * token)
00940 {
00941 VecBlockPtr implied = currentBlock->GetImpliedBlocks();
00942 for (VecBlockPtr::iterator impIt = implied.begin(); impIt != implied.end(); ++impIt)
00943 {
00944 NxsBlock * nb = *impIt;
00945 NCL_ASSERT(nb);
00946 NxsString impID = nb->GetID();
00947 bool storeBlock = true;
00948 if (destroyRepeatedTaxaBlocks && impID.EqualsCaseInsensitive("TAXA"))
00949 {
00950 NxsTaxaBlockAPI * oldTB = this->GetOriginalTaxaBlock((NxsTaxaBlockAPI *) nb);
00951 if (oldTB)
00952 {
00953 storeBlock = ! currentBlock->SwapEquivalentTaxaBlock(oldTB);
00954 const std::string altTitle = nb->GetTitle();
00955 this->RegisterAltTitle(oldTB, altTitle);
00956 if (!storeBlock)
00957 {
00958 delete nb;
00959 }
00960
00961 }
00962 }
00963 if (storeBlock)
00964 {
00965 NxsString m;
00966 m << "storing implied block: " << impID;
00967 this->statusMessage(m);
00968 this->AddBlockToUsedBlockList(impID, nb, token);
00969 }
00970 }
00971 NxsString s;
00972 s << "storing read block: " << currentBlock->GetID();
00973 this->statusMessage(s);
00974 this->AddBlockToUsedBlockList(currBlockName, currentBlock, token);
00975 }
00976
00981 const char * NxsReader::NCLCopyrightNotice()
00982 {
00983 return NCL_COPYRIGHT;
00984 }
00985
00989 const char * NxsReader::NCLHomePageURL()
00990 {
00991 return NCL_HOMEPAGEURL;
00992 }
00993
00998 const char * NxsReader::NCLNameAndVersion()
00999 {
01000 return NCL_NAME_AND_VERSION;
01001 }
01002
01010 void NxsReader::ExecuteStarting()
01011 {
01012 }
01013
01021 void NxsReader::ExecuteStopping()
01022 {
01023 }
01024
01029 void NxsReader::NexusError(
01030 NxsString ,
01031 file_pos ,
01032 long ,
01033 long )
01034 {
01035 }
01036
01042 void NxsReader::OutputComment(
01043 const NxsString &)
01044 {
01045 }
01046
01051 void NxsReader::SkippingBlock(
01052 NxsString )
01053 {
01054 }
01055
01061 void NxsReader::SkippingDisabledBlock(
01062 NxsString )
01063 {
01064 }
01065
01066
01068 bool NxsReader::ReadUntilEndblock(NxsToken &token, const std::string & )
01069 {
01070 for (;;)
01071 {
01072 token.GetNextToken();
01073 if (token.Equals("END") || token.Equals("ENDBLOCK"))
01074 {
01075 token.GetNextToken();
01076 if (!token.Equals(";"))
01077 {
01078 std::string errormsg = "Expecting ';' after END or ENDBLOCK command, but found ";
01079 errormsg += token.GetToken();
01080 errormsg += " instead";
01081 NexusError(NxsString(errormsg.c_str()), token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
01082 return false;
01083 }
01084 return true;
01085 }
01086 else
01087 token.ProcessAsCommand(NULL);
01088 }
01089 }
01090
01092 void NxsReader::SetTaxaBlockFactory(NxsTaxaBlockFactory *f)
01093 {
01094 if (this->taxaBlockFactory)
01095 this->RemoveFactory(this->taxaBlockFactory);
01096 this->taxaBlockFactory = f;
01097 if (taxaBlockFactory)
01098 this->AddFactory(this->taxaBlockFactory);
01099 }
01105 NxsTaxaBlockAPI *NxsReader::GetLastStoredTaxaBlock()
01106 {
01107 const std::string idstring("TAXA");
01108 NxsBlock * nb = GetLastStoredBlockByID(idstring);
01109 return static_cast<NxsTaxaBlockAPI *>(nb);
01110 }
01111
01117 NxsCharactersBlockAPI *NxsReader::GetLastStoredCharactersBlock()
01118 {
01119 const std::string idstring("CHARACTERS");
01120 NxsBlock * nb = GetLastStoredBlockByID(idstring);
01121 return static_cast<NxsCharactersBlockAPI *>(nb);
01122 }
01123
01129 NxsTreesBlockAPI *NxsReader::GetLastStoredTreesBlock()
01130 {
01131 const std::string idstring("TREES");
01132 NxsBlock * nb = GetLastStoredBlockByID(idstring);
01133 return static_cast<NxsTreesBlockAPI *>(nb);
01134 }
01135
01139 NxsBlock *NxsReader::GetLastStoredBlockByID(const std::string &key)
01140 {
01141 BlockTypeToBlockList::iterator bttblIt = blockTypeToBlockList.find(key);
01142 if (bttblIt == blockTypeToBlockList.end())
01143 return NULL;
01144 return bttblIt->second.back();
01145 }
01146
01153 void NxsReader::NewBlockTitleCheckHook(const std::string &blockname, NxsBlock *p, NxsToken *token)
01154 {
01155 NxsBlockTitleHistoryMap::iterator mIt = blockTitleHistoryMap.find(blockname);
01156 if (mIt == blockTitleHistoryMap.end())
01157 {
01158 std::list<std::string> mt;
01159 blockTitleHistoryMap[blockname] = NxsBlockTitleHistory(1, mt);
01160 mIt = blockTitleHistoryMap.find(blockname);
01161 NCL_ASSERT(mIt != blockTitleHistoryMap.end());
01162 }
01163 NxsBlockTitleHistory & titleHist = mIt->second;
01164 unsigned n = titleHist.first;
01165 std::list<std::string> & previousTitles = titleHist.second;
01166 std::list<std::string>::iterator lsIt;
01167 std::string pTitle = p->GetTitle();
01168 std::string origTitle = pTitle;
01169 NxsString::to_upper(pTitle);
01170 if (pTitle.empty())
01171 {
01172 while (pTitle.empty())
01173 {
01174 NxsString autoName = "Untitled ";
01175 autoName += p->GetID().c_str();
01176 autoName += " Block ";
01177 autoName += n++;
01178 pTitle.assign(autoName.c_str());
01179 NxsString::to_upper(pTitle);
01180 lsIt = find(previousTitles.begin(), previousTitles.end(), pTitle);
01181 if (lsIt == previousTitles.end())
01182 {
01183 p->SetTitle(autoName, true);
01184 titleHist.first = n;
01185 }
01186 else
01187 pTitle.clear();
01188 }
01189 }
01190 else
01191 {
01192 lsIt = find(previousTitles.begin(), previousTitles.end(), pTitle);
01193 if (lsIt != previousTitles.end())
01194 {
01195 NxsString msg = "Block titles cannot be repeated. The TITLE ";
01196 msg += origTitle;
01197 msg += " has already been used for a ";
01198 msg += blockname;
01199 msg += " block.";
01200 if (token)
01201 throw NxsException(msg, *token);
01202 else
01203 throw NxsException(msg, 0, -1, -1);
01204 }
01205 }
01206 previousTitles.push_back(pTitle);
01207 }
01208
01214 void NxsReader::AddBlockToUsedBlockList(const std::string &blockTypeID, NxsBlock *p, NxsToken *token)
01215 {
01216 NCL_ASSERT(p);
01217 std::string n;
01218 if (blockTypeID == "DATA")
01219 n = std::string("CHARACTERS");
01220 else
01221 n = blockTypeID;
01222 NewBlockTitleCheckHook(n, p, token);
01223 BlockTypeToBlockList::iterator bttblIt = blockTypeToBlockList.find(n);
01224 if (bttblIt == blockTypeToBlockList.end())
01225 blockTypeToBlockList[n] = BlockReaderList(1, p);
01226 else
01227 bttblIt->second.push_back(p);
01228 blocksInOrder.remove(p);
01229 blocksInOrder.push_back(p);
01230 if (this->GetBlockPriority(p) < 0)
01231 AssignBlockPriority(p, 0);
01232
01233 lastExecuteBlocksInOrder.remove(p);
01234 lastExecuteBlocksInOrder.push_back(p);
01235 }
01236
01241 unsigned NxsReader::RemoveBlockFromUsedBlockList(NxsBlock *p)
01242 {
01243 unsigned totalDel = 0;
01244 unsigned before, after;
01245 std::vector<std::string> keysToDel;
01246 for (BlockTypeToBlockList::iterator bttblIt = blockTypeToBlockList.begin(); bttblIt != blockTypeToBlockList.end(); ++bttblIt)
01247 {
01248 BlockReaderList & brl = bttblIt->second;
01249 before = (unsigned)brl.size();
01250 brl.remove(p);
01251 after = (unsigned)brl.size();
01252 if (after == 0)
01253 keysToDel.push_back(bttblIt->first);
01254 totalDel += before - after;
01255 }
01256 for (std::vector<std::string>::const_iterator keyIt = keysToDel.begin(); keyIt != keysToDel.end(); ++keyIt)
01257 blockTypeToBlockList.erase(*keyIt);
01258 blocksInOrder.remove(p);
01259 blockPriorities.erase(p);
01260 lastExecuteBlocksInOrder.remove(p);
01261 std::string blockID = p->GetID();
01262 NxsBlockTitleHistoryMap::iterator mIt = blockTitleHistoryMap.find(blockID);
01263 if (mIt != blockTitleHistoryMap.end())
01264 {
01265 std::string blockName = p->GetTitle();
01266 NxsBlockTitleHistory & titleHist = mIt->second;
01267 std::list<std::string> & previousTitles = titleHist.second;
01268 std::list<std::string>::iterator ptIt = previousTitles.begin();
01269 while (ptIt != previousTitles.end())
01270 {
01271 if (NxsString::case_insensitive_equals(ptIt->c_str(), blockName.c_str()))
01272 ptIt = previousTitles.erase(ptIt);
01273 else
01274 ++ptIt;
01275 }
01276 }
01277 return totalDel;
01278 }
01279
01282 std::set<NxsBlock*> NxsReader::GetSetOfAllUsedBlocks()
01283 {
01284 std::set<NxsBlock*> s;
01285 for (BlockTypeToBlockList::iterator bttblIt = blockTypeToBlockList.begin(); bttblIt != blockTypeToBlockList.end(); ++bttblIt)
01286 {
01287 BlockReaderList & brl = bttblIt->second;
01288 s.insert(brl.begin(), brl.end());
01289 }
01290 return s;
01291 }
01292
01293 void ExceptionRaisingNxsReader::NexusWarn(const std::string &msg, NxsWarnLevel warnLevel, file_pos pos, long line, long col)
01294 {
01295 if (warnLevel < currentWarningLevel)
01296 return;
01297 if (warnLevel >= this->warningToErrorThreshold)
01298 {
01299 NxsString e(msg.c_str());
01300 throw NxsException(e, pos, line, col);
01301 }
01302
01303 if (warnMode == NxsReader::IGNORE_WARNINGS)
01304 return;
01305 if (warnMode == NxsReader::WARNINGS_TO_STDERR)
01306 {
01307 std::cerr << "\nWarning: ";
01308 std::cerr << "\n " << msg << std::endl;
01309 if (line > 0 || pos > 0)
01310 std::cerr << "at line " << line << ", column (approximately) " << col << " (file position " << pos << ")\n";
01311 }
01312 else if (warnMode != NxsReader::WARNINGS_TO_STDOUT)
01313 {
01314 std::cout << "\nWarning: ";
01315 if (line > 0 || pos > 0)
01316 std::cout << "at line " << line << ", column " << col << " (file position " << pos << "):\n";
01317 std::cout << "\n " << msg << '\n';
01318 if (line > 0 || pos > 0)
01319 std::cout << "at line " << line << ", column (approximately) " << col << " (file position " << pos << ')' << std::endl;
01320 }
01321 else
01322 {
01323 NxsString m("WARNING:\n ");
01324 m += msg.c_str();
01325 NexusError(m, pos, line, col);
01326 }
01327 }
01328
01329 void ExceptionRaisingNxsReader::SkippingBlock(NxsString blockName)
01330 {
01331 if (warnMode == NxsReader::IGNORE_WARNINGS)
01332 return;
01333 if (warnMode == NxsReader::WARNINGS_TO_STDERR)
01334 std::cerr << "[!Skipping unknown block (" << blockName << ")...]" << std::endl;
01335 else if (warnMode != NxsReader::WARNINGS_TO_STDOUT)
01336 std::cout << "[!Skipping unknown block (" << blockName << ")...]" << std::endl;
01337 }
01338
01339 void ExceptionRaisingNxsReader::SkippingDisabledBlock(NxsString blockName)
01340 {
01341 if (warnMode == NxsReader::IGNORE_WARNINGS)
01342 return;
01343 if (warnMode == NxsReader::WARNINGS_TO_STDERR)
01344 std::cerr << "[!Skipping disabled block (" << blockName << ")...]" << std::endl;
01345 else if (warnMode != NxsReader::WARNINGS_TO_STDOUT)
01346 std::cout << "[!Skipping disabled block (" << blockName << ")...]" << std::endl;
01347 }
01348
01349 void NxsReader::statusMessage(const std::string & m) const
01350 {
01351 if (alwaysReportStatusMessages || currentWarningLevel == UNCOMMON_SYNTAX_WARNING) {
01352 std::cerr << m << std::endl;
01353 }
01354 }
01355
01362 void NxsReader::ClearUsedBlockList()
01363 {
01364 RemoveBlocksFromFactoriesFromUsedBlockLists();
01365 blocksInOrder.clear();
01366 blockPriorities.clear();
01367 lastExecuteBlocksInOrder.clear();
01368 blockTypeToBlockList.clear();
01369 }
01370
01371 void NxsReader::AssignBlockPriority(NxsBlock *b, int priorityLevel)
01372 {
01373 blockPriorities[b] = priorityLevel;
01374 }
01375
01376 int NxsReader::GetBlockPriority(NxsBlock *b) const
01377 {
01378 std::map<NxsBlock *, int>::const_iterator bIt = blockPriorities.find(b);
01379 if (bIt == blockPriorities.end())
01380 return 0;
01381 return bIt->second;
01382 }
01383
01384 void NxsReader::DemoteBlocks(int priorityLevel)
01385 {
01386 BlockReaderList brl = GetUsedBlocksInOrder();
01387 BlockReaderList::iterator brlIt = brl.begin();
01388 for (; brlIt != brl.end(); ++brlIt)
01389 {
01390 NxsBlock * b = *brlIt;
01391 AssignBlockPriority(b, priorityLevel);
01392 }
01393 }
01394
01395
01396