Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcli.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include <ctype.h></ctype.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
using namespace TCli;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// Release
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void printToonzRelease(ostream &out)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << "Toonz 7.1" << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void printLibRelease(ostream &out)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << "Tnzcore 1.0 - " __DATE__ << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// local UsageError
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// local UsageElements
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SpecialUsageElement : public UsageElement
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SpecialUsageElement(string name) : UsageElement(name, " "){};
Toshihiro Shimizu 890ddd
	void dumpValue(ostream &) const {};
Toshihiro Shimizu 890ddd
	void resetValue(){};
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static SpecialUsageElement bra("[");
Toshihiro Shimizu 890ddd
static SpecialUsageElement ket("]");
Toshihiro Shimizu 890ddd
static Switcher help("-help", "Print this help page");
Toshihiro Shimizu 890ddd
static Switcher release("-release", "Print the current Toonz version");
Toshihiro Shimizu 890ddd
static Switcher libRelease("-librelease", "");
Toshihiro Shimizu 890ddd
// hidden: print the lib version
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// helper function
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fetchElement(int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (index >= argc)
Toshihiro Shimizu 890ddd
		throw UsageError("missing argument");
Toshihiro Shimizu 890ddd
	for (int i = index; i < argc - 1; i++)
Toshihiro Shimizu 890ddd
		argv[i] = argv[i + 1];
Toshihiro Shimizu 890ddd
	argc--;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fetchElement(int &dst, int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string s = argv[index];
Toshihiro Shimizu 890ddd
	if (isInt(s))
Toshihiro Shimizu 890ddd
		dst = toInt(s);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw UsageError("expected int");
Toshihiro Shimizu 890ddd
	fetchElement(index, argc, argv);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fetchElement(string &dst, int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	char *s = argv[index];
Toshihiro Shimizu 890ddd
	fetchElement(index, argc, argv);
Toshihiro Shimizu 890ddd
	if (*s == '-')
Toshihiro Shimizu 890ddd
		throw UsageError("expected argument");
Toshihiro Shimizu 890ddd
	dst = string(s);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// UsageElement
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageElement::UsageElement(string name, string help)
Toshihiro Shimizu 890ddd
	: m_name(name), m_help(help), m_selected(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageElement::print(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << m_name;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageElement::printHelpLine(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << "  " << m_name << endl;
Toshihiro Shimizu 890ddd
	out << "       " << m_help << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// Qualifier
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Qualifier::print(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isSwitcher())
Toshihiro Shimizu 890ddd
		out << m_name;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		out << "[ " << m_name << " ]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SimpleQualifier::fetch(int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	fetchElement(index, argc, argv);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SimpleQualifier::dumpValue(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << m_name << " = " << (isSelected() ? "on" : "off") << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void SimpleQualifier::resetValue()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_selected = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// Argument & MultiArgument
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Argument::fetch(int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (index >= argc)
Toshihiro Shimizu 890ddd
		throw UsageError("missing argument");
Toshihiro Shimizu 890ddd
	if (!assign(argv[index]))
Toshihiro Shimizu 890ddd
		throw UsageError(string("bad argument type :") + argv[index]);
Toshihiro Shimizu 890ddd
	for (int i = index; i < argc - 1; i++)
Toshihiro Shimizu 890ddd
		argv[i] = argv[i + 1];
Toshihiro Shimizu 890ddd
	argc--;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultiArgument::fetch(int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (index >= argc)
Toshihiro Shimizu 890ddd
		throw UsageError("missing argument(s)");
Toshihiro Shimizu 890ddd
	allocate(argc - index);
Toshihiro Shimizu 890ddd
	for (m_index = 0; m_index < m_count; m_index++)
Toshihiro Shimizu 890ddd
		if (!assign(argv[index + m_index]))
Toshihiro Shimizu 890ddd
			throw UsageError(string("bad argument type :") + argv[index + m_index]);
Toshihiro Shimizu 890ddd
	argc -= m_count;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// UsageLine<t></t>
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine()
Toshihiro Shimizu 890ddd
	: m_elements(0), m_count(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::~UsageLine()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_elements) {
Toshihiro Shimizu 890ddd
		delete[] m_elements;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine(const UsageLine &src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_count = src.m_count;
Toshihiro Shimizu 890ddd
	m_elements = new UsageElementPtr[m_count];
Toshihiro Shimizu 890ddd
	::memcpy(m_elements, src.m_elements, m_count * sizeof(m_elements[0]));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine &UsageLine::operator=(const UsageLine &src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (src.m_elements != m_elements) {
Toshihiro Shimizu 890ddd
		delete[] m_elements;
Toshihiro Shimizu 890ddd
		m_elements = new UsageElementPtr[src.m_count];
Toshihiro Shimizu 890ddd
		::memcpy(m_elements, src.m_elements, src.m_count * sizeof(m_elements[0]));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_count = src.m_count;
Toshihiro Shimizu 890ddd
	return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine(const UsageLine &src, UsageElement &elem)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_count = src.m_count;
Toshihiro Shimizu 890ddd
	m_elements = new UsageElementPtr[m_count + 1];
Toshihiro Shimizu 890ddd
	::memcpy(m_elements, src.m_elements, m_count * sizeof(m_elements[0]));
Toshihiro Shimizu 890ddd
	m_elements[m_count++] = &elem;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine(int count)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_count = count;
Toshihiro Shimizu 890ddd
	m_elements = new UsageElementPtr[m_count];
Toshihiro Shimizu 890ddd
	::memset(m_elements, 0, m_count * sizeof(m_elements[0]));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine(UsageElement &elem)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_count = 1;
Toshihiro Shimizu 890ddd
	m_elements = new UsageElementPtr[m_count];
Toshihiro Shimizu 890ddd
	m_elements[0] = &elem;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine::UsageLine(UsageElement &a, UsageElement &b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_count = 2;
Toshihiro Shimizu 890ddd
	m_elements = new UsageElementPtr[m_count];
Toshihiro Shimizu 890ddd
	m_elements[0] = &a;
Toshihiro Shimizu 890ddd
	m_elements[1] = &b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine TCli::UsageLine::operator+(UsageElement &elem)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return UsageLine(*this, elem);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine TCli::operator+(UsageElement &a, UsageElement &b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return UsageLine(a, b);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageLine TCli::operator+(const UsageLine &a, const Optional &b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UsageLine ul(a.getCount() + b.getCount());
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < a.getCount(); i++)
Toshihiro Shimizu 890ddd
		ul[i] = a[i];
Toshihiro Shimizu 890ddd
	for (int j = 0; j < b.getCount(); j++)
Toshihiro Shimizu 890ddd
		ul[i++] = b[j];
Toshihiro Shimizu 890ddd
	return ul;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Optional::Optional(const UsageLine &ul)
Toshihiro Shimizu 890ddd
	: UsageLine(ul.getCount() + 2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_elements[0] = &bra;
Toshihiro Shimizu 890ddd
	m_elements[m_count - 1] = &ket;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < ul.getCount(); i++)
Toshihiro Shimizu 890ddd
		m_elements[i + 1] = ul[i];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// UsageImp
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TCli::UsageImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string m_progName;
Toshihiro Shimizu 890ddd
	vector<usageline> m_usageLines;</usageline>
Toshihiro Shimizu 890ddd
	std::map<string, *="" qualifier=""> m_qtable;</string,>
Toshihiro Shimizu 890ddd
	vector<qualifier *=""> m_qlist;</qualifier>
Toshihiro Shimizu 890ddd
	vector<argument *=""> m_args;</argument>
Toshihiro Shimizu 890ddd
	typedef std::map<string, *="" qualifier="">::iterator qiterator;</string,>
Toshihiro Shimizu 890ddd
	typedef std::map<string, *="" qualifier="">::const_iterator const_qiterator;</string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UsageLine *m_selectedUsageLine;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UsageImp(string progName);
Toshihiro Shimizu 890ddd
	~UsageImp(){};
Toshihiro Shimizu 890ddd
	void add(const UsageLine &);
Toshihiro Shimizu 890ddd
	void addStandardUsages();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void registerQualifier(Qualifier *q);
Toshihiro Shimizu 890ddd
	void registerQualifier(string name, Qualifier *q);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void registerArgument(Argument *arg);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void printUsageLine(ostream &out, const UsageLine &ul) const;
Toshihiro Shimizu 890ddd
	void printUsageLines(ostream &out) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void print(ostream &out) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void resetValues();
Toshihiro Shimizu 890ddd
	void clear();
Toshihiro Shimizu 890ddd
	void parse(int argc, char *argv[]);
Toshihiro Shimizu 890ddd
	void fetchArguments(
Toshihiro Shimizu 890ddd
		UsageLine &ul, int a, int b,
Toshihiro Shimizu 890ddd
		int &argc, char *argv[]);
Toshihiro Shimizu 890ddd
	bool matchSwitcher(const UsageLine &ul) const;
Toshihiro Shimizu 890ddd
	bool hasSwitcher(const UsageLine &ul) const;
Toshihiro Shimizu 890ddd
	bool matchArgCount(const UsageLine &ul, int a, int b, int argc) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void dumpValues(ostream &out) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getArgCountRange(const UsageLine &ul, int a, int b,
Toshihiro Shimizu 890ddd
						  int &min, int &max) const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static const int InfiniteArgCount;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const int UsageImp::InfiniteArgCount = 2048;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UsageImp::UsageImp(string progName)
Toshihiro Shimizu 890ddd
	: m_progName(progName), m_selectedUsageLine(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addStandardUsages();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::addStandardUsages()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	add(help);
Toshihiro Shimizu 890ddd
	add(release);
Toshihiro Shimizu 890ddd
	add(libRelease);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_usageLines.clear();
Toshihiro Shimizu 890ddd
	m_qtable.clear();
Toshihiro Shimizu 890ddd
	m_qlist.clear();
Toshihiro Shimizu 890ddd
	m_args.clear();
Toshihiro Shimizu 890ddd
	m_selectedUsageLine = 0;
Toshihiro Shimizu 890ddd
	addStandardUsages();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::registerArgument(Argument *arg)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_args.size() && m_args[i] != arg; i++) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i == m_args.size())
Toshihiro Shimizu 890ddd
		m_args.push_back(arg);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::registerQualifier(string name, Qualifier *q)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_qtable[name] = q;
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_qlist.size() && m_qlist[i] != q; i++) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i == m_qlist.size())
Toshihiro Shimizu 890ddd
		m_qlist.push_back(q);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::registerQualifier(Qualifier *q)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string str = q->getName();
Toshihiro Shimizu 890ddd
	const char *s0 = str.c_str();
Toshihiro Shimizu 890ddd
	while (*s0 == ' ')
Toshihiro Shimizu 890ddd
		s0++;
Toshihiro Shimizu 890ddd
	const char *s = s0;
Toshihiro Shimizu 890ddd
	for (;;) {
Toshihiro Shimizu 890ddd
		if (*s != '-') {
Toshihiro Shimizu 890ddd
			assert(!"Qualifier name must start with '-'");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		do
Toshihiro Shimizu 890ddd
			s++;
Toshihiro Shimizu 890ddd
		while (isalnum(*s));
Toshihiro Shimizu 890ddd
		if (s == s0 + 1) {
Toshihiro Shimizu 890ddd
			assert(!"Empty qualifier name");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		string name(s0, s - s0);
Toshihiro Shimizu 890ddd
		registerQualifier(name, q);
Toshihiro Shimizu 890ddd
		while (*s == ' ')
Toshihiro Shimizu 890ddd
			s++;
Toshihiro Shimizu 890ddd
		// ignoro gli eventuali parametri
Toshihiro Shimizu 890ddd
		while (isalnum(*s)) {
Toshihiro Shimizu 890ddd
			while (isalnum(*s))
Toshihiro Shimizu 890ddd
				s++;
Toshihiro Shimizu 890ddd
			while (*s == ' ')
Toshihiro Shimizu 890ddd
				s++;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (*s != '|')
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		s++;
Toshihiro Shimizu 890ddd
		while (*s == ' ')
Toshihiro Shimizu 890ddd
			s++;
Toshihiro Shimizu 890ddd
		s0 = s;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (*s != '\0') {
Toshihiro Shimizu 890ddd
		assert(!"Unexpected character");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::add(const UsageLine &ul)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_usageLines.push_back(ul);
Toshihiro Shimizu 890ddd
	for (int i = 0; i < ul.getCount(); i++) {
Toshihiro Shimizu 890ddd
		Qualifier *q = dynamic_cast<qualifier *="">(ul[i]);</qualifier>
Toshihiro Shimizu 890ddd
		if (q)
Toshihiro Shimizu 890ddd
			registerQualifier(q);
Toshihiro Shimizu 890ddd
		Argument *a = dynamic_cast<argument *="">(ul[i]);</argument>
Toshihiro Shimizu 890ddd
		if (a)
Toshihiro Shimizu 890ddd
			registerArgument(a);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::printUsageLine(ostream &out, const UsageLine &ul) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << m_progName;
Toshihiro Shimizu 890ddd
	for (int j = 0; j < ul.getCount(); j++)
Toshihiro Shimizu 890ddd
		if (!ul[j]->isHidden()) {
Toshihiro Shimizu 890ddd
			out << " ";
Toshihiro Shimizu 890ddd
			ul[j]->print(out);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	out << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::printUsageLines(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool first = true;
Toshihiro Shimizu 890ddd
	for (unsigned int i = 0; i < m_usageLines.size(); i++) {
Toshihiro Shimizu 890ddd
		const UsageLine &ul = m_usageLines[i];
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0; j < ul.getCount(); j++)
Toshihiro Shimizu 890ddd
			if (!ul[j]->isHidden())
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		if (j == ul.getCount())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		out << (first ? "usage: " : "       ");
Toshihiro Shimizu 890ddd
		printUsageLine(out, ul);
Toshihiro Shimizu 890ddd
		first = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	out << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::print(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printUsageLines(out);
Toshihiro Shimizu 890ddd
	out << endl;
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_qlist.size(); i++)
Toshihiro Shimizu 890ddd
		if (!m_qlist[i]->isHidden())
Toshihiro Shimizu 890ddd
			m_qlist[i]->printHelpLine(out);
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_args.size(); i++)
Toshihiro Shimizu 890ddd
		m_args[i]->printHelpLine(out);
Toshihiro Shimizu 890ddd
	out << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::parse(int argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	resetValues();
Toshihiro Shimizu 890ddd
	if (argc == 0 || argv[0] == 0)
Toshihiro Shimizu 890ddd
		throw UsageError("missing program name");
Toshihiro Shimizu 890ddd
	m_progName = string(argv[0]);
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 1; i < (unsigned int)argc;)
Toshihiro Shimizu 890ddd
		if (argv[i][0] == '-') {
Toshihiro Shimizu 890ddd
			string qname(argv[i]);
Toshihiro Shimizu 890ddd
			qiterator qit = m_qtable.find(qname);
Toshihiro Shimizu 890ddd
			if (qit == m_qtable.end()) {
Toshihiro Shimizu 890ddd
				string msg = "unknown qualifier '" + qname + "'";
Toshihiro Shimizu 890ddd
				throw UsageError(msg);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			Qualifier *qualifier = qit->second;
Toshihiro Shimizu 890ddd
			qualifier->fetch(i, argc, argv);
Toshihiro Shimizu 890ddd
			qualifier->select();
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<usageline *=""> usages;</usageline>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_usageLines.size(); i++)
Toshihiro Shimizu 890ddd
		if (hasSwitcher(m_usageLines[i]) &&
Toshihiro Shimizu 890ddd
			matchSwitcher(m_usageLines[i]))
Toshihiro Shimizu 890ddd
			usages.push_back(&m_usageLines[i]);
Toshihiro Shimizu 890ddd
	if (usages.empty())
Toshihiro Shimizu 890ddd
		for (i = 0; i < m_usageLines.size(); i++)
Toshihiro Shimizu 890ddd
			if (!hasSwitcher(m_usageLines[i]))
Toshihiro Shimizu 890ddd
				usages.push_back(&m_usageLines[i]);
Toshihiro Shimizu 890ddd
	if (usages.size() == 0)
Toshihiro Shimizu 890ddd
		throw UsageError("unrecognized syntax");
Toshihiro Shimizu 890ddd
	if (usages.size() > 1) {
Toshihiro Shimizu 890ddd
		int min = InfiniteArgCount;
Toshihiro Shimizu 890ddd
		int max = 0;
Toshihiro Shimizu 890ddd
		std::vector<usageline *="">::iterator it;</usageline>
Toshihiro Shimizu 890ddd
		for (it = usages.begin(); it != usages.end();) {
Toshihiro Shimizu 890ddd
			UsageLine &ul = **it;
Toshihiro Shimizu 890ddd
			int lmin, lmax;
Toshihiro Shimizu 890ddd
			getArgCountRange(ul, 0, ul.getCount() - 1, lmin, lmax);
Toshihiro Shimizu 890ddd
			min = tmin(min, lmin);
Toshihiro Shimizu 890ddd
			max = tmax(max, lmax);
Toshihiro Shimizu 890ddd
			if (matchArgCount(ul, 0, ul.getCount() - 1, argc - 1) == false)
Toshihiro Shimizu 890ddd
				it = usages.erase(it);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				it++;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (usages.size() == 0) {
Toshihiro Shimizu 890ddd
			if (argc - 1 < min)
Toshihiro Shimizu 890ddd
				throw UsageError("missing argument(s)");
Toshihiro Shimizu 890ddd
			else if (argc - 1 > max)
Toshihiro Shimizu 890ddd
				throw UsageError("too many arguments");
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				throw UsageError("bad argument number");
Toshihiro Shimizu 890ddd
		} else if (usages.size() > 1)
Toshihiro Shimizu 890ddd
			throw UsageError("ambiguous syntax");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (usages.size() == 1) {
Toshihiro Shimizu 890ddd
		UsageLine *found = usages[0];
Toshihiro Shimizu 890ddd
		if (found->getCount() > 0)
Toshihiro Shimizu 890ddd
			fetchArguments(*found, 0, found->getCount() - 1, argc, argv);
Toshihiro Shimizu 890ddd
		if (argc > 1)
Toshihiro Shimizu 890ddd
			throw UsageError("too many arguments");
Toshihiro Shimizu 890ddd
		m_selectedUsageLine = found;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::fetchArguments(
Toshihiro Shimizu 890ddd
	UsageLine &ul,
Toshihiro Shimizu 890ddd
	int a, int b, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(0 <= a && a <= b && b < ul.getCount());
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = a; i <= b; i++) {
Toshihiro Shimizu 890ddd
		if (ul[i] == &bra || ul[i]->isMultiArgument())
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		if (ul[i]->isArgument()) {
Toshihiro Shimizu 890ddd
			Argument *argument = dynamic_cast<argument *="">(ul[i]);</argument>
Toshihiro Shimizu 890ddd
			assert(argument);
Toshihiro Shimizu 890ddd
			argument->fetch(1, argc, argv);
Toshihiro Shimizu 890ddd
			argument->select();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i > b) {
Toshihiro Shimizu 890ddd
	} else if (ul[i] == &bra) {
Toshihiro Shimizu 890ddd
		int n = 0;
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = b; j > i && ul[j] != &ket; j--)
Toshihiro Shimizu 890ddd
			if (ul[j]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		assert(j > i + 1);
Toshihiro Shimizu 890ddd
		if (argc - 1 > n)
Toshihiro Shimizu 890ddd
			fetchArguments(ul, i + 1, j - 1, argc, argv);
Toshihiro Shimizu 890ddd
		if (j + 1 <= b)
Toshihiro Shimizu 890ddd
			fetchArguments(ul, j + 1, b, argc, argv);
Toshihiro Shimizu 890ddd
	} else if (ul[i]->isMultiArgument()) {
Toshihiro Shimizu 890ddd
		MultiArgument *argument = dynamic_cast<multiargument *="">(ul[i]);</multiargument>
Toshihiro Shimizu 890ddd
		assert(argument);
Toshihiro Shimizu 890ddd
		int n = 0;
Toshihiro Shimizu 890ddd
		for (int j = i + 1; j <= b; j++)
Toshihiro Shimizu 890ddd
			if (ul[j]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		int oldArgc = argc;
Toshihiro Shimizu 890ddd
		argc -= n;
Toshihiro Shimizu 890ddd
		argument->fetch(1, argc, argv);
Toshihiro Shimizu 890ddd
		argument->select();
Toshihiro Shimizu 890ddd
		argc += n;
Toshihiro Shimizu 890ddd
		if (n > 0) {
Toshihiro Shimizu 890ddd
			if (argc < oldArgc)
Toshihiro Shimizu 890ddd
				for (int j = n; j > 0; j--)
Toshihiro Shimizu 890ddd
					argv[argc - j] = argv[oldArgc - j];
Toshihiro Shimizu 890ddd
			fetchArguments(ul, i + 1, b, argc, argv);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool UsageImp::matchSwitcher(const UsageLine &ul) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int i = 0; i < ul.getCount(); i++)
Toshihiro Shimizu 890ddd
		if (ul[i]->isSwitcher() &&
Toshihiro Shimizu 890ddd
			!ul[i]->isSelected())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool UsageImp::hasSwitcher(const UsageLine &ul) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (int i = 0; i < ul.getCount(); i++)
Toshihiro Shimizu 890ddd
		if (ul[i]->isSwitcher())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool UsageImp::matchArgCount(const UsageLine &ul,
Toshihiro Shimizu 890ddd
							 int a, int b, int argc) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int n = 0;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = a; i <= b; i++) {
Toshihiro Shimizu 890ddd
		if (ul[i] == &bra || ul[i]->isMultiArgument())
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		if (ul[i]->isArgument())
Toshihiro Shimizu 890ddd
			n++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i > b)
Toshihiro Shimizu 890ddd
		return argc == n;
Toshihiro Shimizu 890ddd
	else if (ul[i] == &bra) {
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = b; j > i && ul[j] != &ket; j--)
Toshihiro Shimizu 890ddd
			if (ul[j]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		assert(j > i + 1);
Toshihiro Shimizu 890ddd
		if (n == argc)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		else if (n > argc)
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return matchArgCount(ul, i + 1, j - 1, argc - n);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		assert(ul[i]->isMultiArgument());
Toshihiro Shimizu 890ddd
		n++;
Toshihiro Shimizu 890ddd
		for (i++; i <= b; i++)
Toshihiro Shimizu 890ddd
			if (ul[i]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		return argc >= n;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::getArgCountRange(const UsageLine &ul, int a, int b,
Toshihiro Shimizu 890ddd
								int &min, int &max) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	min = max = 0;
Toshihiro Shimizu 890ddd
	int n = 0;
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = a; i <= b; i++) {
Toshihiro Shimizu 890ddd
		if (ul[i] == &bra || ul[i]->isMultiArgument())
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		if (ul[i]->isArgument())
Toshihiro Shimizu 890ddd
			n++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (i > b) {
Toshihiro Shimizu 890ddd
		min = max = n;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else if (ul[i] == &bra) {
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = b; j > i && ul[j] != &ket; j--)
Toshihiro Shimizu 890ddd
			if (ul[j]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		assert(j > i + 1);
Toshihiro Shimizu 890ddd
		min = max = n;
Toshihiro Shimizu 890ddd
		int lmin, lmax;
Toshihiro Shimizu 890ddd
		getArgCountRange(ul, i + 1, j - 1, lmin, lmax);
Toshihiro Shimizu 890ddd
		if (lmax == InfiniteArgCount)
Toshihiro Shimizu 890ddd
			max = InfiniteArgCount;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			max += lmax;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		assert(ul[i]->isMultiArgument());
Toshihiro Shimizu 890ddd
		n++;
Toshihiro Shimizu 890ddd
		for (i++; i <= b; i++)
Toshihiro Shimizu 890ddd
			if (ul[i]->isArgument())
Toshihiro Shimizu 890ddd
				n++;
Toshihiro Shimizu 890ddd
		min = n;
Toshihiro Shimizu 890ddd
		max = InfiniteArgCount;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::dumpValues(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_selectedUsageLine == 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	cout << "selected usage: ";
Toshihiro Shimizu 890ddd
	printUsageLine(out, *m_selectedUsageLine);
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_qlist.size(); i++)
Toshihiro Shimizu 890ddd
		m_qlist[i]->dumpValue(out);
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_args.size(); i++)
Toshihiro Shimizu 890ddd
		m_args[i]->dumpValue(out);
Toshihiro Shimizu 890ddd
	out << endl
Toshihiro Shimizu 890ddd
		<< endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void UsageImp::resetValues()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_qlist.size(); i++)
Toshihiro Shimizu 890ddd
		m_qlist[i]->resetValue();
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_args.size(); i++)
Toshihiro Shimizu 890ddd
		m_args[i]->resetValue();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// Usage
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Usage::Usage(string progName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp = new UsageImp(progName);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Usage::~Usage()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Usage::add(const UsageLine &ul)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->add(ul);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Usage::print(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->print(out);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Usage::dumpValues(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->dumpValues(out);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Usage::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Usage::parse(const char *argvString, ostream &err)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string s = string(argvString);
Toshihiro Shimizu 890ddd
	std::vector<char *=""> argv;</char>
Toshihiro Shimizu 890ddd
	int len = s.size();
Toshihiro Shimizu 890ddd
	for (int i = 0; i < len;) {
Toshihiro Shimizu 890ddd
		while (s[i] == ' ' || s[i] == '\t')
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
		if (i < len)
Toshihiro Shimizu 890ddd
			argv.push_back(&s[i]);
Toshihiro Shimizu 890ddd
		while (i < len && !(s[i] == ' ' || s[i] == '\t'))
Toshihiro Shimizu 890ddd
			i++;
Toshihiro Shimizu 890ddd
		if (i < len)
Toshihiro Shimizu 890ddd
			s[i++] = '\0';
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return parse(argv.size(), &argv[0], err);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Usage::parse(int argc, char *argv[], ostream &err)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		m_imp->parse(argc, argv);
Toshihiro Shimizu 890ddd
		if (help) {
Toshihiro Shimizu 890ddd
			print(err);
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (release) {
Toshihiro Shimizu 890ddd
			printToonzRelease(err);
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (libRelease) {
Toshihiro Shimizu 890ddd
			printLibRelease(err);
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	} catch (UsageError e) {
Toshihiro Shimizu 890ddd
		err << "Usage error: " << e.getError() << endl;
Toshihiro Shimizu 890ddd
		m_imp->printUsageLines(err);
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// RangeQualifier
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RangeQualifier::RangeQualifier()
Toshihiro Shimizu 890ddd
	: Qualifier("-range from to | -frame fr",
Toshihiro Shimizu 890ddd
				"frame range"),
Toshihiro Shimizu 890ddd
	  m_from(0), m_to(-1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RangeQualifier::fetch(int index, int &argc, char *argv[])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(index < argc);
Toshihiro Shimizu 890ddd
	string qname(argv[index]);
Toshihiro Shimizu 890ddd
	fetchElement(index, argc, argv);
Toshihiro Shimizu 890ddd
	if (qname == "-range") {
Toshihiro Shimizu 890ddd
		fetchElement(m_from, index, argc, argv);
Toshihiro Shimizu 890ddd
		fetchElement(m_to, index, argc, argv);
Toshihiro Shimizu 890ddd
	} else if (qname == "-frame") {
Toshihiro Shimizu 890ddd
		fetchElement(m_from, index, argc, argv);
Toshihiro Shimizu 890ddd
		m_to = m_from;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		assert(0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ostream &operator<<(ostream &out, const RangeQualifier &range)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return out << "[" << range.getFrom() << ", " << range.getTo() << "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RangeQualifier::dumpValue(ostream &out) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	out << m_name << " = ";
Toshihiro Shimizu 890ddd
	if (m_from <= m_to)
Toshihiro Shimizu 890ddd
		out << m_from << ", " << m_to;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		out << "undefined";
Toshihiro Shimizu 890ddd
	out << endl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RangeQualifier::resetValue()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_from = 0;
Toshihiro Shimizu 890ddd
	m_to = -1;
Toshihiro Shimizu 890ddd
	m_selected = false;
Toshihiro Shimizu 890ddd
}