[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project
klfdefs.cpp
1 /***************************************************************************
2  * file klfdefs.cpp
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist at bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id: klfdefs.cpp 603 2011-02-26 23:14:55Z phfaist $ */
23 
24 #include <stdlib.h>
25 #include <stdio.h> // vsprintf(), vsnprintf
26 #include <stdarg.h> // va_list, va_arg, va_end in klfFmt()
27 #include <sys/time.h>
28 
29 #include <qdir.h>
30 #include <qfile.h>
31 #include <qfileinfo.h>
32 #include <qregexp.h>
33 #include <qapplication.h>
34 #include <qmetaobject.h>
35 
36 #ifdef KLFBACKEND_QT4
37 #include <QDebug>
38 #endif
39 
40 #include "klfdefs.h"
41 #include "klfqt34common.h"
42 
744 // INTERNAL
745 
769 static char __klf_version_string[] = KLF_VERSION_STRING;
770 
771 
772 KLF_EXPORT const char * klfVersion()
773 {
774  return __klf_version_string;
775 }
776 
777 KLF_EXPORT int klfVersionMaj()
778 {
779  return KLF_VERSION_MAJ;
780 }
781 KLF_EXPORT int klfVersionMin()
782 {
783  return KLF_VERSION_MIN;
784 }
785 KLF_EXPORT int klfVersionRelease()
786 {
787  return KLF_VERSION_REL;
788 }
789 
790 
791 
792 
793 // declared in klfdebug.h
794 
795 struct KLFDebugObjectWatcherPrivate
796 {
797  QMap<quintptr, QString> refInfos;
798 };
799 
800 // static
801 KLFDebugObjectWatcher *KLFDebugObjectWatcher::instance = NULL;
802 // static
803 KLFDebugObjectWatcher *KLFDebugObjectWatcher::getWatcher()
804 {
805  if (instance == NULL)
806  instance = new KLFDebugObjectWatcher;
807  return instance;
808 }
809 
810 void KLFDebugObjectWatcher::registerObjectRefInfo(QObject *object, const QString& refinfo)
811 {
812  p->refInfos[(quintptr)object] = refinfo;
813 }
814 
815 KLFDebugObjectWatcher::KLFDebugObjectWatcher()
816  : QObject(qApp)
817 {
818  p = new KLFDebugObjectWatcherPrivate;
819 }
820 KLFDebugObjectWatcher::~KLFDebugObjectWatcher()
821 {
822  delete p;
823 }
824 void KLFDebugObjectWatcher::debugObjectDestroyed(QObject *object)
825 {
826  quintptr obji = (quintptr) object;
827  if (p->refInfos.contains(obji)) {
828  klfDbg(klfFmtCC("Object destroyed: (%s*)%p; object reference name is `%s'",
829  (object ? object->metaObject()->className() : "void"),
830  object, qPrintable(p->refInfos[obji])));
831  } else {
832  klfDbg(klfFmtCC("Object destroyed: (%s*)%p",
833  (object ? object->metaObject()->className() : "void"),
834  object));
835  }
836 }
837 
838 
839 
840 KLF_EXPORT QByteArray klfShortFuncSignature(const QByteArray& ba_funcname)
841 {
842  QString funcname(ba_funcname);
843  // returns the section between the last space before the first open paren and the first open paren
844  int iSpc, iParen;
845 #ifdef KLFBACKEND_QT4
846  iParen = funcname.indexOf('(');
847  iSpc = funcname.lastIndexOf(' ', iParen-2);
848 #else
849  iParen = funcname.find('(');
850  iSpc = funcname.findRev(' ', iParen-2);
851 #endif
852  // if iSpc is -1, leave it at -1 (eg. constructor signature), the following code still works.
853  if (iParen == -1 || iSpc > iParen) {
854  qWarning("klfShortFuncSignature('%s'): Signature parse error!", qPrintable(funcname));
855  return ba_funcname;
856  }
857  // shorten name
858  QString f = funcname.mid(iSpc+1, iParen-(iSpc+1));
859  QByteArray data = f.s_toLocal8Bit();
860  return data;
861 }
862 
863 
864 
865 
866 KLF_EXPORT QByteArray klfFmt(const char * fmt, va_list pp)
867 {
868  static const int bufferSize = 8192;
869  char buffer[bufferSize];
870  int len;
871 #if defined(_BSD_SOURCE) || _XOPEN_SOURCE >= 500 || defined(_ISOC99_SOURCE)
872  // stdio.h provided vsnprintf()
873  len = vsnprintf(buffer, bufferSize, fmt, pp);
874  if (len >= bufferSize) {
875  // output was truncated
876  qWarning("%s(): output from format string \"%s\" was truncated from %d to %d bytes.",
877  KLF_FUNC_NAME, fmt, len, (bufferSize-1));
878  len = bufferSize-1;
879  }
880 #else
881  len = vsprintf(buffer, fmt, pp);
882 #endif
883 
884  if (len < 0) {
885  qWarning("%s(): vs(n)printf() failed for format \"%s\"", KLF_FUNC_NAME, fmt);
886  return QByteArray();
887  }
888 
889  // create a QByteArray
890  QByteArray data;
891 #ifdef KLFBACKEND_QT4
892  data = QByteArray(buffer, len);
893 #else
894  data.duplicate(buffer, len);
895 #endif
896  return data;
897 }
898 
899 KLF_EXPORT QByteArray klfFmt(const char * fmt, ...)
900 {
901  va_list pp;
902  va_start(pp, fmt);
903  QByteArray data = klfFmt(fmt, pp);
904  va_end(pp);
905  return data;
906 }
907 
908 
909 KLF_EXPORT QString klfTimeOfDay(bool shortfmt)
910 {
911  struct timeval tv;
912  gettimeofday(&tv, NULL);
913  char temp[128];
914  if (shortfmt)
915  sprintf(temp, "%03ld.%06ld", (ulong)tv.tv_sec % 1000, (ulong)tv.tv_usec);
916  else
917  sprintf(temp, "%ld.%06ld", (ulong)tv.tv_sec, (ulong)tv.tv_usec);
918  return QString::fromAscii(temp);
919 }
920 
921 
922 #ifdef KLF_DEBUG
923 static int __klf_dbg_block_depth_counter = 0;
924 #endif
925 
926 KLFDebugBlock::KLFDebugBlock(const QString& blockName)
927  : pBlockName(blockName), pPrintMsg(true)
928 {
929 #ifdef KLF_DEBUG
930  qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
931 #endif
932 }
933 KLFDebugBlock::KLFDebugBlock(bool printmsg, const QString& blockName)
934  : pBlockName(blockName), pPrintMsg(printmsg)
935 {
936 #ifdef KLF_DEBUG
937  // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
938  if (printmsg)
939  qDebug("%s: [%02d]block begin", qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
940 #endif
941 }
942 KLFDebugBlock::~KLFDebugBlock()
943 {
944 #ifdef KLF_DEBUG
945  // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
946  if (pPrintMsg)
947  qDebug("%s: [%02d]block end", qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
948 #endif
949 }
950 KLFDebugBlockTimer::KLFDebugBlockTimer(const QString& blockName)
951  : KLFDebugBlock(false, blockName)
952 {
953 #ifdef KLF_DEBUG
954  // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
955  qDebug("+T:%s: %s: [%02d]block begin", KLF_SHORT_TIME, qPrintable(pBlockName), ++__klf_dbg_block_depth_counter);
956 #endif
957 }
958 KLFDebugBlockTimer::~KLFDebugBlockTimer()
959 {
960 #ifdef KLF_DEBUG
961  // convention: __klf_dbg_block_depth_counter is incremented/decremented only when displayed
962  qDebug("+T:%s: %s: [%02d]block end", KLF_SHORT_TIME, qPrintable(pBlockName), __klf_dbg_block_depth_counter--);
963 #endif
964 }
965 
966 // the following is defined for both debug and non-debug modes. In non-debug modes, it provides the symbol __klf_dbg_hdr
967 // for debugging eg. plugins compiled in debug mode (NEEDS TESTING...?)
968 #ifdef KLFBACKEND_QT4
969 // QT 4 >>
970 KLF_EXPORT QDebug __klf_dbg_hdr(QDebug dbg, const char * funcname, const char *refinstance, const char * shorttime)
971 {
972  if (shorttime == NULL)
973  return dbg.nospace()<<funcname<<"():"<<refinstance<<"\n ";
974  else
975  return dbg.nospace()<<"+T:"<<shorttime<<": "<<funcname<<"():"<<refinstance<<"\n ";
976 }
977 // << QT 4
978 #else
979 // QT 3 >>
980 int __klf_dbg_string_obj::operator=(const QString& msg)
981 {
982 # ifdef KLF_DEBUG
983  qDebug("%s", qPrintable(hdr + msg));
984 # endif
985  return 0;
986 }
987 KLF_EXPORT __klf_dbg_string_obj
988 /* */ __klf_dbg_hdr_qt3(const char *funcname, const char *refinstance, const char *shorttime)
989 {
990 # ifdef KLF_DEBUG
991  QString s;
992  if (shorttime == NULL)
993  s = QString::fromLocal8Bit(funcname) + "():" + refinstance + "\n ";
994  else
995  s = QString::fromLocal8Bit("+T:") + shorttime + ": " + funcname + "(): " + refinstance + "\n ";
996  return __klf_dbg_string_obj(s);
997 # else
998  return __klf_dbg_string_obj(QString());
999 # endif
1000 }
1001 // << QT 3
1002 #endif
1003 
1004 
1005 
1006 
1007 // ----------------------------------------------------------------------
1008 
1009 
1010 
1011 
1013 {
1014  return KLF_CMAKE_ARCH;
1015 }
1016 
1018 {
1019 #if defined(Q_OS_LINUX)
1020  return Linux;
1021 #elif defined(Q_OS_DARWIN)
1022  return MacOsX;
1023 #elif defined(Q_OS_WIN32)
1024  return Win32;
1025 #else
1026  return OtherOs;
1027 #endif
1028 }
1029 
1031 {
1032  switch (sysos) {
1033  case Linux: return QLatin1String("linux");
1034  case MacOsX: return QLatin1String("macosx");
1035  case Win32: return QLatin1String("win32");
1036  case OtherOs: return QString();
1037  default: ;
1038  }
1039  qWarning("KLFSysInfo::osString: unknown OS: %d", sysos);
1040  return QString();
1041 }
1042 
1043 
1044 QStringList klf_version_suffixes =
1045  QStringList() << "a" << "alpha" << "b" << "beta" << "p" << "pre" << "preview" << "RC" << "rc"
1046 /* */ << "" // empty suffix or any unrecognized suffix
1047 /* */ << "post" << "dev" << "devel";
1048 
1049 static int __klf_version_compare_suffix_words(QString w1, QString w2)
1050 {
1051  // a list of known words
1052  const QStringList& words = klf_version_suffixes;
1053  // now compare the words
1054  int borderBeforeAfter = words.list_indexOf("");
1055  if (borderBeforeAfter < 0)
1056  qWarning("klfVersionCompare: suffix words list doesn't contain \"\"!");
1057  int i1 = words.list_indexOf(w1);
1058  int i2 = words.list_indexOf(w2);
1059  if (i1 == -1 && i2 == -1)
1060  return QString::compare(w1, w2);
1061  if (i2 == -1)
1062  return i1 < borderBeforeAfter ? -1 : +1;
1063  if (i1 == -1)
1064  return i2 < borderBeforeAfter ? +1 : -1;
1065  // both are recognized words
1066  return i1 - i2;
1067 }
1068 
1069 
1070 KLF_EXPORT int klfVersionCompare(const QString& v1, const QString& v2)
1071 {
1072  qDebug("klfVersionCompare(): Comparing versions %s and %s", qPrintable(v1), qPrintable(v2));
1073  if (v1 == v2)
1074  return 0;
1075  if (v1.isEmpty()) // v1 is empty, but v2 is not empty because of test above
1076  return -1;
1077  if (v2.isEmpty()) // v2 is empty, but not v1 because of test above
1078  return 1;
1079  // *1 2 *3 4 *5 *6
1080  QRegExp rx1("^(\\d+)(\\.(\\d+)(\\.(\\d+)([a-zA-Z]+\\d*)?)?)?$");
1081  QRegExp rx2(rx1);
1082  if (!rx1.exactMatch(v1)) {
1083  qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v1));
1084  return -200;
1085  }
1086  if (!rx2.exactMatch(v2)) {
1087  qWarning("klfVersionLessThan: Invalid version number format: %s", qPrintable(v2));
1088  return -200;
1089  }
1090  int maj1 = rx1.cap(1).toInt();
1091  int maj2 = rx2.cap(1).toInt();
1092  if (maj1 != maj2)
1093  return maj1 - maj2;
1094  bool hasmin1 = !rx1.cap(2).isEmpty();
1095  bool hasmin2 = !rx2.cap(2).isEmpty();
1096  if ( ! hasmin1 && ! hasmin2 )
1097  return 0; // equal
1098  if ( ! hasmin1 && hasmin2 )
1099  return -1; // 3 < 3.x
1100  if ( hasmin1 && ! hasmin2 )
1101  return +1; // 3.x > 3
1102  int min1 = rx1.cap(3).toInt();
1103  int min2 = rx2.cap(3).toInt();
1104  if ( min1 != min2 )
1105  return min1 - min2;
1106 
1107  bool hasrel1 = !rx1.cap(4).isEmpty();
1108  bool hasrel2 = !rx2.cap(4).isEmpty();
1109  if ( ! hasrel1 && ! hasrel2 )
1110  return 0; // equal
1111  if ( ! hasrel1 && hasrel2 )
1112  return -1; // 3.x < 3.x.y
1113  if ( hasrel1 && ! hasrel2 )
1114  return +1; // 3.x.y > 3.x
1115  int rel1 = rx1.cap(5).toInt();
1116  int rel2 = rx2.cap(5).toInt();
1117  if ( rel1 != rel2 )
1118  return rel1 - rel2;
1119 
1120  QString suffix1 = rx1.cap(6);
1121  QString suffix2 = rx2.cap(6);
1122 
1123  // qDebug("Suffix1=%s, suffix2=%s", qPrintable(suffix1), qPrintable(suffix2));
1124 
1125  if (suffix1 == suffix2)
1126  return 0; // equal
1127 
1128  // 1 2
1129  QRegExp rxs1("^([a-zA-Z]*)(\\d*)$");
1130  QRegExp rxs2(rxs1);
1131  rxs1.exactMatch(suffix1); // must necessarily match, already matched global regex
1132  rxs2.exactMatch(suffix2);
1133 
1134  QString w1 = rxs1.cap(1);
1135  QString w2 = rxs2.cap(1);
1136  QString ns1 = rxs1.cap(2);
1137  QString ns2 = rxs2.cap(2);
1138 
1139  int cmp = __klf_version_compare_suffix_words(w1, w2);
1140  if (cmp != 0)
1141  return cmp; // words are enough to make the difference
1142 
1143  // the words are the same -> compare ns1<->ns2
1144  if (ns1.isEmpty()) {
1145  if (ns2.isEmpty())
1146  return 0; // equal
1147  // with suffix number compares greater than without
1148  return -1;
1149  }
1150  if (ns2.isEmpty()) {
1151  return +1;
1152  }
1153 
1154  int n1 = ns1.toInt();
1155  int n2 = ns2.toInt();
1156  return n1 - n2;
1157 }
1158 
1159 KLF_EXPORT bool klfVersionCompareLessThan(const QString& v1, const QString& v2)
1160 {
1161  return klfVersionCompare(v1,v2) < 0;
1162 }
1163 
1164 
1165 
1166 // negative limit means "no limit"
1167 static QStringList __search_find_test(const QString& root, const QStringList& pathlist,
1168  int level, int limit)
1169 {
1170  if (limit == 0)
1171  return QStringList();
1172 
1173  if (limit < 0)
1174  limit = -1; // normalize negative values to -1 (mostly cosmetic...)
1175 
1176  QStringList newpathlist = pathlist;
1177  // our level: levelpathlist contains items in pathlist from 0 to level-1 inclusive.
1178  QStringList levelpathlist;
1179  int k;
1180  for (k = 0; k < level; ++k) { levelpathlist << newpathlist[k]; }
1181  // the dir/file at our level:
1182  QString flpath = root+levelpathlist.join("/");
1183  QFileInfo flinfo(flpath);
1184  if (flinfo.isDir()) {
1185  QDir d(flpath);
1186  QStringList entries;
1187 #ifdef KLFBACKEND_QT4
1188  entries = d.entryList(QStringList()<<pathlist[level]);
1189 #else
1190  entries = d.entryList(pathlist[level]);
1191 #endif
1192  QStringList hitlist;
1193  for (k = 0; k < (int)entries.size(); ++k) {
1194  newpathlist[level] = entries[k];
1195  hitlist += __search_find_test(root, newpathlist, level+1, limit - hitlist.size());
1196  if (limit >= 0 && (int)hitlist.size() >= limit) // reached limit
1197  break;
1198  }
1199  return hitlist;
1200  }
1201  if (flinfo.exists()) {
1202  return QStringList() << dir_native_separators(root+pathlist.join("/"));
1203  }
1204  return QStringList();
1205 }
1206 
1207 KLF_EXPORT QStringList klfSearchFind(const QString& wildcard_expression, int limit)
1208 {
1209  klfDbg("looking for "+wildcard_expression) ;
1210 
1211  QString expr;
1212 #ifdef KLFBACKEND_QT4
1213  expr = QDir::fromNativeSeparators(wildcard_expression);
1214 #else
1215  expr = wildcard_expression; expr.replace(QDir::separator(), "/");
1216 #endif
1217  QStringList pathlist = str_split(expr, "/", false);
1218  QString root = "/";
1219  static QRegExp driveregexp("^[A-Za-z]:$");
1220  if (driveregexp.exactMatch(pathlist[0])) {
1221  // Windows System with X: drive letter
1222  root = pathlist[0]+"/";
1223  pathlist.pop_front();
1224  }
1225  return __search_find_test(root, pathlist, 0, limit);
1226 }
1227 
1228 KLF_EXPORT QString klfSearchPath(const QString& programName, const QString& extra_path)
1229 {
1230  static const QString PATH = getenv("PATH");
1231  static const QString pathsep = QString("")+KLF_PATH_SEP;
1232 
1233  QString path = PATH;
1234  if (!extra_path.isEmpty())
1235  path = extra_path + pathsep + path;
1236 
1237  const QStringList paths = str_split(path, pathsep, true);
1238  QString test;
1239  int k, j;
1240  for (k = 0; k < (int)paths.size(); ++k) {
1241  klfDbg("searching in "+paths[k]) ;
1242  QStringList hits = klfSearchFind(paths[k]+"/"+programName);
1243  klfDbg("\t...resulting in hits = "+hits.join(" ;; ")) ;
1244  for (j = 0; j < (int)hits.size(); ++j) {
1245  if ( QFileInfo(hits[j]).isExecutable() ) {
1246  klfDbg("\tFound definitive (executable) hit at "+hits[j]) ;
1247  return hits[j];
1248  }
1249  }
1250  }
1251  return QString::null;
1252 }
1253 
1254 
1255 
1256 
1257 
fromAscii(const char *str, int size=-1)
cap(int nth=0)
fromNativeSeparators(const QString &pathName)
KLF_EXPORT int klfVersionRelease()
Definition: klfdefs.cpp:785
Base declarations for klatexformula and some utilities.
KLF_EXPORT int klfVersionMin()
Definition: klfdefs.cpp:781
Utility to time the execution of a block.
Definition: klfdebug.h:54
KLF_EXPORT int klfVersionMaj()
Definition: klfdefs.cpp:777
#define klfDbg(streamableItems)
print debug stream items
join(const QString &separator)
systems on which Q_OS_LINUX is defined
Definition: klfdefs.h:85
separator()
KLF_EXPORT QString klfTimeOfDay(bool shortFmt=true)
Definition: klfdefs.cpp:909
replace(int position, int n, const QString &after)
KLF_EXPORT bool klfVersionCompareLessThan(const QString &v1, const QString &v2)
Same as klfVersionCompare(v1,v2) < 0
Definition: klfdefs.cpp:1159
KLF_EXPORT const char * klfVersion()
Definition: klfdefs.cpp:772
fromLocal8Bit(const char *str, int size=-1)
QByteArray klfShortFuncSignature(const char *fullFuncName)
Definition: klfdebug.h:38
KLF_EXPORT QStringList klfSearchFind(const QString &wildcard_expression, int limit=-1)
Find files matching a path with wildcards.
Definition: klfdefs.cpp:1207
KLF_EXPORT QString klfSearchPath(const QString &prog, const QString &extra_path="")
Smart executable searching in a given path list with wildcards.
Definition: klfdefs.cpp:1228
toInt(bool *ok=0, int base=10)
Os
List of known operating systems.
Definition: klfdefs.h:85
compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
#define klfFmtCC
Definition: klfdefs.h:70
KLF_EXPORT QString arch()
The architecture of this sytem.
Definition: klfdefs.cpp:1012
#define KLF_FUNC_NAME
systems on which Q_OS_DARWIN is defined
Definition: klfdefs.h:85
KLF_EXPORT QString osString(KLFSysInfo::Os sysos=os())
The operating system we are running, returned as a string.
Definition: klfdefs.cpp:1030
KLF_EXPORT int klfVersionCompare(const QString &v1, const QString &v2)
Compares two version strings.
Definition: klfdefs.cpp:1070
systems on which neither Q_OS_{LINUX|WIN32|DARWIN} is defined
Definition: klfdefs.h:85
KLF_EXPORT KLFSysInfo::Os os()
Which operating system this system is running.
Definition: klfdefs.cpp:1017
exactMatch(const QString &str)
duplicate(const QByteArray &a)
#define KLF_PATH_SEP
The character used in the $PATH environment variable to separate different locations.
Definition: klfdefs.h:107
KLF_EXPORT QByteArray klfFmt(const char *fmt,...)
Definition: klfdefs.cpp:899
systems on which Q_OS_WIN32 is defined
Definition: klfdefs.h:85

Generated by doxygen 1.8.8