[8] | 1 | /*
|
---|
| 2 | * TOPPERS Software
|
---|
| 3 | * Toyohashi Open Platform for Embedded Real-Time Systems
|
---|
| 4 | *
|
---|
| 5 | * Copyright (C) 2007-2009 by TAKAGI Nobuhisa
|
---|
| 6 | * Copyright (C) 2010 by Meika Sugimoto
|
---|
| 7 | *
|
---|
| 8 | * ãLì ÒÍCȺÌ(1)`(4)Ìðð½·êÉÀèC{\tgEF
|
---|
| 9 | * Ai{\tgEFAðüϵ½àÌðÜÞDȺ¯¶jðgpE¡»Eü
|
---|
| 10 | * ÏEÄzziȺCpÆÄÔj·é±Æð³Åø·éD
|
---|
| 11 | * (1) {\tgEFAð\[XR[hÌ`Åp·éêÉÍCãLÌì
|
---|
| 12 | * \¦C±Ìpð¨æѺL̳ÛØKèªC»ÌÜÜÌ`Å\[
|
---|
| 13 | * XR[hÉÜÜêÄ¢é±ÆD
|
---|
| 14 | * (2) {\tgEFAðCCu`®ÈÇC¼Ì\tgEFAJÉg
|
---|
| 15 | * pÅ«é`ÅÄzz·éêÉÍCÄzzɺ¤hL
|
---|
| 16 | gip
|
---|
| 17 | * Ò}j
|
---|
| 18 | AÈÇjÉCãLÌì \¦C±Ìpð¨æѺL
|
---|
| 19 | * ̳ÛØKèðfÚ·é±ÆD
|
---|
| 20 | * (3) {\tgEFAðC@íÉgÝÞÈÇC¼Ì\tgEFAJÉg
|
---|
| 21 | * pÅ«È¢`ÅÄzz·éêÉÍCÌ¢¸ê©Ìðð½·±
|
---|
| 22 | * ÆD
|
---|
| 23 | * (a) Äzzɺ¤hL
|
---|
| 24 | gipÒ}j
|
---|
| 25 | AÈÇjÉCãLÌ
|
---|
| 26 | * ì \¦C±Ìpð¨æѺL̳ÛØKèðfÚ·é±ÆD
|
---|
| 27 | * (b) ÄzzÌ`ÔðCÊÉèßéû@ÉæÁÄCTOPPERSvWFNgÉ
|
---|
| 28 | * ñ·é±ÆD
|
---|
| 29 | * (4) {\tgEFAÌpÉæè¼ÚIܽÍÔÚIɶ¶é¢©Èé¹
|
---|
| 30 | * Q©çàCãLì Ò¨æÑTOPPERSvWFNgðÆÓ·é±ÆD
|
---|
| 31 | * ܽC{\tgEFAÌ[UܽÍGh[U©çÌ¢©Èé
|
---|
| 32 | * RÉîÿ©çàCãLì Ò¨æÑTOPPERSvWFNgð
|
---|
| 33 | * ÆÓ·é±ÆD
|
---|
| 34 | *
|
---|
| 35 | * {\tgEFAÍC³ÛØÅñ³êÄ¢éàÌÅ éDãLì Ò¨
|
---|
| 36 | * æÑTOPPERSvWFNgÍC{\tgEFAÉÖµÄCÁèÌgpÚI
|
---|
| 37 | * ÉηéK«àÜßÄC¢©ÈéÛØàsíÈ¢DܽC{\tgEF
|
---|
| 38 | * AÌpÉæè¼ÚIܽÍÔÚIɶ¶½¢©Èé¹QÉÖµÄàC»
|
---|
| 39 | * ÌÓCðíÈ¢D
|
---|
| 40 | *
|
---|
| 41 | */
|
---|
| 42 | #include "cfg.hpp"
|
---|
| 43 | #include <boost/program_options.hpp>
|
---|
| 44 | #include <boost/spirit.hpp>
|
---|
| 45 |
|
---|
| 46 | #include <crtdbg.h>
|
---|
| 47 |
|
---|
| 48 | namespace
|
---|
| 49 | {
|
---|
| 50 |
|
---|
| 51 | //! A±µ½XbV
|
---|
| 52 | / ðPêÌXbV
|
---|
| 53 | Éu··é
|
---|
| 54 | std::string slashes_to_single_slash( std::string const& str )
|
---|
| 55 | {
|
---|
| 56 | std::string result( str );
|
---|
| 57 | std::string::size_type pos = 0;
|
---|
| 58 | while ( ( pos = result.find( "//", pos ) ) != std::string::npos )
|
---|
| 59 | {
|
---|
| 60 | result.erase( pos, 1 );
|
---|
| 61 | }
|
---|
| 62 | return result;
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | //! N®IvVÌðÍ
|
---|
| 66 | int parse_program_options( int argc, char* argv[] )
|
---|
| 67 | {
|
---|
| 68 | namespace po = boost::program_options;
|
---|
| 69 | int pass = 0;
|
---|
| 70 |
|
---|
| 71 | // êÊIvV
|
---|
| 72 | po::options_description generic( _( "Generic options" ) );
|
---|
| 73 | generic.add_options()
|
---|
| 74 | ( "help", _( "display this information" ) )
|
---|
| 75 | ( "version,v", _( "display cfg version number" ) )
|
---|
| 76 | ;
|
---|
| 77 |
|
---|
| 78 | // ÝèIvV
|
---|
| 79 | po::options_description config( _( "Configuration" ) );
|
---|
| 80 | config.add_options()
|
---|
| 81 | ( "kernel,k", po::value< std::string >()->default_value( std::string( "atk" ) ), _( "kernel type (default: atk)" ) )
|
---|
| 82 | ( "pass,p", po::value< int >( &pass )->default_value( 0 ), _( "run for pass #`arg\'" ) )
|
---|
| 83 | ( "include-path,I", po::value< std::vector< std::string > >(), _( "include path" ) )
|
---|
| 84 | ( "template-file,T", po::value< std::string >(), _( "template file" ) )
|
---|
| 85 | ( "input-charset", po::value< std::string >()->default_value( std::string( "ascii" ) ), _( "character set of input file (default: ascii)" ) )
|
---|
| 86 | ( "api-table", po::value< std::vector< std::string > >(), _( "specify static API table" ) )
|
---|
| 87 | ( "cfg1-def-table", po::value< std::vector< std::string > >(), _( "specify cfg1 definition table" ) )
|
---|
| 88 | ( "cfg1_out", po::value< std::string >()->default_value( std::string( "cfg1_out" ) ), _( "specify file name instead of `cfg1_out.srec\' (default: cfg1_out)" ) )
|
---|
| 89 | ( "rom-image,r", po::value< std::string >(), _( "ROM image (S-record)" ) )
|
---|
| 90 | ( "symbol-table,s", po::value< std::string >(), _( "Symbol table (`nm' style)" ) )
|
---|
| 91 | ( "cfg-directory,d", po::value< std::string >(), _( "cfg directory" ) )
|
---|
| 92 | ( "msgcat-directory,m", po::value< std::vector< std::string > >(), _( "msgcat(*.po) directory" ) )
|
---|
| 93 | ( "destination-directory,n", po::value< std::string >()->default_value( "." ), _( "destination directory" ) )
|
---|
| 94 | ( "alignof-fp", po::value< std::size_t >()->default_value( 1 ), _( "alignment of pointer to function" ) )
|
---|
| 95 | ( "print-dependencies,M", po::value< std::string >(), _( "output dependencies of source file (for `make\')" ) )
|
---|
| 96 | ;
|
---|
| 97 |
|
---|
| 98 | // ñ\¦IvV
|
---|
| 99 | po::options_description hidden( _( "Hidden options" ) );
|
---|
| 100 | hidden.add_options()
|
---|
| 101 | ( "input-file,s", po::value< std::string >(), _( "input file" ) )
|
---|
| 102 | ;
|
---|
| 103 |
|
---|
| 104 | po::options_description cmdline_options;
|
---|
| 105 | cmdline_options.add( generic ).add( config ).add( hidden );
|
---|
| 106 |
|
---|
| 107 | po::options_description visible( _( "Allowed options" ) );
|
---|
| 108 | visible.add( generic ).add( config );
|
---|
| 109 |
|
---|
| 110 | po::positional_options_description p;
|
---|
| 111 | p.add( "input-file", -1 );
|
---|
| 112 |
|
---|
| 113 | po::variables_map vm;
|
---|
| 114 | try
|
---|
| 115 | {
|
---|
| 116 | store( po::command_line_parser( argc, argv ).
|
---|
| 117 | options( cmdline_options ).positional( p ).run(), vm );
|
---|
| 118 | notify( vm );
|
---|
| 119 | }
|
---|
| 120 | catch ( boost::program_options::error& )
|
---|
| 121 | {
|
---|
| 122 | toppers::fatal( _( "illegal options" ) );
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | // O[oÏÌÝè
|
---|
| 126 | if ( vm.count( "print-dependencies" ) )
|
---|
| 127 | {
|
---|
| 128 | toppers::global( "print-dependencies" ) = vm["print-dependencies"].as< std::string >();
|
---|
| 129 | pass = 1; // ˶ÖWÌoͪKvÈêA§IÉpX1ÉÏX
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | toppers::global( "pass" ) = pass;
|
---|
| 133 | if ( vm.count( "kernel" ) )
|
---|
| 134 | {
|
---|
| 135 | std::string kernel = toppers::tolower( vm["kernel"].as< std::string >() );
|
---|
| 136 | toppers::global( "kernel" ) = kernel;
|
---|
| 137 | bool has_class = false;
|
---|
| 138 | bool has_domain = false;
|
---|
| 139 |
|
---|
| 140 | if ( kernel == "fmp" )
|
---|
| 141 | {
|
---|
| 142 | has_class = true;
|
---|
| 143 | }
|
---|
| 144 | if ( kernel == "hrp2" )
|
---|
| 145 | {
|
---|
| 146 | has_domain = true;
|
---|
| 147 | }
|
---|
| 148 |
|
---|
| 149 | toppers::global( "max-pass" ) = ( has_domain ? 4 : 3 );
|
---|
| 150 | toppers::global( "has-class" ) = has_class;
|
---|
| 151 | toppers::global( "has-domain" ) = has_domain;
|
---|
| 152 | }
|
---|
| 153 | if ( vm.count( "include-path" ) )
|
---|
| 154 | {
|
---|
| 155 | std::vector< std::string > v( vm["include-path"].as< std::vector< std::string > >() );
|
---|
| 156 | std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
|
---|
| 157 | toppers::global( "include-path" ) = v;
|
---|
| 158 | }
|
---|
| 159 | if ( vm.count( "template-file" ) )
|
---|
| 160 | {
|
---|
| 161 | toppers::global( "template-file" )
|
---|
| 162 | = slashes_to_single_slash( vm["template-file"].as< std::string >() );
|
---|
| 163 | }
|
---|
| 164 | if ( vm.count( "input-file" ) )
|
---|
| 165 | {
|
---|
| 166 | toppers::global( "input-file" )
|
---|
| 167 | = slashes_to_single_slash( vm["input-file"].as< std::string >() );
|
---|
| 168 | }
|
---|
| 169 | if ( vm.count( "input-charset" ) )
|
---|
| 170 | {
|
---|
| 171 | std::string input_charset( toppers::tolower( vm["input-charset"].as< std::string >() ) );
|
---|
| 172 | toppers::global( "input-charset" ) = input_charset;
|
---|
| 173 |
|
---|
| 174 | toppers::codeset_t codeset = toppers::ascii;
|
---|
| 175 | if ( ( input_charset == "cp932" )
|
---|
| 176 | || ( input_charset == "shift_jis" )
|
---|
| 177 | || ( input_charset == "sjis" ) )
|
---|
| 178 | {
|
---|
| 179 | codeset = toppers::shift_jis;
|
---|
| 180 | }
|
---|
| 181 | else if ( ( input_charset == "eucjp" )
|
---|
| 182 | || ( input_charset == "euc-jp" )
|
---|
| 183 | || ( input_charset == "euc" ) )
|
---|
| 184 | {
|
---|
| 185 | codeset = toppers::euc_jp;
|
---|
| 186 | }
|
---|
| 187 | else if ( ( input_charset == "utf-8" )
|
---|
| 188 | || ( input_charset == "utf8" ) )
|
---|
| 189 | {
|
---|
| 190 | codeset = toppers::utf8;
|
---|
| 191 | }
|
---|
| 192 | toppers::global( "codeset" ) = codeset;
|
---|
| 193 | }
|
---|
| 194 | if ( vm.count( "api-table" ) )
|
---|
| 195 | {
|
---|
| 196 | std::vector< std::string > v( vm["api-table"].as< std::vector< std::string > >() );
|
---|
| 197 | std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
|
---|
| 198 | toppers::global( "api-table" ) = v;
|
---|
| 199 | }
|
---|
| 200 | if ( vm.count( "cfg1-def-table" ) )
|
---|
| 201 | {
|
---|
| 202 | std::vector< std::string > v( vm["cfg1-def-table"].as< std::vector< std::string > >() );
|
---|
| 203 | std::transform( v.begin(), v.end(), v.begin(), &slashes_to_single_slash );
|
---|
| 204 | toppers::global( "cfg1-def-table" ) = v;
|
---|
| 205 | }
|
---|
| 206 | if ( vm.count( "cfg1_out" ) )
|
---|
| 207 | {
|
---|
| 208 | toppers::global( "cfg1_out" ) = vm["cfg1_out"].as< std::string >();
|
---|
| 209 | }
|
---|
| 210 | else
|
---|
| 211 | {
|
---|
| 212 | toppers::global( "cfg1_out" ) = std::string( "cfg1_out" );
|
---|
| 213 | }
|
---|
| 214 | if ( vm.count( "cfg-directory" ) )
|
---|
| 215 | {
|
---|
| 216 | std::string cfg_directory( vm["cfg-directory"].as< std::string >() );
|
---|
| 217 | toppers::global( "cfg-directory" ) = slashes_to_single_slash( cfg_directory );
|
---|
| 218 | toppers::load_msgcat( cfg_directory );
|
---|
| 219 | }
|
---|
| 220 | if ( vm.count( "msgcat-directory" ) )
|
---|
| 221 | {
|
---|
| 222 | std::vector< std::string > msgcat_dirs( vm["msgcat-directory"].as< std::vector< std::string > >() );
|
---|
| 223 | std::transform( msgcat_dirs.begin(), msgcat_dirs.end(), msgcat_dirs.begin(), &slashes_to_single_slash );
|
---|
| 224 | std::for_each( msgcat_dirs.begin(), msgcat_dirs.end(), &toppers::load_msgcat );
|
---|
| 225 | }
|
---|
| 226 | if ( true ) // include-path ðóɵÄÍÈçÈ¢
|
---|
| 227 | {
|
---|
| 228 | std::vector< std::string > include_path;
|
---|
| 229 | boost::any t( toppers::global( "include-path" ) );
|
---|
| 230 | if ( !t.empty() )
|
---|
| 231 | {
|
---|
| 232 | include_path = boost::any_cast< std::vector< std::string > >( t );
|
---|
| 233 | }
|
---|
| 234 | include_path.push_back( toppers::get_global< std::string >( "cfg-directory" ) );
|
---|
| 235 | toppers::global( "include-path" ) = include_path;
|
---|
| 236 | }
|
---|
| 237 | if ( vm.count( "output-directory" ) )
|
---|
| 238 | {
|
---|
| 239 | toppers::global( "output-directory" ) = slashes_to_single_slash( vm["output-directory"].as< std::string >() );
|
---|
| 240 | }
|
---|
| 241 | if ( vm.count( "rom-image" ) )
|
---|
| 242 | {
|
---|
| 243 | toppers::global( "rom-image" ) = slashes_to_single_slash( vm["rom-image"].as< std::string >() );
|
---|
| 244 | }
|
---|
| 245 | if ( vm.count( "symbol-table" ) )
|
---|
| 246 | {
|
---|
| 247 | toppers::global( "symbol-table" ) = slashes_to_single_slash( vm["symbol-table"].as< std::string >() );
|
---|
| 248 | }
|
---|
| 249 | else
|
---|
| 250 | {
|
---|
| 251 | toppers::global( "symbol-table" ) = toppers::get_global< std::string >( "kernel" ) + ".syms";
|
---|
| 252 | }
|
---|
| 253 | if ( vm.count( "id-output-file" ) )
|
---|
| 254 | {
|
---|
| 255 | toppers::global( "id-output-file" ) = slashes_to_single_slash( vm["id-output-file"].as< std::string >() );
|
---|
| 256 | }
|
---|
| 257 | if ( vm.count( "id-input-file" ) )
|
---|
| 258 | {
|
---|
| 259 | toppers::global( "id-input-file" ) = slashes_to_single_slash( vm["id-input-file"].as< std::string >() );
|
---|
| 260 | }
|
---|
| 261 | if ( vm.count( "alignof-fp" ) )
|
---|
| 262 | {
|
---|
| 263 | toppers::global( "alignof-fp" ) = vm["alignof-fp"].as< std::size_t >();
|
---|
| 264 | }
|
---|
| 265 | toppers::global( "external-id" ) = vm.count( "external-id" ) ? true : false;
|
---|
| 266 |
|
---|
| 267 | toppers::global( "version" ) = std::string( CFG_VERSION );
|
---|
| 268 |
|
---|
| 269 | if ( vm.count( "version" ) )
|
---|
| 270 | {
|
---|
| 271 | std::cout << "TOPPERS Kernel Configurator version " << CFG_VERSION << std::endl;
|
---|
| 272 | toppers::global( "pass0" ) = true;
|
---|
| 273 | }
|
---|
| 274 | if ( vm.count( "help" ) )
|
---|
| 275 | {
|
---|
| 276 | toppers::global( "help" ) = boost::lexical_cast< std::string >( visible );
|
---|
| 277 | std::cout << visible << std::endl;
|
---|
| 278 | toppers::global( "pass0" ) = true;
|
---|
| 279 | }
|
---|
| 280 | return pass;
|
---|
| 281 | }
|
---|
| 282 |
|
---|
| 283 | }
|
---|
| 284 |
|
---|
| 285 | //! RtBM
|
---|
| 286 | [^ÌC
|
---|
| 287 | int cfg_main( int argc, char* argv[] )
|
---|
| 288 | {
|
---|
| 289 | using namespace toppers;
|
---|
| 290 |
|
---|
| 291 | std::string const cfg_path( argv[0] );
|
---|
| 292 | std::string const cfg_name( "cfg" );
|
---|
| 293 | std::string::const_iterator iter = std::find_end( cfg_path.begin(), cfg_path.end(), cfg_name.begin(), cfg_name.end() );
|
---|
| 294 | // «ÏÌT[`ÜÅÍsíÈ¢
|
---|
| 295 | std::string cfg_dir( cfg_path.begin(), iter );
|
---|
| 296 | if ( *cfg_dir.rbegin() == '/' || *cfg_dir.rbegin() == '\\' )
|
---|
| 297 | {
|
---|
| 298 | cfg_dir.resize( cfg_dir.size() - 1 );
|
---|
| 299 | }
|
---|
| 300 | toppers::global( "cfg-directory" ) = cfg_dir;
|
---|
| 301 | toppers::global( "argv0" ) = std::string( argv[ 0 ] ); // vO¼
|
---|
| 302 | toppers::global( "timestamp" ) = cfg_timestamp(); // ^CX^v
|
---|
| 303 |
|
---|
| 304 | int pass = parse_program_options( argc, argv );
|
---|
| 305 | bool ( * pfn_cfg[] )() = { &cfg0_main, &cfg1_main, &cfg2_main, };
|
---|
| 306 | int max_pass = toppers::get_global< int >( "max-pass" );
|
---|
| 307 |
|
---|
| 308 | if ( pass < 0 || max_pass < pass )
|
---|
| 309 | {
|
---|
| 310 | fatal( _( "illegal cfg pass #%d" ), pass );
|
---|
| 311 | }
|
---|
| 312 |
|
---|
| 313 | if ( !( *pfn_cfg[ pass ] )() )
|
---|
| 314 | {
|
---|
| 315 | return EXIT_FAILURE;
|
---|
| 316 | }
|
---|
| 317 | return EXIT_SUCCESS;
|
---|
| 318 | }
|
---|
| 319 |
|
---|
| 320 | int main( int arg, char* argv[] )
|
---|
| 321 | {
|
---|
| 322 | int status;
|
---|
| 323 |
|
---|
| 324 | // [N¸pÌú»
|
---|
| 325 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
---|
| 326 |
|
---|
| 327 | try
|
---|
| 328 | {
|
---|
| 329 | toppers::set_program_name( "cfg" );
|
---|
| 330 | status = cfg_main( arg, argv );
|
---|
| 331 | if ( status != EXIT_SUCCESS && toppers::get_error_count() == 0 )
|
---|
| 332 | {
|
---|
| 333 | std::fprintf( stderr, "cfg: %s\n", _( "unknown error" ) );
|
---|
| 334 | }
|
---|
| 335 | if ( toppers::get_error_count() > 0 )
|
---|
| 336 | {
|
---|
| 337 | status = EXIT_FAILURE;
|
---|
| 338 | }
|
---|
| 339 | }
|
---|
| 340 | catch ( toppers::normal_exit& )
|
---|
| 341 | {
|
---|
| 342 | status = EXIT_SUCCESS;
|
---|
| 343 | }
|
---|
| 344 | catch ( std::exception& e )
|
---|
| 345 | {
|
---|
| 346 | std::fprintf( stderr, "cfg: %s\n", e.what() );
|
---|
| 347 | status = EXIT_FAILURE;
|
---|
| 348 | }
|
---|
| 349 | catch ( ... )
|
---|
| 350 | {
|
---|
| 351 | std::fprintf( stderr, "cfg: %s\n", _( "internal error" ) );
|
---|
| 352 | status = EXIT_FAILURE;
|
---|
| 353 | }
|
---|
| 354 | return status;
|
---|
| 355 | }
|
---|