annotate DEPENDENCIES/generic/include/boost/test/utils/runtime/cla/parser.ipp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // (C) Copyright Gennadiy Rozental 2005-2008.
Chris@16 2 // Use, modification, and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 // See http://www.boost.org/libs/test for the library home page.
Chris@16 7 //
Chris@16 8 // File : $RCSfile$
Chris@16 9 //
Chris@101 10 // Version : $Revision$
Chris@16 11 //
Chris@16 12 // Description : implements parser - public interface for CLA parsing and accessing
Chris@16 13 // ***************************************************************************
Chris@16 14
Chris@16 15 #ifndef BOOST_RT_CLA_PARSER_IPP_062904GER
Chris@16 16 #define BOOST_RT_CLA_PARSER_IPP_062904GER
Chris@16 17
Chris@16 18 // Boost.Runtime.Parameter
Chris@16 19 #include <boost/test/utils/runtime/config.hpp>
Chris@16 20 #include <boost/test/utils/runtime/trace.hpp>
Chris@16 21 #include <boost/test/utils/runtime/argument.hpp>
Chris@16 22
Chris@16 23 #include <boost/test/utils/runtime/cla/argv_traverser.hpp>
Chris@16 24 #include <boost/test/utils/runtime/cla/parameter.hpp>
Chris@16 25 #include <boost/test/utils/runtime/cla/modifier.hpp>
Chris@16 26 #include <boost/test/utils/runtime/cla/validation.hpp>
Chris@16 27 #include <boost/test/utils/runtime/cla/parser.hpp>
Chris@16 28
Chris@16 29 // Boost.Test
Chris@16 30 #include <boost/test/utils/basic_cstring/io.hpp>
Chris@16 31 #include <boost/test/utils/foreach.hpp>
Chris@16 32
Chris@16 33 // Boost
Chris@16 34 #include <boost/lexical_cast.hpp>
Chris@16 35
Chris@16 36 namespace boost {
Chris@16 37
Chris@16 38 namespace BOOST_RT_PARAM_NAMESPACE {
Chris@16 39
Chris@16 40 namespace cla {
Chris@16 41
Chris@16 42 // ************************************************************************** //
Chris@16 43 // ************** runtime::cla::parser ************** //
Chris@16 44 // ************************************************************************** //
Chris@16 45
Chris@16 46 BOOST_RT_PARAM_INLINE
Chris@16 47 parser::parser( cstring program_name )
Chris@16 48 {
Chris@16 49 assign_op( m_program_name, program_name, 0 );
Chris@16 50 }
Chris@16 51
Chris@16 52 //____________________________________________________________________________//
Chris@16 53
Chris@16 54 BOOST_RT_PARAM_INLINE parser::param_iterator
Chris@16 55 parser::first_param() const
Chris@16 56 {
Chris@16 57 return m_parameters.begin();
Chris@16 58 }
Chris@16 59
Chris@16 60 //____________________________________________________________________________//
Chris@16 61
Chris@16 62 BOOST_RT_PARAM_INLINE parser::param_iterator
Chris@16 63 parser::last_param() const
Chris@16 64 {
Chris@16 65 return m_parameters.end();
Chris@16 66 }
Chris@16 67
Chris@16 68 //____________________________________________________________________________//
Chris@16 69
Chris@16 70 BOOST_RT_PARAM_INLINE argument const&
Chris@16 71 parser::valid_argument( cstring string_id ) const
Chris@16 72 {
Chris@16 73 const_argument_ptr arg = (*this)[string_id];
Chris@16 74
Chris@16 75 BOOST_RT_PARAM_VALIDATE_LOGIC( !!arg, "Actual argument for parameter " << string_id << " is not present" );
Chris@16 76
Chris@16 77 return *arg;
Chris@16 78 }
Chris@16 79
Chris@16 80 //____________________________________________________________________________//
Chris@16 81
Chris@16 82 BOOST_RT_PARAM_INLINE parser&
Chris@16 83 parser::operator<<( parameter_ptr new_param )
Chris@16 84 {
Chris@16 85 BOOST_TEST_FOREACH( parameter_ptr, old_param, m_parameters ) {
Chris@16 86 BOOST_RT_PARAM_VALIDATE_LOGIC( !old_param->conflict_with( *new_param ),
Chris@16 87 BOOST_RT_PARAM_LITERAL( "Definition of parameter " ) << new_param->id_2_report() <<
Chris@16 88 BOOST_RT_PARAM_LITERAL( " conflicts with defintion of parameter " ) << old_param->id_2_report() );
Chris@16 89 }
Chris@16 90
Chris@16 91 m_parameters.push_back( new_param );
Chris@16 92
Chris@16 93 return *this;
Chris@16 94 }
Chris@16 95
Chris@16 96 //____________________________________________________________________________//
Chris@16 97
Chris@16 98 BOOST_RT_PARAM_INLINE void
Chris@16 99 parser::parse( int& argc, char_type** argv )
Chris@16 100 {
Chris@16 101 if( m_program_name.empty() ) {
Chris@16 102 m_program_name.assign( argv[0] );
Chris@16 103 dstring::size_type pos = m_program_name.find_last_of( BOOST_RT_PARAM_LITERAL( "/\\" ) );
Chris@16 104
Chris@16 105 if( pos != static_cast<dstring::size_type>(cstring::npos) )
Chris@16 106 m_program_name.erase( 0, pos+1 );
Chris@16 107 }
Chris@16 108
Chris@16 109 m_traverser.init( argc, argv );
Chris@16 110
Chris@16 111 try {
Chris@16 112 while( !m_traverser.eoi() ) {
Chris@16 113 parameter_ptr found_param;
Chris@16 114
Chris@16 115 BOOST_RT_PARAM_TRACE( "Total " << m_parameters.size() << " parameters registered" );
Chris@16 116
Chris@16 117 BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Chris@16 118 BOOST_RT_PARAM_TRACE( "Try parameter " << curr_param->id_2_report() );
Chris@16 119
Chris@16 120 if( curr_param->matching( m_traverser, !found_param ) ) {
Chris@16 121 BOOST_RT_PARAM_TRACE( "Match found" );
Chris@16 122 BOOST_RT_CLA_VALIDATE_INPUT( !found_param, (m_traverser.rollback(),m_traverser), "Ambiguous input" );
Chris@16 123
Chris@16 124 found_param = curr_param;
Chris@16 125 }
Chris@16 126
Chris@16 127 m_traverser.rollback();
Chris@16 128 }
Chris@16 129
Chris@16 130 if( !found_param ) {
Chris@16 131 BOOST_RT_PARAM_TRACE( "No match found" );
Chris@16 132 BOOST_RT_CLA_VALIDATE_INPUT( m_traverser.handle_mismatch(), m_traverser,
Chris@16 133 BOOST_RT_PARAM_LITERAL( "Unexpected input" ) );
Chris@16 134
Chris@16 135 continue;
Chris@16 136 }
Chris@16 137
Chris@16 138 BOOST_RT_PARAM_TRACE( "Parse argument value" );
Chris@16 139 found_param->produce_argument( m_traverser );
Chris@16 140
Chris@16 141 m_traverser.commit();
Chris@16 142 }
Chris@16 143
Chris@16 144 BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Chris@16 145 if( !curr_param->p_optional && !curr_param->actual_argument() ) {
Chris@16 146 curr_param->produce_argument( *this );
Chris@16 147
Chris@16 148 BOOST_RT_PARAM_VALIDATE_LOGIC( curr_param->actual_argument(),
Chris@16 149 BOOST_RT_PARAM_LITERAL( "Required argument for parameter " ) << curr_param->id_2_report()
Chris@16 150 << BOOST_RT_PARAM_LITERAL( " is missing" ) );
Chris@16 151 }
Chris@16 152 }
Chris@16 153 }
Chris@16 154 catch( bad_lexical_cast const& ) {
Chris@16 155 BOOST_RT_PARAM_REPORT_LOGIC_ERROR(
Chris@16 156 BOOST_RT_PARAM_LITERAL( "String to value convertion error during input parsing" ) );
Chris@16 157 }
Chris@16 158
Chris@16 159 m_traverser.remainder( argc, argv );
Chris@16 160 }
Chris@16 161
Chris@16 162 //____________________________________________________________________________//
Chris@16 163
Chris@16 164 BOOST_RT_PARAM_INLINE const_argument_ptr
Chris@16 165 parser::operator[]( cstring string_id ) const
Chris@16 166 {
Chris@16 167 parameter_ptr found_param;
Chris@16 168
Chris@16 169 BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Chris@16 170 if( curr_param->responds_to( string_id ) ) {
Chris@16 171 BOOST_RT_PARAM_VALIDATE_LOGIC( !found_param,
Chris@16 172 BOOST_RT_PARAM_LITERAL( "Ambiguous parameter string id: " ) << string_id );
Chris@16 173
Chris@16 174 found_param = curr_param;
Chris@16 175 }
Chris@16 176 }
Chris@16 177
Chris@16 178 return found_param ? found_param->actual_argument() : argument_ptr();
Chris@16 179 }
Chris@16 180
Chris@16 181 //____________________________________________________________________________//
Chris@16 182
Chris@16 183 BOOST_RT_PARAM_INLINE cstring
Chris@16 184 parser::get( cstring string_id ) const
Chris@16 185 {
Chris@16 186 return get<cstring>( string_id );
Chris@16 187 }
Chris@16 188
Chris@16 189 //____________________________________________________________________________//
Chris@16 190
Chris@16 191 BOOST_RT_PARAM_INLINE void
Chris@16 192 parser::usage( out_stream& ostr )
Chris@16 193 {
Chris@16 194 if( m_program_name.empty() )
Chris@16 195 assign_op( m_program_name, BOOST_RT_PARAM_CSTRING_LITERAL( "<program>" ), 0 );
Chris@16 196
Chris@16 197 format_stream fs;
Chris@16 198
Chris@16 199 fs << m_program_name;
Chris@16 200
Chris@16 201 BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Chris@16 202 fs << BOOST_RT_PARAM_LITERAL( ' ' );
Chris@16 203
Chris@16 204 if( curr_param->p_optional )
Chris@16 205 fs << BOOST_RT_PARAM_LITERAL( '[' );
Chris@16 206
Chris@16 207 curr_param->usage_info( fs );
Chris@16 208
Chris@16 209 if( curr_param->p_optional )
Chris@16 210 fs << BOOST_RT_PARAM_LITERAL( ']' );
Chris@16 211
Chris@16 212 if( curr_param->p_multiplicable ) {
Chris@16 213 fs << BOOST_RT_PARAM_CSTRING_LITERAL( " ... " );
Chris@16 214
Chris@16 215 if( curr_param->p_optional )
Chris@16 216 fs << BOOST_RT_PARAM_LITERAL( '[' );
Chris@16 217
Chris@16 218 curr_param->usage_info( fs );
Chris@16 219
Chris@16 220 if( curr_param->p_optional )
Chris@16 221 fs << BOOST_RT_PARAM_LITERAL( ']' );
Chris@16 222 }
Chris@16 223 }
Chris@16 224
Chris@16 225 ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "Usage:\n" ) << fs.str() << std::endl;
Chris@16 226 }
Chris@16 227
Chris@16 228 //____________________________________________________________________________//
Chris@16 229
Chris@16 230 BOOST_RT_PARAM_INLINE void
Chris@16 231 parser::help( out_stream& ostr )
Chris@16 232 {
Chris@16 233 usage( ostr );
Chris@16 234
Chris@16 235 bool need_where = true;
Chris@16 236
Chris@16 237 BOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Chris@16 238 if( curr_param->p_description->empty() )
Chris@16 239 continue;
Chris@16 240
Chris@16 241 if( need_where ) {
Chris@16 242 ostr << BOOST_RT_PARAM_CSTRING_LITERAL( "where:\n" );
Chris@16 243 need_where = false;
Chris@16 244 }
Chris@16 245
Chris@16 246 ostr << curr_param->id_2_report() << BOOST_RT_PARAM_CSTRING_LITERAL( " - " ) << curr_param->p_description << std::endl;
Chris@16 247 }
Chris@16 248 }
Chris@16 249
Chris@16 250 //____________________________________________________________________________//
Chris@16 251
Chris@16 252 } // namespace cla
Chris@16 253
Chris@16 254 } // namespace BOOST_RT_PARAM_NAMESPACE
Chris@16 255
Chris@16 256 } // namespace boost
Chris@16 257
Chris@16 258 #endif // BOOST_RT_CLA_PARSER_IPP_062904GER