- Add "sh4" architectures.
[platform/upstream/libzypp.git] / zypp / Arch.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Arch.cc
10  *
11 */
12 #include <iostream>
13 #include <set>
14
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/NonCopyable.h"
17 #include "zypp/base/Tr1hash.h"
18 #include "zypp/Arch.h"
19 #include "zypp/Bit.h"
20
21 using std::endl;
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27   ///////////////////////////////////////////////////////////////////
28   //
29   //    CLASS NAME : Arch::CompatEntry
30   //
31   /** Holds an architecture ID and it's compatible relation.
32    * An architecture is compatibleWith, if it's _idBit is set in
33    * _compatBits. noarch has ID 0, non builtin archs ID 1 and
34    * have to be treated specialy.
35   */
36   struct Arch::CompatEntry
37   {
38     /** Bitfield for architecture IDs and compatBits relation.
39      * \note Need one bit for each builtin Arch.
40     */
41     typedef bit::BitField<uint32_t> CompatBits;
42
43     CompatEntry( const std::string & archStr_r,
44                  CompatBits::IntT idBit_r = 1 )
45     : _idStr( archStr_r )
46     , _archStr( archStr_r )
47     , _idBit( idBit_r )
48     , _compatBits( idBit_r )
49     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
50     {}
51
52     CompatEntry( IdString archStr_r,
53                  CompatBits::IntT idBit_r = 1 )
54     : _idStr( archStr_r )
55     , _archStr( archStr_r.asString() )
56     , _idBit( idBit_r )
57     , _compatBits( idBit_r )
58     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
59     {}
60
61     void addCompatBit( const CompatBits & idBit_r ) const
62     {
63       if ( idBit_r && ! (_compatBits & idBit_r) )
64         {
65           _compatBits |= idBit_r;
66           ++_compatScore;
67         }
68     }
69
70     /** Return whether \c this is compatible with \a targetEntry_r.*/
71     bool compatibleWith( const CompatEntry & targetEntry_r ) const
72     {
73       switch ( _idBit.value() )
74         {
75         case 0:
76           // this is noarch and always comatible
77           return true;
78           break;
79         case 1:
80           // this is a non builtin: self compatible only
81           return _archStr == targetEntry_r._archStr;
82           break;
83         }
84       // This is a builtin: compatible if mentioned in targetEntry_r
85       return targetEntry_r._compatBits & _idBit;
86     }
87
88     /** compare by score, then archStr. */
89     int compare( const CompatEntry & rhs ) const
90     {
91       if ( _compatScore != rhs._compatScore )
92         return( _compatScore < rhs._compatScore ? -1 : 1 );
93       return _archStr.compare( rhs._archStr );
94     }
95
96     bool isBuiltIn() const
97     { return( _idBit != CompatBits(1) ); }
98
99     IdString::IdType id() const
100     { return _idStr.id(); }
101
102     IdString            _idStr;
103     std::string         _archStr; // frequently used by the UI so we keep a reference
104     CompatBits          _idBit;
105     mutable CompatBits  _compatBits;
106     mutable unsigned    _compatScore;
107   };
108   ///////////////////////////////////////////////////////////////////
109
110   /** \relates Arch::CompatEntry Stream output */
111   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
112   {
113     return str << str::form( "%-15s ", obj._archStr.c_str() ) << obj._idBit << ' '
114                << obj._compatBits << ' ' << obj._compatScore;
115   }
116
117   /** \relates Arch::CompatEntry */
118   inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
119   { return lhs._idStr == rhs._idStr; }
120   /** \relates Arch::CompatEntry */
121   inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
122   { return ! ( lhs == rhs ); }
123
124   /////////////////////////////////////////////////////////////////
125 } // namespace zypp
126 ///////////////////////////////////////////////////////////////////
127
128 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
129
130 ///////////////////////////////////////////////////////////////////
131 namespace zypp
132 { /////////////////////////////////////////////////////////////////
133
134   ///////////////////////////////////////////////////////////////////
135   namespace
136   { /////////////////////////////////////////////////////////////////
137
138     // builtin architecture STRING VALUES
139     //
140     // For arch 'foo' this macro defines:
141     // const IdString  _foo( "foo" );     // to be used in defCompatibleWith below!
142     // const Arch      Arch_foo( _foo );
143     //
144 #define DEF_BUILTIN(A) const IdString  _##A( #A ); const Arch Arch_##A( _##A )
145     DEF_BUILTIN( noarch );
146
147     DEF_BUILTIN( i386 );
148     DEF_BUILTIN( i486 );
149     DEF_BUILTIN( i586 );
150     DEF_BUILTIN( i686 );
151     DEF_BUILTIN( athlon );
152     DEF_BUILTIN( x86_64 );
153
154     DEF_BUILTIN( pentium3 );
155     DEF_BUILTIN( pentium4 );
156
157     DEF_BUILTIN( s390 );
158     DEF_BUILTIN( s390x );
159
160     DEF_BUILTIN( ppc );
161     DEF_BUILTIN( ppc64 );
162
163     DEF_BUILTIN( ia64 );
164
165     DEF_BUILTIN( alphaev67 );
166     DEF_BUILTIN( alphaev6 );
167     DEF_BUILTIN( alphapca56 );
168     DEF_BUILTIN( alphaev56 );
169     DEF_BUILTIN( alphaev5 );
170     DEF_BUILTIN( alpha );
171
172     DEF_BUILTIN( sparc64 );
173     DEF_BUILTIN( sparcv9 );
174     DEF_BUILTIN( sparcv8 );
175     DEF_BUILTIN( sparc );
176
177     DEF_BUILTIN( armv6l );
178     DEF_BUILTIN( armv5tejl );
179     DEF_BUILTIN( armv5tel );
180     DEF_BUILTIN( armv5l );
181     DEF_BUILTIN( armv4tl );
182     DEF_BUILTIN( armv4l );
183     DEF_BUILTIN( armv3l );
184
185     DEF_BUILTIN( sh3 );
186
187     DEF_BUILTIN( sh4 );
188     DEF_BUILTIN( sh4a );
189 #undef DEF_BUILTIN
190
191     ///////////////////////////////////////////////////////////////////
192     //
193     //  CLASS NAME : CompatSet
194     //
195     /** Maintain architecture compatibility (Singleton by the way it is used).
196      *
197      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
198      * compatibleWith relation.
199      * \li \c noarch has _idBit 0
200      * \li \c nonbuiltin archs have _idBit 1
201     */
202     struct ArchCompatSet : private base::NonCopyable
203     {
204       typedef Arch::CompatEntry       CompatEntry;
205       typedef CompatEntry::CompatBits CompatBits;
206
207       typedef std::tr1::unordered_set<CompatEntry> Set;
208       typedef Set::iterator           iterator;
209       typedef Set::const_iterator     const_iterator;
210
211       /** Singleton access. */
212       static ArchCompatSet & instance()
213       {
214         static ArchCompatSet _instance;
215         return _instance;
216       }
217
218       /** Return the entry related to \a archStr_r.
219        * Creates an entry for nonbuiltin archs.
220       */
221       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
222       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
223       /** \overload */
224       const Arch::CompatEntry & assertDef( IdString archStr_r )
225       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
226
227       const_iterator begin() const
228       { return _compatSet.begin(); }
229
230       const_iterator end() const
231       { return _compatSet.end(); }
232
233       std::ostream & dumpOn( std::ostream & str ) const
234       {
235         str << "ArchCompatSet:";
236         for ( const_iterator it = _compatSet.begin(); it != _compatSet.end(); ++it )
237           {
238             str << endl << ' ' << *it;
239           }
240         return str;
241       }
242
243     private:
244       /** Singleton ctor. */
245       ArchCompatSet()
246       {
247         // _noarch must have _idBit 0.
248         // Other builtins have 1-bit set
249         // and are initialized done on the fly.
250         _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
251         ///////////////////////////////////////////////////////////////////
252         // Define the CompatibleWith relation:
253         //
254         defCompatibleWith( _i386,       _noarch );
255         defCompatibleWith( _i486,       _noarch,_i386 );
256         defCompatibleWith( _i586,       _noarch,_i386,_i486 );
257         defCompatibleWith( _i686,       _noarch,_i386,_i486,_i586 );
258         defCompatibleWith( _athlon,     _noarch,_i386,_i486,_i586,_i686 );
259         defCompatibleWith( _x86_64,     _noarch,_i386,_i486,_i586,_i686,_athlon );
260
261         defCompatibleWith( _pentium3,   _noarch,_i386,_i486,_i586,_i686 );
262         defCompatibleWith( _pentium4,   _noarch,_i386,_i486,_i586,_i686,_pentium3 );
263
264         defCompatibleWith( _ia64,       _noarch,_i386,_i486,_i586,_i686 );
265         //
266         defCompatibleWith( _s390,       _noarch );
267         defCompatibleWith( _s390x,      _noarch,_s390 );
268         //
269         defCompatibleWith( _ppc,        _noarch );
270         defCompatibleWith( _ppc64,      _noarch,_ppc );
271         //
272         defCompatibleWith( _alpha,      _noarch );
273         defCompatibleWith( _alphaev5,   _noarch,_alpha );
274         defCompatibleWith( _alphaev56,  _noarch,_alpha,_alphaev5 );
275         defCompatibleWith( _alphapca56, _noarch,_alpha,_alphaev5,_alphaev56 );
276         defCompatibleWith( _alphaev6,   _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
277         defCompatibleWith( _alphaev67,  _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
278         //
279         defCompatibleWith( _sparc,      _noarch );
280         defCompatibleWith( _sparcv8,    _noarch,_sparc );
281         //
282         defCompatibleWith( _sparcv9,    _noarch,_sparc );
283         defCompatibleWith( _sparc64,    _noarch,_sparc,_sparcv9 );
284         //
285         defCompatibleWith( _armv3l,     _noarch );
286         defCompatibleWith( _armv4l,     _noarch,_armv3l );
287         defCompatibleWith( _armv4tl,    _noarch,_armv3l,_armv4l );
288         defCompatibleWith( _armv5l,     _noarch,_armv3l,_armv4l,_armv4tl );
289         defCompatibleWith( _armv5tel,   _noarch,_armv3l,_armv4l,_armv4tl,_armv5l );
290         defCompatibleWith( _armv5tejl,  _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel );
291         defCompatibleWith( _armv6l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl );
292         //
293         defCompatibleWith( _sh3,        _noarch );
294         //
295         defCompatibleWith( _sh4,        _noarch );
296         defCompatibleWith( _sh4a,       _noarch,_sh4 );
297         //
298         ///////////////////////////////////////////////////////////////////
299         //dumpOn( USR ) << endl;
300       }
301
302     private:
303       /** Return the next avialable _idBit.
304        * Ctor injects _noarch into the _compatSet, 1 is for
305        * nonbuiltin archs, so we can use <tt>size</tt> for
306        * buitin archs.
307       */
308       CompatBits::IntT nextIdBit() const
309       {
310         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
311         assert( nextBit ); // need more bits in CompatBits::IntT
312         return nextBit;
313       }
314
315       /** Assert each builtin Arch gets an unique _idBit when
316        *  inserted into the _compatSet.
317       */
318       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
319       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
320
321       /** Initialize builtin Archs and set _compatBits.
322       */
323       void defCompatibleWith( IdString targetArch_r,
324                               IdString arch0_r,
325                               IdString arch1_r = IdString(),
326                               IdString arch2_r = IdString(),
327                               IdString arch3_r = IdString(),
328                               IdString arch4_r = IdString(),
329                               IdString arch5_r = IdString(),
330                               IdString arch6_r = IdString(),
331                               IdString arch7_r = IdString(),
332                               IdString arch8_r = IdString(),
333                               IdString arch9_r = IdString() )
334       {
335         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
336         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
337 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
338         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
339         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
340 #undef _SETARG
341       }
342
343     private:
344       Set _compatSet;
345     };
346
347     /////////////////////////////////////////////////////////////////
348   } // namespace
349   ///////////////////////////////////////////////////////////////////
350
351   ///////////////////////////////////////////////////////////////////
352   //
353   //    CLASS NAME : Arch
354   //
355   ///////////////////////////////////////////////////////////////////
356
357   const Arch Arch_empty ( IdString::Empty );
358
359   // all other Arch_* constants are defined via
360   // the DEF_BUILTIN macro. See Above.
361
362   ///////////////////////////////////////////////////////////////////
363   //
364   //    METHOD NAME : Arch::Arch
365   //    METHOD TYPE : Ctor
366   //
367   Arch::Arch()
368   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
369   {}
370
371   Arch::Arch( IdString::IdType id_r )
372   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
373   {}
374
375   Arch::Arch( const IdString & idstr_r )
376   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
377   {}
378
379   Arch::Arch( const std::string & str_r )
380   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
381   {}
382
383   Arch::Arch( const char * cstr_r )
384   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
385   {}
386
387   Arch::Arch( const CompatEntry & rhs )
388   : _entry( &rhs )
389   {}
390
391   ///////////////////////////////////////////////////////////////////
392   //
393   //    METHOD NAME : Arch::idStr
394   //    METHOD TYPE : IdString
395   //
396   IdString Arch::idStr() const
397   { return _entry->_idStr; }
398
399   ///////////////////////////////////////////////////////////////////
400   //
401   //    METHOD NAME : Arch::asString
402   //    METHOD TYPE : const std::string &
403   //
404   const std::string & Arch::asString() const
405   { return _entry->_archStr; }
406
407   ///////////////////////////////////////////////////////////////////
408   //
409   //    METHOD NAME : Arch::isBuiltIn
410   //    METHOD TYPE : bool
411   //
412   bool Arch::isBuiltIn() const
413   { return _entry->isBuiltIn(); }
414
415   ///////////////////////////////////////////////////////////////////
416   //
417   //    METHOD NAME : Arch::compatibleWith
418   //    METHOD TYPE : bool
419   //
420   bool Arch::compatibleWith( const Arch & targetArch_r ) const
421   { return _entry->compatibleWith( *targetArch_r._entry ); }
422
423   ///////////////////////////////////////////////////////////////////
424   //
425   //    METHOD NAME : Arch::compare
426   //    METHOD TYPE : bool
427   //
428   int Arch::compare( const Arch & rhs ) const
429   { return _entry->compare( *rhs._entry ); }
430
431   ///////////////////////////////////////////////////////////////////
432   //
433   //    METHOD NAME : Arch::compatSet
434   //    METHOD TYPE : Arch::CompatSet
435   //
436   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
437   {
438     Arch::CompatSet ret;
439
440     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
441           it != ArchCompatSet::instance().end(); ++it )
442       {
443         if ( it->compatibleWith( *targetArch_r._entry ) )
444           {
445             ret.insert( Arch(*it) );
446           }
447       }
448
449     return ret;
450   }
451
452   /////////////////////////////////////////////////////////////////
453 } // namespace zypp
454 ///////////////////////////////////////////////////////////////////