00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <list>
00014 #include <inttypes.h>
00015
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/Exception.h"
00018 #include "zypp/base/NonCopyable.h"
00019 #include "zypp/base/Tr1hash.h"
00020 #include "zypp/Arch.h"
00021 #include "zypp/Bit.h"
00022
00023 using std::endl;
00024
00026 namespace zypp
00027 {
00028
00030
00031
00032
00038 struct Arch::CompatEntry
00039 {
00044 typedef bit::BitField<uint64_t> CompatBits;
00045
00046 CompatEntry( const std::string & archStr_r,
00047 CompatBits::IntT idBit_r = 1 )
00048 : _idStr( archStr_r )
00049 , _archStr( archStr_r )
00050 , _idBit( idBit_r )
00051 , _compatBits( idBit_r )
00052 {}
00053
00054 CompatEntry( IdString archStr_r,
00055 CompatBits::IntT idBit_r = 1 )
00056 : _idStr( archStr_r )
00057 , _archStr( archStr_r.asString() )
00058 , _idBit( idBit_r )
00059 , _compatBits( idBit_r )
00060 {}
00061
00062 void addCompatBit( const CompatBits & idBit_r ) const
00063 {
00064 if ( idBit_r && ! (_compatBits & idBit_r) )
00065 {
00066 _compatBits |= idBit_r;
00067 }
00068 }
00069
00071 bool compatibleWith( const CompatEntry & targetEntry_r ) const
00072 {
00073 switch ( _idBit.value() )
00074 {
00075 case 0:
00076
00077 return true;
00078 break;
00079 case 1:
00080
00081 return _archStr == targetEntry_r._archStr;
00082 break;
00083 }
00084
00085 return targetEntry_r._compatBits & _idBit;
00086 }
00087
00089 int compare( const CompatEntry & rhs ) const
00090 {
00091 if ( _idBit.value() != rhs. _idBit.value() )
00092 return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 );
00093 return _archStr.compare( rhs._archStr );
00094 }
00095
00096 bool isBuiltIn() const
00097 { return( _idBit != CompatBits(1) ); }
00098
00099 IdString::IdType id() const
00100 { return _idStr.id(); }
00101
00102 IdString _idStr;
00103 std::string _archStr;
00104 CompatBits _idBit;
00105 mutable CompatBits _compatBits;
00106 };
00108
00110 inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
00111 {
00112 Arch::CompatEntry::CompatBits bit( obj._idBit );
00113 unsigned bitnum = 0;
00114 while ( bit )
00115 {
00116 ++bitnum;
00117 bit >>= 1;
00118 }
00119 return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
00120 << obj._compatBits << ' ' << obj._compatBits.value();
00121 }
00122
00124 inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00125 { return lhs._idStr == rhs._idStr; }
00127 inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00128 { return ! ( lhs == rhs ); }
00129
00131 }
00133
00134 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
00135
00137 namespace zypp
00138 {
00139
00141 namespace
00142 {
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 #define DEF_BUILTIN(A) const IdString _##A( #A );
00156 DEF_BUILTIN( noarch );
00157
00158 DEF_BUILTIN( i386 );
00159 DEF_BUILTIN( i486 );
00160 DEF_BUILTIN( i586 );
00161 DEF_BUILTIN( i686 );
00162 DEF_BUILTIN( athlon );
00163 DEF_BUILTIN( x86_64 );
00164
00165 DEF_BUILTIN( pentium3 );
00166 DEF_BUILTIN( pentium4 );
00167
00168 DEF_BUILTIN( s390 );
00169 DEF_BUILTIN( s390x );
00170
00171 DEF_BUILTIN( ppc );
00172 DEF_BUILTIN( ppc64 );
00173
00174 DEF_BUILTIN( ia64 );
00175
00176 DEF_BUILTIN( alphaev67 );
00177 DEF_BUILTIN( alphaev6 );
00178 DEF_BUILTIN( alphapca56 );
00179 DEF_BUILTIN( alphaev56 );
00180 DEF_BUILTIN( alphaev5 );
00181 DEF_BUILTIN( alpha );
00182
00183 DEF_BUILTIN( sparc64v );
00184 DEF_BUILTIN( sparcv9v );
00185 DEF_BUILTIN( sparc64 );
00186 DEF_BUILTIN( sparcv9 );
00187 DEF_BUILTIN( sparcv8 );
00188 DEF_BUILTIN( sparc );
00189
00190 DEF_BUILTIN( armv7nhl );
00191 DEF_BUILTIN( armv7hl );
00192 DEF_BUILTIN( armv7l );
00193 DEF_BUILTIN( armv6l );
00194 DEF_BUILTIN( armv5tejl );
00195 DEF_BUILTIN( armv5tel );
00196 DEF_BUILTIN( armv5l );
00197 DEF_BUILTIN( armv4tl );
00198 DEF_BUILTIN( armv4l );
00199 DEF_BUILTIN( armv3l );
00200
00201 DEF_BUILTIN( sh3 );
00202
00203 DEF_BUILTIN( sh4 );
00204 DEF_BUILTIN( sh4a );
00205 #undef DEF_BUILTIN
00206
00208
00209
00210
00218 struct ArchCompatSet : private base::NonCopyable
00219 {
00220 typedef Arch::CompatEntry CompatEntry;
00221 typedef CompatEntry::CompatBits CompatBits;
00222
00223 typedef std::tr1::unordered_set<CompatEntry> Set;
00224 typedef Set::iterator iterator;
00225 typedef Set::const_iterator const_iterator;
00226
00228 static ArchCompatSet & instance()
00229 {
00230 static ArchCompatSet _instance;
00231 return _instance;
00232 }
00233
00237 const Arch::CompatEntry & assertDef( const std::string & archStr_r )
00238 { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00240 const Arch::CompatEntry & assertDef( IdString archStr_r )
00241 { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00242
00243 const_iterator begin() const
00244 { return _compatSet.begin(); }
00245
00246 const_iterator end() const
00247 { return _compatSet.end(); }
00248
00249 struct DumpOnCompare
00250 {
00251 int operator()( const CompatEntry & lhs, const CompatEntry & rhs ) const
00252 { return lhs._idBit.value() < rhs._idBit.value(); }
00253 };
00254
00255 std::ostream & dumpOn( std::ostream & str ) const
00256 {
00257 str << "ArchCompatSet:";
00258 std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
00259 ov.sort( DumpOnCompare() );
00260 for_( it, ov.begin(), ov.end() )
00261 {
00262 str << endl << ' ' << *it;
00263 }
00264 return str;
00265 }
00266
00267 private:
00269 ArchCompatSet()
00270 {
00271
00272
00273
00274 _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
00276
00277
00278
00279
00280
00281 defCompatibleWith( _i386, _noarch );
00282 defCompatibleWith( _i486, _noarch,_i386 );
00283 defCompatibleWith( _i586, _noarch,_i386,_i486 );
00284 defCompatibleWith( _i686, _noarch,_i386,_i486,_i586 );
00285 defCompatibleWith( _athlon, _noarch,_i386,_i486,_i586,_i686 );
00286 defCompatibleWith( _x86_64, _noarch,_i386,_i486,_i586,_i686,_athlon );
00287
00288 defCompatibleWith( _pentium3, _noarch,_i386,_i486,_i586,_i686 );
00289 defCompatibleWith( _pentium4, _noarch,_i386,_i486,_i586,_i686,_pentium3 );
00290
00291 defCompatibleWith( _ia64, _noarch,_i386,_i486,_i586,_i686 );
00292
00293 defCompatibleWith( _s390, _noarch );
00294 defCompatibleWith( _s390x, _noarch,_s390 );
00295
00296 defCompatibleWith( _ppc, _noarch );
00297 defCompatibleWith( _ppc64, _noarch,_ppc );
00298
00299 defCompatibleWith( _alpha, _noarch );
00300 defCompatibleWith( _alphaev5, _noarch,_alpha );
00301 defCompatibleWith( _alphaev56, _noarch,_alpha,_alphaev5 );
00302 defCompatibleWith( _alphapca56, _noarch,_alpha,_alphaev5,_alphaev56 );
00303 defCompatibleWith( _alphaev6, _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
00304 defCompatibleWith( _alphaev67, _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
00305
00306 defCompatibleWith( _sparc, _noarch );
00307 defCompatibleWith( _sparcv8, _noarch,_sparc );
00308 defCompatibleWith( _sparcv9, _noarch,_sparc,_sparcv8 );
00309 defCompatibleWith( _sparcv9v, _noarch,_sparc,_sparcv8,_sparcv9 );
00310
00311 defCompatibleWith( _sparc64, _noarch,_sparc,_sparcv8,_sparcv9 );
00312 defCompatibleWith( _sparc64v, _noarch,_sparc,_sparcv8,_sparcv9,_sparcv9v,_sparc64 );
00313
00314 defCompatibleWith( _armv3l, _noarch );
00315 defCompatibleWith( _armv4l, _noarch,_armv3l );
00316 defCompatibleWith( _armv4tl, _noarch,_armv3l,_armv4l );
00317 defCompatibleWith( _armv5l, _noarch,_armv3l,_armv4l,_armv4tl );
00318 defCompatibleWith( _armv5tel, _noarch,_armv3l,_armv4l,_armv4tl,_armv5l );
00319 defCompatibleWith( _armv5tejl, _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel );
00320 defCompatibleWith( _armv6l, _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl );
00321 defCompatibleWith( _armv7l, _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl,_armv6l );
00322 defCompatibleWith( _armv7hl, _noarch );
00323 defCompatibleWith( _armv7nhl, _noarch, _armv7hl );
00324
00325 defCompatibleWith( _sh3, _noarch );
00326
00327 defCompatibleWith( _sh4, _noarch );
00328 defCompatibleWith( _sh4a, _noarch,_sh4 );
00329
00331
00332 }
00333
00334 private:
00340 CompatBits::IntT nextIdBit() const
00341 {
00342 if ( CompatBits::size == _compatSet.size() )
00343 {
00344
00345 INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
00346 ZYPP_THROW( Exception("Need more bits to encode architectures.") );
00347 }
00348 CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
00349 return nextBit;
00350 }
00351
00355 const CompatEntry & assertCompatSetEntry( IdString archStr_r )
00356 { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
00357
00360 void defCompatibleWith( IdString targetArch_r,
00361 IdString arch0_r,
00362 IdString arch1_r = IdString(),
00363 IdString arch2_r = IdString(),
00364 IdString arch3_r = IdString(),
00365 IdString arch4_r = IdString(),
00366 IdString arch5_r = IdString(),
00367 IdString arch6_r = IdString(),
00368 IdString arch7_r = IdString(),
00369 IdString arch8_r = IdString(),
00370 IdString arch9_r = IdString() )
00371 {
00372 const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
00373 target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
00374 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
00375 _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
00376 _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
00377 #undef _SETARG
00378 }
00379
00380 private:
00381 Set _compatSet;
00382 };
00383
00385 }
00387
00389
00390
00391
00393
00394 const Arch Arch_empty ( IdString::Empty );
00395 const Arch Arch_noarch( _noarch );
00396
00397 const Arch Arch_i386( _i386 );
00398 const Arch Arch_i486( _i486 );
00399 const Arch Arch_i586( _i586 );
00400 const Arch Arch_i686( _i686 );
00401 const Arch Arch_athlon( _athlon );
00402 const Arch Arch_x86_64( _x86_64 );
00403
00404 const Arch Arch_pentium3( _pentium3 );
00405 const Arch Arch_pentium4( _pentium4 );
00406
00407 const Arch Arch_s390( _s390 );
00408 const Arch Arch_s390x( _s390x );
00409
00410 const Arch Arch_ppc( _ppc );
00411 const Arch Arch_ppc64( _ppc64 );
00412
00413 const Arch Arch_ia64( _ia64 );
00414
00415 const Arch Arch_alphaev67( _alphaev67 );
00416 const Arch Arch_alphaev6( _alphaev6 );
00417 const Arch Arch_alphapca56( _alphapca56 );
00418 const Arch Arch_alphaev56( _alphaev56 );
00419 const Arch Arch_alphaev5( _alphaev5 );
00420 const Arch Arch_alpha( _alpha );
00421
00422 const Arch Arch_sparc64v( _sparc64v );
00423 const Arch Arch_sparc64( _sparc64 );
00424 const Arch Arch_sparcv9v( _sparcv9v );
00425 const Arch Arch_sparcv9( _sparcv9 );
00426 const Arch Arch_sparcv8( _sparcv8 );
00427 const Arch Arch_sparc( _sparc );
00428
00429 const Arch Arch_armv7nhl ( _armv7nhl );
00430 const Arch Arch_armv7hl ( _armv7hl );
00431 const Arch Arch_armv7l( _armv7l );
00432 const Arch Arch_armv6l( _armv6l );
00433 const Arch Arch_armv5tejl( _armv5tejl );
00434 const Arch Arch_armv5tel( _armv5tel );
00435 const Arch Arch_armv5l( _armv5l );
00436 const Arch Arch_armv4tl( _armv4tl );
00437 const Arch Arch_armv4l( _armv4l );
00438 const Arch Arch_armv3l( _armv3l );
00439
00440 const Arch Arch_sh3( _sh3 );
00441
00442 const Arch Arch_sh4( _sh4 );
00443 const Arch Arch_sh4a( _sh4a );
00444
00446
00447
00448
00449
00450 Arch::Arch()
00451 : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
00452 {}
00453
00454 Arch::Arch( IdString::IdType id_r )
00455 : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
00456 {}
00457
00458 Arch::Arch( const IdString & idstr_r )
00459 : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
00460 {}
00461
00462 Arch::Arch( const std::string & str_r )
00463 : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
00464 {}
00465
00466 Arch::Arch( const char * cstr_r )
00467 : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
00468 {}
00469
00470 Arch::Arch( const CompatEntry & rhs )
00471 : _entry( &rhs )
00472 {}
00473
00475
00476
00477
00478
00479 IdString Arch::idStr() const
00480 { return _entry->_idStr; }
00481
00483
00484
00485
00486
00487 const std::string & Arch::asString() const
00488 { return _entry->_archStr; }
00489
00491
00492
00493
00494
00495 bool Arch::isBuiltIn() const
00496 { return _entry->isBuiltIn(); }
00497
00499
00500
00501
00502
00503 bool Arch::compatibleWith( const Arch & targetArch_r ) const
00504 { return _entry->compatibleWith( *targetArch_r._entry ); }
00505
00507
00508
00509
00510
00511 Arch Arch::baseArch( ) const
00512 {
00513
00514 if (Arch_x86_64.compatibleWith(*this))
00515 {
00516 return Arch_x86_64;
00517 }
00518 if (Arch_sparc64v.compatibleWith(*this))
00519 {
00520 return Arch_sparc64v;
00521 }
00522 if (Arch_sparc64.compatibleWith(*this))
00523 {
00524 return Arch_sparc64;
00525 }
00526 if (Arch_ppc64.compatibleWith(*this))
00527 {
00528 return Arch_ppc64;
00529 }
00530 if (Arch_s390x.compatibleWith(*this))
00531 {
00532 return Arch_s390x;
00533 }
00534
00535 CompatSet cset( compatSet( *this ) );
00536 if ( cset.size() > 2 )
00537 {
00538 return *(++cset.rbegin());
00539 }
00540 return *this;
00541 }
00542
00544
00545
00546
00547
00548 int Arch::compare( const Arch & rhs ) const
00549 { return _entry->compare( *rhs._entry ); }
00550
00552
00553
00554
00555
00556 Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
00557 {
00558 Arch::CompatSet ret;
00559
00560 for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
00561 it != ArchCompatSet::instance().end(); ++it )
00562 {
00563 if ( it->compatibleWith( *targetArch_r._entry ) )
00564 {
00565 ret.insert( Arch(*it) );
00566 }
00567 }
00568
00569 return ret;
00570 }
00571
00573 }