tripwire-open-source/src/core/cmdlineparser.h

268 lines
9.8 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to 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. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
///////////////////////////////////////////////////////////////////////////////
// cmdlineparser.h
//
// cCmdLineParser.h -- class that tokenizes the command line
#ifndef __CMDLINEPARSER_H
#define __CMDLINEPARSER_H
#ifndef __HASHTABLE_H
#include "hashtable.h"
#endif
#ifndef __DEBUG_H
#include "debug.h"
#endif
#ifndef __ERROR_H
#include "error.h"
#endif
//=============================================================================
// eCmdLine
//=============================================================================
TSS_EXCEPTION( eCmdLine, eError )
TSS_EXCEPTION( eCmdLineInvalidArg, eCmdLine ) // an arg on the command line is not recognized
TSS_EXCEPTION( eCmdLineBadArgParam, eCmdLine ) // wrong number of parameters to an argument
TSS_EXCEPTION( eCmdLineBadParam, eCmdLine ) // wrong number of paramters to the executable (not associated with any arguments)
TSS_EXCEPTION( eCmdLineBadSwitchPos,eCmdLine ) // a '-' arg appeared after the final parameter list
TSS_EXCEPTION( eCmdLineMutEx, eCmdLine ) // a mutual exclusion error has occured
TSS_EXCEPTION( eCmdLineDependency, eCmdLine ) // a dependency error has occurred.
TSS_EXCEPTION( eCmdLineMultiArg, eCmdLine ) // an arg was found twice in the command line
/*
// cCmdLineParser owns errors 600-699
// these can be turned into a string by using cErrorTable
enum ErrorType
{
ERR_NONE = 601, // no error
ERR_INVALID_ARG = 602, // an arg on the command line is not recognized
ERR_BAD_ARG_PARAMS = 603, // wrong number of parameters to an argument
ERR_BAD_PARAMS = 604, // wrong number of paramters to the executable (not associated with any arguments)
ERR_SWITCH_AFTER_FINAL_LIST = 605, // a '-' arg appeared after the final paramter list
ERR_MUTUAL_EXCLUSION = 606, // a mutual exclusion error has occured
ERR_MULTIPLE_ARG = 607, // an arg was found twice in the command line
ERR_INVALID // top of enum
};
// for storing error information
ErrorType mCurError;
TSTRING mCurErrorString;
void GetErrorInfo(ErrorType& et, TSTRING& errorData) const;
// returns information on the type of error that occured in a Parse() command. Only
// returns valid information if Parse() had just been called and returned false. A
// second call to Parse() might alter existing error info
*/
//=============================================================================
// cCmdLineParser
//=============================================================================
class cCmdLineParser
{
public:
cCmdLineParser();
~cCmdLineParser();
enum ParamCount
{
PARAM_NONE, // no parameters to arg
PARAM_ONE, // one parameter to arg
PARAM_MANY, // zero or more paramters to arg
PARAM_INVALID // top of enum
};
void AddArg(int argId, const TSTRING& arg, const TSTRING& alias, ParamCount numParams, bool multipleAllowed = false);
// this method should be called for each argument that can appear on the
// command line.
// argId -- a number that uniquely identifies the argument; no two arguments
// may have the same id (ASSERT-enforced)
// arg -- string that comes after the '-'. can be _T("") if there is only
// a string representation
// alias -- string that comes after '--' which has the same meaning. Can be _T("")
// if there is no alias. If both arg and alias are empty strings, then this arg
// represents the list of arguments that comes at the end of the command line
// numParams -- number of parameters that this argument needs
void AddMutEx(int argId1, int argId2);
// this adds a mutual exclusion constraint. When Parse() is called, if argId1 and
// argId2 both exist on the command line, then the parse will fail and the error
// value ERR_MUTUAL_EXCLUSION will be set.
void AddDependency(int argId1, int argId2, bool mutual = false );
// This adds a dependency constraint. When Parse() is called, if argId1
// exists on the command line independent from argId2, then the parse will fail.
// If the default param mutual is true, then the command parser will check for
// argId1 if argId2 is passed. We do this, since it is possible for one arg to
// depend on another, but have the other arg alone on the command line, legally.
void Parse(int argc, const TCHAR *const * argv); // throw eCmdLine
// after AddArg() has been called for every argument that could be processed by the
// command line, call this to tokenize argv. If the return value is false, then
// the input was invalid in some way; the actual error can be determined by calling
// GetErrorInfo() below.
void Clear();
// clear out all information that this class contains
bool LookupArgInfo(int argId, TSTRING& arg, TSTRING& alias) const;
// given an argId, fill out the strings with the argument and alias strings. Returns false
// if the argId cannot be found. This method is not very fast, so don't use it often.
#ifdef _DEBUG
void TraceContents(int dl = -1) ;
#endif
private:
void TestMutEx();
// tests for mutual exclusion violations; if it fails, the current error is set and false
// is returned.
void TestDependency();
// tests for all dependency violations.
bool ArgInList(int argId);
// returns true if an argument with the specified id already exists in the list; this is used
// to make sure the same arg doesn't appear >1 time on the command line
// for storing information on paramers
struct cArgInfo
{
int mId;
ParamCount mNumParams;
cArgInfo(int i = -1, ParamCount p = PARAM_INVALID) : mId(i), mNumParams(p) {}
};
// for storing parsed argv information
struct cArgData
{
int mId;
std::vector<TSTRING> mParams;
TSTRING mActualParam; // a string representation of what was actually on the command line
cArgData(int id = -1, const TSTRING& actualParam = TSTRING(_T(""))) : mId(id), mActualParam(actualParam) {}
};
cHashTable<TSTRING, cArgInfo> mArgTable;
cArgInfo mLastArgInfo; // info on the argument that comes at the end of the command line (with no associated '-x' or '--x')
std::list<cArgData> mArgData;
std::list<std::pair<int,int> > mMutExList; // all of the mutual exclusions
std::list< std::pair < std::pair<int,int>, bool > > mDependencyList; // all of the dependencies
std::set< int > mMultipleAllowed;
friend class cCmdLineIter;
};
///////////////////////////////////////////////////////////////////////////////
// cCmdLineIter -- used to iterate over the tokenized command line parameters;
// is only useful after cCmdLineParser::Parse() has been called.
///////////////////////////////////////////////////////////////////////////////
class cCmdLineIter
{
public:
cCmdLineIter(const cCmdLineParser& parser);
// iteration
void SeekBegin() const;
bool Done() const;
bool IsEmpty() const;
void Next() const;
bool SeekToArg(int argId) const;
// seeks to the argument with the given argId. returns
// false and Done() == true if it couldn't find it.
// access to the argument data
int ArgId() const;
// returns the id of this arg; ASSERTs if Done() == true
int NumParams() const;
// returns the number of parameters this argument has
const TSTRING& ActualParam() const;
// returns exactly what was passed on the command line (ie -- what the user typed)
const TSTRING& ParamAt(int index) const;
// returns the parameter at the specified index. ASSERTs if
// the index is out of range.
private:
const std::list<cCmdLineParser::cArgData>& mList;
mutable std::list<cCmdLineParser::cArgData>::const_iterator mIter;
};
//#############################################################################
// inline implementation
//#############################################################################
inline cCmdLineIter::cCmdLineIter(const cCmdLineParser& parser) :
mList(parser.mArgData)
{
SeekBegin();
}
inline void cCmdLineIter::SeekBegin() const
{
mIter = mList.begin();
}
inline bool cCmdLineIter::Done() const
{
return (mIter == mList.end());
}
inline bool cCmdLineIter::IsEmpty() const
{
return (mList.size() == 0);
}
inline void cCmdLineIter::Next() const
{
mIter++;
}
inline int cCmdLineIter::ArgId() const
{
ASSERT(! Done());
return mIter->mId;
}
inline int cCmdLineIter::NumParams() const
{
ASSERT(! Done());
return mIter->mParams.size();
}
inline const TSTRING& cCmdLineIter::ActualParam() const
{
ASSERT(! Done());
return mIter->mActualParam;
}
inline const TSTRING& cCmdLineIter::ParamAt(int index) const
{
ASSERT((index >= 0) && (index < NumParams()));
return mIter->mParams[index];
}
#endif