[med-svn] [Git][med-team/cmaple][upstream] New upstream version 2.0.0+dfsg

Andreas Tille (@tille) gitlab at salsa.debian.org
Fri Sep 11 16:23:27 BST 2026



Andreas Tille pushed to branch upstream at Debian Med / cmaple


Commits:
38d8ad37 by Andreas Tille at 2026-09-11T16:33:10+02:00
New upstream version 2.0.0+dfsg
- - - - -


14 changed files:

- + libraries/ncl/CMakeLists.txt
- + libraries/ncl/ncl.h
- + libraries/ncl/nxsblock.cpp
- + libraries/ncl/nxsblock.h
- + libraries/ncl/nxsdefs.h
- + libraries/ncl/nxsexception.cpp
- + libraries/ncl/nxsexception.h
- + libraries/ncl/nxsindent.h
- + libraries/ncl/nxsreader.cpp
- + libraries/ncl/nxsreader.h
- + libraries/ncl/nxsstring.cpp
- + libraries/ncl/nxsstring.h
- + libraries/ncl/nxstoken.cpp
- + libraries/ncl/nxstoken.h


Changes:

=====================================
libraries/ncl/CMakeLists.txt
=====================================
@@ -0,0 +1,21 @@
+add_library(ncl 
+#nxsassumptionsblock.cpp
+nxsblock.h nxsblock.cpp
+#nxscharactersblock.cpp
+#nxsdatablock.cpp
+#nxsdiscretedatum.cpp
+#nxsdiscretematrix.cpp
+#nxsdistancedatum.cpp
+#nxsdistancesblock.cpp
+#nxsemptyblock.cpp
+nxsexception.h nxsexception.cpp
+nxsdefs.h
+nxsreader.h nxsreader.cpp
+#nxssetreader.cpp
+nxsindent.h
+nxsstring.h nxsstring.cpp
+#nxstaxablock.cpp
+nxstoken.h nxstoken.cpp
+#nxstreesblock.cpp
+ncl.h
+)


=====================================
libraries/ncl/ncl.h
=====================================
@@ -0,0 +1,108 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NCL_H
+#define NCL_NCL_H
+
+#if defined(_MSC_VER) && !defined(CLANG_UNDER_VS)
+#	pragma warning(disable:4786)
+#	pragma warning(disable:4291)
+#endif
+
+#if !defined(__DECCXX)
+#	include <cassert>
+#	include <cctype>
+#	include <cmath>
+#	include <cstdarg>
+#	include <cstdio>
+#	include <cstdarg>
+#	include <cstdlib>
+#	include <ctime>
+#	include <cfloat>
+#else
+#	include <assert.h>
+#	include <ctype.h>
+#	include <stdarg.h>
+#	include <math.h>
+#	include <stdarg.h>
+#	include <stdio.h>
+#	include <stdlib.h>
+#	include <time.h>
+#	include <float.h>
+#endif
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <list>
+#include <map>
+#include <set>
+#include <stdexcept>
+#include <string>
+#if defined(__GNUC__)
+#	if __GNUC__ < 3
+#		include <strstream>
+#	else
+#		include <sstream>
+#	endif
+#endif
+#include <vector>
+using namespace std;
+
+#if defined(__MWERKS__)
+#	if __ide_target("Simple-Win Release") || __ide_target("Phorest-Mac-Release")
+#		define NDEBUG
+#	else
+#		undef NDEBUG
+#	endif
+#endif
+
+#if defined( __BORLANDC__ )
+#	include <dos.h>
+#endif
+
+#if defined(__MWERKS__)
+#	define HAVE_PRAGMA_UNUSED
+		// mwerks (and may be other compilers) want return values even if the function throws an exception
+		//
+#	define DEMANDS_UNREACHABLE_RETURN
+
+#endif
+
+#include "nxsdefs.h"
+#include "nxstoken.h"
+#include "nxsblock.h"
+#include "nxsexception.h"
+#include "nxsstring.h"
+#include "nxsreader.h"
+/*
+#include "nxssetreader.h"
+#include "nxstaxablock.h"
+#include "nxstreesblock.h"
+#include "nxsdistancedatum.h"
+#include "nxsdistancesblock.h"
+#include "nxsdiscretedatum.h"
+#include "nxsdiscretematrix.h"
+#include "nxscharactersblock.h"
+#include "nxsassumptionsblock.h"
+#include "nxsdatablock.h"
+#include "nxsemptyblock.h"*/
+
+#endif


