⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmdoptns.cpp

📁 贡献一份commoncpp2,有兴趣的可以研究一下
💻 CPP
字号:
// Copyright (C) 2001-2005 Gianni Mariani//// This program 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.//// This program 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 this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// As a special exception, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  This exception does not however    // invalidate any other reasons why the executable file might be covered by// the GNU General Public License.    //// This exception applies only to the code released under the name GNU// Common C++.  If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way.  To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//// // cmdoptns.cpp //#include <cc++/config.h>#include <cc++/string.h>#include <cc++/thread.h>#include <cc++/exception.h>#include <cc++/export.h>#include <cc++/cmdoptns.h>#ifndef HAVE_GETOPT_LONG// fix problem with vc++ library#undef __argc#undef __argv#include "getopt.h"#else#include <getopt.h>#endif#ifndef WIN32#include <unistd.h>#endif#include <cstdlib>#include <iostream>#include <fstream>using std::fstream;#ifdef	CCXX_NAMESPACESnamespace ost {#endif//// In most cases, users will use this default option list.//CommandOption * defaultCommandOptionList = 0;CommandOption::CommandOption(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	OptionType		  inOptionType,	bool			  inRequired,	CommandOption  ** ppNext)	:	optionName( inOptionName ),		optionLetter( inOptionLetter ),		description( inDescription ),		optionType( inOptionType ),		required( inRequired ),		next( * ppNext ){	* ppNext = this;}CommandOptionWithArg::CommandOptionWithArg(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	OptionType		  inOptionType,	bool			  inRequired,	CommandOption  ** ppNext)	: CommandOption(		inOptionName,		inOptionLetter,		inDescription,		inOptionType,		inRequired,		ppNext	), values( 0 ), numValue( 0 ){}CommandOptionArg::CommandOptionArg(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	bool			  inRequired,	CommandOption  ** ppNext)	: CommandOptionWithArg(		inOptionName,		inOptionLetter,		inDescription,		hasArg,		inRequired,		ppNext	){}CommandOptionRest::CommandOptionRest(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	bool			  inRequired,	CommandOption  ** ppNext)	: CommandOptionWithArg(		inOptionName,		inOptionLetter,		inDescription,		trailing,		inRequired,		ppNext	){}CommandOptionCollect::CommandOptionCollect(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	bool			  inRequired,	CommandOption  ** ppNext)	: CommandOptionWithArg(		inOptionName,		inOptionLetter,		inDescription,		collect,		inRequired,		ppNext	){}CommandOptionNoArg::CommandOptionNoArg(	const char		* inOptionName,	const char		* inOptionLetter,	const char		* inDescription,	bool			  inRequired,	CommandOption  ** ppNext)	: CommandOption(		inOptionName,		inOptionLetter,		inDescription,		noArg,		inRequired,		ppNext	), numSet( 0 ){}// ======== CommandOption =============================================// PURPOSE://	CommandOption dummy methods ..//void CommandOption::parseDone( CommandOptionParse * cop ){}void CommandOption::foundOption( CommandOptionParse * cop, const char * value){}void CommandOption::foundOption( CommandOptionParse * cop, const char ** value, int num ){}void CommandOption::performTask( CommandOptionParse * cop ){}	bool CommandOption::hasValue(){	return true;}CommandOption::~CommandOption(){}CommandOptionWithArg::~CommandOptionWithArg(){	if ( values ) {		free( values );		values = 0;	}}CommandOptionParse::~CommandOptionParse(void){}// ======== CommandOptionArg ==========================================// PURPOSE://	Methods for CommandOptionArg//bool CommandOptionWithArg::hasValue(){	return numValue > 0;}CommandOptionArg::~CommandOptionArg(){}	////static void my_alloc( char *** vals, int num, int incr ){	int	num_alloc = 0;	if ( * vals ) {		num_alloc = num | 3;	}	if ( ( incr + num ) > num_alloc ) {		int newsiz = ( incr + num ) | 3;		* vals = ( char ** ) realloc( * vals, sizeof( ** vals ) * newsiz );	}}void CommandOptionWithArg::foundOption( CommandOptionParse * cop, const char * value ){	if ( value ) {		my_alloc( ( char *** ) & values, numValue ? numValue + 1 : 0, 1 );		values[ numValue ++ ] = value;		values[ numValue ] = 0;	}}void CommandOptionWithArg::foundOption( CommandOptionParse * cop, const char ** value, int num ){	my_alloc( ( char *** ) & values, numValue ? numValue + 1 : 0, num + 1 );	int	j = 0;	for ( int i = numValue; j < num; i ++, j ++ ) {		values[ i ] = value[ j ];	}	numValue += num;	values[ numValue ] = 0;}void CommandOptionNoArg::foundOption( CommandOptionParse * cop, const char * value){	numSet ++;}// ======== CommandOptionParse ========================================// PURPOSE://	methods for CommandOptionParse//class CommandOptionParse_impl : public CommandOptionParse {public:	char			* comment;	int				  num_options;	struct option   * long_options;	CommandOption  ** opt_list;	CommandOption  ** co_list;	char		    * optstring;	int		argc;	char		** argv;	bool		has_err;	char		* fail_arg;	bool		usage_string_set;	bool		required_errors_set;	String		error_msgs;	CommandOption	* fail_option;	CommandOption	* trailing;	String			  usage_string;	virtual ~CommandOptionParse_impl()	{		delete[] opt_list;		delete[] co_list;		delete[] optstring;		delete[] long_options;	}	CommandOptionParse_impl(		int				in_argc,		char		 ** in_argv,		char		  * in_comment,		CommandOption * options	) :		comment( in_comment ),		argc( in_argc ),		argv( in_argv ),		has_err( false ),		fail_arg( 0 ),		usage_string_set( false ),		required_errors_set( false ),		error_msgs( "" ),		fail_option( 0 ),		trailing(0)	{		// First need to count all options.		CommandOption		* to = options;		int					  ocnt = 0;		int					  ccnt = 0;		int					  flag;		while ( to ) {			if ( to->optionName ) ocnt ++;			ccnt ++;			to = to->next;		}		num_options = ccnt;#ifdef	__KCC		co_list = new (CommandOption **)[ocnt];		opt_list = new (CommandOption **)[ccnt];#else		// fix compiling bug in vc++		typedef CommandOption* PCommandOption;		co_list = new PCommandOption[ocnt];		opt_list = new PCommandOption[ccnt];#endif		long_options = new option[ccnt+1];		optstring = new char[ 2*ccnt+2 ];		// initialize the last option count		long_options[ ocnt ].name = 0;		long_options[ ocnt ].has_arg = 0;		long_options[ ocnt ].flag = 0;		long_options[ ocnt ].val = 0;				char	*tos = optstring;		*(tos++) = '+';		to = options;		while ( to ) {			if ( to->optionType == CommandOption::trailing ) {				if ( ! trailing ) {					trailing = to;				}			} else if ( to->optionType == CommandOption::collect ) {				trailing = to;			}			opt_list[ -- ccnt ] = to;			if ( to->optionName ) {				-- ocnt;				co_list[ ocnt ] = to;				long_options[ ocnt ].name = to->optionName;				long_options[ ocnt ].has_arg = to->optionType == CommandOption::hasArg;				long_options[ ocnt ].flag = & flag;				long_options[ ocnt ].val = ocnt;			}			if (  to->optionLetter && to->optionLetter[ 0 ] ) {				* tos ++ = to->optionLetter[ 0 ];				if ( to->optionType == CommandOption::hasArg ) {					* tos ++ = ':';				}			}						to = to->next;		}		* tos = 0;		int c;		int optionIndex;		opterr = 0;	// tell getopt_long not to print any errors		flag = -1;		while ( optind < argc ) {			if (				(					c = getopt_long(						argc, argv, optstring, long_options, &optionIndex					)				) == -1			) {				if ( ! trailing ) {					break;				} else if ( trailing->optionType == CommandOption::trailing ) {					break;				} else {					optarg = argv[ optind ];					optind ++;					to = trailing;				}			} else if ( flag != -1 ) {				to = co_list[ flag ];				flag = -1;			} else if ( c == '?' ) {				if ( optind < 2 ) {					fail_arg = argv[ optind ];				} else {					fail_arg = argv[ optind - 1 ];				}								has_err = true;				return;							} else {				// need to search through the options.				for ( int i = 0; i < num_options; i ++ ) {					to = opt_list[ i ];					if ( ! to->optionLetter ) continue;										if ( c == to->optionLetter[ 0 ] ) {						break;					}				}				// assert( to );			}			// do we terminate here ?			if ( to->optionType == CommandOption::trailing ) {				break;			}			if ( c != ':' ) {				to->foundOption( this, optarg );			} else {				has_err = true;				fail_option = to;				break;			}						}		if ( optind < argc ) {			if ( trailing ) {				trailing->foundOption(					this,					( const char ** ) ( argv + optind ),					argc - optind				);			} else {				has_err = true;				fail_arg = argv[ optind ];			}		}		// Now check to see that all required args made it !		for ( int i = 0; i < num_options; i ++ ) {			CommandOption	* toq = opt_list[ i ];			// Tell this parameter that it's done now.			toq->parseDone( this );						if ( toq->required && ! toq->hasValue() ) {				has_err = true;				break;			}		}			}		bool	argsHaveError();	virtual const char * printUsage();	virtual const char * printErrors();	void makePrintErrors()	{		if ( required_errors_set ) return;		required_errors_set = true;		if ( fail_arg ) {			error_msgs = error_msgs + "Unknown/malformed option '" + fail_arg + "' \n";		} else if ( fail_option ) {			String name;			bool name_msg;			if ( fail_option->optionName ) {				name_msg = true;				name = fail_option->optionName;			} else if ( fail_option->optionLetter ) {				name_msg = true;				name = fail_option->optionLetter;			} else if ( fail_option == trailing ) {				name_msg = false;			} else {				name = "--option with no name--";				name_msg = true;			}			if ( name_msg ) {				error_msgs = error_msgs + "Option '" + name + "' requires value\n";			}		} else if ( has_err ) {			// loop thru all required args						for ( int i = 0; i < num_options; i ++ ) {				CommandOption	* to = opt_list[ i ];					if ( to->required && ! to->hasValue() ) {					error_msgs = error_msgs + "Value required for option '";										if ( to->optionName ) {						error_msgs = error_msgs + "--" + to->optionName;					} else if ( to->optionLetter && to->optionLetter[ 0 ] ) {						error_msgs = error_msgs + '-' + to->optionLetter[ 0 ];					} else {						error_msgs = error_msgs + to->description;					}					error_msgs = error_msgs + "' is missing\n";				}			}				}	}		void makePrintUsage()	{		if ( usage_string_set ) return;		String	str( "" );				String	str_argv0 = argv[ 0 ];		str = str + "Usage : ";		String::size_type slashpos = str_argv0.rfind('/');		if ( slashpos > str_argv0.length() ) {			slashpos = 0;		} else {			slashpos ++;		}		str.append( str_argv0, slashpos, str_argv0.length() - slashpos );		str = str + ' ' + comment + '\n';				for ( int i = 0; i < num_options; i ++ ) {			CommandOption	* to = opt_list[ i ];			char			* begin = "\t";			char			* obegin = "\t";			to = opt_list[ i ];			if ( to->optionLetter && to->optionLetter[ 0 ] ) {				str = str + begin + '-' + to->optionLetter[ 0 ];				begin = ", ";				obegin = " - ";			}						if ( to->optionName ) {				str = str + begin + "--" + to->optionName;				begin = ", ";				obegin = " - ";			}			if ( to->optionType == CommandOption::hasArg ) {				str = str + begin + " <value>";			} else if ( to->optionType == CommandOption::trailing ) {				str = str + begin + " <rest of command...>";			} else if ( to->optionType == CommandOption::collect ) {				str = str + begin + " <...>";			}			str = str + obegin + to->description + "\n";		}		usage_string = str;	}    virtual void registerError( const char * errMsg )	{		error_msgs = error_msgs + errMsg + '\n';		has_err = true;	}	virtual void performTask()	{		for ( int i = 0; i < num_options; i ++ ) {			CommandOption	* to = opt_list[ i ];			// Each parameter has this invoked			to->performTask( this );					}	}};CommandOptionParse * makeCommandOptionParse(	int				   argc,	char			** argv,	char			 * comment,	CommandOption	 * options) {	return new CommandOptionParse_impl( argc, argv, comment, options );}bool	CommandOptionParse_impl::argsHaveError(){	return has_err;}const char * CommandOptionParse_impl::printUsage(){	makePrintUsage();	return usage_string.c_str();}const char * CommandOptionParse_impl::printErrors()	{	makePrintErrors();	return error_msgs.c_str();}#ifdef	CCXX_NAMESPACES}#endif/** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -