summaryrefslogtreecommitdiff
path: root/boost/test/utils/runtime/cla/parser.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/test/utils/runtime/cla/parser.ipp')
-rw-r--r--boost/test/utils/runtime/cla/parser.ipp258
1 files changed, 258 insertions, 0 deletions
diff --git a/boost/test/utils/runtime/cla/parser.ipp b/boost/test/utils/runtime/cla/parser.ipp
new file mode 100644
index 0000000000..995411a73f
--- /dev/null
+++ b/boost/test/utils/runtime/cla/parser.ipp
@@ -0,0 +1,258 @@
+// (C) Copyright Gennadiy Rozental 2005-2008.
+// Use, modification, and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+// File : $RCSfile$
+//
+// Version : $Revision: 54633 $
+//
+// Description : implements parser - public interface for CLA parsing and accessing
+// ***************************************************************************
+
+#ifndef BOOST_RT_CLA_PARSER_IPP_062904GER
+#define BOOST_RT_CLA_PARSER_IPP_062904GER
+
+// Boost.Runtime.Parameter
+#include <boost/test/utils/runtime/config.hpp>
+#include <boost/test/utils/runtime/trace.hpp>
+#include <boost/test/utils/runtime/argument.hpp>
+
+#include <boost/test/utils/runtime/cla/argv_traverser.hpp>
+#include <boost/test/utils/runtime/cla/parameter.hpp>
+#include <boost/test/utils/runtime/cla/modifier.hpp>
+#include <boost/test/utils/runtime/cla/validation.hpp>
+#include <boost/test/utils/runtime/cla/parser.hpp>
+
+// Boost.Test
+#include <boost/test/utils/basic_cstring/io.hpp>
+#include <boost/test/utils/foreach.hpp>
+
+// Boost
+#include <boost/lexical_cast.hpp>
+
+namespace boost {
+
+namespace BOOST_RT_PARAM_NAMESPACE {
+
+namespace cla {
+
+// ************************************************************************** //
+// ************** runtime::cla::parser ************** //
+// ************************************************************************** //
+
+BOOST_RT_PARAM_INLINE
+parser::parser( cstring program_name )
+{
+ assign_op( m_program_name, program_name, 0 );
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE parser::param_iterator
+parser::first_param() const
+{
+ return m_parameters.begin();
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE parser::param_iterator
+parser::last_param() const
+{
+ return m_parameters.end();
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE argument const&
+parser::valid_argument( cstring string_id ) const
+{
+ const_argument_ptr arg = (*this)[string_id];
+
+ BOOST_RT_PARAM_VALIDATE_LOGIC( !!arg, "Actual argument for parameter " << string_id << " is not present" );
+
+ return *arg;
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE parser&
+parser::operator<<( parameter_ptr new_param )
+{
+ BOOST_TEST_FOREACH( parameter_ptr, old_param, m_parameters ) {
+ BOOST_RT_PARAM_VALIDATE_LOGIC( !old_param->conflict_with( *new_param ),
+ BOOST_RT_PARAM_LITERAL( "Definition of parameter " ) << new_param->id_2_report() <<
+ BOOST_RT_PARAM_LITERAL( " conflicts with defintion of parameter " ) << old_param->id_2_report() );
+ }
+
+ m_parameters.push_back( new_param );
+
+ return *this;
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE void
+parser::parse( int& argc, char_type** argv )
+{
+ if( m_program_name.empty() ) {
+ m_program_name.assign( argv[0] );
+ dstring::size_type pos = m_program_name.find_last_of( BOOST_RT_PARAM_LITERAL( "/\\" ) );
+
+ if( pos != static_cast<dstring::size_type>(cstring::npos) )
+ m_program_name.erase( 0, pos+1 );
+ }
+
+ m_traverser.init( argc, argv );
+
+ try {
+ while( !m_traverser.eoi() ) {
+ parameter_ptr found_param;
+
+ BOOST_RT_PARAM_TRACE( "Total " << m_parameters.size() << " parameters registered" );
+
+ BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
+ BOOST_RT_PARAM_TRACE( "Try parameter " << curr_param->id_2_report() );
+
+ if( curr_param->matching( m_traverser, !found_param ) ) {
+ BOOST_RT_PARAM_TRACE( "Match found" );
+ BOOST_RT_CLA_VALIDATE_INPUT( !found_param, (m_traverser.rollback(),m_traverser), "Ambiguous input" );
+
+ found_param = curr_param;
+ }
+
+ m_traverser.rollback();
+ }
+
+ if( !found_param ) {
+ BOOST_RT_PARAM_TRACE( "No match found" );
+ BOOST_RT_CLA_VALIDATE_INPUT( m_traverser.handle_mismatch(), m_traverser,
+ BOOST_RT_PARAM_LITERAL( "Unexpected input" ) );
+
+ continue;
+ }
+
+ BOOST_RT_PARAM_TRACE( "Parse argument value" );
+ found_param->produce_argument( m_traverser );
+
+ m_traverser.commit();
+ }
+
+ BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
+ if( !curr_param->p_optional && !curr_param->actual_argument() ) {
+ curr_param->produce_argument( *this );
+
+ BOOST_RT_PARAM_VALIDATE_LOGIC( curr_param->actual_argument(),
+ BOOST_RT_PARAM_LITERAL( "Required argument for parameter " ) << curr_param->id_2_report()
+ << BOOST_RT_PARAM_LITERAL( " is missing" ) );
+ }
+ }
+ }
+ catch( bad_lexical_cast const& ) {
+ BOOST_RT_PARAM_REPORT_LOGIC_ERROR(
+ BOOST_RT_PARAM_LITERAL( "String to value convertion error during input parsing" ) );
+ }
+
+ m_traverser.remainder( argc, argv );
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE const_argument_ptr
+parser::operator[]( cstring string_id ) const
+{
+ parameter_ptr found_param;
+
+ BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
+ if( curr_param->responds_to( string_id ) ) {
+ BOOST_RT_PARAM_VALIDATE_LOGIC( !found_param,
+ BOOST_RT_PARAM_LITERAL( "Ambiguous parameter string id: " ) << string_id );
+
+ found_param = curr_param;
+ }
+ }
+
+ return found_param ? found_param->actual_argument() : argument_ptr();
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE cstring
+parser::get( cstring string_id ) const
+{
+ return get<cstring>( string_id );
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE void
+parser::usage( out_stream& ostr )
+{
+ if( m_program_name.empty() )
+ assign_op( m_program_name, BOOST_RT_PARAM_CSTRING_LITERAL( "<program>" ), 0 );
+
+ format_stream fs;
+
+ fs << m_program_name;
+
+ BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
+ fs << BOOST_RT_PARAM_LITERAL( ' ' );
+
+ if( curr_param->p_optional )
+ fs << BOOST_RT_PARAM_LITERAL( '[' );
+
+ curr_param->usage_info( fs );
+
+ if( curr_param->p_optional )
+ fs << BOOST_RT_PARAM_LITERAL( ']' );
+
+ if( curr_param->p_multiplicable ) {
+ fs << BOOST_RT_PARAM_CSTRING_LITERAL( " ... " );
+
+ if( curr_param->p_optional )
+ fs << BOOST_RT_PARAM_LITERAL( '[' );
+
+ curr_param->usage_info( fs );
+
+ if( curr_param->p_optional )
+ fs << BOOST_RT_PARAM_LITERAL( ']' );
+ }
+ }
+
+ ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "Usage:\n" ) << fs.str() << std::endl;
+}
+
+//____________________________________________________________________________//
+
+BOOST_RT_PARAM_INLINE void
+parser::help( out_stream& ostr )
+{
+ usage( ostr );
+
+ bool need_where = true;
+
+ BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
+ if( curr_param->p_description->empty() )
+ continue;
+
+ if( need_where ) {
+ ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "where:\n" );
+ need_where = false;
+ }
+
+ ostr << curr_param->id_2_report() << BOOST_RT_PARAM_CSTRING_LITERAL( " - " ) << curr_param->p_description << std::endl;
+ }
+}
+
+//____________________________________________________________________________//
+
+} // namespace cla
+
+} // namespace BOOST_RT_PARAM_NAMESPACE
+
+} // namespace boost
+
+#endif // BOOST_RT_CLA_PARSER_IPP_062904GER