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