00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <stdarg.h>
00027 #include <sys/time.h>
00028
00029 #include <qdir.h>
00030 #include <qfile.h>
00031 #include <qfileinfo.h>
00032 #include <qregexp.h>
00033 #include <qapplication.h>
00034 #include <qmetaobject.h>
00035
00036 #ifdef KLFBACKEND_QT4
00037 #include <QDebug>
00038 #endif
00039
00040 #include "klfdefs.h"
00041 #include "klfqt34common.h"
00042
00711
00712
00736 static char __klf_version_string[] = KLF_VERSION_STRING;
00737
00738
00739 KLF_EXPORT const char * klfVersion()
00740 {
00741 return __klf_version_string;
00742 }
00743
00744 KLF_EXPORT int klfVersionMaj()
00745 {
00746 return KLF_VERSION_MAJ;
00747 }
00748 KLF_EXPORT int klfVersionMin()
00749 {
00750 return KLF_VERSION_MIN;
00751 }
00752 KLF_EXPORT int klfVersionRelease()
00753 {
00754 return KLF_VERSION_REL;
00755 }
00756
00757
00758
00759
00760
00761
00762 struct KLFDebugObjectWatcherPrivate
00763 {
00764 QMap<quintptr, QString> refInfos;
00765 };
00766
00767
00768 KLFDebugObjectWatcher *KLFDebugObjectWatcher::instance = NULL;
00769
00770 KLFDebugObjectWatcher *KLFDebugObjectWatcher::getWatcher()
00771 {
00772 if (instance == NULL)
00773 instance = new KLFDebugObjectWatcher;
00774 return instance;
00775 }
00776
00777 void KLFDebugObjectWatcher::registerObjectRefInfo(QObject *object, const QString& refinfo)
00778 {
00779 p->refInfos[(quintptr)object] = refinfo;
00780 }
00781
00782 KLFDebugObjectWatcher::KLFDebugObjectWatcher()
00783 : QObject(qApp)
00784 {
00785 p = new KLFDebugObjectWatcherPrivate;
00786 }
00787 KLFDebugObjectWatcher::~KLFDebugObjectWatcher()
00788 {
00789 delete p;
00790 }
00791 void KLFDebugObjectWatcher::debugObjectDestroyed(QObject *object)
00792 {
00793 quintptr obji = (quintptr) object;
00794 if (p->refInfos.contains(obji)) {
00795 klfDbg(klfFmtCC("Object destroyed: (%s*)%p; object reference name is `%s'",
00796 (object ? object->metaObject()->className() : "void"),
00797 object, qPrintable(p->refInfos[obji])));
00798 } else {
00799 klfDbg(klfFmtCC("Object destroyed: (%s*)%p",
00800 (object ? object->metaObject()->className() : "void"),
00801 object));
00802 }
00803 }
00804
00805
00806
00807 KLF_EXPORT QByteArray klfShortFuncSignature(const QByteArray& ba_funcname)
00808 {
00809 QString funcname(ba_funcname);
00810
00811 int iSpc, iParen;
00812 #ifdef KLFBACKEND_QT4
00813 iParen = funcname.indexOf('(');
00814 iSpc = funcname.lastIndexOf(' ', iParen-2);
00815 #else
00816 iParen = funcname.find('(');
00817 iSpc = funcname.findRev(' ', iParen-2);
00818 #endif
00819
00820 if (iParen == -1 || iSpc > iParen) {
00821 qWarning("klfShortFuncSignature('%s'): Signature parse error!", qPrintable(funcname));
00822 return ba_funcname;
00823 }
00824
00825 QString f = funcname.mid(iSpc+1, iParen-(iSpc+1));
00826 QByteArray data = f.s_toLocal8Bit();
00827 return data;
00828 }
00829
00830
00831
00832
00833 KLF_EXPORT QByteArray klfFmt(const char * fmt, va_list pp)
00834 {
00835 static const int bufferSize = 8192;
00836 char buffer[bufferSize];
00837 int len;
00838 #if defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || defined(_ISOC99_SOURCE)
00839
00840 len = vsnprintf(buffer, bufferSize, fmt, pp);
00841 if (len >= bufferSize) {
00842
00843 qWarning("%s(): output from format string \"%s\" was truncated from %d to %d bytes.",
00844 KLF_FUNC_NAME, fmt, len, (bufferSize-1));
00845 len = bufferSize-1;
00846 }
00847 #else
00848 len = vsprintf(buffer, fmt, pp);
00849 #endif
00850
00851 if (len < 0) {
00852 qWarning("%s(): vs(n)printf() failed for format \"%s\"", KLF_FUNC_NAME, fmt);
00853 return QByteArray();
00854 }
00855
00856
00857 QByteArray data;
00858 #ifdef KLFBACKEND_QT4
00859 data = QByteArray(buffer, len);
00860 #else
00861 data.duplicate(buffer, len);
00862 #endif
00863 return data;
00864 }
00865
00866 KLF_EXPORT QByteArray klfFmt(const char * fmt, ...)
00867 {
00868 va_list pp;
00869 va_start(pp, fmt);
00870 QByteArray data = klfFmt(fmt, pp);
00871 va_end(pp);
00872 return data;
00873 }
00874
00875
00876 KLF_EXPORT QString klfTimeOfDay(bool shortfmt)
00877 {
00878 struct timeval tv;
00879 gettimeofday(&tv, NULL);
00880 char temp[128];
00881 if (shortfmt)
00882 sprintf(temp, "%03ld.%06ld", (ulong)tv.tv_sec % 1000, (ulong)tv.tv_usec);
00883 else
00884 sprintf(temp, "%ld.%06ld", (ulong)tv.tv_sec, (ulong)tv.tv_usec);
00885 return QString::fromAscii(temp);
00886 }
00887
00888
00889 #ifdef KLF_DEBUG
00890 static int __klf_dbg_block_depth_counter = 0;
00891 #endif
00892
00893 KLFDebugBlock::KLFDebugBlock(const QString& blockName)
00894 : pBlockName(blockName), pPrintMsg(true)
00895 {
00896 #ifdef KLF_DEBUG
00897 qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
00898 #endif
00899 }
00900 KLFDebugBlock::KLFDebugBlock(bool printmsg, const QString& blockName)
00901 : pBlockName(blockName), pPrintMsg(printmsg)
00902 {
00903 #ifdef KLF_DEBUG
00904
00905 if (printmsg)
00906 qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
00907 #endif
00908 }
00909 KLFDebugBlock::~KLFDebugBlock()
00910 {
00911 #ifdef KLF_DEBUG
00912
00913 if (pPrintMsg)
00914 qDebug("%s: [%02d]block end", qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
00915 #endif
00916 }
00917 KLFDebugBlockTimer::KLFDebugBlockTimer(const QString& blockName)
00918 : KLFDebugBlock(false, blockName)
00919 {
00920 #ifdef KLF_DEBUG
00921
00922 qDebug("+T:%s: %s: [%02d]block begin", KLF_SHORT_TIME, qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
00923 #endif
00924 }
00925 KLFDebugBlockTimer::~KLFDebugBlockTimer()
00926 {
00927 #ifdef KLF_DEBUG
00928
00929 qDebug("+T:%s: %s: [%02d]block end", KLF_SHORT_TIME, qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
00930 #endif
00931 }
00932
00933
00934
00935 #ifdef KLFBACKEND_QT4
00936
00937 KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char * funcname, const char *refinstance, const char * shorttime)
00938 {
00939 if (shorttime == NULL)
00940 return dbg.nospace()<<funcname<<"():"<<refinstance<<"\n ";
00941 else
00942 return dbg.nospace()<<"+T:"<<shorttime<<": "<<funcname<<"():"<<refinstance<<"\n ";
00943 }
00944
00945 #else
00946
00947 int __klf_dbg_string_obj::operator=(const QString& msg)
00948 {
00949 # ifdef KLF_DEBUG
00950 qDebug("%s", qPrintable(hdr + msg));
00951 # endif
00952 return 0;
00953 }
00954 KLF_EXPORT __klf_dbg_string_obj
00955 __klf_dbg_hdr_qt3(const char *funcname, const char *refinstance, const char *shorttime)
00956 {
00957 # ifdef KLF_DEBUG
00958 QString s;
00959 if (shorttime == NULL)
00960 s = QString::fromLocal8Bit(funcname) + "():" + refinstance + "\n ";
00961 else
00962 s = QString::fromLocal8Bit("+T:") + shorttime + ": " + funcname + "(): " + refinstance + "\n ";
00963 return __klf_dbg_string_obj(s);
00964 # else
00965 return __klf_dbg_string_obj(QString());
00966 # endif
00967 }
00968
00969 #endif
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 KLF_EXPORT QString KLFSysInfo::arch()
00980 {
00981 return KLF_CMAKE_ARCH;
00982 }
00983
00984 KLF_EXPORT KLFSysInfo::Os KLFSysInfo::os()
00985 {
00986 #if defined(Q_OS_LINUX)
00987 return Linux;
00988 #elif defined(Q_OS_DARWIN)
00989 return MacOsX;
00990 #elif defined(Q_OS_WIN32)
00991 return Win32;
00992 #else
00993 return OtherOs;
00994 #endif
00995 }
00996
00997 KLF_EXPORT QString KLFSysInfo::osString(Os sysos)
00998 {
00999 switch (sysos) {
01000 case Linux: return QLatin1String("linux");
01001 case MacOsX: return QLatin1String("macosx");
01002 case Win32: return QLatin1String("win32");
01003 case OtherOs: return QString();
01004 default: ;
01005 }
01006 qWarning("KLFSysInfo::osString: unknown OS: %d", sysos);
01007 return QString();
01008 }
01009
01010
01011 QStringList klf_version_suffixes =
01012 QStringList() << "a" << "alpha" << "b" << "beta" << "p" << "pre" << "preview" << "RC" << "rc"
01013 << ""
01014 << "post" << "dev" << "devel";
01015
01016 static int __klf_version_compare_suffix_words(QString w1, QString w2)
01017 {
01018
01019 const QStringList& words = klf_version_suffixes;
01020
01021 int borderBeforeAfter = words.list_indexOf("");
01022 if (borderBeforeAfter < 0)
01023 qWarning("klfVersionCompare: suffix words list doesn't contain \"\"!");
01024 int i1 = words.list_indexOf(w1);
01025 int i2 = words.list_indexOf(w2);
01026 if (i1 == -1 && i2 == -1)
01027 return QString::compare(w1, w2);
01028 if (i2 == -1)
01029 return i1 < borderBeforeAfter ? -1 : +1;
01030 if (i1 == -1)
01031 return i2 < borderBeforeAfter ? +1 : -1;
01032
01033 return i1 - i2;
01034 }
01035
01036
01037 KLF_EXPORT int klfVersionCompare(const QString& v1, const QString& v2)
01038 {
01039 qDebug("klfVersionCompare(): Comparing versions %s and %s", qPrintable(v1), qPrintable(v2));
01040 if (v1 == v2)
01041 return 0;
01042 if (v1.isEmpty())
01043 return -1;
01044 if (v2.isEmpty())
01045 return 1;
01046
01047 QRegExp rx1("^(\\d+)(\\.(\\d+)(\\.(\\d+)([a-zA-Z]+\\d*)?)?)?$");
01048 QRegExp rx2(rx1);
01049 if (!rx1.exactMatch(v1)) {
01050 qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v1));
01051 return -200;
01052 }
01053 if (!rx2.exactMatch(v2)) {
01054 qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v2));
01055 return -200;
01056 }
01057 int maj1 = rx1.cap(1).toInt();
01058 int maj2 = rx2.cap(1).toInt();
01059 if (maj1 != maj2)
01060 return maj1 - maj2;
01061 bool hasmin1 = !rx1.cap(2).isEmpty();
01062 bool hasmin2 = !rx2.cap(2).isEmpty();
01063 if ( ! hasmin1 && ! hasmin2 )
01064 return 0;
01065 if ( ! hasmin1 && hasmin2 )
01066 return -1;
01067 if ( hasmin1 && ! hasmin2 )
01068 return +1;
01069 int min1 = rx1.cap(3).toInt();
01070 int min2 = rx2.cap(3).toInt();
01071 if ( min1 != min2 )
01072 return min1 - min2;
01073
01074 bool hasrel1 = !rx1.cap(4).isEmpty();
01075 bool hasrel2 = !rx2.cap(4).isEmpty();
01076 if ( ! hasrel1 && ! hasrel2 )
01077 return 0;
01078 if ( ! hasrel1 && hasrel2 )
01079 return -1;
01080 if ( hasrel1 && ! hasrel2 )
01081 return +1;
01082 int rel1 = rx1.cap(5).toInt();
01083 int rel2 = rx2.cap(5).toInt();
01084 if ( rel1 != rel2 )
01085 return rel1 - rel2;
01086
01087 QString suffix1 = rx1.cap(6);
01088 QString suffix2 = rx2.cap(6);
01089
01090
01091
01092 if (suffix1 == suffix2)
01093 return 0;
01094
01095
01096 QRegExp rxs1("^([a-zA-Z]*)(\\d*)$");
01097 QRegExp rxs2(rxs1);
01098 rxs1.exactMatch(suffix1);
01099 rxs2.exactMatch(suffix2);
01100
01101 QString w1 = rxs1.cap(1);
01102 QString w2 = rxs2.cap(1);
01103 QString ns1 = rxs1.cap(2);
01104 QString ns2 = rxs2.cap(2);
01105
01106 int cmp = __klf_version_compare_suffix_words(w1, w2);
01107 if (cmp != 0)
01108 return cmp;
01109
01110
01111 if (ns1.isEmpty()) {
01112 if (ns2.isEmpty())
01113 return 0;
01114
01115 return -1;
01116 }
01117 if (ns2.isEmpty()) {
01118 return +1;
01119 }
01120
01121 int n1 = ns1.toInt();
01122 int n2 = ns2.toInt();
01123 return n1 - n2;
01124 }
01125
01126 KLF_EXPORT bool klfVersionCompareLessThan(const QString& v1, const QString& v2)
01127 {
01128 return klfVersionCompare(v1,v2) < 0;
01129 }
01130
01131
01132
01133
01134 static QStringList __search_find_test(const QString& root, const QStringList& pathlist,
01135 int level, int limit)
01136 {
01137 if (limit == 0)
01138 return QStringList();
01139
01140 if (limit < 0)
01141 limit = -1;
01142
01143 QStringList newpathlist = pathlist;
01144
01145 QStringList levelpathlist;
01146 int k;
01147 for (k = 0; k < level; ++k) { levelpathlist << newpathlist[k]; }
01148
01149 QString flpath = root+levelpathlist.join("/");
01150 QFileInfo flinfo(flpath);
01151 if (flinfo.isDir()) {
01152 QDir d(flpath);
01153 QStringList entries;
01154 #ifdef KLFBACKEND_QT4
01155 entries = d.entryList(QStringList()<<pathlist[level]);
01156 #else
01157 entries = d.entryList(pathlist[level]);
01158 #endif
01159 QStringList hitlist;
01160 for (k = 0; k < (int)entries.size(); ++k) {
01161 newpathlist[level] = entries[k];
01162 hitlist += __search_find_test(root, newpathlist, level+1, limit - hitlist.size());
01163 if (limit >= 0 && (int)hitlist.size() >= limit)
01164 break;
01165 }
01166 return hitlist;
01167 }
01168 if (flinfo.exists()) {
01169 return QStringList() << dir_native_separators(root+pathlist.join("/"));
01170 }
01171 return QStringList();
01172 }
01173
01174 KLF_EXPORT QStringList klfSearchFind(const QString& wildcard_expression, int limit)
01175 {
01176 klfDbg("looking for "+wildcard_expression) ;
01177
01178 QString expr;
01179 #ifdef KLFBACKEND_QT4
01180 expr = QDir::fromNativeSeparators(wildcard_expression);
01181 #else
01182 expr = wildcard_expression; expr.replace(QDir::separator(), "/");
01183 #endif
01184 QStringList pathlist = str_split(expr, "/", false);
01185 QString root = "/";
01186 static QRegExp driveregexp("^[A-Za-z]:$");
01187 if (driveregexp.exactMatch(pathlist[0])) {
01188
01189 root = pathlist[0]+"/";
01190 pathlist.pop_front();
01191 }
01192 return __search_find_test(root, pathlist, 0, limit);
01193 }
01194
01195 KLF_EXPORT QString klfSearchPath(const QString& programName, const QString& extra_path)
01196 {
01197 static const QString PATH = getenv("PATH");
01198 static const QString pathsep = QString("")+KLF_PATH_SEP;
01199
01200 QString path = PATH;
01201 if (!extra_path.isEmpty())
01202 path = extra_path + pathsep + path;
01203
01204 const QStringList paths = str_split(path, pathsep, true);
01205 QString test;
01206 int k, j;
01207 for (k = 0; k < (int)paths.size(); ++k) {
01208 klfDbg("searching in "+paths[k]) ;
01209 QStringList hits = klfSearchFind(paths[k]+"/"+programName);
01210 klfDbg("\t...resulting in hits = "+hits.join(" ;; ")) ;
01211 for (j = 0; j < (int)hits.size(); ++j) {
01212 if ( QFileInfo(hits[j]).isExecutable() ) {
01213 klfDbg("\tFound definitive (executable) hit at "+hits[j]) ;
01214 return hits[j];
01215 }
01216 }
01217 }
01218 return QString::null;
01219 }
01220
01221
01222
01223
01224