libzypp  10.5.0
Arch.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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   //    CLASS NAME : Arch::CompatEntry
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           // this is noarch and always comatible
00077           return true;
00078           break;
00079         case 1:
00080           // this is a non builtin: self compatible only
00081           return _archStr == targetEntry_r._archStr;
00082           break;
00083         }
00084       // This is a builtin: compatible if mentioned in targetEntry_r
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 ); // Id 1: non builtin
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; // frequently used by the UI so we keep a reference
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 } // namespace zypp
00133 
00134 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
00135 
00137 namespace zypp
00138 { 
00139 
00141   namespace
00142   { 
00143 
00144     // Builtin architecture STRING VALUES to be
00145     // used in defCompatibleWith below!
00146     //
00147     // const IdString  _foo( "foo" );
00148     //
00149     // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
00150     //       You have to change them accordingly.
00151     //
00152     // NOTE: Thake care CompatBits::IntT is able to provide one
00153     //       bit for each architecture.
00154     //
00155 #define DEF_BUILTIN(A) static inline const IdString & _##A () { static IdString __str(#A); return __str; }
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( armv7tnhl );
00191     DEF_BUILTIN( armv7thl );
00192     DEF_BUILTIN( armv7nhl );
00193     DEF_BUILTIN( armv7hl );
00194     DEF_BUILTIN( armv7l );
00195     DEF_BUILTIN( armv6l );
00196     DEF_BUILTIN( armv5tejl );
00197     DEF_BUILTIN( armv5tel );
00198     DEF_BUILTIN( armv5l );
00199     DEF_BUILTIN( armv4tl );
00200     DEF_BUILTIN( armv4l );
00201     DEF_BUILTIN( armv3l );
00202 
00203     DEF_BUILTIN( sh3 );
00204 
00205     DEF_BUILTIN( sh4 );
00206     DEF_BUILTIN( sh4a );
00207 #undef DEF_BUILTIN
00208 
00210     //
00211     //  CLASS NAME : CompatSet
00212     //
00220     struct ArchCompatSet : private base::NonCopyable
00221     {
00222       typedef Arch::CompatEntry       CompatEntry;
00223       typedef CompatEntry::CompatBits CompatBits;
00224 
00225       typedef std::tr1::unordered_set<CompatEntry> Set;
00226       typedef Set::iterator           iterator;
00227       typedef Set::const_iterator     const_iterator;
00228 
00230       static ArchCompatSet & instance()
00231       {
00232         static ArchCompatSet _instance;
00233         return _instance;
00234       }
00235 
00239       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
00240       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00242       const Arch::CompatEntry & assertDef( IdString archStr_r )
00243       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00244 
00245       const_iterator begin() const
00246       { return _compatSet.begin(); }
00247 
00248       const_iterator end() const
00249       { return _compatSet.end(); }
00250 
00251       struct DumpOnCompare
00252       {
00253         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
00254         { return lhs._idBit.value() < rhs._idBit.value(); }
00255       };
00256 
00257       std::ostream & dumpOn( std::ostream & str ) const
00258       {
00259         str << "ArchCompatSet:";
00260         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
00261         ov.sort( DumpOnCompare() );
00262         for_( it, ov.begin(), ov.end() )
00263           {
00264             str << endl << ' ' << *it;
00265           }
00266         return str;
00267       }
00268 
00269     private:
00271       ArchCompatSet()
00272       {
00273         // _noarch must have _idBit 0.
00274         // Other builtins have 1-bit set
00275         // and are initialized done on the fly.
00276         _compatSet.insert( Arch::CompatEntry( _noarch(), 0 ) );
00278         // Define the CompatibleWith relation:
00279         //
00280         // NOTE: Order of definition is significant! (Arch::compare)
00281         //       - define compatible (less) architectures first!
00282         //
00283         defCompatibleWith( _i386(),             _noarch() );
00284         defCompatibleWith( _i486(),             _noarch(),_i386() );
00285         defCompatibleWith( _i586(),             _noarch(),_i386(),_i486() );
00286         defCompatibleWith( _i686(),             _noarch(),_i386(),_i486(),_i586() );
00287         defCompatibleWith( _athlon(),           _noarch(),_i386(),_i486(),_i586(),_i686() );
00288         defCompatibleWith( _x86_64(),           _noarch(),_i386(),_i486(),_i586(),_i686(),_athlon() );
00289 
00290         defCompatibleWith( _pentium3(),         _noarch(),_i386(),_i486(),_i586(),_i686() );
00291         defCompatibleWith( _pentium4(),         _noarch(),_i386(),_i486(),_i586(),_i686(),_pentium3() );
00292 
00293         defCompatibleWith( _ia64(),             _noarch(),_i386(),_i486(),_i586(),_i686() );
00294         //
00295         defCompatibleWith( _s390(),             _noarch() );
00296         defCompatibleWith( _s390x(),            _noarch(),_s390() );
00297         //
00298         defCompatibleWith( _ppc(),              _noarch() );
00299         defCompatibleWith( _ppc64(),            _noarch(),_ppc() );
00300         //
00301         defCompatibleWith( _alpha(),            _noarch() );
00302         defCompatibleWith( _alphaev5(),         _noarch(),_alpha() );
00303         defCompatibleWith( _alphaev56(),        _noarch(),_alpha(),_alphaev5() );
00304         defCompatibleWith( _alphapca56(),       _noarch(),_alpha(),_alphaev5(),_alphaev56() );
00305         defCompatibleWith( _alphaev6(),         _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56() );
00306         defCompatibleWith( _alphaev67(),        _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56(),_alphaev6() );
00307         //
00308         defCompatibleWith( _sparc(),            _noarch() );
00309         defCompatibleWith( _sparcv8(),          _noarch(),_sparc() );
00310         defCompatibleWith( _sparcv9(),          _noarch(),_sparc(),_sparcv8() );
00311         defCompatibleWith( _sparcv9v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9() );
00312         //
00313         defCompatibleWith( _sparc64(),          _noarch(),_sparc(),_sparcv8(),_sparcv9() );
00314         defCompatibleWith( _sparc64v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9(),_sparcv9v(),_sparc64() );
00315         //
00316         defCompatibleWith( _armv3l(),           _noarch() );
00317         defCompatibleWith( _armv4l(),           _noarch(),_armv3l() );
00318         defCompatibleWith( _armv4tl(),          _noarch(),_armv3l(),_armv4l() );
00319         defCompatibleWith( _armv5l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl() );
00320         defCompatibleWith( _armv5tel(),         _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l() );
00321         defCompatibleWith( _armv5tejl(),        _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel() );
00322         defCompatibleWith( _armv6l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl() );
00323         defCompatibleWith( _armv7l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl(),_armv6l() );
00324         defCompatibleWith( _armv7hl(),          _noarch() );
00325         defCompatibleWith( _armv7nhl(),         _noarch(),_armv7hl() );
00326         defCompatibleWith( _armv7thl(),         _noarch(),_armv7hl() );
00327         defCompatibleWith( _armv7tnhl(),        _noarch(),_armv7hl(),_armv7nhl(),_armv7thl() );
00328         //
00329         defCompatibleWith( _sh3(),              _noarch() );
00330         //
00331         defCompatibleWith( _sh4(),              _noarch() );
00332         defCompatibleWith( _sh4a(),             _noarch(),_sh4() );
00333         //
00335         // dumpOn( USR ) << endl;
00336       }
00337 
00338     private:
00344       CompatBits::IntT nextIdBit() const
00345       {
00346         if ( CompatBits::size == _compatSet.size() )
00347         {
00348           // Provide more bits in CompatBits::IntT
00349           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
00350           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
00351         }
00352         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
00353         return nextBit;
00354       }
00355 
00359       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
00360       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
00361 
00364       void defCompatibleWith( IdString targetArch_r,
00365                               IdString arch0_r,
00366                               IdString arch1_r = IdString(),
00367                               IdString arch2_r = IdString(),
00368                               IdString arch3_r = IdString(),
00369                               IdString arch4_r = IdString(),
00370                               IdString arch5_r = IdString(),
00371                               IdString arch6_r = IdString(),
00372                               IdString arch7_r = IdString(),
00373                               IdString arch8_r = IdString(),
00374                               IdString arch9_r = IdString() )
00375       {
00376         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
00377         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
00378 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
00379         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
00380         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
00381 #undef _SETARG
00382       }
00383 
00384     private:
00385       Set _compatSet;
00386     };
00387 
00389   } // namespace
00391 
00393   //
00394   //    CLASS NAME : Arch
00395   //
00397 
00398   const Arch Arch_empty ( IdString::Empty );
00399   const Arch Arch_noarch( _noarch() );
00400 
00401   const Arch Arch_i386( _i386() );
00402   const Arch Arch_i486( _i486() );
00403   const Arch Arch_i586( _i586() );
00404   const Arch Arch_i686( _i686() );
00405   const Arch Arch_athlon( _athlon() );
00406   const Arch Arch_x86_64( _x86_64() );
00407 
00408   const Arch Arch_pentium3( _pentium3() );
00409   const Arch Arch_pentium4( _pentium4() );
00410 
00411   const Arch Arch_s390( _s390() );
00412   const Arch Arch_s390x( _s390x() );
00413 
00414   const Arch Arch_ppc( _ppc() );
00415   const Arch Arch_ppc64( _ppc64() );
00416 
00417   const Arch Arch_ia64( _ia64() );
00418 
00419   const Arch Arch_alphaev67( _alphaev67() );
00420   const Arch Arch_alphaev6( _alphaev6() );
00421   const Arch Arch_alphapca56( _alphapca56() );
00422   const Arch Arch_alphaev56( _alphaev56() );
00423   const Arch Arch_alphaev5( _alphaev5() );
00424   const Arch Arch_alpha( _alpha() );
00425 
00426   const Arch Arch_sparc64v( _sparc64v() );
00427   const Arch Arch_sparc64( _sparc64() );
00428   const Arch Arch_sparcv9v( _sparcv9v() );
00429   const Arch Arch_sparcv9( _sparcv9() );
00430   const Arch Arch_sparcv8( _sparcv8() );
00431   const Arch Arch_sparc( _sparc() );
00432 
00433   const Arch Arch_armv7tnhl( _armv7tnhl() );
00434   const Arch Arch_armv7thl( _armv7thl() );
00435   const Arch Arch_armv7nhl ( _armv7nhl() );
00436   const Arch Arch_armv7hl ( _armv7hl() );
00437   const Arch Arch_armv7l( _armv7l() );
00438   const Arch Arch_armv6l( _armv6l() );
00439   const Arch Arch_armv5tejl( _armv5tejl() );
00440   const Arch Arch_armv5tel( _armv5tel() );
00441   const Arch Arch_armv5l( _armv5l() );
00442   const Arch Arch_armv4tl( _armv4tl() );
00443   const Arch Arch_armv4l( _armv4l() );
00444   const Arch Arch_armv3l( _armv3l() );
00445 
00446   const Arch Arch_sh3( _sh3() );
00447 
00448   const Arch Arch_sh4( _sh4() );
00449   const Arch Arch_sh4a( _sh4a() );
00450 
00452   //
00453   //    METHOD NAME : Arch::Arch
00454   //    METHOD TYPE : Ctor
00455   //
00456   Arch::Arch()
00457   : _entry( &ArchCompatSet::instance().assertDef( _noarch() ) )
00458   {}
00459 
00460   Arch::Arch( IdString::IdType id_r )
00461   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
00462   {}
00463 
00464   Arch::Arch( const IdString & idstr_r )
00465   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
00466   {}
00467 
00468   Arch::Arch( const std::string & str_r )
00469   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
00470   {}
00471 
00472   Arch::Arch( const char * cstr_r )
00473   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
00474   {}
00475 
00476   Arch::Arch( const CompatEntry & rhs )
00477   : _entry( &rhs )
00478   {}
00479 
00481   //
00482   //    METHOD NAME : Arch::idStr
00483   //    METHOD TYPE : IdString
00484   //
00485   IdString Arch::idStr() const
00486   { return _entry->_idStr; }
00487 
00489   //
00490   //    METHOD NAME : Arch::asString
00491   //    METHOD TYPE : const std::string &
00492   //
00493   const std::string & Arch::asString() const
00494   { return _entry->_archStr; }
00495 
00497   //
00498   //    METHOD NAME : Arch::isBuiltIn
00499   //    METHOD TYPE : bool
00500   //
00501   bool Arch::isBuiltIn() const
00502   { return _entry->isBuiltIn(); }
00503 
00505   //
00506   //    METHOD NAME : Arch::compatibleWith
00507   //    METHOD TYPE : bool
00508   //
00509   bool Arch::compatibleWith( const Arch & targetArch_r ) const
00510   { return _entry->compatibleWith( *targetArch_r._entry ); }
00511 
00513   //
00514   //    METHOD NAME : Arch::baseArch
00515   //    METHOD TYPE : Arch
00516   //
00517   Arch Arch::baseArch( ) const
00518   {
00519     // check the multilib archs:
00520     if (Arch_x86_64.compatibleWith(*this))
00521     {
00522       return Arch_x86_64;
00523     }
00524     if (Arch_sparc64v.compatibleWith(*this))
00525     {
00526       return Arch_sparc64v;
00527     }
00528     if (Arch_sparc64.compatibleWith(*this))
00529     {
00530       return Arch_sparc64;
00531     }
00532     if (Arch_ppc64.compatibleWith(*this))
00533     {
00534       return Arch_ppc64;
00535     }
00536     if (Arch_s390x.compatibleWith(*this))
00537     {
00538       return Arch_s390x;
00539     }
00540     // Here: no multilib; return arch before noarch
00541     CompatSet cset( compatSet( *this ) );
00542     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
00543     {
00544       return *(++cset.rbegin());
00545     }
00546     return *this;
00547   }
00548 
00550   //
00551   //    METHOD NAME : Arch::compare
00552   //    METHOD TYPE : bool
00553   //
00554   int Arch::compare( const Arch & rhs ) const
00555   { return _entry->compare( *rhs._entry ); }
00556 
00558   //
00559   //    METHOD NAME : Arch::compatSet
00560   //    METHOD TYPE : Arch::CompatSet
00561   //
00562   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
00563   {
00564     Arch::CompatSet ret;
00565 
00566     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
00567           it != ArchCompatSet::instance().end(); ++it )
00568       {
00569         if ( it->compatibleWith( *targetArch_r._entry ) )
00570           {
00571             ret.insert( Arch(*it) );
00572           }
00573       }
00574 
00575     return ret;
00576   }
00577 
00579 } // namespace zypp