src/corelib/plugin/qlibrary.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qplatformdefs.h"
       
    43 #include "qlibrary.h"
       
    44 
       
    45 #ifndef QT_NO_LIBRARY
       
    46 
       
    47 #include "qlibrary_p.h"
       
    48 #include <qstringlist.h>
       
    49 #include <qfile.h>
       
    50 #include <qfileinfo.h>
       
    51 #include <qmutex.h>
       
    52 #include <qmap.h>
       
    53 #include <qsettings.h>
       
    54 #include <qdatetime.h>
       
    55 #ifdef Q_OS_MAC
       
    56 #  include <private/qcore_mac_p.h>
       
    57 #endif
       
    58 #ifndef NO_ERRNO_H
       
    59 #include <errno.h>
       
    60 #endif // NO_ERROR_H
       
    61 #include <qdebug.h>
       
    62 #include <qvector.h>
       
    63 #include <qdir.h>
       
    64 
       
    65 QT_BEGIN_NAMESPACE
       
    66 
       
    67 //#define QT_DEBUG_COMPONENT
       
    68 
       
    69 #ifdef QT_NO_DEBUG
       
    70 #  define QLIBRARY_AS_DEBUG false
       
    71 #else
       
    72 #  define QLIBRARY_AS_DEBUG true
       
    73 #endif
       
    74 
       
    75 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
       
    76 // We don't use separate debug and release libs on UNIX, so we want
       
    77 // to allow loading plugins, regardless of how they were built.
       
    78 #  define QT_NO_DEBUG_PLUGIN_CHECK
       
    79 #endif
       
    80 
       
    81 Q_GLOBAL_STATIC(QMutex, qt_library_mutex)
       
    82 
       
    83 /*!
       
    84     \class QLibrary
       
    85     \reentrant
       
    86     \brief The QLibrary class loads shared libraries at runtime.
       
    87 
       
    88 
       
    89     \ingroup plugins
       
    90 
       
    91     An instance of a QLibrary object operates on a single shared
       
    92     object file (which we call a "library", but is also known as a
       
    93     "DLL"). A QLibrary provides access to the functionality in the
       
    94     library in a platform independent way. You can either pass a file
       
    95     name in the constructor, or set it explicitly with setFileName().
       
    96     When loading the library, QLibrary searches in all the
       
    97     system-specific library locations (e.g. \c LD_LIBRARY_PATH on
       
    98     Unix), unless the file name has an absolute path. If the file
       
    99     cannot be found, QLibrary tries the name with different
       
   100     platform-specific file suffixes, like ".so" on Unix, ".dylib" on
       
   101     the Mac, or ".dll" on Windows and Symbian. This makes it possible
       
   102     to specify shared libraries that are only identified by their
       
   103     basename (i.e. without their suffix), so the same code will work
       
   104     on different operating systems.
       
   105 
       
   106     The most important functions are load() to dynamically load the
       
   107     library file, isLoaded() to check whether loading was successful,
       
   108     and resolve() to resolve a symbol in the library. The resolve()
       
   109     function implicitly tries to load the library if it has not been
       
   110     loaded yet. Multiple instances of QLibrary can be used to access
       
   111     the same physical library. Once loaded, libraries remain in memory
       
   112     until the application terminates. You can attempt to unload a
       
   113     library using unload(), but if other instances of QLibrary are
       
   114     using the same library, the call will fail, and unloading will
       
   115     only happen when every instance has called unload().
       
   116 
       
   117     A typical use of QLibrary is to resolve an exported symbol in a
       
   118     library, and to call the C function that this symbol represents.
       
   119     This is called "explicit linking" in contrast to "implicit
       
   120     linking", which is done by the link step in the build process when
       
   121     linking an executable against a library.
       
   122 
       
   123     Note: In Symbian resolving symbols using their names is supported
       
   124     only if the library is built as STDDLL. Otherwise ordinals must
       
   125     be used. Also, in Symbian the path of the library is ignored and
       
   126     system default library location is always used.
       
   127 
       
   128     The following code snippet loads a library, resolves the symbol
       
   129     "mysymbol", and calls the function if everything succeeded. If
       
   130     something goes wrong, e.g. the library file does not exist or the
       
   131     symbol is not defined, the function pointer will be 0 and won't be
       
   132     called.
       
   133 
       
   134     \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 0
       
   135 
       
   136     The symbol must be exported as a C function from the library for
       
   137     resolve() to work. This means that the function must be wrapped in
       
   138     an \c{extern "C"} block if the library is compiled with a C++
       
   139     compiler. On Windows, this also requires the use of a \c dllexport
       
   140     macro; see resolve() for the details of how this is done. For
       
   141     convenience, there is a static resolve() function which you can
       
   142     use if you just want to call a function in a library without
       
   143     explicitly loading the library first:
       
   144 
       
   145     \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 1
       
   146 
       
   147     \sa QPluginLoader
       
   148 */
       
   149 
       
   150 /*!
       
   151     \enum QLibrary::LoadHint
       
   152 
       
   153     This enum describes the possible hints that can be used to change the way
       
   154     libraries are handled when they are loaded. These values indicate how
       
   155     symbols are resolved when libraries are loaded, and are specified using
       
   156     the setLoadHints() function.
       
   157 
       
   158     \value ResolveAllSymbolsHint
       
   159     Causes all symbols in a library to be resolved when it is loaded, not
       
   160     simply when resolve() is called.
       
   161     \value ExportExternalSymbolsHint
       
   162     Exports unresolved and external symbols in the library so that they can be
       
   163     resolved in other dynamically-loaded libraries loaded later.
       
   164     \value LoadArchiveMemberHint
       
   165     Allows the file name of the library to specify a particular object file
       
   166     within an archive file.
       
   167     If this hint is given, the filename of the library consists of
       
   168     a path, which is a reference to an archive file, followed by
       
   169     a reference to the archive member.
       
   170 
       
   171     \sa loadHints
       
   172 */
       
   173 
       
   174 
       
   175 #ifndef QT_NO_PLUGIN_CHECK
       
   176 struct qt_token_info
       
   177 {
       
   178     qt_token_info(const char *f, const ulong fc)
       
   179         : fields(f), field_count(fc), results(fc), lengths(fc)
       
   180     {
       
   181         results.fill(0);
       
   182         lengths.fill(0);
       
   183     }
       
   184 
       
   185     const char *fields;
       
   186     const ulong field_count;
       
   187 
       
   188     QVector<const char *> results;
       
   189     QVector<ulong> lengths;
       
   190 };
       
   191 
       
   192 /*
       
   193   return values:
       
   194        1 parse ok
       
   195        0 eos
       
   196       -1 parse error
       
   197 */
       
   198 static int qt_tokenize(const char *s, ulong s_len, ulong *advance,
       
   199                         qt_token_info &token_info)
       
   200 {
       
   201     ulong pos = 0, field = 0, fieldlen = 0;
       
   202     char current;
       
   203     int ret = -1;
       
   204     *advance = 0;
       
   205     for (;;) {
       
   206         current = s[pos];
       
   207 
       
   208         // next char
       
   209         ++pos;
       
   210         ++fieldlen;
       
   211         ++*advance;
       
   212 
       
   213         if (! current || pos == s_len + 1) {
       
   214             // save result
       
   215             token_info.results[(int)field] = s;
       
   216             token_info.lengths[(int)field] = fieldlen - 1;
       
   217 
       
   218             // end of string
       
   219             ret = 0;
       
   220             break;
       
   221         }
       
   222 
       
   223         if (current == token_info.fields[field]) {
       
   224             // save result
       
   225             token_info.results[(int)field] = s;
       
   226             token_info.lengths[(int)field] = fieldlen - 1;
       
   227 
       
   228             // end of field
       
   229             fieldlen = 0;
       
   230             ++field;
       
   231             if (field == token_info.field_count - 1) {
       
   232                 // parse ok
       
   233                 ret = 1;
       
   234             }
       
   235             if (field == token_info.field_count) {
       
   236                 // done parsing
       
   237                 break;
       
   238             }
       
   239 
       
   240             // reset string and its length
       
   241             s = s + pos;
       
   242             s_len -= pos;
       
   243             pos = 0;
       
   244         }
       
   245     }
       
   246 
       
   247     return ret;
       
   248 }
       
   249 
       
   250 /*
       
   251   returns true if the string s was correctly parsed, false otherwise.
       
   252 */
       
   253 static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key)
       
   254 {
       
   255     bool ret = true;
       
   256 
       
   257     qt_token_info pinfo("=\n", 2);
       
   258     int parse;
       
   259     ulong at = 0, advance, parselen = qstrlen(s);
       
   260     do {
       
   261         parse = qt_tokenize(s + at, parselen, &advance, pinfo);
       
   262         if (parse == -1) {
       
   263             ret = false;
       
   264             break;
       
   265         }
       
   266 
       
   267         at += advance;
       
   268         parselen -= advance;
       
   269 
       
   270         if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) {
       
   271             // parse version string
       
   272             qt_token_info pinfo2("..-", 3);
       
   273             if (qt_tokenize(pinfo.results[1], pinfo.lengths[1],
       
   274                               &advance, pinfo2) != -1) {
       
   275                 QByteArray m(pinfo2.results[0], pinfo2.lengths[0]);
       
   276                 QByteArray n(pinfo2.results[1], pinfo2.lengths[1]);
       
   277                 QByteArray p(pinfo2.results[2], pinfo2.lengths[2]);
       
   278                 *version  = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt();
       
   279             } else {
       
   280                 ret = false;
       
   281                 break;
       
   282             }
       
   283         } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) {
       
   284             *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0;
       
   285         } else if (qstrncmp("buildkey", pinfo.results[0],
       
   286                               pinfo.lengths[0]) == 0){
       
   287             // save buildkey
       
   288             *key = QByteArray(pinfo.results[1], pinfo.lengths[1]);
       
   289         }
       
   290     } while (parse == 1 && parselen > 0);
       
   291 
       
   292     return ret;
       
   293 }
       
   294 #endif // QT_NO_PLUGIN_CHECK
       
   295 
       
   296 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
       
   297 
       
   298 #if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX)
       
   299 #  define USE_MMAP
       
   300 QT_BEGIN_INCLUDE_NAMESPACE
       
   301 #  include <sys/types.h>
       
   302 #  include <sys/mman.h>
       
   303 QT_END_INCLUDE_NAMESPACE
       
   304 #endif // Q_OS_FREEBSD || Q_OS_LINUX
       
   305 
       
   306 static long qt_find_pattern(const char *s, ulong s_len,
       
   307                              const char *pattern, ulong p_len)
       
   308 {
       
   309     /*
       
   310       we search from the end of the file because on the supported
       
   311       systems, the read-only data/text segments are placed at the end
       
   312       of the file.  HOWEVER, when building with debugging enabled, all
       
   313       the debug symbols are placed AFTER the data/text segments.
       
   314 
       
   315       what does this mean?  when building in release mode, the search
       
   316       is fast because the data we are looking for is at the end of the
       
   317       file... when building in debug mode, the search is slower
       
   318       because we have to skip over all the debugging symbols first
       
   319     */
       
   320 
       
   321     if (! s || ! pattern || p_len > s_len) return -1;
       
   322     ulong i, hs = 0, hp = 0, delta = s_len - p_len;
       
   323 
       
   324     for (i = 0; i < p_len; ++i) {
       
   325         hs += s[delta + i];
       
   326         hp += pattern[i];
       
   327     }
       
   328     i = delta;
       
   329     for (;;) {
       
   330         if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
       
   331             return i;
       
   332         if (i == 0)
       
   333             break;
       
   334         --i;
       
   335         hs -= s[i + p_len];
       
   336         hs += s[i];
       
   337     }
       
   338 
       
   339     return -1;
       
   340 }
       
   341 
       
   342 /*
       
   343   This opens the specified library, mmaps it into memory, and searches
       
   344   for the QT_PLUGIN_VERIFICATION_DATA.  The advantage of this approach is that
       
   345   we can get the verification data without have to actually load the library.
       
   346   This lets us detect mismatches more safely.
       
   347 
       
   348   Returns false if version/key information is not present, or if the
       
   349                 information could not be read.
       
   350   Returns  true if version/key information is present and successfully read.
       
   351 */
       
   352 static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0)
       
   353 {
       
   354     QFile file(library);
       
   355     if (!file.open(QIODevice::ReadOnly)) {
       
   356         if (lib)
       
   357             lib->errorString = file.errorString();
       
   358         if (qt_debug_component()) {
       
   359             qWarning("%s: %s", (const char*) QFile::encodeName(library),
       
   360                 qPrintable(qt_error_string(errno)));
       
   361         }
       
   362         return false;
       
   363     }
       
   364 
       
   365     QByteArray data;
       
   366     char *filedata = 0;
       
   367     ulong fdlen = 0;
       
   368 
       
   369 # ifdef USE_MMAP
       
   370     char *mapaddr = 0;
       
   371     size_t maplen = file.size();
       
   372     mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0);
       
   373     if (mapaddr != MAP_FAILED) {
       
   374         // mmap succeeded
       
   375         filedata = mapaddr;
       
   376         fdlen = maplen;
       
   377     } else {
       
   378         // mmap failed
       
   379         if (qt_debug_component()) {
       
   380             qWarning("mmap: %s", qPrintable(qt_error_string(errno)));
       
   381         }
       
   382         if (lib)
       
   383             lib->errorString = QLibrary::tr("Could not mmap '%1': %2")
       
   384                 .arg(library)
       
   385                 .arg(qt_error_string());
       
   386 # endif // USE_MMAP
       
   387         // try reading the data into memory instead
       
   388         data = file.readAll();
       
   389         filedata = data.data();
       
   390         fdlen = data.size();
       
   391 # ifdef USE_MMAP
       
   392     }
       
   393 # endif // USE_MMAP
       
   394 
       
   395     // verify that the pattern is present in the plugin
       
   396     const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
       
   397     const ulong plen = qstrlen(pattern);
       
   398     long pos = qt_find_pattern(filedata, fdlen, pattern, plen);
       
   399 
       
   400     bool ret = false;
       
   401     if (pos >= 0)
       
   402         ret = qt_parse_pattern(filedata + pos, version, debug, key);
       
   403 
       
   404     if (!ret && lib)
       
   405         lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
       
   406 # ifdef USE_MMAP
       
   407     if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) {
       
   408         if (qt_debug_component())
       
   409             qWarning("munmap: %s", qPrintable(qt_error_string(errno)));
       
   410         if (lib)
       
   411             lib->errorString = QLibrary::tr("Could not unmap '%1': %2")
       
   412                 .arg(library)
       
   413                 .arg( qt_error_string() );
       
   414     }
       
   415 # endif // USE_MMAP
       
   416 
       
   417     file.close();
       
   418     return ret;
       
   419 }
       
   420 
       
   421 #endif // Q_OS_UNIX && !Q_OS_MAC && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
       
   422 
       
   423 typedef QMap<QString, QLibraryPrivate*> LibraryMap;
       
   424 
       
   425 struct LibraryData {
       
   426     LibraryData() : settings(0) { }
       
   427     ~LibraryData() {
       
   428         delete settings;
       
   429     }
       
   430 
       
   431     QSettings *settings;
       
   432     LibraryMap libraryMap;
       
   433 };
       
   434 
       
   435 Q_GLOBAL_STATIC(LibraryData, libraryData)
       
   436 
       
   437 static LibraryMap *libraryMap()
       
   438 {
       
   439     LibraryData *data = libraryData();
       
   440     return data ? &data->libraryMap : 0;
       
   441 }
       
   442 
       
   443 QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
       
   444     :pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0),
       
   445      libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin)
       
   446 { libraryMap()->insert(canonicalFileName, this); }
       
   447 
       
   448 QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
       
   449 {
       
   450     QMutexLocker locker(qt_library_mutex());
       
   451     if (QLibraryPrivate *lib = libraryMap()->value(fileName)) {
       
   452         lib->libraryRefCount.ref();
       
   453         return lib;
       
   454     }
       
   455 
       
   456     return new QLibraryPrivate(fileName, version);
       
   457 }
       
   458 
       
   459 QLibraryPrivate::~QLibraryPrivate()
       
   460 {
       
   461     LibraryMap * const map = libraryMap();
       
   462     if (map) {
       
   463         QLibraryPrivate *that = map->take(fileName);
       
   464         Q_ASSERT(this == that);
       
   465 	Q_UNUSED(that);
       
   466     }
       
   467 }
       
   468 
       
   469 void *QLibraryPrivate::resolve(const char *symbol)
       
   470 {
       
   471     if (!pHnd)
       
   472         return 0;
       
   473     return resolve_sys(symbol);
       
   474 }
       
   475 
       
   476 
       
   477 bool QLibraryPrivate::load()
       
   478 {
       
   479     libraryUnloadCount.ref();
       
   480     if (pHnd)
       
   481         return true;
       
   482     if (fileName.isEmpty())
       
   483         return false;
       
   484     return load_sys();
       
   485 }
       
   486 
       
   487 bool QLibraryPrivate::unload()
       
   488 {
       
   489     if (!pHnd)
       
   490         return false;
       
   491     if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
       
   492         if (instance)
       
   493             delete instance();
       
   494         if  (unload_sys()) {
       
   495             instance = 0;
       
   496             pHnd = 0;
       
   497         }
       
   498     }
       
   499 
       
   500     return (pHnd == 0);
       
   501 }
       
   502 
       
   503 void QLibraryPrivate::release()
       
   504 {
       
   505     QMutexLocker locker(qt_library_mutex());
       
   506     if (!libraryRefCount.deref())
       
   507         delete this;
       
   508 }
       
   509 
       
   510 bool QLibraryPrivate::loadPlugin()
       
   511 {
       
   512     if (instance) {
       
   513         libraryUnloadCount.ref();
       
   514         return true;
       
   515     }
       
   516     if (load()) {
       
   517         instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
       
   518 #if defined(Q_OS_SYMBIAN)
       
   519         if (!instance) {
       
   520             // If resolving with function name failed (i.e. not STDDLL),
       
   521             // try resolving using known ordinal, which for
       
   522             // qt_plugin_instance function is always "2".
       
   523             instance = (QtPluginInstanceFunction)resolve("2");
       
   524         }
       
   525 #endif
       
   526         return instance;
       
   527     }
       
   528     return false;
       
   529 }
       
   530 
       
   531 /*!
       
   532     Returns true if \a fileName has a valid suffix for a loadable
       
   533     library; otherwise returns false.
       
   534 
       
   535     \table
       
   536     \header \i Platform \i Valid suffixes
       
   537     \row \i Windows     \i \c .dll
       
   538     \row \i Unix/Linux  \i \c .so
       
   539     \row \i AIX  \i \c .a
       
   540     \row \i HP-UX       \i \c .sl, \c .so (HP-UXi)
       
   541     \row \i Mac OS X    \i \c .dylib, \c .bundle, \c .so
       
   542     \endtable
       
   543 
       
   544     Trailing versioning numbers on Unix are ignored.
       
   545  */
       
   546 bool QLibrary::isLibrary(const QString &fileName)
       
   547 {
       
   548 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
       
   549     return fileName.endsWith(QLatin1String(".dll"));
       
   550 #elif defined(Q_OS_SYMBIAN)
       
   551     // Plugin stubs are also considered libraries in Symbian.
       
   552     return (fileName.endsWith(QLatin1String(".dll")) ||
       
   553             fileName.endsWith(QLatin1String(".qtplugin")));
       
   554 #else
       
   555     QString completeSuffix = QFileInfo(fileName).completeSuffix();
       
   556     if (completeSuffix.isEmpty())
       
   557         return false;
       
   558     QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
       
   559 # if defined(Q_OS_DARWIN)
       
   560 
       
   561     // On Mac, libs look like libmylib.1.0.0.dylib
       
   562     const QString lastSuffix = suffixes.at(suffixes.count() - 1);
       
   563     const QString firstSuffix = suffixes.at(0);
       
   564 
       
   565     bool valid = (lastSuffix == QLatin1String("dylib")
       
   566             || firstSuffix == QLatin1String("so")
       
   567             || firstSuffix == QLatin1String("bundle"));
       
   568 
       
   569     return valid;
       
   570 # else  // Generic Unix
       
   571     QStringList validSuffixList;
       
   572 
       
   573 #  if defined(Q_OS_HPUX)
       
   574 /*
       
   575     See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
       
   576     "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
       
   577     the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
       
   578  */
       
   579     validSuffixList << QLatin1String("sl");
       
   580 #   if defined __ia64
       
   581     validSuffixList << QLatin1String("so");
       
   582 #   endif
       
   583 #  elif defined(Q_OS_AIX)
       
   584     validSuffixList << QLatin1String("a") << QLatin1String("so");
       
   585 #  elif defined(Q_OS_UNIX)
       
   586     validSuffixList << QLatin1String("so");
       
   587 #  endif
       
   588 
       
   589     // Examples of valid library names:
       
   590     //  libfoo.so
       
   591     //  libfoo.so.0
       
   592     //  libfoo.so.0.3
       
   593     //  libfoo-0.3.so
       
   594     //  libfoo-0.3.so.0.3.0
       
   595 
       
   596     int suffix;
       
   597     int suffixPos = -1;
       
   598     for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix)
       
   599         suffixPos = suffixes.indexOf(validSuffixList.at(suffix));
       
   600 
       
   601     bool valid = suffixPos != -1;
       
   602     for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
       
   603         if (i != suffixPos)
       
   604             suffixes.at(i).toInt(&valid);
       
   605     return valid;
       
   606 # endif
       
   607 #endif
       
   608 
       
   609 }
       
   610 
       
   611 bool QLibraryPrivate::isPlugin(QSettings *settings)
       
   612 {
       
   613     errorString.clear();
       
   614     if (pluginState != MightBeAPlugin)
       
   615         return pluginState == IsAPlugin;
       
   616 
       
   617 #ifndef QT_NO_PLUGIN_CHECK
       
   618     bool debug = !QLIBRARY_AS_DEBUG;
       
   619     QByteArray key;
       
   620     bool success = false;
       
   621 
       
   622     QFileInfo fileinfo(fileName);
       
   623 
       
   624 #ifndef QT_NO_DATESTRING
       
   625     lastModified  = fileinfo.lastModified().toString(Qt::ISODate);
       
   626 #endif
       
   627     QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4")
       
   628                      .arg((QT_VERSION & 0xff0000) >> 16)
       
   629                      .arg((QT_VERSION & 0xff00) >> 8)
       
   630                      .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
       
   631                      .arg(fileName);
       
   632     QStringList reg;
       
   633 #ifndef QT_NO_SETTINGS
       
   634     if (!settings) {
       
   635         settings = libraryData()->settings;
       
   636         if (!settings) {
       
   637             settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
       
   638             libraryData()->settings = settings;
       
   639         }
       
   640     }
       
   641     reg = settings->value(regkey).toStringList();
       
   642 #endif
       
   643     if (reg.count() == 4 && lastModified == reg.at(3)) {
       
   644         qt_version = reg.at(0).toUInt(0, 16);
       
   645         debug = bool(reg.at(1).toInt());
       
   646         key = reg.at(2).toLatin1();
       
   647         success = qt_version != 0;
       
   648     } else {
       
   649 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)
       
   650         if (!pHnd) {
       
   651             // use unix shortcut to avoid loading the library
       
   652             success = qt_unix_query(fileName, &qt_version, &debug, &key, this);
       
   653         } else
       
   654 #endif
       
   655         {
       
   656             bool temporary_load = false;
       
   657 #ifdef Q_OS_WIN
       
   658             HMODULE hTempModule = 0;
       
   659 #endif
       
   660             if (!pHnd) {
       
   661 #ifdef Q_OS_WIN
       
   662                 hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES);
       
   663 #else
       
   664 #  if defined(Q_OS_SYMBIAN)
       
   665                 //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists
       
   666                 if (fileinfo.exists())
       
   667 #  endif
       
   668                 temporary_load =  load_sys();
       
   669 #endif
       
   670             }
       
   671 #  ifdef Q_CC_BOR
       
   672             typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();
       
   673 #  else
       
   674             typedef const char * (*QtPluginQueryVerificationDataFunction)();
       
   675 #  endif
       
   676 #ifdef Q_OS_WIN
       
   677             QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule
       
   678                 ? (QtPluginQueryVerificationDataFunction)
       
   679 #ifdef Q_OS_WINCE
       
   680                     ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
       
   681 #else
       
   682                     ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
       
   683 #endif
       
   684                 : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
       
   685 #else
       
   686             QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
       
   687 #  if defined(Q_OS_SYMBIAN)
       
   688             if (temporary_load) {
       
   689                 qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
       
   690                 // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal
       
   691                 if (!qtPluginQueryVerificationDataFunction)
       
   692                     qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1");
       
   693             }
       
   694 #  else
       
   695             qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
       
   696 #  endif
       
   697 #endif
       
   698 
       
   699             if (!qtPluginQueryVerificationDataFunction
       
   700                 || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) {
       
   701                 qt_version = 0;
       
   702                 key = "unknown";
       
   703                 if (temporary_load)
       
   704                     unload_sys();
       
   705             } else {
       
   706                 success = true;
       
   707             }
       
   708 #ifdef Q_OS_WIN
       
   709             if (hTempModule) {
       
   710                 BOOL ok = ::FreeLibrary(hTempModule);
       
   711                 if (ok) {
       
   712                     hTempModule = 0;
       
   713                 }
       
   714 
       
   715             }
       
   716 #endif
       
   717         }
       
   718 
       
   719         // Qt 4.5 compatibility: stl doesn't affect binary compatibility
       
   720         key.replace(" no-stl", "");
       
   721 
       
   722 #ifndef QT_NO_SETTINGS
       
   723         QStringList queried;
       
   724         queried << QString::number(qt_version,16)
       
   725                 << QString::number((int)debug)
       
   726                 << QLatin1String(key)
       
   727                 << lastModified;
       
   728         settings->setValue(regkey, queried);
       
   729 #endif
       
   730     }
       
   731 
       
   732     if (!success) {
       
   733         if (errorString.isEmpty()){
       
   734             if (fileName.isEmpty())
       
   735                 errorString = QLibrary::tr("The shared library was not found.");
       
   736             else
       
   737                 errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
       
   738         }
       
   739         return false;
       
   740     }
       
   741 
       
   742     pluginState = IsNotAPlugin; // be pessimistic
       
   743 
       
   744     if ((qt_version > QT_VERSION) || ((QT_VERSION & 0xff0000) > (qt_version & 0xff0000))) {
       
   745         if (qt_debug_component()) {
       
   746             qWarning("In %s:\n"
       
   747                  "  Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
       
   748                  (const char*) QFile::encodeName(fileName),
       
   749                  (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
       
   750                  debug ? "debug" : "release");
       
   751         }
       
   752         errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
       
   753             .arg(fileName)
       
   754             .arg((qt_version&0xff0000) >> 16)
       
   755             .arg((qt_version&0xff00) >> 8)
       
   756             .arg(qt_version&0xff)
       
   757             .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
       
   758     } else if (key != QT_BUILD_KEY
       
   759 #ifdef QT_BUILD_KEY_COMPAT
       
   760                // be sure to load plugins using an older but compatible build key
       
   761                && key != QT_BUILD_KEY_COMPAT
       
   762 #endif
       
   763                ) {
       
   764         if (qt_debug_component()) {
       
   765             qWarning("In %s:\n"
       
   766                  "  Plugin uses incompatible Qt library\n"
       
   767                  "  expected build key \"%s\", got \"%s\"",
       
   768                  (const char*) QFile::encodeName(fileName),
       
   769                  QT_BUILD_KEY,
       
   770                  key.isEmpty() ? "<null>" : (const char *) key);
       
   771         }
       
   772         errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
       
   773                  " Expected build key \"%2\", got \"%3\"")
       
   774                  .arg(fileName)
       
   775                  .arg(QLatin1String(QT_BUILD_KEY))
       
   776                  .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key));
       
   777 #ifndef QT_NO_DEBUG_PLUGIN_CHECK
       
   778     } else if(debug != QLIBRARY_AS_DEBUG) {
       
   779         //don't issue a qWarning since we will hopefully find a non-debug? --Sam
       
   780         errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
       
   781                  " (Cannot mix debug and release libraries.)").arg(fileName);
       
   782 #endif
       
   783     } else {
       
   784         pluginState = IsAPlugin;
       
   785     }
       
   786 
       
   787     return pluginState == IsAPlugin;
       
   788 #else
       
   789     Q_UNUSED(settings);
       
   790     return pluginState == MightBeAPlugin;
       
   791 #endif
       
   792 }
       
   793 
       
   794 /*!
       
   795     Loads the library and returns true if the library was loaded
       
   796     successfully; otherwise returns false. Since resolve() always
       
   797     calls this function before resolving any symbols it is not
       
   798     necessary to call it explicitly. In some situations you might want
       
   799     the library loaded in advance, in which case you would use this
       
   800     function.
       
   801 
       
   802     \sa unload()
       
   803 */
       
   804 bool QLibrary::load()
       
   805 {
       
   806     if (!d)
       
   807         return false;
       
   808     if (did_load)
       
   809         return d->pHnd;
       
   810     did_load = true;
       
   811     return d->load();
       
   812 }
       
   813 
       
   814 /*!
       
   815     Unloads the library and returns true if the library could be
       
   816     unloaded; otherwise returns false.
       
   817 
       
   818     This happens automatically on application termination, so you
       
   819     shouldn't normally need to call this function.
       
   820 
       
   821     If other instances of QLibrary are using the same library, the
       
   822     call will fail, and unloading will only happen when every instance
       
   823     has called unload().
       
   824 
       
   825     Note that on Mac OS X 10.3 (Panther), dynamic libraries cannot be unloaded.
       
   826 
       
   827     \sa resolve(), load()
       
   828 */
       
   829 bool QLibrary::unload()
       
   830 {
       
   831     if (did_load) {
       
   832         did_load = false;
       
   833         return d->unload();
       
   834     }
       
   835     return false;
       
   836 }
       
   837 
       
   838 /*!
       
   839     Returns true if the library is loaded; otherwise returns false.
       
   840 
       
   841     \sa load()
       
   842  */
       
   843 bool QLibrary::isLoaded() const
       
   844 {
       
   845     return d && d->pHnd;
       
   846 }
       
   847 
       
   848 
       
   849 /*!
       
   850     Constructs a library with the given \a parent.
       
   851  */
       
   852 QLibrary::QLibrary(QObject *parent)
       
   853     :QObject(parent), d(0), did_load(false)
       
   854 {
       
   855 }
       
   856 
       
   857 
       
   858 /*!
       
   859     Constructs a library object with the given \a parent that will
       
   860     load the library specified by \a fileName.
       
   861 
       
   862     We recommend omitting the file's suffix in \a fileName, since
       
   863     QLibrary will automatically look for the file with the appropriate
       
   864     suffix in accordance with the platform, e.g. ".so" on Unix,
       
   865     ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
       
   866 
       
   867     Note: In Symbian the path portion of the \a fileName is ignored.
       
   868  */
       
   869 QLibrary::QLibrary(const QString& fileName, QObject *parent)
       
   870     :QObject(parent), d(0), did_load(false)
       
   871 {
       
   872     setFileName(fileName);
       
   873 }
       
   874 
       
   875 
       
   876 /*!
       
   877     Constructs a library object with the given \a parent that will
       
   878     load the library specified by \a fileName and major version number \a verNum.
       
   879     Currently, the version number is ignored on Windows and Symbian.
       
   880 
       
   881     We recommend omitting the file's suffix in \a fileName, since
       
   882     QLibrary will automatically look for the file with the appropriate
       
   883     suffix in accordance with the platform, e.g. ".so" on Unix,
       
   884     ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
       
   885 
       
   886     Note: In Symbian the path portion of the \a fileName is ignored.
       
   887 */
       
   888 QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
       
   889     :QObject(parent), d(0), did_load(false)
       
   890 {
       
   891     setFileNameAndVersion(fileName, verNum);
       
   892 }
       
   893 
       
   894 /*!
       
   895     Constructs a library object with the given \a parent that will
       
   896     load the library specified by \a fileName and full version number \a version.
       
   897     Currently, the version number is ignored on Windows and Symbian.
       
   898 
       
   899     We recommend omitting the file's suffix in \a fileName, since
       
   900     QLibrary will automatically look for the file with the appropriate
       
   901     suffix in accordance with the platform, e.g. ".so" on Unix,
       
   902     ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
       
   903 
       
   904     Note: In Symbian the path portion of the \a fileName is ignored.
       
   905  */
       
   906 QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
       
   907     :QObject(parent), d(0), did_load(false)
       
   908 {
       
   909     setFileNameAndVersion(fileName, version);
       
   910 }
       
   911 
       
   912 /*!
       
   913     Destroys the QLibrary object.
       
   914 
       
   915     Unless unload() was called explicitly, the library stays in memory
       
   916     until the application terminates.
       
   917 
       
   918     \sa isLoaded(), unload()
       
   919 */
       
   920 QLibrary::~QLibrary()
       
   921 {
       
   922     if (d)
       
   923         d->release();
       
   924 }
       
   925 
       
   926 
       
   927 /*!
       
   928     \property QLibrary::fileName
       
   929     \brief the file name of the library
       
   930 
       
   931     We recommend omitting the file's suffix in the file name, since
       
   932     QLibrary will automatically look for the file with the appropriate
       
   933     suffix (see isLibrary()).
       
   934 
       
   935     When loading the library, QLibrary searches in all system-specific
       
   936     library locations (e.g. \c LD_LIBRARY_PATH on Unix), unless the
       
   937     file name has an absolute path. After loading the library
       
   938     successfully, fileName() returns the fully-qualified file name of
       
   939     the library, including the full path to the library if one was given
       
   940     in the constructor or passed to setFileName().
       
   941 
       
   942     For example, after successfully loading the "GL" library on Unix
       
   943     platforms, fileName() will return "libGL.so". If the file name was
       
   944     originally passed as "/usr/lib/libGL", fileName() will return
       
   945     "/usr/lib/libGL.so".
       
   946 
       
   947     Note: In Symbian the path portion of the \a fileName is ignored.
       
   948 */
       
   949 
       
   950 void QLibrary::setFileName(const QString &fileName)
       
   951 {
       
   952     QLibrary::LoadHints lh;
       
   953     if (d) {
       
   954         lh = d->loadHints;
       
   955         d->release();
       
   956         d = 0;
       
   957         did_load = false;
       
   958     }
       
   959     d = QLibraryPrivate::findOrCreate(fileName);
       
   960     d->loadHints = lh;
       
   961 }
       
   962 
       
   963 QString QLibrary::fileName() const
       
   964 {
       
   965     if (d)
       
   966         return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
       
   967     return QString();
       
   968 }
       
   969 
       
   970 /*!
       
   971     \fn void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)
       
   972 
       
   973     Sets the fileName property and major version number to \a fileName
       
   974     and \a versionNumber respectively.
       
   975     The \a versionNumber is ignored on Windows and Symbian.
       
   976 
       
   977     Note: In Symbian the path portion of the \a fileName is ignored.
       
   978 
       
   979     \sa setFileName()
       
   980 */
       
   981 void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
       
   982 {
       
   983     QLibrary::LoadHints lh;
       
   984     if (d) {
       
   985         lh = d->loadHints;
       
   986         d->release();
       
   987         d = 0;
       
   988         did_load = false;
       
   989     }
       
   990     d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
       
   991     d->loadHints = lh;
       
   992 }
       
   993 
       
   994 /*!
       
   995     \since 4.4
       
   996 
       
   997     Sets the fileName property and full version number to \a fileName
       
   998     and \a version respectively.
       
   999     The \a version parameter is ignored on Windows and Symbian.
       
  1000 
       
  1001     Note: In Symbian the path portion of the \a fileName is ignored.
       
  1002 
       
  1003     \sa setFileName()
       
  1004 */
       
  1005 void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)
       
  1006 {
       
  1007     QLibrary::LoadHints lh;
       
  1008     if (d) {
       
  1009         lh = d->loadHints;
       
  1010         d->release();
       
  1011         d = 0;
       
  1012         did_load = false;
       
  1013     }
       
  1014     d = QLibraryPrivate::findOrCreate(fileName, version);
       
  1015     d->loadHints = lh;
       
  1016 }
       
  1017 
       
  1018 /*!
       
  1019     Returns the address of the exported symbol \a symbol. The library is
       
  1020     loaded if necessary. The function returns 0 if the symbol could
       
  1021     not be resolved or if the library could not be loaded.
       
  1022 
       
  1023     Example:
       
  1024     \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 2
       
  1025 
       
  1026     The symbol must be exported as a C function from the library. This
       
  1027     means that the function must be wrapped in an \c{extern "C"} if
       
  1028     the library is compiled with a C++ compiler. On Windows you must
       
  1029     also explicitly export the function from the DLL using the
       
  1030     \c{__declspec(dllexport)} compiler directive, for example:
       
  1031 
       
  1032     \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 3
       
  1033 
       
  1034     with \c MY_EXPORT defined as
       
  1035 
       
  1036     \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 4
       
  1037 
       
  1038     Note: In Symbian resolving with symbol names works only if the loaded
       
  1039     library was built as STDDLL. Otherwise, the ordinals must be used.
       
  1040 */
       
  1041 void *QLibrary::resolve(const char *symbol)
       
  1042 {
       
  1043     if (!load())
       
  1044         return 0;
       
  1045     return d->resolve(symbol);
       
  1046 }
       
  1047 
       
  1048 /*!
       
  1049     \overload
       
  1050 
       
  1051     Loads the library \a fileName and returns the address of the
       
  1052     exported symbol \a symbol. Note that \a fileName should not
       
  1053     include the platform-specific file suffix; (see \l{fileName}). The
       
  1054     library remains loaded until the application exits.
       
  1055 
       
  1056     The function returns 0 if the symbol could not be resolved or if
       
  1057     the library could not be loaded.
       
  1058 
       
  1059     Note: In Symbian resolving with symbol names works only if the loaded
       
  1060     library was built as STDDLL. Otherwise, the ordinals must be used.
       
  1061 
       
  1062     \sa resolve()
       
  1063 */
       
  1064 void *QLibrary::resolve(const QString &fileName, const char *symbol)
       
  1065 {
       
  1066     QLibrary library(fileName);
       
  1067     return library.resolve(symbol);
       
  1068 }
       
  1069 
       
  1070 /*!
       
  1071     \overload
       
  1072 
       
  1073     Loads the library \a fileName with major version number \a verNum and
       
  1074     returns the address of the exported symbol \a symbol.
       
  1075     Note that \a fileName should not include the platform-specific file suffix;
       
  1076     (see \l{fileName}). The library remains loaded until the application exits.
       
  1077     \a verNum is ignored on Windows.
       
  1078 
       
  1079     The function returns 0 if the symbol could not be resolved or if
       
  1080     the library could not be loaded.
       
  1081 
       
  1082     Note: In Symbian resolving with symbol names works only if the loaded
       
  1083     library was built as STDDLL. Otherwise, the ordinals must be used.
       
  1084 
       
  1085     \sa resolve()
       
  1086 */
       
  1087 void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
       
  1088 {
       
  1089     QLibrary library(fileName, verNum);
       
  1090     return library.resolve(symbol);
       
  1091 }
       
  1092 
       
  1093 /*!
       
  1094     \overload
       
  1095     \since 4.4
       
  1096 
       
  1097     Loads the library \a fileName with full version number \a version and
       
  1098     returns the address of the exported symbol \a symbol.
       
  1099     Note that \a fileName should not include the platform-specific file suffix;
       
  1100     (see \l{fileName}). The library remains loaded until the application exits.
       
  1101     \a version is ignored on Windows.
       
  1102 
       
  1103     The function returns 0 if the symbol could not be resolved or if
       
  1104     the library could not be loaded.
       
  1105 
       
  1106     Note: In Symbian resolving with symbol names works only if the loaded
       
  1107     library was built as STDDLL. Otherwise, the ordinals must be used.
       
  1108 
       
  1109     \sa resolve()
       
  1110 */
       
  1111 void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
       
  1112 {
       
  1113     QLibrary library(fileName, version);
       
  1114     return library.resolve(symbol);
       
  1115 }
       
  1116 
       
  1117 /*!
       
  1118     \fn QString QLibrary::library() const
       
  1119 
       
  1120     Use fileName() instead.
       
  1121 */
       
  1122 
       
  1123 /*!
       
  1124     \fn void QLibrary::setAutoUnload( bool b )
       
  1125 
       
  1126     Use load(), isLoaded(), and unload() as necessary instead.
       
  1127 */
       
  1128 
       
  1129 /*!
       
  1130     \since 4.2
       
  1131 
       
  1132     Returns a text string with the description of the last error that occurred.
       
  1133     Currently, errorString will only be set if load(), unload() or resolve() for some reason fails.
       
  1134 */
       
  1135 QString QLibrary::errorString() const
       
  1136 {
       
  1137     return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
       
  1138 }
       
  1139 
       
  1140 /*!
       
  1141     \property QLibrary::loadHints
       
  1142     \brief Give the load() function some hints on how it should behave.
       
  1143 
       
  1144     You can give some hints on how the symbols are resolved. Usually,
       
  1145     the symbols are not resolved at load time, but resolved lazily,
       
  1146     (that is, when resolve() is called). If you set the loadHint to
       
  1147     ResolveAllSymbolsHint, then all symbols will be resolved at load time
       
  1148     if the platform supports it.
       
  1149 
       
  1150     Setting ExportExternalSymbolsHint will make the external symbols in the
       
  1151     library available for resolution in subsequent loaded libraries.
       
  1152 
       
  1153     If LoadArchiveMemberHint is set, the file name
       
  1154     is composed of two components: A path which is a reference to an
       
  1155     archive file followed by the second component which is the reference to
       
  1156     the archive member. For instance, the fileName \c libGL.a(shr_64.o) will refer
       
  1157     to the library \c shr_64.o in the archive file named \c libGL.a. This
       
  1158     is only supported on the AIX platform.
       
  1159 
       
  1160     The interpretation of the load hints is platform dependent, and if
       
  1161     you use it you are probably making some assumptions on which platform
       
  1162     you are compiling for, so use them only if you understand the consequences
       
  1163     of them.
       
  1164 
       
  1165     By default, none of these flags are set, so libraries will be loaded with
       
  1166     lazy symbol resolution, and will not export external symbols for resolution
       
  1167     in other dynamically-loaded libraries.
       
  1168 */
       
  1169 void QLibrary::setLoadHints(LoadHints hints)
       
  1170 {
       
  1171     if (!d) {
       
  1172         d = QLibraryPrivate::findOrCreate(QString());   // ugly, but we need a d-ptr
       
  1173         d->errorString.clear();
       
  1174     }
       
  1175     d->loadHints = hints;
       
  1176 }
       
  1177 
       
  1178 QLibrary::LoadHints QLibrary::loadHints() const
       
  1179 {
       
  1180     return d ? d->loadHints : (QLibrary::LoadHints)0;
       
  1181 }
       
  1182 
       
  1183 /* Internal, for debugging */
       
  1184 bool qt_debug_component()
       
  1185 {
       
  1186 #if defined(QT_DEBUG_COMPONENT)
       
  1187     return true;    //compatibility?
       
  1188 #else
       
  1189     static int debug_env = -1;
       
  1190     if (debug_env == -1)
       
  1191        debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt();
       
  1192 
       
  1193     return debug_env != 0;
       
  1194 #endif
       
  1195 }
       
  1196 
       
  1197 QT_END_NAMESPACE
       
  1198 
       
  1199 #endif // QT_NO_LIBRARY