=====================================
libraries/ncl/nxsblock.cpp
=====================================
@@ -0,0 +1,193 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include "ncl.h"
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Initializes all pointer data members to NULL, and all bool data members to true except isUserSupplied, which is
+|	initialized to false.
+*/
+NxsBlock::NxsBlock()
+	{
+	next			= NULL;
+	nexus			= NULL;
+	isEmpty			= true;
+	isEnabled		= true;
+	isUserSupplied	= false;
+
+	id.clear();
+	errormsg.clear();
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Nothing to be done.
+*/
+NxsBlock::~NxsBlock()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This base class version simply returns 0 but a derived class should override this function if it needs to construct
+|	and run a NxsSetReader object to read a set involving characters. The NxsSetReader object may need to use this 
+|	function to look up a character label encountered in the set. A class that overrides this method should return the
+|	character index in the range [1..nchar].
+*/
+unsigned NxsBlock::CharLabelToNumber(
+  NxsString s)	/* the character label to be translated to the character's number */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(s)
+#	endif
+	return 0;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets the value of isEnabled to false. A NxsBlock can be disabled (by calling this method) if blocks of that type
+|	are to be skipped during execution of the NEXUS file. If a disabled block is encountered, the virtual
+|	NxsReader::SkippingDisabledBlock function is called, giving your application the opportunity to inform the user
+|	that a block was skipped.
+*/
+void NxsBlock::Disable()
+	{
+	isEnabled = false;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets the value of isEnabled to true. A NxsBlock can be disabled (by calling Disable) if blocks of that type are to
+|	be skipped during execution of the NEXUS file. If a disabled block is encountered, the virtual 
+|	NxsReader::SkippingDisabledBlock function is called, giving your application the opportunity to inform the user
+|	that a block was skipped.
+*/
+void NxsBlock::Enable()
+	{
+	isEnabled = true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns value of isEnabled, which can be controlled through use of the Enable and Disable member functions. A 
+|	NxsBlock should be disabled if blocks of that type are to be skipped during execution of the NEXUS file. If a 
+|	disabled block is encountered, the virtual NxsReader::SkippingDisabledBlock function is called, giving your 
+|	application the opportunity to inform the user that a block was skipped.
+*/
+bool NxsBlock::IsEnabled()
+	{
+	return isEnabled;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns value of isUserSupplied, which is true if and only if this block's Read function is called to process a 
+|	block of this type appearing in a data file. This is useful because in some cases, a block object may be created 
+|	internally (e.g. a NxsTaxaBlock may be populated using taxon names provided in a DATA block), and such blocks do 
+|	not require permission from the user to delete data stored therein.
+*/
+bool NxsBlock::IsUserSupplied()
+	{
+	return isUserSupplied;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if Read function has not been called since the last Reset. This base class version simply returns the 
+|	value of the data member isEmpty. If you derive a new block class from NxsBlock, be sure to set isEmpty to true in 
+|	your Reset function and isEmpty to false in your Read function.
+*/
+bool NxsBlock::IsEmpty()
+	{
+	return isEmpty;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns the id NxsString.
+*/
+NxsString NxsBlock::GetID()
+	{
+	return id;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This virtual function must be overridden for each derived class to provide the ability to read everything following
+|	the block name (which is read by the NxsReader object) to the end or endblock statement. Characters are read from 
+|	the input stream 'in'. Note that to get output comments displayed, you must derive a class from NxsToken, override 
+|	the member function OutputComment to display a supplied comment, and then pass a reference to an object of the 
+|	derived class to this function.
+*/
+void NxsBlock::Read(
+  NxsToken &token)	/* the NxsToken to use for reading block */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(token)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This virtual function should be overridden for each derived class to completely reset the block object in 
+|	preparation for reading in another block of this type. This function is called by the NxsReader object just prior to
+|	calling the block object's Read function.
+*/
+void NxsBlock::Reset()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This virtual function provides a brief report of the contents of the block.
+*/
+void NxsBlock::Report(
+  ostream &out)	/* the output stream to which the report is sent */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(out)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets the nexus data member of the NxsBlock object to 'nxsptr'.
+*/
+void NxsBlock::SetNexus(
+  NxsReader *nxsptr)	/* pointer to a NxsReader object */
+	{
+	nexus = nxsptr;
+	}
+ 
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function is called when an unknown command named commandName is about to be skipped. This version of the 
+|	function does nothing (i.e., no warning is issued that a command was unrecognized). Override this virtual function 
+|	in a derived class to provide such warnings to the user.
+*/
+void NxsBlock::SkippingCommand(
+  NxsString commandName)	/* the name of the command being skipped */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(commandName)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This base class version simply returns 0, but a derived class should override this function if it needs to construct
+|	and run a NxsSetReader object to read a set involving taxa. The NxsSetReader object may need to use this function to
+|	look up a taxon label encountered in the set. A class that overrides this method should return the taxon index in
+|	the range [1..ntax].
+*/
+unsigned NxsBlock::TaxonLabelToNumber(
+  NxsString s)	/* the taxon label to be translated to a taxon number */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(s)
+#	endif
+	return 0;
+	}
+


=====================================
libraries/ncl/nxsblock.h
=====================================
@@ -0,0 +1,76 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+#ifndef NCL_NXSBLOCK_H
+#define NCL_NXSBLOCK_H
+
+#include "nxsstring.h"	//for NxsString
+#include "nxstoken.h"   //for NxsToken
+class NxsReader;
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This is the base class from which all block classes are derived. A NxsBlock-derived class encapsulates a Nexus block
+|	(e.g. DATA block, TREES block, etc.). The abstract virtual function Read must be overridden for each derived class 
+|	to provide the ability to read everything following the block name (which is read by the NxsReader object) to the 
+|	end or endblock statement. Derived classes must provide their own data storage and access functions. The abstract
+|	virtual function Report must be overridden to provide some feedback to user on contents of block. The abstract
+|	virtual function Reset must be overridden to empty the block of all its contents, restoring it to its 
+|	just-constructed state.
+*/
+class NxsBlock
+	{
+	friend class NxsReader;
+
+	public:
+							NxsBlock();
+		virtual				~NxsBlock();
+
+		void				SetNexus(NxsReader *nxsptr);
+
+		NxsString			GetID();
+		bool				IsEmpty();
+
+		void				Enable();
+		void				Disable();
+		bool				IsEnabled();
+		bool				IsUserSupplied();
+
+		virtual unsigned	CharLabelToNumber(NxsString s);
+		virtual unsigned	TaxonLabelToNumber(NxsString s);
+
+		virtual void		SkippingCommand(NxsString commandName);
+
+		virtual void		Report(std::ostream &out);
+		virtual void		Reset();
+
+		NxsString			errormsg;			/* workspace for creating error messages */
+
+	protected:
+		bool				isEmpty;			/* true if this object is currently storing data */
+		bool				isEnabled;			/* true if this block is currently ebabled */
+		bool				isUserSupplied;		/* true if this object has been read from a file; false otherwise */
+		NxsReader			*nexus;				/* pointer to the Nexus file reader object */
+		NxsBlock			*next;				/* pointer to next block in list */
+		NxsString			id;					/* holds name of block (e.g., "DATA", "TREES", etc.) */
+				
+		virtual void		Read(NxsToken &token);
+	};
+
+#endif
+
+


=====================================
libraries/ncl/nxsdefs.h
=====================================
@@ -0,0 +1,85 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+#ifndef NCL_NXSDEFS_H
+#define NCL_NXSDEFS_H
+
+#define NCL_NAME_AND_VERSION  "NCL version 2.0"
+#define NCL_COPYRIGHT         "Copyright (c) 1999-2003 by Paul O. Lewis"
+#define NCL_HOMEPAGEURL       "http://lewis.eeb.uconn.edu/ncl/"
+
+// Maximum number of states that can be stored; the only limitation is that this
+// number be less than the maximum size of an int (not likely to be a problem).
+// A good number for this is 76, which is 96 (the number of distinct symbols
+// able to be input from a standard keyboard) less 20 (the number of symbols
+// symbols disallowed by the NEXUS standard for use as state symbols)
+//
+#define NCL_MAX_STATES         76
+
+#if defined(__MWERKS__) || defined(__DECCXX) || defined(_MSC_VER) 
+	typedef long		file_pos;
+#else
+	typedef streampos	file_pos;
+#endif
+
+#define	SUPPORT_OLD_NCL_NAMES
+
+#include <vector>	//for std::vector
+#include <set>      //for std::set
+#include <map>      //for std::map
+#ifdef CLANG_UNDER_VS
+#include <xstddef>  //for std::less
+#endif 
+
+#include "nxsstring.h"
+
+typedef std::vector<bool>										NxsBoolVector;
+typedef std::vector<char>										NxsCharVector;
+typedef std::vector<unsigned>									NxsUnsignedVector;
+typedef std::vector<NxsStringVector>								NxsAllelesVector;
+
+typedef std::set< unsigned, std::less<unsigned> >						NxsUnsignedSet;
+
+typedef std::map< unsigned, NxsStringVector, std::less<unsigned> >	NxsStringVectorMap;
+typedef std::map< NxsString, NxsString, std::less<NxsString> >		NxsStringMap;
+typedef std::map< NxsString, NxsUnsignedSet, std::less<NxsString> >	NxsUnsignedSetMap;
+
+// The following typedefs are simply for maintaining compatibility with existing code.
+// The names on the right are deprecated and should not be used.
+//
+typedef	NxsBoolVector		BoolVect;
+typedef NxsUnsignedSet		IntSet;
+typedef NxsUnsignedSetMap	IntSetMap;
+typedef NxsAllelesVector	AllelesVect;
+typedef NxsStringVector		LabelList;
+typedef NxsStringVector		StrVec;
+typedef NxsStringVector		vecStr;
+typedef NxsStringVectorMap	LabelListBag;
+typedef NxsStringMap		AssocList;
+
+//class NxsTreesBlock;
+//class NxsTaxaBlock;
+//class NxsAllelesBlock;
+//class NxsAssumptionsBlock;
+//class NxsCharactersBlock;
+//class NxsDistancesBlock;
+//class NxsAssumptionsBlock;
+//class NxsDiscreteDatum;
+//class NxsDiscreteMatrix;
+
+#endif


=====================================
libraries/ncl/nxsexception.cpp
=====================================
@@ -0,0 +1,49 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include "ncl.h"
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Copies 's' to msg and sets line, col and pos to the current line, column and position in the file where parsing
+|	stopped.
+*/
+NxsException::NxsException(
+  const NxsString &s,	/* the message for the user */
+  file_pos fp,	/* the current file position */
+  long fl,		/* the current file line */
+  long fc)		/* the current file column */
+	{
+	pos		= fp;
+	line	= fl;
+	col		= fc;
+	msg		= s;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Creates a NxsException object with the specified message, getting file position information from the NxsToken.
+*/
+NxsException::NxsException(
+  const NxsString &s,		/* message that describes the error */
+  const NxsToken &t)		/* NxsToken that was supplied the last token (the token that caused the error) */
+	{
+	msg		= s; 
+	pos		= t.GetFilePosition();
+	line	= t.GetFileLine();
+	col		= t.GetFileColumn();
+  	}


=====================================
libraries/ncl/nxsexception.h
=====================================
@@ -0,0 +1,45 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NXSEXCEPTION_H
+#define NCL_NXSEXCEPTION_H
+
+#include "nxsstring.h" //for NxsString
+#include "nxsdefs.h"   //for file_pos
+
+class NxsToken;
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Exception class that conveys a message specific to the problem encountered.
+*/
+class NxsException
+	{
+	public:
+		NxsString	msg;	/* NxsString to hold message */
+		file_pos	pos;	/* current file position */
+		long		line;	/* current line in file */
+		long		col;	/* column of current line */
+
+		explicit NxsException(const NxsString &s, file_pos fp = 0, long fl = 0L, long fc = 0L);
+		NxsException(const NxsString &s, const NxsToken &t);
+	};
+
+typedef NxsException XNexus;
+
+#endif


=====================================
libraries/ncl/nxsindent.h
=====================================
@@ -0,0 +1,58 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis and Mark T. Holder
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NXSINDENT_H
+#define NCL_NXSINDENT_H
+
+#include <ostream> //for std::ostream
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Manipulator for use in indenting text `leftMarg' characters.
+*/
+class Indent
+	{
+	public:
+					Indent(unsigned i);
+
+		unsigned	leftMarg;	/* the amount by which to indent */
+	};
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	Initializes `leftMarg' to `i'.
+*/
+inline Indent::Indent(
+  unsigned i)	/* the amount (in characters) by which to indent */
+	{
+	leftMarg = i;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Output operator for the Indent manipulator.
+*/
+inline std::ostream &operator <<(
+  std::ostream &o,		/* the ostream object */
+  const Indent &i)	/* the Indent object to be sent to `o' */
+	{
+#if defined (HAVE_PRAGMA_UNUSED)
+#	pragma unused(i)
+#endif
+	return o;
+	}
+
+#endif


=====================================
libraries/ncl/nxsreader.cpp
=====================================
@@ -0,0 +1,493 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+#include "ncl.h"
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Initializes both `blockList' and `currBlock' to NULL.
+*/
+NxsReader::NxsReader()
+	{
+	blockList	= NULL;
+	currBlock	= NULL;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Nothing to be done.
+*/
+NxsReader::~NxsReader()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Adds `newBlock' to the end of the list of NxsBlock objects growing from `blockList'. If `blockList' points to NULL,
+|	this function sets `blockList' to point to `newBlock'. Calls SetNexus method of `newBlock' to inform `newBlock' of
+|	the NxsReader object that now owns it. This is useful when the `newBlock' object needs to communicate with the 
+|	outside world through the NxsReader object, such as when it issues progress reports as it is reading the contents
+|	of its block.
+*/
+void NxsReader::Add(
+  NxsBlock *newBlock)	/* a pointer to an existing block object */
+	{
+	assert(newBlock != NULL);
+
+	newBlock->SetNexus(this);
+
+	if (!blockList)
+		blockList = newBlock;
+	else
+		{
+		// Add new block to end of list
+		//
+		NxsBlock *curr;
+		for (curr = blockList; curr && curr->next;)
+			curr = curr->next;
+		assert(curr && !curr->next);
+		curr->next = newBlock;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns position (first block has position 0) of block `b' in `blockList'. Returns UINT_MAX if `b' cannot be found
+|	in `blockList'.
+*/
+unsigned NxsReader::PositionInBlockList(
+  NxsBlock *b)	/* a pointer to an existing block object */
+	{
+	unsigned pos = 0;
+	NxsBlock *curr = blockList;
+
+	for (;;)
+		{
+		if (curr == NULL || curr == b)
+			break;
+		pos++;
+		curr = curr->next;
+		}
+
+	if (curr == NULL)
+		pos = UINT_MAX;
+
+	return pos;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reassign should be called if a block (`oldb') is about to be deleted (perhaps to make way for new data). Create 
+|	the new block (`newb') before deleting `oldb', then call Reassign to replace `oldb' in `blockList' with `newb'. 
+|	Assumes `oldb' exists and is in `blockList'.
+*/
+void NxsReader::Reassign(
+  NxsBlock *oldb,	/* a pointer to the block object soon to be deleted */
+  NxsBlock *newb)	/* a pointer to oldb's replacement */
+	{
+	NxsBlock *prev = NULL;
+	NxsBlock *curr = blockList;
+	newb->SetNexus(this);
+
+	for (;;)
+		{
+		if (curr == NULL || curr == oldb)
+			break;
+		prev = curr;
+		curr = curr->next;
+		}
+
+	assert(curr != NULL);
+
+	newb->next = curr->next;
+	if (prev == NULL) 
+		blockList = newb;
+	else 
+		prev->next = newb;
+	curr->next = NULL;
+	curr->SetNexus(NULL);
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	If `blockList' data member still equals NULL, returns true; otherwise, returns false. `blockList' will not be equal
+|	to NULL if the Add function has been called to add a block object to the list.
+*/
+bool NxsReader::BlockListEmpty()
+	{
+	return (blockList == NULL ? true : false);
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function was created for purposes of debugging a new NxsBlock. This version does nothing; to create an active
+|	DebugReportBlock function, override this version in the derived class and call the Report function of `nexusBlock'.
+|	This function is called whenever the main NxsReader Execute function encounters the [&spillall] command comment 
+|	between blocks in the data file. The Execute function goes through all blocks and passes them, in turn, to this 
+|	DebugReportBlock function so that their contents are displayed. Placing the [&spillall] command comment between
+|	different versions of a block allows multiple blocks of the same type to be tested using one long data file. Say 
+|	you are interested in testing whether the normal, transpose, and interleave format of a matrix can all be read 
+|	correctly. If you put three versions of the block in the data file one after the other, the second one will wipe out
+|	the first, and the third one will wipe out the second, unless you have a way to report on each one before the next 
+|	one is read. This function provides that ability.
+*/
+void NxsReader::DebugReportBlock(
+  NxsBlock &nexusBlock)	/* the block that should be reported */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(nexusBlock)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Detaches `oldBlock' from the list of NxsBlock objects growing from `blockList'. If `blockList' itself points to 
+|	`oldBlock', this function sets `blockList' to point to `oldBlock->next'. Note: the object pointed to by `oldBlock' 
+|	is not deleted, it is simply detached from the linked list. No harm is done in Detaching a block pointer that has 
+|	already been detached previously; if `oldBlock' is not found in the block list, Detach simply returns quietly. If 
+|	`oldBlock' is found, its SetNexus object is called to set the NxsReader pointer to NULL, indicating that it is no 
+|	longer owned by (i.e., attached to) a NxsReader object.
+*/
+void NxsReader::Detach(
+  NxsBlock *oldBlock)	/* a pointer to an existing block object */
+	{
+	assert(oldBlock != NULL);
+
+	// Return quietly if there are not blocks attached
+	//
+	if (blockList == NULL)
+		return;
+
+	if (blockList == oldBlock) 
+		{
+		blockList = oldBlock->next;
+		oldBlock->SetNexus(NULL);
+		}
+	else 
+		{
+		// Bug fix MTH 6/17/2002: old version detached intervening blocks as well
+		//
+		NxsBlock *curr = blockList;
+		for (; curr->next != NULL && curr->next != oldBlock;)
+			curr = curr->next;
+
+		// Line below can be uncommented to find cases where Detach function is 
+		// called for pointers that are not in the linked list. If line below is
+		// uncommented, the part of the descriptive comment that precedes this
+		// function about "...simply returns quietly" will be incorrect (at least
+		// in the Debugging version of the program where asserts are active).
+		//
+		//assert(curr->next == oldBlock);
+
+		if (curr->next == oldBlock) 
+			{
+			curr->next = oldBlock->next;
+			oldBlock->SetNexus(NULL);
+			}
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Called by the NxsReader object when a block named `blockName' is entered. Allows derived class overriding this
+|	function to notify user of progress in parsing the NEXUS file. Also gives program the opportunity to ask user if it
+|	is ok to purge data currently contained in this block. If user is asked whether existing data should be deleted, and
+|	the answer comes back no, then then the overrided function should return false, otherwise it should return true.
+|	This (base class) version always returns true.
+*/
+bool NxsReader::EnteringBlock(
+  NxsString blockName)	/* the name of the block just entered */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(blockName)
+#	endif
+	return true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Called by the NxsReader object when a block named `blockName' is being exited. Allows derived class overriding this
+|	function to notify user of progress in parsing the NEXUS file.
+*/
+void NxsReader::ExitingBlock(
+  NxsString blockName)	/* the name of the block being exited */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(blockName)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads the NxsReader data file from the input stream provided by `token'. This function is responsible for reading 
+|	through the name of a each block. Once it has read a block name, it searches `blockList' for a block object to 
+|	handle reading the remainder of the block's contents. The block object is responsible for reading the END or 
+|	ENDBLOCK command as well as the trailing semicolon. This function also handles reading comments that are outside 
+|	of blocks, as well as the initial "#NEXUS" keyword. The `notifyStartStop' argument is provided in case you do not 
+|	wish the ExecuteStart and ExecuteStop functions to be called. These functions are primarily used for creating and 
+|	destroying a dialog box to show progress, and nested Execute calls can thus cause problems (e.g., a dialog box is 
+|	destroyed when the inner Execute calls ExecuteStop and the outer Execute still expects the dialog box to be 
+|	available). Specifying `notifyStartStop' false for all the nested Execute calls thus allows the outermost Execute 
+|	call to control creation and destruction of the dialog box.
+*/
+void NxsReader::Execute(
+  NxsToken	&token,				/* the token object used to grab NxsReader tokens */
+  bool		notifyStartStop)	/* if true, ExecuteStarting and ExecuteStopping will be called */
+	{
+	char id_str[256];
+	currBlock = NULL;
+
+	bool disabledBlock = false;
+	NxsString errormsg;
+
+	try
+		{
+		token.GetNextToken();
+		}
+	catch (NxsException x)
+		{
+		NexusError(token.errormsg, 0, 0, 0);
+		return;
+		}
+
+	if (!token.Equals("#NEXUS"))
+		{
+		errormsg = "Expecting #NEXUS to be the first token in the file, but found ";
+		errormsg += token.GetToken();
+		errormsg += " instead";
+		NexusError(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
+		return;
+		}
+
+	if (notifyStartStop)
+		ExecuteStarting();
+
+	for (;;)
+		{
+		token.SetLabileFlagBit(NxsToken::saveCommandComments);
+		token.GetNextToken();
+
+		if (token.AtEOF())
+			break;
+
+		if (token.Equals("BEGIN"))
+			{
+			disabledBlock = false;
+			token.GetNextToken();
+
+			for (currBlock = blockList; currBlock != NULL; currBlock = currBlock->next)
+				{
+				if (token.Equals(currBlock->GetID()))
+					{
+					if (currBlock->IsEnabled()) 
+						{
+						strcpy(id_str, currBlock->GetID().c_str());
+						bool ok_to_read = EnteringBlock(id_str);
+						if (!ok_to_read) 
+							currBlock = NULL;
+						else
+							{
+							currBlock->Reset();
+
+							// We need to back up currBlock, because the Read statement might trigger
+							// a recursive call to Execute (if the block contains instructions to execute 
+							// another file, then the same NxsReader object may be used and any member fields (e.g. currBlock)
+							//  could be trashed.
+							//
+							NxsBlock *tempBlock = currBlock;	
+
+							try 
+								{
+								currBlock->Read(token);
+								currBlock = tempBlock;
+								}
+
+							catch (NxsException x) 
+								{
+								currBlock = tempBlock;
+								if (currBlock->errormsg.length() > 0)
+									NexusError(currBlock->errormsg, x.pos, x.line, x.col);
+								else
+									NexusError(x.msg, x.pos, x.line, x.col);
+								currBlock = NULL;
+								return;
+								}	// catch (NxsException x) 
+							ExitingBlock(id_str /*currBlock->GetID()*/);
+							}	// else
+						}	// if (currBlock->IsEnabled()) 
+
+					else
+						{
+						disabledBlock = true;
+						SkippingDisabledBlock(token.GetToken());
+						}
+					break;
+					}	// if (token.Equals(currBlock->GetID()))
+				}	// for (currBlock = blockList; currBlock != NULL; currBlock = currBlock->next)
+
+			if (currBlock == NULL)
+				{
+				token.BlanksToUnderscores();
+				NxsString currBlockName = token.GetToken();
+
+				if (!disabledBlock) 
+					SkippingBlock(currBlockName);
+
+				for (;;)
+					{
+                    token.SetLabileFlagBit(token.hyphenNotPunctuation);
+					token.GetNextToken();
+
+					if (token.Equals("END") || token.Equals("ENDBLOCK")) 
+						{
+						token.GetNextToken();
+
+						if (!token.Equals(";")) 
+							{
+							errormsg = "Expecting ';' after END or ENDBLOCK command, but found ";
+							errormsg += token.GetToken();
+							errormsg += " instead";
+							NexusError(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
+							return;
+							}
+						break;
+						}
+
+					if (token.AtEOF()) 
+						{
+						errormsg = "Encountered end of file before END or ENDBLOCK in block ";
+						errormsg += currBlockName;
+						NexusError(errormsg, token.GetFilePosition(), token.GetFileLine(), token.GetFileColumn());
+						return;
+						}
+					}	// for (;;)
+				}	// if (currBlock == NULL)
+			currBlock = NULL;
+			}	// if (token.Equals("BEGIN"))
+
+		else if (token.Equals("&SHOWALL"))
+			{
+			for (NxsBlock*  showBlock = blockList; showBlock != NULL; showBlock = showBlock->next)
+				{
+				DebugReportBlock(*showBlock);
+				}
+			}
+
+		else if (token.Equals("&LEAVE"))
+			{
+			break;
+			}
+
+		} // for (;;)
+
+	if (notifyStartStop)
+		ExecuteStopping();
+
+	currBlock = NULL;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns a string containing the copyright notice for the NxsReader Class Library, useful for reporting the use of 
+|	this library by programs that interact with the user.
+*/
+const char *NxsReader::NCLCopyrightNotice()
+	{
+	return NCL_COPYRIGHT;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns a string containing the URL for the NxsReader Class Library internet home page.
+*/
+const char *NxsReader::NCLHomePageURL()
+	{
+	return NCL_HOMEPAGEURL;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns a string containing the name and current version of the NxsReader Class Library, useful for reporting the 
+|	use of this library by programs that interact with the user.
+*/
+const char *NxsReader::NCLNameAndVersion()
+	{
+	return NCL_NAME_AND_VERSION;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Called just after Execute member function reads the opening "#NEXUS" token in a NEXUS data file. Override this 
+|	virtual base class function if your application needs to do anything at this point in the execution of a NEXUS data
+|	file (e.g. good opportunity to pop up a dialog box showing progress). Be sure to call the Execute function with the
+|	`notifyStartStop' argument set to true, otherwise ExecuteStarting will not be called.
+|	
+*/
+void NxsReader::ExecuteStarting()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Called when Execute member function encounters the end of the NEXUS data file, or the special comment [&LEAVE] is
+|	found between NEXUS blocks. Override this virtual base class function if your application needs to do anything at 
+|	this point in the execution of a NEXUS data file (e.g. good opportunity to hide or destroy a dialog box showing 
+|	progress). Be sure to call the Execute function with the `notifyStartStop' argument set to true, otherwise 
+|	ExecuteStopping will not be called.
+*/
+void NxsReader::ExecuteStopping()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Called when an error is encountered in a NEXUS file. Allows program to give user details of the error as well as 
+|	the precise location of the error.
+*/
+void NxsReader::NexusError(
+  NxsString	msg,	/* the error message to be displayed */
+  file_pos	pos,	/* the current file position */
+  long	line,	/* the current file line */
+  long	col)	/* the current column within the current file line */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(msg, pos, line, col)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function may be used to report progess while reading through a file. For example, the NxsAllelesBlock class 
+|	uses this function to report the name of the population it is currently reading so the user doesn't think the 
+|	program has hung on large data sets.
+*/
+void NxsReader::OutputComment(
+  const NxsString &comment)	/* a comment to be shown on the output */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(comment)
+#	endif
+	}
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function is called when an unknown block named `blockName' is about to be skipped. Override this pure virtual
+|	function to provide an indication of progress as the NEXUS file is being read.
+*/
+void NxsReader::SkippingBlock(
+  NxsString blockName)	/* the name of the block being skipped */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(blockName)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function is called when a disabled block named `blockName' is encountered in a NEXUS data file being executed.
+|	Override this pure virtual function to handle this event in an appropriate manner. For example, the program may 
+|	wish to inform the user that a data block was encountered in what is supposed to be a tree file.
+*/
+void NxsReader::SkippingDisabledBlock(
+  NxsString blockName)	/* the name of the disabled block being skipped */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(blockName)
+#	endif
+	}
+


=====================================
libraries/ncl/nxsreader.h
=====================================
@@ -0,0 +1,78 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NXSREADER_H
+#define NCL_NXSREADER_H
+#include <climits>
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	This is the class that orchestrates the reading of a NEXUS data file. An object of this class should be created, 
+|	and objects of any block classes that are expected to be needed should be added to `blockList' using the Add 
+|	member function. The Execute member function is then called, which reads the data file until encountering a block 
+|	name, at which point the correct block is looked up in `blockList' and that object's Read method called. 
+*/
+class NxsReader
+	{
+	public:
+		enum	NxsTolerateFlags	/* Flags used with data member tolerate used to allow some flexibility with respect to the NEXUS format */
+			{
+			allowMissingInEquate	= 0x0001,	/* if set, equate symbols are allowed for missing data symbol */
+			allowPunctuationInNames	= 0x0002	/* if set, some punctuation is allowed within tokens representing labels for taxa, characters, and sets */
+			};
+
+						NxsReader();
+		virtual			~NxsReader();
+
+		bool			BlockListEmpty();
+		unsigned		PositionInBlockList(NxsBlock *b);
+		void			Add(NxsBlock *newBlock);
+		void			Detach(NxsBlock *newBlock);
+		void			Reassign(NxsBlock *oldb, NxsBlock *newb);
+		void			Execute(NxsToken& token, bool notifyStartStop = true);
+
+		virtual void	DebugReportBlock(NxsBlock &nexusBlock);
+
+		const char			*NCLNameAndVersion();
+		const char			*NCLCopyrightNotice();
+		const char			*NCLHomePageURL();
+
+		virtual void	ExecuteStarting();
+		virtual void	ExecuteStopping();
+
+		virtual bool	EnteringBlock(NxsString blockName);
+		virtual void	ExitingBlock(NxsString blockName);
+
+		virtual void	OutputComment(const NxsString &comment);
+
+		virtual void	NexusError(NxsString msg, file_pos pos, long line, long col);
+
+		virtual void	SkippingDisabledBlock(NxsString blockName);
+		virtual void	SkippingBlock(NxsString blockName);
+
+	protected:
+
+		NxsBlock		*blockList;	/* pointer to first block in list of blocks */
+		NxsBlock		*currBlock;	/* pointer to current block in list of blocks */
+	};
+
+typedef NxsBlock NexusBlock;
+typedef NxsReader Nexus;
+
+#endif
+


=====================================
libraries/ncl/nxsstring.cpp
=====================================
@@ -0,0 +1,896 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis and Mark T. Holder
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include "ncl.h"
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Capitalizes every character in the stored string.
+*/
+NxsString &NxsString::ToUpper()
+	{
+	for (NxsString::iterator sIt = begin(); sIt != end(); sIt++)
+		*sIt = (char) toupper(*sIt);
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Appends a string representation of the supplied double to the stored string and returns a reference to itself.
+*/
+NxsString &NxsString::operator+=(
+  const double d)	/* the double value to append */
+	{
+	char tmp[81];
+
+	// Create a C-string representing the supplied double value. 
+	// The # causes a decimal point to always be output.
+	//
+	snprintf(tmp, sizeof(tmp), "%#3.6f", d);
+	unsigned tmplen = (unsigned)strlen(tmp);
+
+	// If the C-string has a lot of trailing zeros, lop them off
+	//
+	for (;;)
+		{
+		if (tmplen < 3 || tmp[tmplen-1] != '0' || tmp[tmplen-2] == '.')
+			break;
+		tmp[tmplen-1] = '\0';
+		tmplen--;
+		}
+
+	append(tmp);
+	return *this;
+	}
+
+/*-------------------------------------------------------------------------------------------------------------------------- 
+|	Adds `n' copies of the character `c' to the end of the stored string and returns a reference to itself.
+*/
+NxsString &NxsString::AddTail(
+  char c,		/* the character to use in the appended tail */
+  unsigned n)	/* the number of times `c' is to be appended */
+	{
+	char s[2];
+	s[0] = c;
+	s[1] = '\0';
+
+	for (unsigned i = 0; i < n; i++)
+		append(s);
+
+	return *this;
+	}
+
+/*-------------------------------------------------------------------------------------------------------------------------- 
+|	Replaces the stored string with a copy of itself surrounded by single quotes (single quotes inside the string are 
+|	converted to the '' pair of characters that signify a single quote). Returns a reference to itself.
+*/
+NxsString &NxsString::AddQuotes() 
+	{
+	NxsString withQuotes;
+	int len = length();
+	withQuotes.reserve(len + 4);
+	withQuotes += '\'';
+	for (NxsString::const_iterator sIt = begin(); sIt != end(); sIt++)
+		{
+		withQuotes += *sIt;
+		if (*sIt == '\'')
+			withQuotes += '\'';
+		}
+	withQuotes += '\'';
+	*this = withQuotes;
+
+	return *this;
+	}
+ 
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Appends a printf-style formatted string onto the end of this NxsString and returns the number of characters added to the 
+|	string. For example, the following code would result in the string s being set to "ts-tv rate ratio = 4.56789":
+|>
+|	double kappa = 4.56789;
+|	NxsString s;
+|	s.PrintF("ts-tv rate ratio = %.5f", kappa);
+|>
+*/
+int NxsString::PrintF(
+  const char *formatStr,	/* the printf-style format string */
+  ...)						/* other arguments referred to by the format string */
+  	{
+  	const int kInitialBufferSize = 256;
+  	char buf[kInitialBufferSize];
+
+	// Create a pointer to the list of optional arguments
+	//
+  	va_list argList;
+
+	// Set arg_ptr to the first optional argument in argList. The
+	// second argument (formatStr) is the last non-optional argument.
+	// 
+  	va_start(argList, formatStr);
+
+	// If vsnprintf returns -1, means kInitialBufferSize was not large enough.
+	// In this case, only kInitialBufferSize bytes are written.
+	//
+  	int nAdded = vsnprintf(buf, kInitialBufferSize, formatStr, argList);
+
+	// Reset the argument list pointer
+	//
+  	va_end(argList);
+
+	// Currently, if formatted string is too long to fit into the supplied buf,
+	// just adding a terminating '\0' and returning the truncated string
+	// Need to think of a better solution
+	//
+	if (nAdded  < 0 || nAdded >= kInitialBufferSize)
+		buf[kInitialBufferSize - 1] = '\0';
+
+	*this << buf;
+
+#if 0
+	// This part not being used anymore because there seems to be some differences
+	// between compilers in what is returned from the vsnprintf function. VC returns
+	// -1 if string is too long, Metrowerks returns the number of bytes that it would
+	// have used had there been enough space! 
+	//
+
+  	if (nAdded >= kInitialBufferSize)
+  		{
+  		char *tempbuf = new char[nAdded + 2];
+
+  		va_list argList;
+  		va_start(argList, formatStr);
+
+  		unsigned newNAdded = vsnprintf(tempbuf, nAdded + 1, formatStr, argList);
+
+  		va_end(argList);
+
+  		assert(nAdded == newNAdded);
+
+  		*this << tempbuf;
+  		delete [] tempbuf;
+  		}
+  	else
+  		*this << buf;
+
+#endif
+
+  	return nAdded;
+  	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if the string is a abbreviation (or complete copy) of the argument `s'.
+*/
+bool NxsString::IsStdAbbreviation(
+  const NxsString &s,	/* the string for which the stored string is potentially an abbreviation */
+  bool respectCase)		/* if true, comparison will be case-sensitive */
+  const
+	{
+	if (empty())
+		return false;
+
+	// s is the unabbreviated comparison string
+	//
+	const unsigned slen = static_cast<unsigned long>(s.size());
+
+	// t is the stored string
+	//
+	const unsigned tlen = static_cast<unsigned long>(size());
+
+	// t cannot be an abbreviation of s if it is longer than s
+	//
+	if (tlen > slen)
+		return false;
+
+	// Examine each character in t and return false (meaning "not an abbreviation")
+	// if at any point the corresponding character in s is different
+	//
+	for (unsigned k = 0; k < tlen; k++)
+		{
+		if (respectCase)
+			{
+			if ((*this)[k] != s[k])
+				return false;
+			}
+		else if (toupper((*this)[k]) != toupper(s[k]))
+			return false;
+		}
+
+	return true;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if the stored string is a case-insensitive abbreviation (or complete copy) of `s' and the stored string 
+| 	has all of the characters that are in the initial capitalized portion of `s'. For example if `s' is "KAPpa" then 
+|	"kappa", "kapp", or "kap" (with any capitalization pattern) will return true and all other strings will return false. 
+|	Always returns false if the stored string has length of zero.
+*/
+bool NxsString::IsCapAbbreviation(
+  const NxsString &s)	/* the string for which the stored string is potentially an abbreviation */
+  const
+	{
+	if (empty())
+		return false;
+
+	// s is the unabbreviated comparison string
+	//
+	const unsigned slen = static_cast<unsigned>(s.size());
+
+	// t is the stored string
+	//
+	const unsigned tlen = static_cast<unsigned>(size());
+
+	// If the stored string is longer than s then it cannot be an abbreviation of s
+	//
+	if (tlen > slen)
+		return false;
+	
+	unsigned k = 0;
+	for (; k < slen; k++) 
+		{
+		if (isupper(s[k]))	
+			{
+			// If still in the uppercase portion of s and we've run out of characters
+			// in t, then t is not a valid abbrevation of s
+			//
+			if (k >= tlen)
+				return false;
+
+			// If kth character in t is not equal to kth character in s, then
+			// t is not an abbrevation of s
+			//
+			char tokenChar = (char)toupper((*this)[k]);
+			if (tokenChar != s[k])
+				return false;
+			}
+		else if (!isalpha(s[k]))
+			{
+			// Get here if we are no longer in the upper case portion of s and 
+			// s[k] is not an alphabetic character. This section is necessary because
+			// we are dealing with a section of s that is not alphabetical and thus
+			// we cannot tell whether this should be part of the abbrevation or not
+			// (i.e. we cannot tell if it is capitalized or not). In this case, we
+			// pretend that we are still in the upper case portion of s and return
+			// false if we have run out of characters in t (meaning that the abbreviation
+			// was too short) or we find a mismatch.
+			//
+			if (k >= tlen)
+				return false;
+
+			if ((*this)[k] != s[k])
+				return false;
+			}
+		else
+			{
+			// Get here if we are no longer in the upper case portion of s and
+			// s[k] is an alphabetic character. Just break because we have determined
+			// that t is in fact a valid abbreviation of s.
+			//
+			break;
+			}
+		}
+
+	// Check the lower case portion of s and any corresponding characters in t for mismatches
+	// Even though the abbreviation is valid up to this point, it will become invalid if
+	// any mismatches are found beyond the upper case portion of s
+	//
+	for (; k < tlen; k++)
+		{
+  		const char tokenChar = (char)toupper((*this)[k]);
+  		const char otherChar = (char)toupper(s[k]);
+		if (tokenChar != otherChar)
+			return false;
+		}
+
+	return true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Right-justifies `x' in a field `w' characters wide, using blank spaces to fill in unused portions on the left-hand 
+|	side of the field. Specify true for `clear_first' to first empty the string. Assumes `w' is large enough to 
+|	accommodate the string representation of `x'.
+*/
+NxsString &NxsString::RightJustifyLong(
+  long x,			/* long value to right justify */
+  unsigned int w,	/* width of field */
+  bool clear_first)	/* if true, initialize string first to empty string */
+	{
+	bool x_negative = (x < 0L ? true : false);
+	unsigned long xabs = (x_negative ? (-x) : x);
+	unsigned num_spaces = w;
+
+	// If w = 10 and x = 123, we need 7 blank spaces before x
+	// log10(123) is 2.09, indicating that x is at least 10^2 = 100 but not
+	// 10^3 = 1000, thus x requires at least 3 characters to display
+	// 
+	unsigned x_width = (x == 0 ? 1 :1 + (int)log10((double)xabs));
+	if (x_negative)
+		x_width++;	// for the minus sign
+
+	assert(x_width <= num_spaces);
+	num_spaces -= x_width;
+
+	if (clear_first)
+		erase();
+
+	for (unsigned k = 0; k < num_spaces; k++)
+		*this += ' ';
+
+	if (x_negative)
+		*this += '-';
+
+	*this += xabs;
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Right-justifies `x' in a field `w' characters wide with precision `p', using blank spaces to fill in unused 
+|	portions on the left-hand side of the field. Specify true for `clear_first' to first empty the string. Assumes that
+|	the specified width is enough to accommodate the string representation of `x'.
+*/
+NxsString &NxsString::RightJustifyDbl(
+  double x,				/* double value to right justify */
+  unsigned w,			/* width of field */
+  unsigned p,			/* precision to use when displaying `x' */
+  bool clear_first)		/* if true, initialize stored string first to the empty string */
+	{
+	if (clear_first)
+		erase();
+
+	char fmtstr[81];
+	snprintf(fmtstr, sizeof(fmtstr), "%%.%df", p);
+	NxsString tmp;
+	tmp.PrintF(fmtstr, x);
+
+	unsigned num_spaces = w - tmp.length();
+	assert(num_spaces >= 0);
+
+	for (unsigned k = 0; k < num_spaces; k++)
+		*this += ' ';
+
+	*this += tmp;
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Right-justifies `s' in a field `w' characters wide, using blank spaces to fill in unused portions on the left-hand
+|	side of the field. Specify true for `clear_first' to first empty the string. Assumes that the specified width is 
+|	enough to accommodate `s'.
+*/
+NxsString &NxsString::RightJustifyString(
+  const NxsString &s,	/* string to right justify */
+  unsigned w,			/* width of field */
+  bool clear_first)		/* if true, initialize string first to the empty string */
+	{
+	if (clear_first)
+		erase();
+
+	unsigned num_spaces = w - s.length();
+	assert(num_spaces >= 0);
+
+	for (unsigned k = 0; k < num_spaces; k++)
+		*this += ' ';
+
+	*this += s;
+	return *this;
+	}
+
+/*-------------------------------------------------------------------------------------------------------------------------- 
+|	Returns true if the string needs to be surrounded by single-quotes to make it a single nexus token.
+*/
+bool NxsString::QuotesNeeded() const
+	{
+	bool quotes_needed = false;
+
+	for (NxsString::const_iterator sIt = begin(); sIt != end(); sIt++)
+		{
+		char c = (*sIt);
+
+		if (!isgraph(c))
+			{
+			// The standard C function isgraph returns zero if c is either a space or is not a printable character.
+			//
+			quotes_needed = true;
+			}
+		else if (strchr("(){}\"-]/\\,;:=*`+<>", c) != NULL)
+			{
+			// Get here if c is any NEXUS punctuation mark except left square bracket ([) or apostrophe (').
+			// Left square bracket characters and apostrophes never get returned as punctuation by NxsToken,
+			// so we should never encounter them here. 
+			//
+			
+			if (length() > 1)
+				quotes_needed = true;
+			}
+		else if (c == '\'' || c == '[')
+			{
+			// Get here if c is either an apostrophe or left square bracket. Quotes are needed if one of these
+			// characters is all there is to this string
+			//
+			//@POL Mark, I'm confused.
+			//
+			quotes_needed = true;
+			}
+
+		if (quotes_needed)
+			break;
+		}
+
+	return quotes_needed;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Converts any blank spaces found in the stored string to the underscore character.
+*/
+NxsString &NxsString::BlanksToUnderscores()
+	{
+	unsigned len = length();
+	for (unsigned k = 0; k < len; k++)
+		{
+		char &ch = at(k);
+		if (ch == ' ')
+			ch = '_';
+		}
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Converts any underscore characters found in the stored string to blank spaces.
+*/
+NxsString &NxsString::UnderscoresToBlanks()
+	{
+	unsigned len = length();
+	for (unsigned k = 0; k < len; k++)
+		{
+		char &ch = at(k);
+		if (ch == '_')
+			ch = ' ';
+		}
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Shortens stored string to `n' - 3 characters, making the last three characters "...". If string is already less than 
+|	`n' characters in length, this function has no effect. This is useful when it is desirable to show some of the
+|	contents of a string, even when the string will not fit in its entirety into the space available for displaying it.
+|	Assumes that `n' is at least 4.
+*/
+NxsString &NxsString::ShortenTo(
+  unsigned n)	/* maximum number of characters available for displaying the string */
+	{
+	assert(n > 3);
+	if (length() <= static_cast<unsigned>(n))
+		return *this;
+	
+	NxsString s;
+	for (NxsString::iterator sIt = begin(); sIt != end(); sIt++)
+		{
+		s += (*sIt);
+		if (s.length() >= n - 3)
+			break;
+		}
+	s += "...";
+
+	*this = s;
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Converts every character in the stored string to its lower case equivalent.
+*/
+NxsString &NxsString::ToLower()
+	{
+	for (NxsString::iterator sIt = begin(); sIt != end(); sIt++)
+		{
+		char c = (char)tolower(*sIt);
+		*sIt = c;
+		}
+	return *this;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if the stored string can be interpreted as a double value, and returns false otherwise.
+*/
+bool NxsString::IsADouble() const
+	{
+	const char	*str			= c_str();
+	unsigned	i				= 0;
+	bool		hadDecimalPt	= false;
+	bool		hadExp			= false;
+	bool		hadDigit		= false;
+	bool		hadDigitInExp	= false;
+
+	//	First char can be -
+	//
+	if (str[i]=='-')
+		i++;
+		
+	while (str[i])
+		{
+		if (isdigit(str[i]))
+			{
+			//	Digits are always OK
+			//
+			if (hadExp)
+				hadDigitInExp = true;
+			else
+				hadDigit = true;
+			}
+		else if (str[i] == '.')
+			{
+			//	One decimal point is allowed and it must be before the exponent
+			//
+			if (hadExp || hadDecimalPt)	
+				return false;
+			hadDecimalPt = true;
+			}
+		else if (str[i] == 'e' || str[i] == 'E')
+			{
+			//	One e is allowed, but it must be after at least one digit
+			//
+			if (hadExp || !hadDigit)
+				return false;
+			hadExp = true;
+			}
+		else if (str[i] == '-')
+			{
+			//	Another - is allowed if it is preceded by e
+			//
+			if (!hadExp || (str[i-1] != 'e' && str[i-1] != 'E')	)
+				return false;
+			}
+		else	
+			return false;
+		i++;
+		}
+		
+	if (hadExp)
+		{
+		if (hadDigitInExp)
+			return true;
+		return false;
+		}
+
+	if (hadDigit)
+		return true;
+	return false;
+	}
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if stored string can be interpreted as a long integer.
+*/
+bool NxsString::IsALong() const
+	{
+	const char *str	= c_str();
+	unsigned i		= 0;
+
+	//	First char can be -
+	//
+	if (str[i]=='-')
+		i++;
+
+	if (!isdigit(str[i]))
+		return false;
+
+	while (str[i])
+		{
+		if (!isdigit(str[i]))
+			return false;
+		i++;
+		}
+
+	return true;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if the stored string is a non-case-sensitive copy of the argument `s'. Note: will return true if both the
+|	stored string and `s' are empty strings.
+*/
+bool NxsString::EqualsCaseInsensitive(
+  const NxsString &s)	/* the comparison string */
+  const
+	{
+	unsigned k;
+	unsigned slen = s.size();
+	unsigned tlen = size();
+	if (slen != tlen)
+		return false;
+
+	for (k = 0; k < tlen; k++)
+		{
+  		if ((char)toupper((*this)[k]) != (char)toupper(s[k]))
+			return false;
+		}
+
+	return true;
+	}
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	Creates a string representation of the hexadecimal version of the long integer `p'. For example, if `p' equals 123,
+|	and if 2 was specified for `nFours', the resulting string would be "7B". If 4 was specified for `nFours', then the
+|	resulting string would be "007B". 
+*/
+NxsString NxsString::ToHex(
+  long p,			/* the value to display in hexadecimal */
+  unsigned nFours)	/* the number of hexadecimal digits to display */
+	{
+	NxsString s;
+	char decod[] = "0123456789ABCDEF";
+	for (int i = nFours - 1; i >= 0 ; i--)
+		{
+		unsigned long k = (p >> (4*i));
+		unsigned long masked = (k & 0x000f);
+		s += decod[masked];
+		}
+	return s;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Checks to see if the stored string begins with upper case letters and, if so, returns all of the contiguous capitalized
+|	prefix. If the stored string begins with lower case letters, an empty string is returned.
+*/
+NxsString NxsString::UpperCasePrefix() const
+	{
+	NxsString x;
+	unsigned i = 0;
+	while (i < size() && isupper((*this)[i]))
+		x += (*this)[i++];
+	return x;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Converts the stored string to an unsigned int using the standard C function strtol, throwing NxsX_NotANumber if the 
+|	conversion fails. Returns UINT_MAX if the number is too large to fit in an unsigned (or was a negative number).
+*/
+unsigned NxsString::ConvertToUnsigned() const
+	{
+	long l = ConvertToLong();
+	if (l < 0 || l >UINT_MAX) 
+		return UINT_MAX;
+	return static_cast<unsigned> (l);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Converts the stored string to an int using the standard C function strtol, throwing NxsX_NotANumber if the conversion 
+|	fails. Returns INT_MAX if the number is too large to fit in an int or -INT_MAX if it is too small.
+*/
+int NxsString::ConvertToInt() const
+	{
+	long l = ConvertToLong();
+	if (l == LONG_MAX || l > INT_MAX)
+		return INT_MAX;
+	if (l == -LONG_MAX || l <-INT_MAX)
+		return -INT_MAX;
+	return static_cast<int> (l);
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Converts the stored string to a long using the standard C function strtol, throwing NxsX_NotANumber if the conversion 
+|	fails.
+*/
+long NxsString::ConvertToLong() const
+	{
+	if (length() == 0 || !(isdigit(at(0)) || at(0) == '-'))
+		throw NxsX_NotANumber();
+	const char *b = c_str();
+	char *endP;
+	long l = strtol(b, &endP, 10);
+	if (l == 0 && endP == b)
+		throw NxsX_NotANumber();
+	return l;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Converts the stored string to a double using the standard C function strtod, throwing NxsX_NotANumber if the conversion
+|	fails. Returns DBL_MAX or -DBL_MAX if the number is out of bounds.
+*/
+double NxsString::ConvertToDouble() const
+	{
+	if (length() == 0)
+		throw NxsX_NotANumber();
+
+	char ch = at(0);
+	if (isdigit(ch) || ch == '-' || ch == '.'|| toupper(ch) == 'E')
+		{
+		const char *b = c_str();
+		char *endP;
+		double d = strtod(b, &endP);
+		if (d == 0.0 && endP == b)
+			throw NxsX_NotANumber();
+		if (d == HUGE_VAL)
+			return DBL_MAX;
+		if (d == -HUGE_VAL)
+			return -DBL_MAX;
+		return d;
+		}
+	throw NxsX_NotANumber();
+#if defined (DEMANDS_UNREACHABLE_RETURN)
+	return DBL_MAX;
+#endif
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Transforms the vector of NxsString objects by making them all lower case and then capitalizing the first portion of 
+|	them so that the capitalized portion is enough to uniquely specify each. Returns true if the strings are long enough 
+|	to uniquely specify each. Horrendously bad algorithm, but shouldn't be called often.
+*/
+bool SetToShortestAbbreviation(
+  NxsStringVector	&strVec,		/* vector of NxsString objects */
+  bool 				allowTooShort)	/* */
+	{
+	NxsStringVector upperCasePortion;
+	unsigned i;
+	for (i = 0; i < strVec.size(); i++)
+		{
+		// Change the next string to lower case
+		//
+		strVec[i].ToLower();
+
+		unsigned prefLen = 0;
+		NxsString pref;
+		
+		if (prefLen >= strVec[i].size())
+			return false;
+		pref += (char) toupper(strVec[i][prefLen++]);
+		bool moreChars = true;
+
+		// Keep adding letters from the current string until pref is unique.
+		// Then add this pref to upperCasePortion (vector of previous prefs)
+		//
+		for (;moreChars;)
+			{
+			size_t prevInd = 0;
+			for (; prevInd < upperCasePortion.size(); prevInd++)
+				{
+				if (pref == upperCasePortion[prevInd])
+					{
+					// 	Conflict  - both abbreviations need to grow
+					//
+					if (prefLen >= strVec[i].size())
+						{
+						if (allowTooShort)
+							{
+							if (prefLen < strVec[prevInd].size())
+								upperCasePortion[prevInd] += (char) toupper(strVec[prevInd][prefLen]);
+							moreChars = false;
+							break;
+							}
+						else
+							return false;
+						}
+					pref += (char) toupper(strVec[i][prefLen]);
+					if (prefLen >= strVec[prevInd].size())
+						{
+						if (allowTooShort)
+							{
+							prevInd = 0;
+							prefLen++;
+							break;
+							}
+						else
+							return false;
+						}
+					upperCasePortion[prevInd] += (char) toupper(strVec[prevInd][prefLen++]);
+					prevInd = 0;
+					break;
+					}
+				else
+					{
+					unsigned j;
+					for (j = 0; j < prefLen; j++)
+						{
+						if (pref[j] != upperCasePortion[prevInd][j])
+							break;
+						}
+					if (j == prefLen)
+						{
+						//	pref agrees with the first part of another abbreviation, lengthen it.
+						//
+						if (prefLen >= strVec[i].size())
+							{
+							if (allowTooShort)
+								{
+								moreChars = false;
+								break;
+								}
+							else
+								return false;
+							}
+						pref += (char) toupper(strVec[i][prefLen++]);
+						break;
+						}
+					}
+				}
+			if (prevInd == upperCasePortion.size() || !moreChars)
+				{
+				// Made it all the way through with no problems, add this 
+				// prefix as command i's upper case portion
+				//
+				upperCasePortion.push_back(pref);
+				break;
+				}
+			}
+		}
+
+	for (i = 0; i < strVec.size(); i++)
+		{
+		for (size_t j = 0; j < upperCasePortion[i].size(); j++)
+			strVec[i][j] = upperCasePortion[i][j];
+		}
+
+	return true;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns a vector of NxsString objects that match the entire `testStr'.
+*/
+NxsStringVector GetVecOfPossibleAbbrevMatches(
+  const NxsString		&testStr,		/* string to match */
+  const NxsStringVector	&possMatches)	/* vector of possible matches */
+	{
+	NxsStringVector matches;
+	for (size_t i = 0; i < possMatches.size(); i++)
+		{
+		if (testStr.Abbreviates(possMatches[i]))
+			matches.push_back(possMatches[i]);
+		}
+	return matches;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Written to make it easy to initialize a vector of strings. Similar to the perl split function. Converts a string like
+|	this -- "A|bro|ken strin|g" -- to a vector of strings with four elements:  "A", "bro", "ken string", and "g".
+*/
+NxsStringVector BreakPipeSeparatedList(
+  const NxsString &strList)	/* the string submitted for splitting */
+  	{
+	NxsString::const_iterator p = strList.begin();
+	NxsString ss;
+	NxsStringVector retVec;
+	for (;;)
+		{
+		bool done = (p == strList.end());
+		if (done || (*p == '|')) 
+			{
+			retVec.push_back(ss);
+			ss.clear();
+			if (done)
+				break;
+			p++;
+			}
+		ss += *p;
+		p++;
+		}
+	return retVec;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if the Equals comparison function is true for this or any element in the vector `s'.
+|   (James B. 23-Jul-2020, moved this here, from nxsstring.h, because the references to NxsStringVector 
+|    were a problem when compiling in Visual Studio).
+*/
+bool NxsString::IsInVector(
+	const NxsStringVector& s, /* the vector of NxsString objects to be searched */
+	NxsString::CmpEnum mode)	/* the argument passed to the Equals function, which is called for every element in the vector `s' */
+	const
+{
+	for (NxsStringVector::const_iterator sIt = s.begin(); sIt != s.end(); sIt++)
+	{
+		if (Equals(*sIt, mode))
+			return true;
+	}
+	return false;
+}
+


=====================================
libraries/ncl/nxsstring.h
=====================================
@@ -0,0 +1,601 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis and Mark T. Holder
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NXSSTRING_H
+#define NCL_NXSSTRING_H
+
+#include <cassert>
+#include <cstring>
+#include <string>
+#include <vector> //for std::vector
+#include "nxsindent.h"
+#include <climits>
+
+class IndexSet;
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	A string class for use with the Nexus Class Library. NxsString inherits most of its functionality from the standard
+|	template library class string, adding certain abilities needed for use in NCL, such as the ability to discern 
+|	whether a short string represents an abbreviation for the string currently stored. Another important addition is
+|	the member function PrintF, which accepts a format string and an arbitrary number of arguments, allowing a string
+|	to be built in a manner similar to the standard C function printf. Many operators are also provided for appending
+|	numbers to the ends of strings, an ability which is very useful for producing default labels (e.g. taxon1, taxon2,
+|	etc.).
+*/
+
+class NxsString
+  : public std::string
+	{
+	public:
+
+		class NxsX_NotANumber {};	/* exception thrown if attempt to convert string to a number fails */
+
+		enum CmpEnum				/* enum that is used to specify string comparison modes */
+			{
+			respect_case,		
+			no_respect_case, 
+			abbrev
+			};
+
+							NxsString();
+							NxsString(const char *s);
+							NxsString(const NxsString &s);
+
+		//	Accessors
+		//
+		bool				Abbreviates(const NxsString &s, NxsString::CmpEnum mode = NxsString::no_respect_case) const;
+		unsigned			ConvertToUnsigned() const;
+		int					ConvertToInt() const;
+		long				ConvertToLong() const;
+		double				ConvertToDouble() const;
+		bool				Equals(const NxsString &s, NxsString::CmpEnum mode = respect_case) const;
+		bool				EqualsCaseInsensitive(const NxsString &s) const;
+		NxsString			GetQuoted() const;
+		bool				IsADouble() const;
+		bool				IsALong() const;
+		bool				IsCapAbbreviation(const NxsString &s) const;
+		bool				IsInVector(const std::vector<NxsString> &s, NxsString::CmpEnum mode = respect_case) const;
+		bool				IsStdAbbreviation(const NxsString &s, bool respectCase) const;
+		bool				IsNexusPunctuation(const char c) const;
+		bool				QuotesNeeded() const;
+		NxsString 			UpperCasePrefix() const;
+		friend std::ostream	&operator<<(std::ostream &out, const NxsString &s);
+
+		//	Modifiers
+		//
+		//NxsString		   &operator=(const NxsString &s);
+		NxsString			&operator=(char);
+		NxsString			&operator=(const char *s);
+		NxsString			&operator+=(const char *s);
+		NxsString			&operator+=(const NxsString &s);
+		NxsString			&operator+=(const char c);
+		NxsString			&operator+=(const int i);
+		NxsString			&operator+=(unsigned i);
+		NxsString			&operator+=(unsigned long i);
+		NxsString			&operator+=(const long l);
+		NxsString			&operator+=(const double d);
+		NxsString			&operator+=(const IndexSet &d);
+		NxsString			&operator<<(int i);
+		NxsString			&operator<<(unsigned i);
+		NxsString			&operator<<(long l);
+		NxsString			&operator<<(unsigned long l);
+		NxsString			&operator<<(double d);
+		NxsString			&operator<<(const char *c);
+		NxsString			&operator<<(char c);
+		NxsString			&operator<<(const NxsString &s);
+		NxsString			&operator<<(const IndexSet &s);
+		NxsString			&operator<<(Indent) {return *this;}	//@temp need a system for handling indentation
+		NxsString			&operator<<(NxsString &(*funcPtr)(NxsString	&));
+
+		// Functions that should be in base class string but aren't
+		void				clear();
+
+		int					PrintF(const char *formatStr, ...);
+
+		unsigned char		*p_str(unsigned char *) const;
+
+		NxsString			&AddQuotes();
+		NxsString 			&AddTail(char c, unsigned n);
+		NxsString			&NumberThenWord(unsigned i, NxsString s);
+		NxsString 			&ShortenTo(unsigned n);
+		NxsString			&AppendDouble(unsigned minFieldFormat, unsigned precFormat, double x);
+		NxsString 			&Capitalize();
+
+		NxsString 			&RightJustifyString(const NxsString &s, unsigned w, bool clear_first = false);
+		NxsString 			&RightJustifyLong(long x, unsigned w, bool clear_first = false);
+		NxsString 			&RightJustifyDbl(double x, unsigned w, unsigned p, bool clear_first = false);
+
+		NxsString 			&ToLower();
+		NxsString 			&ToUpper();
+
+		NxsString 			&BlanksToUnderscores();
+		NxsString 			&UnderscoresToBlanks();
+
+		//	Debugging
+		//	
+		static NxsString 	ToHex(long p, unsigned nFours);
+	};
+
+typedef std::vector<NxsString>									NxsStringVector;
+
+#if defined (NXS_SUPPORT_OLD_NAMES)
+	typedef NxsString nxsstring;
+#endif
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Function object (Unary Predicate functor) that stores one string. The ()(const NxsString &) operator then returns the 
+|	result of a case-insensitive compare. Useful for STL find algorithms. Could be made faster than sequential case 
+|	insenstive comparisons, because the string stored in the object is just capitalized once.
+*/
+class NStrCaseInsensitiveEquals 
+	{
+	public :
+
+					NStrCaseInsensitiveEquals(const NxsString &s);
+		bool		operator()(const NxsString &s);
+		
+	protected :
+
+		NxsString	compStr;
+	};
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Function object (Unary Predicate functor) that stores one string. The ()(const NxsString &) operator then returns the 
+|	result of a case-sensitive compare. Useful for STL find algorithms.
+*/
+class NStrCaseSensitiveEquals 
+	{
+	public :
+
+					NStrCaseSensitiveEquals(const NxsString &s);
+		bool		operator()(const NxsString &s) const;
+
+	protected :
+
+		NxsString	compStr;
+	};
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Binary function class that performs case-Insensitive string compares.
+*/
+/*struct NxsStringEqual
+  : public std::binary_function<NxsString, NxsString, bool>
+	{
+	bool operator()(const NxsString &x, const NxsString &y) const;
+	};*/
+
+// ############################# start NStrCaseInsensitiveEquals functions ##########################
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Creates a function object for case-insensitive comparisons of `s' to a container of strings. 
+*/
+inline NStrCaseInsensitiveEquals::NStrCaseInsensitiveEquals(
+  const NxsString &s)	/* the string to be compared */
+	{
+	compStr = s;
+	compStr.Capitalize();
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns the result of a case-sensitive compare of `s' and the string stored when the NStrCaseInsensitiveEquals object  
+|	was created. Could be made more efficient (currently capitalizes the entire argument even though the first character may 
+|	be wrong).
+*/
+inline bool NStrCaseInsensitiveEquals::operator()(
+  const NxsString &s)	/* the string to be compared */
+	{
+	if (s.length() == compStr.length())
+		{
+		NxsString capS(s);
+		capS.Capitalize();
+		return capS == compStr;
+		}
+	return false;
+	}
+
+// ############################# start NStrCaseSensitiveEquals functions ##########################
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Creates a function object for case-sensitive comparisons of `s' to a container of strings. 
+*/
+inline NStrCaseSensitiveEquals::NStrCaseSensitiveEquals(
+  const NxsString &s)	/* the string that all other strings will be compared to when the (const NxsString &) operator is called */  
+	{
+	compStr = s;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns the result of a case-sensitive compare of `s' and the string stored when the NStrCaseSensitiveEquals was 
+|	created.
+*/
+inline bool NStrCaseSensitiveEquals::operator()(
+  const NxsString &s)	/* the string to be compared */
+  const
+	{
+	return (compStr == s);
+	}
+	
+// ############################# start NxsStringEqual functions ##########################
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if the strings `x' and `y' are identical (NOT case sensitive)
+*/
+/*inline bool NxsStringEqual::operator()(
+  const NxsString &x,
+  const NxsString &y)
+  const
+	{
+	return x.EqualsCaseInsensitive(y);
+	}*/
+
+// ############################# start NxsString functions ##########################
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	The default constructor.
+*/
+inline NxsString::NxsString()
+  : std::string()
+	{
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns a single-quoted version of the NxsString. The calling object is not altered. Written for ease of use. Simply 
+|	copies the stored string, then returns the copy after calling its AddQuotes function.
+*/
+inline NxsString NxsString::GetQuoted()
+  const
+	{
+	NxsString s(*this);
+	s.AddQuotes();
+	return s;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Most containers in the standard template library can be completely erased using the clear function, but none is 
+|	provided for the class string and hence is provided here.
+*/
+inline void NxsString::clear()
+	{
+	erase();
+	}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	A copy constructor taking a C-string argument.
+*/
+inline NxsString::NxsString(
+  const char *s)	/* the C-string that forms the basis for the new NxsString object */
+	{
+	assign(s);
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	A copy constructor taking a NxsString reference argument.
+*/
+inline NxsString::NxsString(
+  const NxsString &s)	/* reference to a NxsString to be used to create this copy */
+	{
+	assign(s);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Sets the stored string equal to the supplied C-string `s'.
+*/
+inline NxsString &NxsString::operator=(
+  const char *s)	/* the string for comparison */
+	{
+	assign(s);
+	return *this;
+	}
+	
+//inline NxsString& NxsString::operator=(
+//  const NxsString &s)
+//	{
+//	assign(s);
+//	return *this;
+//	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Appends the supplied C-string `s' to the stored string.
+*/
+inline NxsString &NxsString::operator+=(
+  const char *s)	/* the C-string to be appended */
+	{
+	append(std::string(s));
+	return *this;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Appends the characters in the supplied NxsString reference `s' to the stored string.
+*/
+inline NxsString &NxsString::operator+=(
+  const NxsString &s)	/* the string to append */
+	{
+	append(s);
+	return *this;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Appends the character `c' to the stored string.
+*/
+inline NxsString &NxsString::operator+=(
+  const char c)	/* the character to append */
+	{
+	char s[2];
+	s[0] = c;
+	s[1] = '\0';
+	append(std::string(s));
+	return *this;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Sets the stored string to the supplied character 'c'.
+*/
+inline NxsString &NxsString::operator=(
+  char c)	/* the character to which the stored string should be set */
+	{
+	clear();
+	return (*this += c);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Uses the standard C sprintf function to append the character representation of the supplied integer i' to the stored
+|	string (format code %d). For example, if the stored string is "taxon" and `i' is 9, the result is "taxon9".
+*/
+inline NxsString &NxsString::operator+=(
+  const int i)	/* the int to append */
+	{
+	char tmp[81];
+	snprintf(tmp, sizeof(tmp), "%d", i);
+	append(tmp);
+	return *this;
+	}
+
+/*-------------------------------------------------------------------------------------------------------------------------- 
+|	Capitalizes all lower case letters in the stored string by calling ToUpper.
+*/
+inline NxsString &NxsString::Capitalize()
+	{
+	ToUpper();
+	return *this;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if the stored string is an abbreviation (or complete copy) of the supplied string `s'.
+*/
+inline bool NxsString::Abbreviates(
+  const NxsString	&s,		/* the full comparison string */
+  NxsString::CmpEnum	mode)	/* if equal to abbrev, a non-case-sensitive comparison will be made, otherwise comparison will respect case */
+  const
+	{
+	if (mode == NxsString::abbrev)
+		return IsCapAbbreviation(s);
+	else
+		return IsStdAbbreviation(s, mode == respect_case);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Uses standard C function sprintf to append the unsigned integer `i' to the stored string (format code %u). 
+*/
+inline NxsString& NxsString::operator+=(
+  unsigned i)	/* the integer to be appended */
+	{
+	char tmp[81];
+	snprintf(tmp, sizeof(tmp), "%u", i);
+	append(tmp);
+	return *this;
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Uses standard C function sprintf to append the long integer `l' to the stored string (format code %ld).
+*/
+inline NxsString& NxsString::operator+=(
+  const long l)	/* the long integer to be appended */
+	{
+	char tmp[81];
+	snprintf(tmp, sizeof(tmp), "%ld", l);
+	append(tmp);
+	return *this;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Uses standard C function sprintf to append the unsigned long integer `l' to the stored string (format code %lu).
+*/
+inline NxsString& NxsString::operator+=(
+  const unsigned long l)	/* the unsigned long integer to be appended */
+	{
+	char tmp[81];
+	snprintf(tmp, sizeof(tmp), "%lu", l);
+	append(tmp);
+	return *this;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Uses the mode argument to call (and return the result of) the correct string comparison function. 
+*/
+inline bool NxsString::Equals(
+  const NxsString &s,		/* the string to which *this is compared */
+  NxsString::CmpEnum mode)	/* should be one of these three: respect_case, no_respect_case or abbrev */
+  const	
+	{
+	switch (mode) {
+		case NxsString::respect_case :
+			return (strcmp(this->c_str(), s.c_str()) == 0);
+		case NxsString::no_respect_case :
+			return this->EqualsCaseInsensitive(s);
+		case NxsString::abbrev :
+			return this->IsCapAbbreviation(s);
+		default :
+			assert(0);// incorrect setting for mode
+		}
+	return false;
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Allows functions that take and return references to NxsString strings to be placed in a series of << operators.
+|	See the NxsString endl function.
+*/
+inline NxsString &NxsString::operator<<(
+  NxsString &(*funcPtr)(NxsString &))	/* pointer to a function returning a reference to a NxsString */
+	{
+	return funcPtr(*this);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns true if `c' is any Nexus punctuation character:
+|>
+|	()[]{}/\,;:=*'"`-+<>
+|>
+*/
+inline bool NxsString::IsNexusPunctuation(
+  const char c)	/* the character in question */
+  const
+	{
+	return (strchr("()[]{}/\\,;:=*\'\"`-+<>", c) != 0);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Creates a new string (and returns a reference to the new string) composed of the integer `i' followed by a space and
+|	then the string `s'. If `i' is not 1, then an 's' character is appended to make `s' plural. For example, if `i' were 0,
+|	1, or 2, and `s' is "character", then the returned string would be "0 characters", "1 character" or "2 characters", 
+|	respectively. Obviously this only works if adding an 's' to the supplied string makes it plural.
+*/
+inline NxsString &NxsString::NumberThenWord(
+  unsigned i,			/* the number */
+  const NxsString s)	/* the string needing to be pluralized */
+  	{
+	(*this).erase();
+  	*this << i << ' ' << s;
+  	if (i != 1)
+  		*this << 's';
+  	return *this;
+  	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  int i)	/* the integer to append */
+  	{
+  	return (*this += i);
+  	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  unsigned i)	/* the unsigned integer to append */
+	{
+	return (*this += (int) i);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  long l)	/* the long integer to append */
+	{
+	return (*this += l);
+	}	
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  unsigned long l)	/* the unsigned long integer to append */
+	{
+	return (*this += l);
+	}	
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  double d)	/* the double floating point value to append */
+	{
+	return (*this += d);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  const char *c)	/* the C-string to append */
+	{	
+	return (*this += c);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  char c)	/* the char to append */
+	{	
+	return (*this += c);
+	}
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Another way to call the += operator (written to make it possible to use a NxsString like an ostream)
+*/
+inline NxsString &NxsString::operator<<(
+  const NxsString &s)	/* the NxsString to append */
+	{
+	return (*this += s);
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Returns string as a Pascal string (array of unsigned characters with the length in the first byte).
+*/
+inline unsigned char *NxsString::p_str(
+  unsigned char *buffer)	/* buffer to receive current string in Pascal form (i.e. length in first byte) */
+  const
+	{
+	memmove(buffer + 1, c_str(), length());
+	buffer[0] = length();
+	return buffer;
+	}
+
+// ############################# start of standalone functions ##########################
+
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Appends a newline character to the string `s' and the returns a reference to `s'. Used with << operator to allow 
+|	strings to be written to like ostreams.
+*/
+inline NxsString &endl(
+  NxsString &s)	/* the string to which the newline character is to be appended */
+	{
+	return (s += '\n');
+	}
+	
+/*--------------------------------------------------------------------------------------------------------------------------
+|	Writes the string `s' to the ostream `out'.
+*/
+inline std::ostream &operator<<(
+  std::ostream &out,			/* the stream to which the string `s' is to be written */
+  const NxsString &s)	/* the string to write */
+	{
+	out << s.c_str();
+	return out;
+	}
+
+NxsStringVector 	BreakPipeSeparatedList(const NxsString &strList);
+NxsStringVector 	GetVecOfPossibleAbbrevMatches(const NxsString &testStr,const NxsStringVector &possMatches);
+bool 				SetToShortestAbbreviation(NxsStringVector &strVec, bool allowTooShort = false);
+
+#endif


=====================================
libraries/ncl/nxstoken.cpp
=====================================
@@ -0,0 +1,622 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+#include "ncl.h"
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets atEOF and atEOL to false, comment and token to the empty string, filecol and fileline to 1, filepos to 0, 
+|	labileFlags to 0 and saved and special to the null character. Initializes the istream reference data 
+|	member in to the supplied istream `i'.
+*/
+NxsToken::NxsToken(
+  istream &i)	/* the istream object to which the token is to be associated */
+  : in(i)
+	{
+	atEOF		= false;
+	atEOL		= false;
+	comment.clear();
+	filecol		= 1L;
+	fileline	= 1L;
+	filepos		= 0L;
+	labileFlags	= 0;
+	saved		= '\0';
+	special		= '\0';
+	
+	whitespace[0]  = ' ';
+	whitespace[1]  = '\t';
+	whitespace[2]  = '\n';
+	whitespace[3]  = '\0';
+
+	punctuation[0]	= '(';
+	punctuation[1]	= ')';
+	punctuation[2]	= '[';
+	punctuation[3]	= ']';
+	punctuation[4]	= '{';
+	punctuation[5]	= '}';
+	punctuation[6]	= '/';
+	punctuation[7]	= '\\';
+	punctuation[8]	= ',';
+	punctuation[9]	= ';';
+	punctuation[10]	= ':';
+	punctuation[11]	= '=';
+	punctuation[12]	= '*';
+	punctuation[13]	= '\'';
+	punctuation[14]	= '"';
+	punctuation[15]	= '`';
+	punctuation[16]	= '+';
+	punctuation[17]	= '-';
+	punctuation[18]	= '<';
+	punctuation[19]	= '>';
+	punctuation[20]	= '\0';
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Nothing needs to be done; all objects take care of deleting themselves.
+*/
+NxsToken::~NxsToken()
+	{
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads rest of comment (starting '[' already input) and acts accordingly. If comment is an output comment, and if 
+|	an output stream has been attached, writes the output comment to the output stream. Otherwise, output comments are 
+|	simply ignored like regular comments. If the labileFlag bit saveCommandComments is in effect, the comment (without 
+|	the square brackets) will be stored in token. 
+*/
+void NxsToken::GetComment()
+	{
+	// Set comment level to 1 initially.  Every ']' encountered reduces
+	// level by one, so that we know we can stop when level becomes 0.
+	//
+	int level = 1;
+
+	// Get first character
+	//
+	char ch = GetNextChar();
+	if (atEOF)
+		{
+		errormsg = "Unexpected end of file inside comment";
+		throw NxsException( errormsg, GetFilePosition(), GetFileLine(), GetFileColumn());
+		}
+
+	// See if first character is the output comment symbol ('!')
+	// or command comment symbol (&)
+	//
+	int printing = 0;
+	int command = 0;
+	if (ch == '!')
+		printing = 1;
+	else if (ch == '&' && labileFlags & saveCommandComments)
+		{
+		command = 1;
+		AppendToToken(ch);
+		}
+	else if (ch == ']')
+		return;
+
+	// Now read the rest of the comment
+	//
+	for(;;)
+		{
+		ch = GetNextChar();
+		if (atEOF)
+			break;
+
+		if (ch == ']')
+			level--;
+		else if (ch == '[')
+			level++;
+
+		if (level == 0)
+			break;
+
+		if (printing)
+			AppendToComment(ch);
+		else if (command)
+			AppendToToken(ch);
+		}
+
+	if (printing)
+		{
+		// Allow output comment to be printed or displayed in most appropriate
+		// manner for target operating system
+		//
+		OutputComment(comment);
+
+		// Now that we are done with it, free the memory used to store the comment
+		//
+		//comment;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads rest of a token surrounded with curly brackets (the starting '{' has already been input) up to and including
+|	the matching '}' character. All nested curly-bracketed phrases will be included.
+*/
+void NxsToken::GetCurlyBracketedToken()
+	{
+	// Set level to 1 initially.  Every '}' encountered reduces
+	// level by one, so that we know we can stop when level becomes 0.
+	//
+	int level = 1;
+
+	char ch;
+	for(;;)
+		{
+		ch = GetNextChar();
+		if (atEOF)
+			break;
+
+		if (ch == '}')
+			level--;
+		else if (ch == '{')
+			level++;
+
+		AppendToToken(ch);
+
+		if (level == 0)
+			break;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Gets remainder of a double-quoted NEXUS word (the first double quote character was read in already by GetNextToken).
+|	This function reads characters until the next double quote is encountered. Tandem double quotes within a 
+|	double-quoted NEXUS word are not allowed and will be treated as the end of the first word and the beginning of the 
+|	next double-quoted NEXUS word. Tandem single quotes inside a double-quoted NEXUS word are saved as two separate 
+|	single quote characters; to embed a single quote inside a double-quoted NEXUS word, simply use the single quote by 
+|	itself (not paired with another tandem single quote).
+*/
+void NxsToken::GetDoubleQuotedToken()
+	{
+	char ch;
+
+	for(;;)
+		{
+		ch = GetNextChar();
+		if (atEOF)
+			break;
+
+		if (ch == '\"')
+			break;
+		else
+			AppendToToken(ch);
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Gets remainder of a quoted NEXUS word (the first single quote character was read in already by GetNextToken). This
+|	function reads characters until the next single quote is encountered. An exception occurs if two single quotes occur
+|	one after the other, in which case the function continues to gather characters until an isolated single quote is
+|	found. The tandem quotes are stored as a single quote character in the token NxsString.
+*/
+void NxsToken::GetQuoted()
+	{
+	char ch;
+
+	for(;;)
+		{
+		ch = GetNextChar();
+		if (atEOF)
+			break;
+
+		if (ch == '\'' && saved == '\'')
+			{
+			// Paired single quotes, save as one single quote
+			//
+			AppendToToken(ch);
+			saved = '\0';
+			}
+		else if (ch == '\'' && saved == '\0')
+			{
+			// Save the single quote to see if it is followed by another
+			//
+			saved = '\'';
+			}
+		else if (saved == '\'')
+			{
+			// Previously read character was single quote but this is something else, save current character so that it will
+			// be the first character in the next token read
+			//
+			saved = ch;
+			break;
+			}
+		else
+			AppendToToken(ch);
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads rest of parenthetical token (starting '(' already input) up to and including the matching ')' character.  All
+|	nested parenthetical phrases will be included.
+*/
+void NxsToken::GetParentheticalToken()
+	{
+	// Set level to 1 initially.  Every ')' encountered reduces
+	// level by one, so that we know we can stop when level becomes 0.
+	//
+	int level = 1;
+
+	char ch;
+	for(;;)
+		{
+		ch = GetNextChar();
+		if (atEOF)
+			break;
+
+		if (ch == ')')
+			level--;
+		else if (ch == '(')
+			level++;
+
+		AppendToToken(ch);
+
+		if (level == 0)
+			break;
+		}
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if token begins with the capitalized portion of `s' and, if token is longer than `s', the remaining 
+|	characters match those in the lower-case portion of `s'. The comparison is case insensitive. This function should be
+|	used instead of the Begins function if you wish to allow for abbreviations of commands and also want to ensure that 
+|	user does not type in a word that does not correspond to any command.
+*/
+bool NxsToken::Abbreviation(
+  NxsString s)	/* the comparison string */
+	{
+	int k;
+	int slen = s.size();
+	int tlen = token.size();
+	char tokenChar, otherChar;
+
+	// The variable mlen refers to the "mandatory" portion
+	// that is the upper-case portion of s
+	//
+	int mlen;
+	for (mlen = 0; mlen < slen; mlen++)
+		{
+		if (!isupper(s[mlen]))
+			break;
+		}
+
+	// User must have typed at least mlen characters in
+	// for there to even be a chance at a match
+	//
+	if (tlen < mlen)
+		return false;
+
+	// If user typed in more characters than are contained in s,
+	// then there must be a mismatch
+	//
+	if (tlen > slen)
+		return false;
+
+	// Check the mandatory portion for mismatches
+	//
+	for (k = 0; k < mlen; k++)
+		{
+		tokenChar = (char)toupper( token[k]);
+		otherChar = s[k];
+		if (tokenChar != otherChar)
+			return false;
+		}
+
+	// Check the auxiliary portion for mismatches (if necessary)
+	//
+	for (k = mlen; k < tlen; k++)
+		{
+		tokenChar = (char)toupper( token[k]);
+		otherChar = (char)toupper( s[k]);
+		if (tokenChar != otherChar)
+			return false;
+		}
+
+	return true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if token NxsString begins with the NxsString `s'. This function should be used instead of the Equals 
+|	function if you wish to allow for abbreviations of commands.
+*/
+bool NxsToken::Begins(
+  NxsString s,			/* the comparison string */
+  bool respect_case)	/* determines whether comparison is case sensitive */
+	{
+	unsigned k;
+	char tokenChar, otherChar;
+
+	unsigned slen = s.size();
+	if (slen > token.size())
+		return false;
+
+	for (k = 0; k < slen; k++)
+		{
+		if (respect_case)
+			{
+			tokenChar = token[k];
+			otherChar = s[k];
+			}
+		else
+			{
+			tokenChar = (char)toupper( token[k]);
+			otherChar = (char)toupper( s[k]);
+			}
+
+		if (tokenChar != otherChar)
+			return false;
+		}
+
+	return true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if token NxsString exactly equals `s'. If abbreviations are to be allowed, either Begins or 
+|	Abbreviation should be used instead of Equals.
+*/
+bool NxsToken::Equals(
+  NxsString s,			/* the string for comparison to the string currently stored in this token */
+  bool respect_case)	/* if true, comparison will be case-sensitive */
+	{
+	unsigned k;
+	char tokenChar, otherChar;
+
+	unsigned slen = s.size();
+	if (slen != token.size())
+		return false;
+
+	for (k = 0; k < token.size(); k++)
+		{
+		if (respect_case)
+			{
+			tokenChar = token[k];
+			otherChar = s[k];
+			}
+		else
+			{
+			tokenChar = (char)toupper( token[k]);
+			otherChar = (char)toupper( s[k]);
+			}
+		if (tokenChar != otherChar)
+			return false;
+		}
+
+	return true;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads characters from in until a complete token has been read and stored in token. GetNextToken performs a number 
+|	of useful operations in the process of retrieving tokens:
+|~
+|	o any underscore characters encountered are stored as blank spaces (unless the labile flag bit preserveUnderscores
+|	  is set)
+|	o if the first character of the next token is an isolated single quote, then the entire quoted NxsString is saved 
+|	  as the next token
+|	o paired single quotes are automatically converted to single quotes before being stored
+|	o comments are handled automatically (normal comments are treated as whitespace and output comments are passed to 
+|	  the function OutputComment which does nothing in the NxsToken class but can be overridden in a derived class to 
+|	  handle these in an appropriate fashion)
+|	o leading whitespace (including comments) is automatically skipped
+|	o if the end of the file is reached on reading this token, the atEOF flag is set and may be queried using the AtEOF 
+|	  member function
+|	o punctuation characters are always returned as individual tokens (see the Maddison, Swofford, and Maddison paper 
+|	  for the definition of punctuation characters) unless the flag ignorePunctuation is set in labileFlags,
+|	  in which case the normal punctuation symbols are treated just like any other darkspace character.
+|~
+|	The behavior of GetNextToken may be altered by using labile flags. For example, the labile flag saveCommandComments 
+|	can be set using the member function SetLabileFlagBit. This will cause comments of the form [&X] to be saved as 
+|	tokens (without the square brackets), but only for the aquisition of the next token. Labile flags are cleared after 
+|	each application.
+*/
+void NxsToken::GetNextToken()
+	{
+	ResetToken();
+
+	char ch = ' ';
+	if (saved == '\0' || IsWhitespace(saved))
+		{
+		// Skip leading whitespace
+		//
+		while( IsWhitespace(ch) && !atEOF)
+			ch = GetNextChar();
+		saved = ch;
+		}
+
+	for(;;)
+		{
+		// Break now if singleCharacterToken mode on and token length > 0.
+		//
+		if (labileFlags & singleCharacterToken && token.size() > 0)
+			break;
+
+		// Get next character either from saved or from input stream.
+		//
+		if (saved != '\0')
+			{
+			ch = saved;
+			saved = '\0';
+			}
+		else
+			ch = GetNextChar();
+
+		// Break now if we've hit EOF.
+		//
+		if (atEOF)
+			break;
+
+		if (ch == '\n' && labileFlags & newlineIsToken)
+			{
+			if (token.size() > 0)
+				{
+				// Newline came after token, save newline until next time when it will be 
+				// reported as a separate token.
+				//
+				atEOL = 0;
+				saved = ch;
+				}
+			else
+				{
+				atEOL = 1;
+				AppendToToken(ch);
+				}
+			break;
+			}
+
+		else if (IsWhitespace(ch))
+			{
+			// Break only if we've begun adding to token (remember, if we hit a comment before a token,
+			// there might be further white space between the comment and the next token).
+			//
+			if (token.size() > 0)
+				break;
+			}
+
+		else if (ch == '_')
+			{
+			// If underscores are discovered in unquoted tokens, they should be 
+			// automatically converted to spaces.
+			//
+			if (!(labileFlags & preserveUnderscores))
+				ch = ' ';
+			AppendToToken(ch);
+			}
+
+		else if (ch == '[')
+			{
+			// Get rest of comment and deal with it, but notice that we only break if the comment ends a token,
+			// not if it starts one (comment counts as whitespace). In the case of command comments 
+			// (if saveCommandComment) GetComment will add to the token NxsString, causing us to break because
+			// token.size() will be greater than 0.
+			//
+			GetComment();
+			if (token.size() > 0)
+			break;
+			}
+
+		else if (ch == '(' && labileFlags & parentheticalToken)
+			{
+			AppendToToken(ch);
+
+			// Get rest of parenthetical token.
+			//
+			GetParentheticalToken();
+			break;
+			}
+
+		else if (ch == '{' && labileFlags & curlyBracketedToken)
+			{
+			AppendToToken(ch);
+
+			// Get rest of curly-bracketed token.
+			//
+			GetCurlyBracketedToken();
+			break;
+			}
+
+		else if (ch == '\"' && labileFlags & doubleQuotedToken)
+			{
+			// Get rest of double-quoted token.
+			//
+			GetDoubleQuotedToken();
+			break;
+			}
+
+		else if (ch == '\'')
+			{
+			if (token.size() > 0)
+				{
+				// We've encountered a single quote after a token has
+				// already begun to be read; should be another tandem
+				// single quote character immediately following.
+				//
+				ch = GetNextChar();
+				if (ch == '\'')
+					AppendToToken(ch);
+				else
+					{
+					errormsg = "Expecting second single quote character";
+					throw NxsException( errormsg, GetFilePosition(), GetFileLine(), GetFileColumn());
+					}
+				}
+			else
+				{
+				// Get rest of quoted NEXUS word and break, since
+				// we will have eaten one token after calling GetQuoted.
+				//
+				GetQuoted();
+				}
+			break;
+			}
+
+		else if (IsPunctuation(ch))
+			{
+			if (token.size() > 0)
+				{
+				// If we've already begun reading the token, encountering
+				// a punctuation character means we should stop, saving
+				// the punctuation character for the next token.
+				//
+				saved = ch;
+				break;
+				}
+			else
+				{
+				// If we haven't already begun reading the token, encountering
+				// a punctuation character means we should stop and return
+				// the punctuation character as this token (i.e., the token
+				// is just the single punctuation character.
+				//
+				AppendToToken(ch);
+				break;
+				}
+			}
+
+		else
+			{
+			AppendToToken(ch);
+			}
+
+		}
+
+	labileFlags = 0;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Strips whitespace from currently-stored token. Removes leading, trailing, and embedded whitespace characters.
+*/
+void NxsToken::StripWhitespace()
+	{
+	NxsString s;
+	for (unsigned j = 0; j < token.size(); j++)
+		{
+		if (IsWhitespace( token[j]))
+			continue;
+		s += token[j];
+		}
+	token = s;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Converts all alphabetical characters in token to upper case.
+*/
+void NxsToken::ToUpper()
+	{
+	for (unsigned i = 0; i < token.size(); i++)
+		token[i] = (char)toupper(token[i]);
+	}
+


=====================================
libraries/ncl/nxstoken.h
=====================================
@@ -0,0 +1,539 @@
+//	Copyright (C) 1999-2003 Paul O. Lewis
+//
+//	This file is part of NCL (Nexus Class Library) version 2.0.
+//
+//	NCL is free software; you can redistribute it and/or modify
+//	it under the terms of the GNU General Public License as published by
+//	the Free Software Foundation; either version 2 of the License, or
+//	(at your option) any later version.
+//
+//	NCL is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//	GNU General Public License for more details.
+//
+//	You should have received a copy of the GNU General Public License
+//	along with NCL; if not, write to the Free Software Foundation, Inc., 
+//	59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef NCL_NXSTOKEN_H
+#define NCL_NXSTOKEN_H
+
+#include <iostream>	      //for std::ostream
+#include "nxsstring.h"    //for NxsString and NxsStringVector
+#include "nxsexception.h" //for NxsException
+#include "nxsdefs.h"      //for file_pos
+/*----------------------------------------------------------------------------------------------------------------------
+|	NxsToken objects are used by NxsReader to extract words (tokens) from a NEXUS data file. NxsToken objects know to
+|	correctly skip NEXUS comments and understand NEXUS punctuation, making reading a NEXUS file as simple as repeatedly
+|	calling the GetNextToken() function and then interpreting the token returned. If the token object is not attached 
+|	to an input stream, calls to GetNextToken() will have no effect. If the token object is not attached to an output
+|	stream, output comments will be discarded (i.e., not output anywhere) and calls to Write or Writeln will be 
+|	ineffective. If input and output streams have been attached to the token object, however, tokens are read one at a
+|	time from the input stream, and comments are correctly read and either written to the output stream (if an output
+|	comment) or ignored (if not an output comment). Sequences of characters surrounded by single quotes are read in as
+|	single tokens. A pair of adjacent single quotes are stored as a single quote, and underscore characters are stored
+|	as blanks.
+*/
+class NxsToken
+	{
+	public:
+
+		enum NxsTokenFlags	/* For use with the variable labileFlags */
+			{
+			saveCommandComments		= 0x0001,	/* if set, command comments of the form [&X] are not ignored but are instead saved as regular tokens (without the square brackets, however) */
+			parentheticalToken		= 0x0002,	/* if set, and if next character encountered is a left parenthesis, token will include everything up to the matching right parenthesis */
+			curlyBracketedToken		= 0x0004,	/* if set, and if next character encountered is a left curly bracket, token will include everything up to the matching right curly bracket */
+			doubleQuotedToken		= 0x0008,	/* if set, grabs entire phrase surrounded by double quotes */
+			singleCharacterToken	= 0x0010,	/* if set, next non-whitespace character returned as token */
+			newlineIsToken			= 0x0020,	/* if set, newline character treated as a token and atEOL set if newline encountered */
+			tildeIsPunctuation		= 0x0040,	/* if set, tilde character treated as punctuation and returned as a separate token */
+			useSpecialPunctuation	= 0x0080,	/* if set, character specified by the data member special is treated as punctuation and returned as a separate token */
+			hyphenNotPunctuation	= 0x0100,	/* if set, the hyphen character is not treated as punctutation (it is normally returned as a separate token) */
+			preserveUnderscores		= 0x0200,	/* if set, underscore characters inside tokens are not converted to blank spaces (normally, all underscores are automatically converted to blanks) */
+			ignorePunctuation		= 0x0400	/* if set, the normal punctuation symbols are treated the same as any other darkspace characters */
+			};
+
+		NxsString		errormsg;
+
+						NxsToken(std::istream &i);
+		virtual			~NxsToken();
+
+		bool			AtEOF();
+		bool			AtEOL();
+		bool			Abbreviation(NxsString s);
+		bool			Begins(NxsString s, bool respect_case = false);
+		void			BlanksToUnderscores();
+		bool			Equals(NxsString s, bool respect_case = false);
+		long			GetFileColumn() const;
+		file_pos		GetFilePosition() const;
+		long			GetFileLine() const;
+		void			GetNextToken();
+		NxsString		GetToken(bool respect_case = true);
+		const char		*GetTokenAsCStr(bool respect_case = true);
+		const NxsString	&GetTokenReference();
+		int				GetTokenLength() const;
+		bool			IsPlusMinusToken();
+		bool			IsPunctuationToken();
+		bool			IsWhitespaceToken();
+		void			ReplaceToken(const NxsString s);
+		void			ResetToken();
+		void			SetSpecialPunctuationCharacter(char c);
+		void			SetLabileFlagBit(int bit);
+		bool			StoppedOn(char ch);
+		void			StripWhitespace();
+		void			ToUpper();
+		void			Write(std::ostream &out);
+		void			Writeln(std::ostream &out);
+
+		virtual void	OutputComment(const NxsString &msg);
+		void GetNextContiguousToken(char stop_char); // Added by BQM
+	protected:
+
+		void			AppendToComment(char ch);
+		void			AppendToToken(char ch);
+		char			GetNextChar();
+		void			GetComment();
+		void			GetCurlyBracketedToken();
+		void			GetDoubleQuotedToken();
+		void			GetQuoted();
+		void			GetParentheticalToken();
+		bool			IsPunctuation(char ch);
+		bool			IsWhitespace(char ch);
+
+	private:
+
+		std::istream	∈				/* reference to input stream from which tokens will be read */
+		file_pos		filepos;			/* current file position (for Metrowerks compiler, type is streampos rather than long) */
+		long			fileline;			/* current file line */
+		long			filecol;			/* current column in current line (refers to column immediately following token just read) */
+		NxsString		token;				/* the character buffer used to store the current token */
+		NxsString		comment;			/* temporary buffer used to store output comments while they are being built */
+		char			saved;				/* either '\0' or is last character read from input stream */
+		bool			atEOF;				/* true if end of file has been encountered */
+		bool			atEOL;				/* true if newline encountered while newlineIsToken labile flag set */
+		char			special;			/* ad hoc punctuation character; default value is '\0' */
+		int				labileFlags;		/* storage for flags in the NxsTokenFlags enum */
+		char			punctuation[21];	/* stores the 20 NEXUS punctuation characters */
+		char			whitespace[4];		/* stores the 3 whitespace characters: blank space, tab and newline */
+	};
+
+typedef NxsToken NexusToken;
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns the token for functions that only need read only access - faster than GetToken.
+*/
+inline const NxsString &NxsToken::GetTokenReference()
+	{
+	return token;
+	}
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	This function is called whenever an output comment (i.e., a comment beginning with an exclamation point) is found 
+|	in the data file. This version of OutputComment does nothing; override this virtual function to display the output 
+|	comment in the most appropriate way for the platform you are supporting.
+*/
+inline void NxsToken::OutputComment(
+  const NxsString &msg)	/* the contents of the printable comment discovered in the NEXUS data file */
+	{
+#	if defined(HAVE_PRAGMA_UNUSED)
+#		pragma unused(msg)
+#	endif
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Adds `ch' to end of comment NxsString.
+*/
+inline void NxsToken::AppendToComment(
+  char ch)	/* character to be appended to comment */
+	{
+	comment += ch;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Adds `ch' to end of current token.
+*/
+inline void NxsToken::AppendToToken(
+  char ch)	/* character to be appended to token */
+	{
+	// First three lines proved necessary to keep Borland's implementation of STL from crashing
+	// under some circumstances (may no longer be necessary)
+	//
+	char s[2];
+	s[0] = ch;
+	s[1] = '\0';
+
+	token += s;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Reads next character from in and does all of the following before returning it to the calling function:
+|~
+|	o if character read is either a carriage return or line feed, the variable line is incremented by one and the
+|	  variable col is reset to zero
+|	o if character read is a carriage return, and a peek at the next character to be read reveals that it is a line
+|	  feed, then the next (line feed) character is read
+|	o if either a carriage return or line feed is read, the character returned to the calling function is '\n' if 
+|	  character read is neither a carriage return nor a line feed, col is incremented by one and the character is
+|	  returned as is to the calling function
+|	o in all cases, the variable filepos is updated using a call to the tellg function of istream.
+|~
+*/
+inline char NxsToken::GetNextChar()
+	{
+	int ch = in.get();
+	int failed = in.bad();
+	if (failed)
+		{
+		errormsg = "Unknown error reading data file (check to make sure file exists)";
+		throw NxsException(errormsg, *this);
+		}
+
+	if (ch == 13 || ch == 10)
+		{
+		fileline++;
+		filecol = 1L;
+
+		if (ch == 13 && (int)in.peek() == 10) 
+			ch = in.get();
+
+		atEOL = 1;
+		}
+	else if (ch == EOF)
+		atEOF = 1;
+	else
+		{
+		filecol++;
+		atEOL = 0;
+		}
+
+#	if defined(__DECCXX)
+		filepos = 0L;
+#	else
+    // BQM this cause crash compiling with clang under Windows!
+//		filepos = in.tellg();
+    filepos += 1;
+#	endif
+
+	if (atEOF)
+		return '\0';
+	else if (atEOL)
+		return '\n';
+	else
+		return (char)ch;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if character supplied is considered a punctuation character. The following twenty characters are 
+|	considered punctuation characters:
+|>
+|	()[]{}/\,;:=*'"`+-<>
+|>
+|	Exceptions:
+|~
+|	o The tilde character ('~') is also considered punctuation if the tildeIsPunctuation labile flag is set
+|	o The special punctuation character (specified using the SetSpecialPunctuationCharacter) is also considered 
+|	  punctuation if the useSpecialPunctuation labile flag is set
+|	o The hyphen (i.e., minus sign) character ('-') is not considered punctuation if the hyphenNotPunctuation 
+|	  labile flag is set
+|~
+|	Use the SetLabileFlagBit method to set one or more NxsLabileFlags flags in `labileFlags'
+*/
+inline bool NxsToken::IsPunctuation(
+  char ch)	/* the character in question */
+	{
+	// PAUP 4.0b10 
+	//  o allows ]`<> inside taxon names
+	//  o allows `<> inside taxset names
+	//
+	bool is_punctuation = false;
+	if (strchr(punctuation, ch))
+		is_punctuation = true;
+	if (labileFlags & tildeIsPunctuation  && ch == '~')
+		is_punctuation = true;
+	if (labileFlags & useSpecialPunctuation  && ch == special)
+		is_punctuation = true;
+	if (labileFlags & hyphenNotPunctuation  && ch == '-')
+		is_punctuation = false;
+
+	return is_punctuation;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if character supplied is considered a whitespace character. Note: treats '\n' as darkspace if labile
+|	flag newlineIsToken is in effect.
+*/
+inline bool NxsToken::IsWhitespace(
+  char ch)	/* the character in question */
+	{
+	bool ws = false;
+
+	// If ch is found in the whitespace array, it's whitespace
+	//
+	if (strchr(whitespace, ch))
+		ws = true;
+
+	// Unless of course ch is the newline character and we're currently
+	// treating newlines as darkspace!
+	//
+	if (labileFlags & newlineIsToken && ch == '\n')
+		ws = false;
+
+	return ws;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if and only if last call to GetNextToken encountered the end-of-file character (or for some reason the 
+|	input stream is now out of commission).
+*/
+inline bool NxsToken::AtEOF()
+	{
+	return atEOF;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if and only if last call to GetNextToken encountered the newline character while the newlineIsToken 
+|	labile flag was in effect.
+*/
+inline bool NxsToken::AtEOL()
+	{
+	return atEOL;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Converts all blanks in token to underscore characters. Normally, underscores found in the tokens read from a NEXUS
+|	file are converted to blanks automatically as they are read; this function reverts the blanks back to underscores. 
+*/
+inline void NxsToken::BlanksToUnderscores()
+	{
+	token.BlanksToUnderscores();
+	}
+	
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns value stored in `filecol', which keeps track of the current column in the data file (i.e., number of 
+|	characters since the last new line was encountered).
+*/
+inline long  NxsToken::GetFileColumn() const
+	{
+	return filecol;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns value stored in filepos, which keeps track of the current position in the data file (i.e., number of 
+|	characters since the beginning of the file).  Note: for Metrowerks compiler, you must use the offset() method of 
+|	the streampos class to use the value returned.
+*/
+inline file_pos  NxsToken::GetFilePosition() const
+	{
+	return filepos;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns value stored in `fileline', which keeps track of the current line in the data file (i.e., number of new 
+|	lines encountered thus far).
+*/
+inline long  NxsToken::GetFileLine() const
+	{
+	return fileline;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns the data member `token'. Specifying false for`respect_case' parameter causes all characters in `token'
+|	to be converted to upper case before `token' is returned. Specifying true results in GetToken returning exactly 
+|	what it read from the file.
+*/
+inline NxsString NxsToken::GetToken(
+  bool respect_case)	/* determines whether token is converted to upper case before being returned */
+	{
+	if (!respect_case)
+		ToUpper();
+
+	return token;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns the data member `token' as a C-style string. Specifying false for`respect_case' parameter causes all 
+|	characters in `token' to be converted to upper case before the `token' C-string is returned. Specifying true 
+|	results in GetTokenAsCStr returning exactly what it read from the file.
+*/
+inline const char *NxsToken::GetTokenAsCStr(
+  bool respect_case)	/* determines whether token is converted to upper case before being returned */
+	{
+	if (!respect_case)
+		ToUpper();
+
+	return token.c_str();
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns token.size().
+*/
+inline int NxsToken::GetTokenLength() const
+	{
+	return token.size();
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if current token is a single character and this character is either '+' or '-'.
+*/
+inline bool NxsToken::IsPlusMinusToken()
+	{
+	if (token.size() == 1 && ( token[0] == '+' || token[0] == '-') )
+		return true;
+	else
+		return false;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if current token is a single character and this character is a punctuation character (as defined in 
+|	IsPunctuation function).
+*/
+inline bool NxsToken::IsPunctuationToken()
+	{
+	if (token.size() == 1 && IsPunctuation( token[0]))
+		return true;
+	else
+		return false;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Returns true if current token is a single character and this character is a whitespace character (as defined in 
+|	IsWhitespace function).
+*/
+inline bool NxsToken::IsWhitespaceToken()
+	{
+	if (token.size() == 1 && IsWhitespace( token[0]))
+		return true;
+	else
+		return false;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Replaces current token NxsString with s.
+*/
+inline void NxsToken::ReplaceToken(
+  const NxsString s)	/* NxsString to replace current token NxsString */
+	{
+	token = s;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets token to the empty NxsString ("").
+*/
+inline void NxsToken::ResetToken()
+	{
+	token.clear();
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets the special punctuation character to `c'. If the labile bit useSpecialPunctuation is set, this character will 
+|	be added to the standard list of punctuation symbols, and will be returned as a separate token like the other 
+|	punctuation characters.
+*/
+inline void NxsToken::SetSpecialPunctuationCharacter(
+  char c)	/* the character to which `special' is set */
+	{
+	special = c;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Sets the bit specified in the variable `labileFlags'. The available bits are specified in the NxsTokenFlags enum.
+|	All bits in `labileFlags' are cleared after each token is read.
+*/
+inline void NxsToken::SetLabileFlagBit(
+  int bit)	/* the bit (see NxsTokenFlags enum) to set in `labileFlags' */
+	{
+	labileFlags |= bit;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Checks character stored in the variable saved to see if it matches supplied character `ch'. Good for checking such 
+|	things as whether token stopped reading characters because it encountered a newline (and labileFlags bit 
+|	newlineIsToken was set):
+|>
+|	StoppedOn('\n');
+|>
+|	or whether token stopped reading characters because of a punctuation character such as a comma:
+|>
+|	StoppedOn(',');
+|>
+*/
+inline bool NxsToken::StoppedOn(
+  char ch)	/* the character to compare with saved character */
+	{
+	if (saved == ch)
+		return true;
+	else
+		return false;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Simply outputs the current NxsString stored in `token' to the output stream `out'. Does not send a newline to the 
+|	output stream afterwards.
+*/
+inline void NxsToken::Write(
+  std::ostream &out)	/* the output stream to which to write token NxsString */
+	{
+	out << token;
+	}
+
+/*----------------------------------------------------------------------------------------------------------------------
+|	Simply outputs the current NxsString stored in `token' to the output stream `out'. Sends a newline to the output 
+|	stream afterwards.
+*/
+inline void NxsToken::Writeln(
+  std::ostream &out)	/* the output stream to which to write `token' */
+	{
+	out << token << std::endl;
+	}
+
+/**
+ * Added by BQM: return the contiguous string (including white space) as token
+ * until hitting stop_char
+ * @param stop_char a character to stop reading in
+ */
+inline void NxsToken::GetNextContiguousToken(char stop_char) {
+	ResetToken();
+
+	char ch = ' ';
+	if (saved == '\0' || IsWhitespace(saved))
+	{
+		// Skip leading whitespace
+		//
+		while( IsWhitespace(ch) && !atEOF)
+			ch = GetNextChar();
+		saved = ch;
+	}
+	for (;;) {
+
+		// Get next character either from saved or from input stream.
+		//
+		if (saved != '\0')
+			{
+			ch = saved;
+			saved = '\0';
+			}
+		else
+			ch = GetNextChar();
+
+		// Break now if we've hit EOF.
+		//
+		if (atEOF)
+			break;
+		if (ch == stop_char) {
+			saved = ch;
+			break;
+		}
+		AppendToToken(ch);
+	}
+	// Skip ending whitespace
+	if (token.empty()) return;
+	NxsString::iterator last = token.end();
+	while (last != token.begin() && IsWhitespace(*(last-1))) {
+		last--;
+	}
+	if (last != token.end()) token.erase(last, token.end());
+}
+
+#endif



View it on GitLab: https://salsa.debian.org/med-team/cmaple/-/commit/38d8ad377e55111d7b6d7f46dd6677b0a523f5b4

-- 
View it on GitLab: https://salsa.debian.org/med-team/cmaple/-/commit/38d8ad377e55111d7b6d7f46dd6677b0a523f5b4
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20260911/b6362e5c/attachment-0001.htm>


More information about the debian-med-commit mailing list