author | llornkcor <llornkcor> | 2003-07-10 02:40:10 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2003-07-10 02:40:10 (UTC) |
commit | 155d68c1e7d7dc0fed2534ac43d6d77ce2781f55 (patch) (side-by-side diff) | |
tree | e6edaa5a7040fe6c224c3943d1094dcf02e4f74c | |
parent | 86703e8a5527ef114facd02c005b6b3a7e62e263 (diff) | |
download | opie-155d68c1e7d7dc0fed2534ac43d6d77ce2781f55.zip opie-155d68c1e7d7dc0fed2534ac43d6d77ce2781f55.tar.gz opie-155d68c1e7d7dc0fed2534ac43d6d77ce2781f55.tar.bz2 |
update qmake to 1.05a
111 files changed, 3893 insertions, 1517 deletions
diff --git a/qmake/Makefile b/qmake/Makefile index 90b0f07..01bb1a1 100644 --- a/qmake/Makefile +++ b/qmake/Makefile @@ -1,172 +1,178 @@ QMAKESPECSDIR=$(OPIEDIR)/mkspecs ######################################################################## ## This file was autogenerated by configure, all changes will be lost ## ######################################################################## CC = gcc CXX = g++ #qmake code OBJS=project.o main.o makefile.o unixmake2.o unixmake.o borland_bmake.o \ - msvc_nmake.o msvc_dsp.o msvc_vcproj.o option.o winmakefile.o \ + mingw_make.o msvc_nmake.o msvc_dsp.o msvc_vcproj.o option.o winmakefile.o \ projectgenerator.o metrowerks_xml.o pbuilder_pbx.o msvc_objectmodel.o #qt code QOBJS=qstring.o qtextstream.o qiodevice.o qglobal.o qgdict.o qcstring.o \ qdatastream.o qgarray.o qbuffer.o qglist.o qptrcollection.o qfile.o \ - qfile_unix.o qregexp.o qgvector.o qgcache.o qbitarray.o qdir.o \ + qfile_unix.o qregexp.o qgvector.o qgcache.o qbitarray.o qdir.o quuid.o \ qfileinfo_unix.o qdir_unix.o qfileinfo.o qdatetime.o qstringlist.o qmap.o \ qconfig.o CFLAGS= \ -I. -Igenerators -Igenerators/unix -Igenerators/win32 -Igenerators/mac \ -I$(OPIEDIR)/qmake/include -I$(OPIEDIR)/qmake/include/qmake -I$(QMAKESPECSDIR)/default \ -I$(OPIEDIR)/qmake/include/private \ -DQT_NO_TEXTCODEC -DQT_LITE_COMPONENT -DQT_NO_STL -DQT_NO_COMPRESS CXXFLAGS= $(CFLAGS) LFLAGS= qmake: $(OBJS) $(QOBJS) $(CXX) -o $@ $(OBJS) $(QOBJS) $(LFLAGS) $(if $(OPIEDIR),rm -f $(OPIEDIR)/bin/$@) $(if $(OPIEDIR),ln -s ../qmake/$@ $(OPIEDIR)/bin/$@) install: qmake [ -d $(INSTALL_ROOT)$(QTDIR)/bin ] || mkdir -p $(INSTALL_ROOT)$(QTDIR)/bin -cp -f $(QTDIR)/bin/qmake $(INSTALL_ROOT)$(QTDIR)/bin [ -d $(INSTALL_ROOT)$(QTDIR) ] || mkdir -p $(INSTALL_ROOT)$(QTDIR) -cp -r -f $(QMAKESPECSDIR) $(INSTALL_ROOT)$(QTDIR) clean:: rm -f $(OBJS) $(QOBJS) distclean:: clean rm -rf qmake .deps # don't use optimization for these qtextstream.o: $(OPIEDIR)/qmake/tools/qtextstream.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qtextstream.cpp qiodevice.o: $(OPIEDIR)/qmake/tools/qiodevice.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qiodevice.cpp qglobal.o: $(OPIEDIR)/qmake/tools/qglobal.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qglobal.cpp qgdict.o: $(OPIEDIR)/qmake/tools/qgdict.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qgdict.cpp qcstring.o: $(OPIEDIR)/qmake/tools/qcstring.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qcstring.cpp qstring.o: $(OPIEDIR)/qmake/tools/qstring.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qstring.cpp qdatastream.o: $(OPIEDIR)/qmake/tools/qdatastream.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qdatastream.cpp qgarray.o: $(OPIEDIR)/qmake/tools/qgarray.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qgarray.cpp qbuffer.o: $(OPIEDIR)/qmake/tools/qbuffer.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qbuffer.cpp qglist.o: $(OPIEDIR)/qmake/tools/qglist.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qglist.cpp qptrcollection.o: $(OPIEDIR)/qmake/tools/qptrcollection.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qptrcollection.cpp qfile.o: $(OPIEDIR)/qmake/tools/qfile.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qfile.cpp qfile_unix.o: $(OPIEDIR)/qmake/tools/qfile_unix.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qfile_unix.cpp qregexp.o: $(OPIEDIR)/qmake/tools/qregexp.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qregexp.cpp qgvector.o: $(OPIEDIR)/qmake/tools/qgvector.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qgvector.cpp qgcache.o: $(OPIEDIR)/qmake/tools/qgcache.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qgcache.cpp qbitarray.o: $(OPIEDIR)/qmake/tools/qbitarray.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qbitarray.cpp qdir.o: $(OPIEDIR)/qmake/tools/qdir.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qdir.cpp +quuid.o: $(OPIEDIR)/qmake/tools/quuid.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/quuid.cpp + qfileinfo_unix.o: $(OPIEDIR)/qmake/tools/qfileinfo_unix.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qfileinfo_unix.cpp qdir_unix.o: $(OPIEDIR)/qmake/tools/qdir_unix.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qdir_unix.cpp qfileinfo.o: $(OPIEDIR)/qmake/tools/qfileinfo.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qfileinfo.cpp qdatetime.o: $(OPIEDIR)/qmake/tools/qdatetime.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qdatetime.cpp qstringlist.o: $(OPIEDIR)/qmake/tools/qstringlist.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qstringlist.cpp qmap.o: $(OPIEDIR)/qmake/tools/qmap.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qmap.cpp qconfig.o: $(OPIEDIR)/qmake/tools/qconfig.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(OPIEDIR)/qmake/tools/qconfig.cpp winmakefile.o: generators/win32/winmakefile.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/winmakefile.cpp project.o: project.cpp project.h option.h $(CXX) -c -o $@ $(CXXFLAGS) project.cpp main.o: main.cpp project.h $(CXX) -c -o $@ $(CXXFLAGS) main.cpp option.o: option.cpp option.h $(CXX) -c -o $@ $(CXXFLAGS) option.cpp makefile.o: generators/makefile.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/makefile.cpp unixmake.o: generators/unix/unixmake.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/unix/unixmake.cpp unixmake2.o: generators/unix/unixmake2.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/unix/unixmake2.cpp borland_bmake.o: generators/win32/borland_bmake.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/borland_bmake.cpp +mingw_make.o: generators/win32/mingw_make.cpp + $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/mingw_make.cpp + msvc_objectmodel.o: generators/win32/msvc_objectmodel.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp msvc_vcproj.o: generators/win32/msvc_vcproj.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_vcproj.cpp msvc_nmake.o: generators/win32/msvc_nmake.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_nmake.cpp metrowerks_xml.o: generators/mac/metrowerks_xml.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/mac/metrowerks_xml.cpp pbuilder_pbx.o: generators/mac/pbuilder_pbx.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp msvc_dsp.o: generators/win32/msvc_dsp.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/win32/msvc_dsp.cpp projectgenerator.o: generators/projectgenerator.cpp $(CXX) -c -o $@ $(CXXFLAGS) generators/projectgenerator.cpp #default rules .c.o: $(CC) -c -o $@ $(CFLAGS) $< .cpp.o: $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index f490313..c12375d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1,2085 +1,2263 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "makefile.h" #include "option.h" #include <qdir.h> #include <qfile.h> #include <qtextstream.h> #include <qregexp.h> #include <qdict.h> #if defined(Q_OS_UNIX) #include <unistd.h> #else #include <io.h> #endif #include <stdio.h> #include <stdlib.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> // Well, Windows doesn't have this, so here's the macro #ifndef S_ISDIR #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif +static QString mkdir_p_asstring(const QString &dir) +{ + QString ret = "@$(CHK_DIR_EXISTS) \"" + dir + "\" "; + if(Option::target_mode == Option::TARG_WIN_MODE) + ret += "$(MKDIR)"; + else + ret += "|| $(MKDIR)"; + ret += " \"" + dir + "\""; + return ret; +} + static bool createDir(const QString& fullPath) { + if(QFile::exists(fullPath)) + return FALSE; + QDir dirTmp; bool ret = TRUE; QString pathComponent, tmpPath; QStringList hierarchy = QStringList::split(QString(Option::dir_sep), fullPath, TRUE); for(QStringList::Iterator it = hierarchy.begin(); it != hierarchy.end(); ++it) { pathComponent = *it + QDir::separator(); tmpPath += pathComponent; if(!dirTmp.mkdir(tmpPath)) { ret = FALSE; // break; } } return ret; } MakefileGenerator::MakefileGenerator(QMakeProject *p) : init_opath_already(FALSE), init_already(FALSE), moc_aware(FALSE), no_io(FALSE), project(p) { } static char *gimme_buffer(off_t s) { static char *big_buffer = NULL; static int big_buffer_size = 0; if(!big_buffer || big_buffer_size < s) big_buffer = (char *)realloc(big_buffer, s); return big_buffer; } bool -MakefileGenerator::generateMocList(QString fn_target) +MakefileGenerator::generateMocList(const QString &fn_target) { if(!findMocDestination(fn_target).isEmpty()) return TRUE; QString fn_local = Option::fixPathToLocalOS(fileFixify(fn_target, QDir::currentDirPath(), Option::output_dir)); int file = open(fn_local.latin1(), O_RDONLY); if(file == -1) return FALSE; struct stat fst; if(fstat(file, &fst) || S_ISDIR(fst.st_mode)) return FALSE; //shouldn't happen char *big_buffer = gimme_buffer(fst.st_size); int total_size_read; for(int have_read = total_size_read = 0; (have_read = read(file, big_buffer + total_size_read, fst.st_size - total_size_read)); total_size_read += have_read); close(file); bool ignore_qobject = FALSE; int line_count = 1; /* qmake ignore Q_OBJECT */ #define COMP_LEN 8 //strlen("Q_OBJECT") #define OBJ_LEN 8 //strlen("Q_OBJECT") #define DIS_LEN 10 //strlen("Q_DISPATCH") int x; for(x = 0; x < (total_size_read-COMP_LEN); x++) { if(*(big_buffer + x) == '/') { x++; if(total_size_read >= x) { if(*(big_buffer + x) == '/') { //c++ style comment for( ;x < total_size_read && *(big_buffer + x) != '\n'; x++); line_count++; } else if(*(big_buffer + x) == '*') { //c style comment for( ;x < total_size_read; x++) { if(*(big_buffer + x) == 't' || *(big_buffer + x) == 'q') { //ignore if(total_size_read >= (x + 20)) { if(!strncmp(big_buffer + x + 1, "make ignore Q_OBJECT", 20)) { debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"", fn_target.latin1(), line_count); x += 20; ignore_qobject = TRUE; } } } else if(*(big_buffer + x) == '*') { if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') { x += 2; break; } } else if(*(big_buffer + x) == '\n') { line_count++; } } } } } #define SYMBOL_CHAR(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || \ (x <= '0' && x >= '9') || x == '_') bool interesting = *(big_buffer+x) == 'Q' && (!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN) || !strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN)); if(interesting) { int len = 0; if(!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN)) { if(ignore_qobject) { debug_msg(2, "Mocgen: %s:%d Ignoring Q_OBJECT", fn_target.latin1(), line_count); interesting = FALSE; } len=OBJ_LEN; } else if(!strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN)) { len=DIS_LEN; } if(SYMBOL_CHAR(*(big_buffer+x+len))) interesting = FALSE; if(interesting) { *(big_buffer+x+len) = '\0'; - debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", fn_target.latin1(), line_count, big_buffer+x); + debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", fn_target.latin1(), + line_count, big_buffer+x); int ext_pos = fn_target.findRev('.'); int ext_len = fn_target.length() - ext_pos; int dir_pos = fn_target.findRev(Option::dir_sep, ext_pos); QString mocFile; if(!project->isEmpty("MOC_DIR")) mocFile = project->first("MOC_DIR"); else if(dir_pos != -1) mocFile = fn_target.left(dir_pos+1); bool cpp_ext = FALSE; - for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { + for(QStringList::Iterator cppit = Option::cpp_ext.begin(); + cppit != Option::cpp_ext.end(); ++cppit) { if((cpp_ext = (fn_target.right(ext_len) == (*cppit)))) break; } if(cpp_ext) { mocFile += fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) + Option::moc_ext; - findDependencies(fn_target).append(mocFile); project->variables()["_SRCMOC"].append(mocFile); } else if(project->variables()["HEADERS"].findIndex(fn_target) != -1) { - for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { + for(QStringList::Iterator hit = Option::h_ext.begin(); + hit != Option::h_ext.end(); ++hit) { if((fn_target.right(ext_len) == (*hit))) { mocFile += Option::moc_mod + fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) + Option::cpp_ext.first(); logicWarn(mocFile, "SOURCES"); project->variables()["_HDRMOC"].append(mocFile); break; } } } if(!mocFile.isEmpty()) { mocFile = Option::fixPathToTargetOS(mocFile); mocablesToMOC[cleanFilePath(fn_target)] = mocFile; mocablesFromMOC[cleanFilePath(mocFile)] = fn_target; } break; } } while(x < total_size_read && SYMBOL_CHAR(*(big_buffer+x))) x++; if(*(big_buffer+x) == '\n') line_count++; } #undef OBJ_LEN #undef DIS_LEN return TRUE; } bool -MakefileGenerator::generateDependencies(QPtrList<MakefileDependDir> &dirs, QString fn, bool recurse) +MakefileGenerator::generateDependencies(QPtrList<MakefileDependDir> &dirs, const QString &f, bool recurse) { - fn = fileFixify(fn); - QStringList &fndeps = findDependencies(fn); + QStringList &fndeps = findDependencies(f); if(!fndeps.isEmpty()) return TRUE; - + QString fn = fileFixify(f, QDir::currentDirPath(), Option::output_dir); fn = Option::fixPathToLocalOS(fn, FALSE); QString fix_env_fn = Option::fixPathToLocalOS(fn); int file = open(fix_env_fn.latin1(), O_RDONLY); if(file == -1) return FALSE; struct stat fst; if(fstat(file, &fst) || S_ISDIR(fst.st_mode)) return FALSE; //shouldn't happen QString fndir, fix_env_fndir; int dl = fn.findRev(Option::dir_sep); if(dl != -1) fndir = fn.left(dl+1); dl = fix_env_fn.findRev(Option::dir_sep); if(dl != -1) fix_env_fndir = fix_env_fn.left(dl + 1); int line_count = 1; char *big_buffer = gimme_buffer(fst.st_size); int total_size_read; for(int have_read = total_size_read = 0; (have_read = read(file, big_buffer + total_size_read, fst.st_size - total_size_read)); total_size_read += have_read); close(file); bool ui_file = fn.endsWith(Option::ui_ext); for(int x = 0; x < total_size_read; x++) { QStringList *outdeps=&fndeps; QString inc; if(!ui_file) { if(*(big_buffer + x) == '/') { x++; if(total_size_read >= x) { if(*(big_buffer + x) == '/') { //c++ style comment for( ; x < total_size_read && *(big_buffer + x) != '\n'; x++); } else if(*(big_buffer + x) == '*') { //c style comment for( ; x < total_size_read; x++) { if(*(big_buffer + x) == '*') { if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') { x += 2; break; } } else if(*(big_buffer + x) == '\n') { line_count++; } } } } } if(*(big_buffer + x) == '#') { x++; while(x < total_size_read && //Skip spaces after hash (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t')) x++; - if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include ", 8)) { - for(x+=8; //skip spaces after keyword + if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include", 7) && + (*(big_buffer + x + 7) == ' ' || *(big_buffer + x + 7) == '\t' || + *(big_buffer + x + 7) == '<' || *(big_buffer + x + 7) == '"')) { + for(x+=7; //skip spaces after keyword x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'); x++); char term = *(big_buffer + x); if(term == '"'); else if(term == '<') term = '>'; else continue; //wtf? x++; int inc_len; for(inc_len = 0; *(big_buffer + x + inc_len) != term; inc_len++); *(big_buffer + x + inc_len) = '\0'; inc = big_buffer + x; } else if(total_size_read >= x + 14 && !strncmp(big_buffer + x, "qmake_warning ", 14)) { for(x+=14; //skip spaces after keyword x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'); x++); char term = '\n'; if(*(big_buffer + x) == '"') term = '"'; if(*(big_buffer + x) == '\'') term = '\''; if(term != '\n') x++; int msg_len; for(msg_len = 0; *(big_buffer + x + msg_len) != term; msg_len++); *(big_buffer + x + msg_len) = '\0'; QString msg = big_buffer + x; debug_msg(0, "%s:%d qmake_warning -- %s", fix_env_fn.latin1(), line_count, msg.latin1()); *(big_buffer + x + msg_len) = term; //put it back } } } else if(ui_file) { // skip whitespaces while(x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t')) x++; if(*(big_buffer + x) == '<') { x++; if(total_size_read >= x + 12 && !strncmp(big_buffer + x, "includehint", 11) && (*(big_buffer + x + 11) == ' ' || *(big_buffer + x + 11) == '>')) { for(x += 12; *(big_buffer + x) != '>'; x++); int inc_len = 0; for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++); *(big_buffer + x + inc_len) = '\0'; inc = big_buffer + x; } else if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include", 7) && (*(big_buffer + x + 7) == ' ' || *(big_buffer + x + 7) == '>')) { for(x += 8; *(big_buffer + x) != '>'; x++) { if(total_size_read >= x + 9 && *(big_buffer + x) == 'i' && !strncmp(big_buffer + x, "impldecl", 8)) { for(x += 8; *(big_buffer + x) != '='; x++); if(*(big_buffer + x) != '=') continue; for(x++; *(big_buffer+x) == '\t' || *(big_buffer+x) == ' '; x++); char quote = 0; if(*(big_buffer+x) == '\'' || *(big_buffer+x) == '"') { quote = *(big_buffer + x); x++; } int val_len; for(val_len = 0; TRUE; val_len++) { if(quote) { if(*(big_buffer+x+val_len) == quote) break; } else if(*(big_buffer + x + val_len) == '>' || *(big_buffer + x + val_len) == ' ') { break; } } char saved = *(big_buffer + x + val_len); *(big_buffer + x + val_len) = '\0'; QString where = big_buffer + x; *(big_buffer + x + val_len) = saved; if(where == "in implementation") { QString cpp = fn.left(fn.length() - Option::ui_ext.length()) + Option::cpp_ext.first(); outdeps = &findDependencies(cpp); } } } int inc_len = 0; for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++); *(big_buffer + x + inc_len) = '\0'; inc = big_buffer + x; } } } if(!inc.isEmpty()) { + bool from_source_dir = TRUE; debug_msg(5, "%s:%d Found dependency to %s", fix_env_fn.latin1(), line_count, inc.latin1()); if(!project->isEmpty("SKIP_DEPENDS")) { bool found = FALSE; QStringList &nodeplist = project->values("SKIP_DEPENDS"); for(QStringList::Iterator it = nodeplist.begin(); it != nodeplist.end(); ++it) { QRegExp regx((*it)); if(regx.search(inc) != -1) { found = TRUE; break; } } if(found) continue; } QString fqn; if(project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH") && !stat(fix_env_fndir + inc, &fst) && !S_ISDIR(fst.st_mode)) { fqn = fndir + inc; + goto handle_fqn; } else { if((Option::target_mode == Option::TARG_MAC9_MODE && inc.find(':')) || (Option::target_mode == Option::TARG_WIN_MODE && inc[1] != ':') || ((Option::target_mode == Option::TARG_UNIX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_MACX_MODE) && inc[0] != '/')) { for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) { if(!stat(mdd->local_dir + QDir::separator() + inc, &fst) && !S_ISDIR(fst.st_mode)) { fqn = mdd->real_dir + QDir::separator() + inc; - break; + goto handle_fqn; } } } } - if(fqn.isEmpty()) { + if(fqn.isEmpty() && Option::mkfile::do_dep_heuristics) { //these are some hacky heuristics it will try to do on an include //however these can be turned off at runtime, I'm not sure how //reliable these will be, most likely when problems arise turn it off //and see if they go away.. - if(Option::mkfile::do_dep_heuristics && depHeuristics.contains(inc)) { + if(depHeuristics.contains(inc)) { fqn = depHeuristics[inc]; } else if(Option::mkfile::do_dep_heuristics) { //some heuristics.. //is it a file from a .ui? QString inc_file = inc.section(Option::dir_sep, -1); int extn = inc_file.findRev('.'); if(extn != -1 && (inc_file.right(inc_file.length()-extn) == Option::cpp_ext.first() || inc_file.right(inc_file.length()-extn) == Option::h_ext.first())) { QString uip = inc_file.left(extn) + Option::ui_ext; QStringList uil = project->variables()["FORMS"]; for(QStringList::Iterator it = uil.begin(); it != uil.end(); ++it) { if((*it).section(Option::dir_sep, -1) == uip) { if(!project->isEmpty("UI_DIR")) fqn = project->first("UI_DIR"); else if(!project->isEmpty("UI_HEADERS_DIR")) fqn = project->first("UI_HEADERS_DIR"); else fqn = (*it).section(Option::dir_sep, 0, -2); if(!fqn.isEmpty() && !fqn.endsWith(Option::dir_sep)) fqn += Option::dir_sep; fqn += inc_file; - break; + from_source_dir = FALSE; //uics go in the output_dir (so don't fix them) + fqn = fileFixify(fqn, QDir::currentDirPath(), Option::output_dir); + goto handle_fqn; + } + } + } + if(project->isActiveConfig("lex_included")) { //is this the lex file? + QString rhs = Option::lex_mod + Option::cpp_ext.first(); + if(inc.endsWith(rhs)) { + QString lhs = inc.left(inc.length() - rhs.length()) + Option::lex_ext; + QStringList ll = project->variables()["LEXSOURCES"]; + for(QStringList::Iterator it = ll.begin(); it != ll.end(); ++it) { + QString s = (*it), d; + int slsh = s.findRev(Option::dir_sep); + if(slsh != -1) { + d = s.left(slsh + 1); + s = s.right(s.length() - slsh - 1); + } + if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) + d = project->first("QMAKE_ABSOLUTE_SOURCE_PATH"); + if(s == lhs) { + fqn = d + inc; + goto handle_fqn; + } } } } - if(fqn.isEmpty()) { //is it from a .y? + { //is it from a .y? QString rhs = Option::yacc_mod + Option::h_ext.first(); if(inc.endsWith(rhs)) { QString lhs = inc.left(inc.length() - rhs.length()) + Option::yacc_ext; QStringList yl = project->variables()["YACCSOURCES"]; for(QStringList::Iterator it = yl.begin(); it != yl.end(); ++it) { QString s = (*it), d; int slsh = s.findRev(Option::dir_sep); if(slsh != -1) { d = s.left(slsh + 1); s = s.right(s.length() - slsh - 1); } if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) d = project->first("QMAKE_ABSOLUTE_SOURCE_PATH"); if(s == lhs) { fqn = d + inc; - break; + goto handle_fqn; + } + } + } + } + if(mocAware() && //is it a moc file? + (inc.endsWith(Option::cpp_ext.first()) || inc.endsWith(Option::moc_ext))) { + QString mocs[] = { QString("_HDRMOC"), QString("_SRCMOC"), QString::null }; + for(int moc = 0; !mocs[moc].isNull(); moc++) { + QStringList &l = project->variables()[mocs[moc]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString file = Option::fixPathToTargetOS((*it)); + if(file.section(Option::dir_sep, -(inc.contains('/')+1)) == inc) { + fqn = (*it); + if(mocs[moc] == "_HDRMOC") { + //Since it is include, no need to link it in as well + project->variables()["_SRCMOC"].append((*it)); + l.remove(it); + } else if(!findMocSource(fqn).endsWith(fn)) { + /* Not really a very good test, but this will at least avoid + confusion if it really does happen (since tmake/qmake + previously didn't even allow this the test is mostly accurate) */ + warn_msg(WarnLogic, + "Found potential multiple MOC include %s (%s) in '%s'", + inc.latin1(), fqn.latin1(), fix_env_fn.latin1()); + } + from_source_dir = FALSE; //mocs go in the output_dir (so don't fix them) + goto handle_fqn; } } } } depHeuristics.insert(inc, fqn); } - if(!Option::mkfile::do_dep_heuristics || fqn.isEmpty()) //I give up - continue; } - - fqn = fileFixify(Option::fixPathToTargetOS(fqn, FALSE)); - debug_msg(4, "Resolved dependancy of %s to %s", inc.latin1(), fqn.latin1()); + handle_fqn: + if(fqn.isEmpty()) //I give up + continue; + fqn = Option::fixPathToTargetOS(fqn, FALSE); + if(from_source_dir) + fqn = fileFixify(fqn); + debug_msg(4, "Resolved dependency of %s to %s", inc.latin1(), fqn.latin1()); if(outdeps && outdeps->findIndex(fqn) == -1) outdeps->append(fqn); } //read past new line now.. for( ; x < total_size_read && (*(big_buffer + x) != '\n'); x++); line_count++; } if(recurse) { for(QStringList::Iterator fnit = fndeps.begin(); fnit != fndeps.end(); ++fnit) { generateDependencies(dirs, (*fnit), recurse); QStringList &deplist = findDependencies((*fnit)); for(QStringList::Iterator it = deplist.begin(); it != deplist.end(); ++it) if(fndeps.findIndex((*it)) == -1) fndeps.append((*it)); } } - debug_msg(2, "Dependancies: %s -> %s", fn.latin1(), fndeps.join(" :: ").latin1()); + debug_msg(2, "Dependencies: %s -> %s", fn.latin1(), fndeps.join(" :: ").latin1()); return TRUE; } void MakefileGenerator::initOutPaths() { if(init_opath_already) return; init_opath_already = TRUE; QMap<QString, QStringList> &v = project->variables(); if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) { if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty() && v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) { QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first(); root = Option::fixPathToTargetOS( root ); if(!root.isEmpty()) { QFileInfo fi(Option::mkfile::cachefile); if(!fi.convertToAbs()) { QString cache_r = fi.dirPath(), pwd = Option::output_dir; if ( pwd.startsWith(cache_r) && !pwd.startsWith(root) ) { pwd = Option::fixPathToTargetOS(root + pwd.mid(cache_r.length())); if(QFile::exists(pwd)) v.insert("QMAKE_ABSOLUTE_SOURCE_PATH", pwd); } } } } } if(!v["QMAKE_ABSOLUTE_SOURCE_PATH"].isEmpty()) { QString &asp = v["QMAKE_ABSOLUTE_SOURCE_PATH"].first(); asp = Option::fixPathToTargetOS( asp ); if(asp.isEmpty() || asp == Option::output_dir) //if they're the same, why bother? v["QMAKE_ABSOLUTE_SOURCE_PATH"].clear(); } QString currentDir = QDir::currentDirPath(); QString dirs[] = { QString("OBJECTS_DIR"), QString("MOC_DIR"), QString("UI_HEADERS_DIR"), QString("UI_SOURCES_DIR"), QString("UI_DIR"), QString("DESTDIR"), QString("SUBLIBS_DIR"), QString::null }; for(int x = 0; dirs[x] != QString::null; x++) { if ( !v[dirs[x]].isEmpty() ) { QString orig_path = v[dirs[x]].first(); { QString &path = v[dirs[x]].first(); path = fileFixify(path, Option::output_dir, Option::output_dir); if(path.right(Option::dir_sep.length()) != Option::dir_sep) path += Option::dir_sep; } if(noIO()) continue; QString path = project->first(dirs[x]); //not to be changed any further path = Option::fixPathToTargetOS(fileFixify(path, QDir::currentDirPath(), Option::output_dir)); debug_msg(3, "Fixed output_dir %s (%s) into %s (%s)", dirs[x].latin1(), orig_path.latin1(), v[dirs[x]].join("::").latin1(), path.latin1()); QDir d; if(path.startsWith(Option::dir_sep)) { d.cd(Option::dir_sep); path = path.right(path.length() - 1); } #ifdef Q_WS_WIN bool driveExists = TRUE; if ( !QDir::isRelativePath( path ) ) { if ( QFile::exists( path.left( 3 ) ) ) { d.cd( path.left( 3 ) ); path = path.right( path.length() - 3 ); } else { warn_msg(WarnLogic, "%s: Cannot access drive '%s' (%s)", dirs[x].latin1(), path.left( 3 ).latin1(), path.latin1() ); driveExists = FALSE; } } if ( driveExists ) { #endif QStringList subs = QStringList::split(Option::dir_sep, path); for(QStringList::Iterator subit = subs.begin(); subit != subs.end(); ++subit) { if(!d.cd(*subit)) { d.mkdir((*subit)); if ( d.exists( (*subit) ) ) d.cd((*subit)); else { warn_msg(WarnLogic, "%s: Cannot access directory '%s' (%s)", dirs[x].latin1(), (*subit).latin1(), path.latin1() ); break; } } } #ifdef Q_WS_WIN } #endif } } QDir::current().cd( currentDir ); } void MakefileGenerator::init() { initOutPaths(); if(init_already) return; init_already = TRUE; QMap<QString, QStringList> &v = project->variables(); QString paths[] = { QString("SOURCES"), QString("FORMS"), QString("YACCSOURCES"), QString("INCLUDEPATH"), QString("HEADERS"), QString("HEADERS_ORIG"), QString("LEXSOURCES"), QString("QMAKE_INTERNAL_INCLUDED_FILES"), QString::null }; for(int y = 0; paths[y] != QString::null; y++) { QStringList &l = v[paths[y]]; if(!l.isEmpty()) l = fileFixify(l); } /* get deps and mocables */ QDict<void> cache_found_files; - QString cache_file(Option::output_dir + QDir::separator() + ".qmake.internal.cache"); + QString cache_file(".qmake.internal.cache"); + if(!project->isEmpty("QMAKE_INTERNAL_CACHE_FILE")) + cache_file = Option::fixPathToLocalOS(project->first("QMAKE_INTERNAL_CACHE_FILE")); + if(cache_file.find(QDir::separator()) == -1) //guess they know what they are doing.. + cache_file.prepend(Option::output_dir + QDir::separator()); if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT || Option::mkfile::do_deps || Option::mkfile::do_mocs) && !noIO()) { QPtrList<MakefileDependDir> deplist; deplist.setAutoDelete(TRUE); if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT || Option::mkfile::do_deps) && doDepends()) { QStringList incDirs = v["DEPENDPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"]; if(project->isActiveConfig("depend_includepath")) incDirs += v["INCLUDEPATH"]; for(QStringList::Iterator it = incDirs.begin(); it != incDirs.end(); ++it) { QString r = (*it), l = Option::fixPathToLocalOS((*it)); deplist.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); } - debug_msg(1, "Dependancy Directories: %s", incDirs.join(" :: ").latin1()); + debug_msg(1, "Dependency Directories: %s", incDirs.join(" :: ").latin1()); if(Option::output.name() != "-" && project->isActiveConfig("qmake_cache")) { QFile cachef(cache_file); if(cachef.open(IO_ReadOnly | IO_Translate)) { QFileInfo cachefi(cache_file); debug_msg(2, "Trying internal cache information: %s", cache_file.latin1()); QTextStream cachet(&cachef); QString line, file; enum { CacheInfo, CacheDepend, CacheMoc } state = CacheInfo; while (!cachet.eof()) { line = cachet.readLine().stripWhiteSpace(); int sep = line.find('='); if(line == "[depend]") { state = CacheDepend; } else if(line == "[mocable]") { state = CacheMoc; } else if(line == "[check]") { state = CacheInfo; } else if(!line.isEmpty() && sep != -1) { file = line.left(sep).stripWhiteSpace(); line = line.right(line.length() - sep - 1).stripWhiteSpace(); if(state == CacheInfo) { if(file == "QMAKE_CACHE_VERSION") { if(line != qmake_version()) break; } else { const QStringList &l = project->variables()[file]; if(!l.isEmpty() && !line.isEmpty() && l.join(" ") != line) break; } } else if(state == CacheDepend) { bool found = (bool)cache_found_files[file]; QStringList files = QStringList::split(" ", line); if(!found) { QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir)); if(fi.exists() && fi.lastModified() < cachefi.lastModified()) { cache_found_files.insert(file, (void *)1); found = TRUE; } } if(found) { for(QStringList::Iterator dep_it = files.begin(); dep_it != files.end(); ++dep_it) { if(!cache_found_files[(*dep_it)]) { QFileInfo fi(fileFixify((*dep_it), QDir::currentDirPath(), Option::output_dir)); if(fi.exists() && fi.lastModified() < cachefi.lastModified()) { cache_found_files.insert((*dep_it), (void *)1); } else { found = FALSE; break; } } } if(found) { - debug_msg(2, "Dependancies (cached): %s -> %s", file.latin1(), + debug_msg(2, "Dependencies (cached): %s -> %s", file.latin1(), files.join(" :: ").latin1()); findDependencies(file) = files; } } } else { void *found = cache_found_files[file]; if(found != (void *)2) { if(found) { cache_found_files.replace(file, (void *)2); } else { QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir)); if(fi.exists() && fi.lastModified() < cachefi.lastModified()) { cache_found_files.insert(file, (void *)2); found = (void*)1; } } } if(found && line != "*qmake_ignore*") { int ext_len = file.length() - file.findRev('.'); bool cpp_ext = FALSE; for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { if((cpp_ext = (file.right(ext_len) == (*cppit)))) break; } if(cpp_ext) { project->variables()["_SRCMOC"].append(line); } else if(project->variables()["HEADERS"].findIndex(file) != -1) { for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { if((file.right(ext_len) == (*hit))) { project->variables()["_HDRMOC"].append(line); break; } } } debug_msg(2, "Mocgen (cached): %s -> %s", file.latin1(), line.latin1()); mocablesToMOC[file] = line; mocablesFromMOC[line] = file; } } } } cachef.close(); } } } if(!noIO()) { QString sources[] = { QString("OBJECTS"), QString("LEXSOURCES"), QString("YACCSOURCES"), QString("HEADERS"), QString("SOURCES"), QString("FORMS"), QString::null }; depHeuristics.clear(); bool write_cache = FALSE, read_cache = QFile::exists(cache_file); for(int x = 0; sources[x] != QString::null; x++) { QStringList vpath, &l = v[sources[x]]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { if(!(*val_it).isEmpty()) { QString file = Option::fixPathToLocalOS((*val_it)); + QStringList file_list(file); if(!QFile::exists(file)) { bool found = FALSE; if(QDir::isRelativePath(file)) { if(vpath.isEmpty()) vpath = v["VPATH_" + sources[x]] + v["VPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"] + v["DEPENDPATH"]; for(QStringList::Iterator vpath_it = vpath.begin(); vpath_it != vpath.end(); ++vpath_it) { QString real_dir = Option::fixPathToLocalOS((*vpath_it)); if(QFile::exists(real_dir + QDir::separator() + (*val_it))) { QString dir = (*vpath_it); if(dir.right(Option::dir_sep.length()) != Option::dir_sep) dir += Option::dir_sep; (*val_it) = fileFixify(dir + (*val_it)); found = TRUE; debug_msg(1, "Found file through vpath %s -> %s", file.latin1(), (*val_it).latin1()); break; } } } if(!found) { QString dir, regex = (*val_it), real_dir; if(regex.findRev(Option::dir_sep) != -1) { dir = regex.left(regex.findRev(Option::dir_sep) + 1); real_dir = fileFixify(Option::fixPathToLocalOS(dir), QDir::currentDirPath(), Option::output_dir); regex = regex.right(regex.length() - dir.length()); } if(real_dir.isEmpty() || QFile::exists(real_dir)) { QDir d(real_dir, regex); if(!d.count()) { debug_msg(1, "%s:%d Failure to find %s in vpath (%s)", __FILE__, __LINE__, (*val_it).latin1(), vpath.join("::").latin1()); warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1()); continue; } else { - (*val_it) = dir + d[0]; - for(int i = 1; i < (int)d.count(); i++) + file_list.clear(); + for(int i = 0; i < (int)d.count(); i++) { + file_list.append(dir + d[i]); + if(i == (int)d.count() - 1) + (*val_it) = dir + d[i]; + else l.insert(val_it, dir + d[i]); } + } } else { debug_msg(1, "%s:%d Cannot match %s%c%s, as %s does not exist.", __FILE__, __LINE__, real_dir.latin1(), QDir::separator(), regex.latin1(), real_dir.latin1()); warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1()); } } } - - QString val_file = fileFixify((*val_it)); + for(QStringList::Iterator file_it = file_list.begin(); + file_it != file_list.end(); ++file_it) { + QString file_list_file = fileFixify((*file_it)); bool found_cache_moc = FALSE, found_cache_dep = FALSE; if(read_cache && Option::output.name() != "-" && project->isActiveConfig("qmake_cache")) { - if(!findDependencies(val_file).isEmpty()) + if(!findDependencies(file_list_file).isEmpty()) found_cache_dep = TRUE; - if(cache_found_files[(*val_it)] == (void *)2) + if(cache_found_files[(*file_it)] == (void *)2) found_cache_moc = TRUE; if(!found_cache_moc || !found_cache_dep) write_cache = TRUE; } - if(!found_cache_dep && sources[x] != "OBJECTS") { - debug_msg(5, "Looking for dependancies for %s", (*val_it).latin1()); - generateDependencies(deplist, (*val_it), doDepends()); - } + /* Do moc before dependency checking since some includes can come from + moc_*.cpp files */ if(found_cache_moc) { - QString moc = findMocDestination(val_file); + QString moc = findMocDestination(file_list_file); if(!moc.isEmpty()) { for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { - if(val_file.endsWith((*cppit))) { - QStringList &deps = findDependencies(val_file); + if(file_list_file.endsWith((*cppit))) { + QStringList &deps = findDependencies(file_list_file); if(!deps.contains(moc)) deps.append(moc); break; } } } } else if(mocAware() && (sources[x] == "SOURCES" || sources[x] == "HEADERS") && (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT || Option::mkfile::do_mocs)) { - generateMocList((*val_it)); + generateMocList((*file_it)); + } + if(!found_cache_dep && sources[x] != "OBJECTS") { + debug_msg(5, "Looking for dependencies for %s", (*file_it).latin1()); + generateDependencies(deplist, (*file_it), doDepends()); + } } } } } if(project->isActiveConfig("qmake_cache") && (write_cache || !read_cache)) { QFile cachef(cache_file); if(cachef.open(IO_WriteOnly | IO_Translate)) { debug_msg(2, "Writing internal cache information: %s", cache_file.latin1()); QTextStream cachet(&cachef); cachet << "[check]" << "\n" << "QMAKE_CACHE_VERSION = " << qmake_version() << "\n" << "QMAKE_ABSOLUTE_SOURCE_PATH = " << var("QMAKE_ABSOLUTE_SOURCE_PATH") << "\n" << "MOC_DIR = " << var("MOC_DIR") << "\n" << "UI_DIR = " << var("UI_DIR") << "\n" << "UI_HEADERS_DIR = " << var("UI_HEADERS_DIR") << "\n" << "UI_SOURCES_DIR = " << var("UI_SOURCES_DIR") << "\n"; cachet << "[depend]" << endl; for(QMap<QString, QStringList>::Iterator it = depends.begin(); it != depends.end(); ++it) cachet << depKeyMap[it.key()] << " = " << it.data().join(" ") << endl; cachet << "[mocable]" << endl; QString mc, moc_sources[] = { QString("HEADERS"), QString("SOURCES"), QString::null }; for(int x = 0; moc_sources[x] != QString::null; x++) { QStringList &l = v[moc_sources[x]]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { - if(!(*val_it).isEmpty()) { - mc = mocablesToMOC[(*val_it)]; + QString f = fileFixify((*val_it)); + if(!f.isEmpty()) { + mc = mocablesToMOC[f]; if(mc.isEmpty()) mc = "*qmake_ignore*"; - cachet << (*val_it) << " = " << mc << endl; + cachet << f << " = " << mc << endl; } } } cachef.close(); } } } } v["OBJECTS"] = createObjectList("SOURCES") + v["OBJECTS"]; // init variables //lex files { QStringList &impls = v["LEXIMPLS"]; QStringList &l = v["LEXSOURCES"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString dir; QFileInfo fi((*it)); if(fi.dirPath() != ".") dir = fi.dirPath() + Option::dir_sep; dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) dir += Option::dir_sep; QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first(); logicWarn(impl, "SOURCES"); logicWarn(impl, "SOURCES"); impls.append(impl); if( ! project->isActiveConfig("lex_included")) { v["SOURCES"].append(impl); // attribute deps of lex file to impl file QStringList &lexdeps = findDependencies((*it)); QStringList &impldeps = findDependencies(impl); for(QStringList::ConstIterator d = lexdeps.begin(); d != lexdeps.end(); ++d) { if(!impldeps.contains(*d)) impldeps.append(*d); } lexdeps.clear(); } } if( ! project->isActiveConfig("lex_included")) v["OBJECTS"] += (v["LEXOBJECTS"] = createObjectList("LEXIMPLS")); } //yacc files { QStringList &decls = v["YACCCDECLS"], &impls = v["YACCIMPLS"]; QStringList &l = v["YACCSOURCES"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString dir; QFileInfo fi((*it)); if(fi.dirPath() != ".") dir = fi.dirPath() + Option::dir_sep; dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) dir += Option::dir_sep; QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first(); logicWarn(impl, "SOURCES"); QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first(); logicWarn(decl, "HEADERS"); decls.append(decl); impls.append(impl); v["SOURCES"].append(impl); QStringList &impldeps = findDependencies(impl); impldeps.append(decl); // attribute deps of yacc file to impl file QStringList &yaccdeps = findDependencies((*it)); for(QStringList::ConstIterator d = yaccdeps.begin(); d != yaccdeps.end(); ++d) { if(!impldeps.contains(*d)) impldeps.append(*d); } if( project->isActiveConfig("lex_included")) { // is there a matching lex file ? Transfer its dependencies. QString lexsrc = fi.baseName(TRUE) + Option::lex_ext; if(fi.dirPath() != ".") lexsrc.prepend(fi.dirPath() + Option::dir_sep); if(v["LEXSOURCES"].findIndex(lexsrc) != -1) { QString trg = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first(); impldeps.append(trg); impldeps += findDependencies(lexsrc); depends[lexsrc].clear(); } } yaccdeps.clear(); } v["OBJECTS"] += (v["YACCOBJECTS"] = createObjectList("YACCIMPLS")); } //UI files { + QStringList &includepath = project->variables()["INCLUDEPATH"]; if(!project->isEmpty("UI_DIR")) - project->variables()["INCLUDEPATH"].append(project->first("UI_DIR")); + includepath.append(project->first("UI_DIR")); else if(!project->isEmpty("UI_HEADERS_DIR")) - project->variables()["INCLUDEPATH"].append(project->first("UI_HEADERS_DIR")); + includepath.append(project->first("UI_HEADERS_DIR")); QStringList &decls = v["UICDECLS"], &impls = v["UICIMPLS"]; QStringList &l = v["FORMS"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString impl, decl; QFileInfo fi(Option::fixPathToLocalOS((*it))); if ( !project->isEmpty("UI_DIR") ) { impl = decl = project->first("UI_DIR"); QString d = fi.dirPath(); if( d == ".") d = QDir::currentDirPath(); - d = fileFixify(d); - if( !project->variables()["INCLUDEPATH"].contains(d)) - project->variables()["INCLUDEPATH"].append(d); + d = fileFixify(d, QDir::currentDirPath(), Option::output_dir); + if(!includepath.contains(d)) + includepath.append(d); } else { if(decl.isEmpty() && !project->isEmpty("UI_HEADERS_DIR")) decl = project->first("UI_HEADERS_DIR"); - if ( !decl.isEmpty() || (project->isEmpty("UI_HEADERS_DIR") && !project->isEmpty("UI_SOURCES_DIR")) ) { + if(!decl.isEmpty() || (project->isEmpty("UI_HEADERS_DIR") && + !project->isEmpty("UI_SOURCES_DIR")) ) { QString d = fi.dirPath(); if( d == ".") d = QDir::currentDirPath(); - d = fileFixify(d); - if( !project->variables()["INCLUDEPATH"].contains(d)) - project->variables()["INCLUDEPATH"].append(d); + d = fileFixify(d, QDir::currentDirPath(), Option::output_dir); + if(includepath.contains(d)) + includepath.append(d); } if(impl.isEmpty() && !project->isEmpty("UI_SOURCES_DIR")) impl = project->first("UI_SOURCES_DIR"); if(fi.dirPath() != ".") { if(impl.isEmpty()) impl = fi.dirPath() + Option::dir_sep; if(decl.isEmpty()) decl = fi.dirPath() + Option::dir_sep; } } - impl += fi.baseName(TRUE) + Option::cpp_ext.first(), + impl = fileFixify(impl, QDir::currentDirPath(), Option::output_dir); + if(!impl.isEmpty()) + impl += Option::dir_sep; + impl += fi.baseName(TRUE) + Option::cpp_ext.first(); + if(Option::output_dir != QDir::currentDirPath() && + project->isEmpty("UI_DIR") && project->isEmpty("UI_HEADERS_DIR")) { + QString decl_fixed = fileFixify(decl, QDir::currentDirPath(), Option::output_dir); + if(!includepath.contains(decl_fixed)) + includepath.append(decl_fixed); + if(!includepath.contains(decl)) + project->variables()["INCLUDEPATH"].append(decl); + } + decl = fileFixify(decl, QDir::currentDirPath(), Option::output_dir); + if(!decl.isEmpty()) + decl += Option::dir_sep; decl += fi.baseName(TRUE) + Option::h_ext.first(); logicWarn(impl, "SOURCES"); logicWarn(decl, "HEADERS"); decls.append(decl); impls.append(impl); findDependencies(impl).append(decl); QString mocable = Option::moc_mod + fi.baseName(TRUE) + Option::cpp_ext.first(); if(!v["MOC_DIR"].isEmpty()) mocable.prepend(v["MOC_DIR"].first()); else if(fi.dirPath() != ".") mocable.prepend(fi.dirPath() + Option::dir_sep); logicWarn(mocable, "SOURCES"); mocablesToMOC[cleanFilePath(decl)] = mocable; mocablesFromMOC[cleanFilePath(mocable)] = decl; v["_UIMOC"].append(mocable); } v["OBJECTS"] += (v["UICOBJECTS"] = createObjectList("UICDECLS")); } //Image files if(!project->isEmpty("IMAGES")) { if(project->isEmpty("QMAKE_IMAGE_COLLECTION")) v["QMAKE_IMAGE_COLLECTION"].append("qmake_image_collection" + Option::cpp_ext.first()); QString imgfile = project->first("QMAKE_IMAGE_COLLECTION"); Option::fixPathToTargetOS(imgfile); if(!project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) { if(imgfile.find(Option::dir_sep) != -1) imgfile = imgfile.right(imgfile.findRev(Option::dir_sep) + 1); imgfile.prepend( (project->isEmpty("UI_DIR") ? project->first("UI_SOURCES_DIR") : project->first("UI_DIR")) ); v["QMAKE_IMAGE_COLLECTION"] = QStringList(imgfile); } logicWarn(imgfile, "SOURCES"); if(!noIO()) { QStringList &l = v["IMAGES"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { if(!QFile::exists((*it))) { warn_msg(WarnLogic, "Failure to open: %s", (*it).latin1()); continue; } findDependencies(imgfile).append(fileFixify((*it))); } } v["OBJECTS"] += (v["IMAGEOBJECTS"] = createObjectList("QMAKE_IMAGE_COLLECTION")); } - - if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) - project->variables()["INCLUDEPATH"].append(Option::output_dir); + if(Option::output_dir != QDir::currentDirPath()) + project->variables()["INCLUDEPATH"].append(fileFixify(Option::output_dir, Option::output_dir, + Option::output_dir)); //moc files if ( mocAware() ) { if(!project->isEmpty("MOC_DIR")) project->variables()["INCLUDEPATH"].append(project->first("MOC_DIR")); v["OBJMOC"] = createObjectList("_HDRMOC") + createObjectList("_UIMOC"); QStringList &l = v["SRCMOC"]; l = v["_HDRMOC"] + v["_UIMOC"] + v["_SRCMOC"]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { if(!(*val_it).isEmpty()) (*val_it) = Option::fixPathToTargetOS((*val_it), FALSE); } } } bool MakefileGenerator::processPrlFile(QString &file) { bool ret = FALSE, try_replace_file=FALSE; QString prl_file; if(file.endsWith(Option::prl_ext)) { try_replace_file = TRUE; prl_file = file; file = ""; } else { QString tmp = file; int ext = tmp.findRev('.'); if(ext != -1) tmp = tmp.left(ext); prl_file = tmp + Option::prl_ext; } prl_file = fileFixify(prl_file); if(!QFile::exists(fileFixify(prl_file, QDir::currentDirPath(), Option::output_dir)) && project->isActiveConfig("qt")) { QString stem = prl_file, dir, extn; int slsh = stem.findRev('/'), hadlib = 0; if(slsh != -1) { dir = stem.left(slsh + 1); stem = stem.right(stem.length() - slsh - 1); } if(stem.startsWith("lib")) { hadlib = 1; stem = stem.right(stem.length() - 3); } int dot = stem.find('.'); if(dot != -1) { extn = stem.right(stem.length() - dot); stem = stem.left(dot); } if(stem == "qt" || stem == "qte" || stem == "qte-mt" || stem == "qt-mt") { if(stem.endsWith("-mt")) stem = stem.left(stem.length() - 3); //lose the -mt else stem += "-mt"; //try the thread case prl_file = dir; if(hadlib) prl_file += "lib"; prl_file += stem + extn; try_replace_file = TRUE; } } QString real_prl_file = Option::fixPathToLocalOS(prl_file); if(project->variables()["QMAKE_PRL_INTERNAL_FILES"].findIndex(prl_file) != -1) { ret = TRUE; } else if(!real_prl_file.isEmpty() && QFile::exists(fileFixify(real_prl_file, QDir::currentDirPath(), Option::output_dir))) { project->variables()["QMAKE_PRL_INTERNAL_FILES"].append(prl_file); QMakeProject proj; debug_msg(1, "Processing PRL file: %s", real_prl_file.latin1()); if(!proj.read(fileFixify(real_prl_file, QDir::currentDirPath(), Option::output_dir), - QDir::currentDirPath())) { + QDir::currentDirPath(), TRUE)) { fprintf(stderr, "Error processing prl file: %s\n", real_prl_file.latin1()); } else { ret = TRUE; QMap<QString, QStringList> &vars = proj.variables(); for( QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it) processPrlVariable(it.key(), it.data()); if(try_replace_file && !proj.isEmpty("QMAKE_PRL_TARGET")) { QString dir; int slsh = real_prl_file.findRev(Option::dir_sep); if(slsh != -1) dir = real_prl_file.left(slsh+1); file = dir + proj.first("QMAKE_PRL_TARGET"); } } if(ret) project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].append(prl_file); } return ret; } void MakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) { if(var == "QMAKE_PRL_LIBS") { QString where = "QMAKE_LIBS"; if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) where = project->first("QMAKE_INTERNAL_PRL_LIBS"); QStringList &out = project->variables()[where]; for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if( out.findIndex((*it)) == -1) out.append((*it)); } } else if(var == "QMAKE_PRL_DEFINES") { QStringList &out = project->variables()["DEFINES"]; for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if(out.findIndex((*it)) == -1 && project->variables()["PRL_EXPORT_DEFINES"].findIndex((*it)) == -1) out.append((*it)); } } } void MakefileGenerator::processPrlFiles() { QDict<void> processed; for(bool ret = FALSE; TRUE; ret = FALSE) { //read in any prl files included.. QStringList l_out; QString where = "QMAKE_LIBS"; if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) where = project->first("QMAKE_INTERNAL_PRL_LIBS"); QStringList &l = project->variables()[where]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString file = (*it); if(!processed[file] && processPrlFile(file)) { processed.insert(file, (void*)1); ret = TRUE; } if(!file.isEmpty()) l_out.append(file); } if(ret) l = l_out; else break; } } void MakefileGenerator::writePrlFile(QTextStream &t) { QString target = project->first("TARGET"); int slsh = target.findRev(Option::dir_sep); if(slsh != -1) target = target.right(target.length() - slsh - 1); QString bdir = Option::output_dir; if(bdir.isEmpty()) bdir = QDir::currentDirPath(); t << "QMAKE_PRL_BUILD_DIR = " << bdir << endl; if(!project->projectFile().isEmpty() && project->projectFile() != "-") t << "QMAKE_PRO_INPUT = " << project->projectFile().section('/', -1) << endl; if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) t << "QMAKE_PRL_SOURCE_DIR = " << project->first("QMAKE_ABSOLUTE_SOURCE_PATH") << endl; t << "QMAKE_PRL_TARGET = " << target << endl; if(!project->isEmpty("PRL_EXPORT_DEFINES")) t << "QMAKE_PRL_DEFINES = " << project->variables()["PRL_EXPORT_DEFINES"].join(" ") << endl; if(!project->isEmpty("CONFIG")) t << "QMAKE_PRL_CONFIG = " << project->variables()["CONFIG"].join(" ") << endl; + if(!project->isEmpty("VERSION")) + t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl; if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) { QStringList libs; if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) libs = project->variables()["QMAKE_INTERNAL_PRL_LIBS"]; else libs << "QMAKE_LIBS"; //obvious one t << "QMAKE_PRL_LIBS = "; for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it) t << project->variables()[(*it)].join(" ") << " "; t << endl; } } bool MakefileGenerator::write() { init(); findLibraries(); if((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || //write prl Option::qmake_mode == Option::QMAKE_GENERATE_PRL) && project->isActiveConfig("create_prl") && project->first("TEMPLATE") == "lib" && !project->isActiveConfig("plugin")) { QString prl = var("TARGET"); int slsh = prl.findRev(Option::dir_sep); if(slsh != -1) prl = prl.right(prl.length() - slsh); int dot = prl.find('.'); if(dot != -1) prl = prl.left(dot); prl += Option::prl_ext; if(!project->isEmpty("DESTDIR")) prl.prepend(var("DESTDIR")); - QString local_prl = fileFixify(prl, QDir::currentDirPath(), Option::output_dir); - fixEnvVariables(local_prl); + QString local_prl = Option::fixPathToLocalOS(fileFixify(prl, QDir::currentDirPath(), Option::output_dir)); QFile ft(local_prl); if(ft.open(IO_WriteOnly)) { project->variables()["ALL_DEPS"].append(prl); project->variables()["QMAKE_INTERNAL_PRL_FILE"].append(prl); QTextStream t(&ft); writePrlFile(t); ft.close(); } } if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE && - project->isActiveConfig("link_prl")) //load up prl's + project->isActiveConfig("link_prl")) //load up prl's' processPrlFiles(); if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { QTextStream t(&Option::output); writeMakefile(t); } return TRUE; } void MakefileGenerator::writeObj(QTextStream &t, const QString &obj, const QString &src) { QStringList &objl = project->variables()[obj]; QStringList &srcl = project->variables()[src]; QStringList::Iterator oit = objl.begin(); QStringList::Iterator sit = srcl.begin(); QString stringSrc("$src"); QString stringObj("$obj"); for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) { if((*sit).isEmpty()) continue; if(!doDepends()) { QString sdep, odep = (*sit) + " "; QStringList deps = findDependencies((*sit)); for(QStringList::Iterator dit = deps.begin(); dit != deps.end(); dit++) { if((*dit).endsWith(Option::moc_ext)) odep += (*dit) + " "; else sdep += (*dit) + " "; } t << (*sit) << ": " << sdep << endl << (*oit) << ": " << odep ; } else { t << (*oit) << ": " << (*sit) << " " << findDependencies((*sit)).join(" \\\n\t\t"); } QString comp, cimp; for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { if((*sit).endsWith((*cppit))) { comp = "QMAKE_RUN_CXX"; cimp = "QMAKE_RUN_CXX_IMP"; break; } } if(comp.isEmpty()) { comp = "QMAKE_RUN_CC"; cimp = "QMAKE_RUN_CC_IMP"; } bool use_implicit_rule = !project->isEmpty(cimp); if(use_implicit_rule) { if(!project->isEmpty("OBJECTS_DIR")) { use_implicit_rule = FALSE; } else { int dot = (*sit).findRev('.'); if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit))) use_implicit_rule = FALSE; } } - if (!use_implicit_rule) { + if (!use_implicit_rule && !project->isEmpty(comp)) { QString p = var(comp); p.replace(stringSrc, (*sit)); p.replace(stringObj, (*oit)); t << "\n\t" << p; } t << endl << endl; } } void MakefileGenerator::writeUicSrc(QTextStream &t, const QString &ui) { QStringList &uil = project->variables()[ui]; for(QStringList::Iterator it = uil.begin(); it != uil.end(); it++) { QString deps = findDependencies((*it)).join(" \\\n\t\t"), decl, impl; { - QString tmp = (*it); + QString tmp = (*it), impl_dir, decl_dir; decl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::h_ext.first()); + decl = fileFixify(decl, QDir::currentDirPath(), Option::output_dir); + int dlen = decl.findRev(Option::dir_sep) + 1; tmp = (*it); impl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::cpp_ext.first()); - int dlen = (*it).findRev(Option::dir_sep) + 1; + impl = fileFixify(impl, QDir::currentDirPath(), Option::output_dir); + int ilen = decl.findRev(Option::dir_sep) + 1; if(!project->isEmpty("UI_DIR")) { + impl_dir = project->first("UI_DIR"); decl = project->first("UI_DIR") + decl.right(decl.length() - dlen); - impl = project->first("UI_DIR") + impl.right(impl.length() - dlen); + impl = project->first("UI_DIR") + impl.right(impl.length() - ilen); } else { - if(!project->isEmpty("UI_HEADERS_DIR")) + if(!project->isEmpty("UI_HEADERS_DIR")) { + decl_dir = project->first("UI_HEADERS_DIR"); decl = project->first("UI_HEADERS_DIR") + decl.right(decl.length() - dlen); - if(!project->isEmpty("UI_SOURCES_DIR")) - impl = project->first("UI_SOURCES_DIR") + impl.right(impl.length() - dlen); } + if(!project->isEmpty("UI_SOURCES_DIR")) { + impl_dir = project->first("UI_SOURCES_DIR"); + impl = project->first("UI_SOURCES_DIR") + impl.right(impl.length() - ilen); + } + } + if(decl_dir.isEmpty()) + decl_dir = decl.left(dlen); + if(impl_dir.isEmpty()) + impl_dir = impl.left(ilen); + if(!impl_dir.isEmpty()) + createDir(Option::output_dir + Option::dir_sep + impl_dir); + if(!decl_dir.isEmpty() && decl_dir != impl_dir) + createDir(Option::output_dir + Option::dir_sep + decl_dir); } t << decl << ": " << (*it) << " " << deps << "\n\t" << "$(UIC) " << (*it) << " -o " << decl << endl << endl; QString mildDecl = decl; int k = mildDecl.findRev( Option::dir_sep ); if ( k != -1 ) mildDecl = mildDecl.mid( k + 1 ); t << impl << ": " << decl << " " << (*it) << " " << deps << "\n\t" << "$(UIC) " << (*it) << " -i " << mildDecl << " -o " << impl << endl << endl; } } void MakefileGenerator::writeMocObj(QTextStream &t, const QString &obj, const QString &src) { QStringList &objl = project->variables()[obj], &srcl = project->variables()[src]; QStringList::Iterator oit = objl.begin(), sit = srcl.begin(); QString stringSrc("$src"), stringObj("$obj"); for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) { QString hdr = findMocSource((*sit)); t << (*oit) << ": " << (*sit) << " " << hdr << " " << findDependencies(hdr).join(" \\\n\t\t"); bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP"); if(use_implicit_rule) { if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("MOC_DIR")) { use_implicit_rule = FALSE; } else { int dot = (*sit).findRev('.'); if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit))) use_implicit_rule = FALSE; } } - if (!use_implicit_rule) { + if (!use_implicit_rule && !project->isEmpty("QMAKE_RUN_CXX")) { QString p = var("QMAKE_RUN_CXX"); p.replace(stringSrc, (*sit)); p.replace(stringObj, (*oit)); t << "\n\t" << p; } t << endl << endl; } } void MakefileGenerator::writeMocSrc(QTextStream &t, const QString &src) { QStringList &l = project->variables()[src]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString m = Option::fixPathToTargetOS(findMocDestination(*it)); if ( !m.isEmpty()) { QString deps; if(!project->isActiveConfig("no_mocdepend")) deps += "$(MOC) "; deps += (*it); t << m << ": " << deps << "\n\t" << "$(MOC) " << (*it) << " -o " << m << endl << endl; } } } void MakefileGenerator::writeYaccSrc(QTextStream &t, const QString &src) { QStringList &l = project->variables()[src]; if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1) warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected." "This can lead to link problems.\n"); QString default_out_h = "y.tab.h", default_out_c = "y.tab.c"; if(!project->isEmpty("QMAKE_YACC_HEADER")) default_out_h = project->first("QMAKE_YACC_HEADER"); if(!project->isEmpty("QMAKE_YACC_SOURCE")) default_out_c = project->first("QMAKE_YACC_SOURCE"); QString stringBase("$base"); for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QFileInfo fi((*it)); - QString dir = fileFixify(Option::output_dir); + QString dir; + if(fi.dirPath() != ".") + dir = fi.dirPath() + Option::dir_sep; + dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) dir += Option::dir_sep; + QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first(); QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first(); QString yaccflags = "$(YACCFLAGS)", mangle = "y"; if(!project->isActiveConfig("yacc_no_name_mangle")) { mangle = fi.baseName(TRUE); yaccflags += " -p " + mangle; } QString out_h = default_out_h, out_c = default_out_c; if(!mangle.isEmpty()) { out_h.replace(stringBase, mangle); out_c.replace(stringBase, mangle); } t << impl << ": " << (*it) << "\n\t" << "$(YACC) " << yaccflags << " " << (*it) << "\n\t" << "-$(DEL_FILE) " << impl << " " << decl << "\n\t" << "-$(MOVE) " << out_h << " " << decl << "\n\t" << "-$(MOVE) " << out_c << " " << impl << endl << endl; t << decl << ": " << impl << endl << endl; } } void MakefileGenerator::writeLexSrc(QTextStream &t, const QString &src) { QStringList &l = project->variables()[src]; if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1) warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected.\n" "This can lead to link problems.\n"); QString default_out_c = "lex.$base.c"; if(!project->isEmpty("QMAKE_LEX_SOURCE")) default_out_c = project->first("QMAKE_LEX_SOURCE"); QString stringBase("$base"); for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QFileInfo fi((*it)); - QString dir = fileFixify(Option::output_dir); + QString dir; + if(fi.dirPath() != ".") + dir = fi.dirPath() + Option::dir_sep; + dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) dir += Option::dir_sep; QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first(); QString lexflags = "$(LEXFLAGS)", stub="yy"; if(!project->isActiveConfig("yacc_no_name_mangle")) { stub = fi.baseName(TRUE); lexflags += " -P" + stub; } QString out_c = default_out_c; if(!stub.isEmpty()) out_c.replace(stringBase, stub); t << impl << ": " << (*it) << " " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t" << ( "$(LEX) " + lexflags + " " ) << (*it) << "\n\t" << "-$(DEL_FILE) " << impl << " " << "\n\t" << "-$(MOVE) " << out_c << " " << impl << endl << endl; } } void MakefileGenerator::writeImageObj(QTextStream &t, const QString &obj) { QStringList &objl = project->variables()[obj]; QString stringSrc("$src"); QString stringObj("$obj"); QString uidir; for(QStringList::Iterator oit = objl.begin(); oit != objl.end(); oit++) { QString src(project->first("QMAKE_IMAGE_COLLECTION")); t << (*oit) << ": " << src; bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP"); if(use_implicit_rule) { if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) { use_implicit_rule = FALSE; } else { int dot = src.findRev('.'); if(dot == -1 || (src.left(dot) + Option::obj_ext != (*oit))) use_implicit_rule = FALSE; } } - if(!use_implicit_rule) { + if(!use_implicit_rule && !project->isEmpty("QMAKE_RUN_CXX")) { QString p = var("QMAKE_RUN_CXX"); p.replace( stringSrc, src); p.replace( stringObj, (*oit)); t << "\n\t" << p; } t << endl << endl; } } void MakefileGenerator::writeImageSrc(QTextStream &t, const QString &src) { QStringList &l = project->variables()[src]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString gen = project->first("MAKEFILE_GENERATOR"); if ( gen == "MSVC" ) { t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t" << "$(UIC) -o " << (*it) << " -embed " << project->first("QMAKE_ORIG_TARGET") << " -f <<\n" << findDependencies((*it)).join(" ") << "\n<<" << endl << endl; } else if ( gen == "BMAKE" ) { t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t" << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET") << " -f &&|\n" << findDependencies((*it)).join(" ") << "\n| -o " << (*it) << endl << endl; } else { t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t" << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET") << " " << findDependencies((*it)).join(" ") << " -o " << (*it) << endl << endl; } } } void MakefileGenerator::writeInstalls(QTextStream &t, const QString &installs) { QString all_installs, all_uninstalls; QStringList &l = project->variables()[installs]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString pvar = (*it) + ".path"; if(project->variables()[pvar].isEmpty()) { warn_msg(WarnLogic, "%s is not defined: install target not created\n", pvar.latin1()); continue; } bool do_default = TRUE; - QString target, dst="$(INSTALL_ROOT)" + Option::fixPathToTargetOS(project->variables()[pvar].first(), FALSE); + const QString root = "$(INSTALL_ROOT)"; + QString target, dst= fileFixify(project->variables()[pvar].first()); +#ifndef Q_WS_WIN if(dst.right(1) != Option::dir_sep) dst += Option::dir_sep; +#endif QStringList tmp, &uninst = project->variables()[(*it) + ".uninstall"]; //other tmp = project->variables()[(*it) + ".extra"]; if(!tmp.isEmpty()) { do_default = FALSE; if(!target.isEmpty()) target += "\n\t"; target += tmp.join(" "); } //masks tmp = project->variables()[(*it) + ".files"]; if(!tmp.isEmpty()) { if(!target.isEmpty()) target += "\n"; do_default = FALSE; for(QStringList::Iterator wild_it = tmp.begin(); wild_it != tmp.end(); ++wild_it) { QString wild = Option::fixPathToLocalOS((*wild_it), FALSE), wild_var = fileFixify(wild); - if(QFile::exists(wild)) { //real file - QFileInfo fi(wild); - target += QString("\t-") + (fi.isDir() ? "$(COPY_DIR)" : "$(COPY_FILE)") + - " \"" + Option::fixPathToTargetOS(fileFixify(wild), FALSE) + "\" \"" + fileFixify(dst) + "\"\n"; - if(!project->isActiveConfig("debug") && - !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP")) - target += QString("\t") + var("QMAKE_STRIP") + " \"" + fileFixify(dst + wild) + "\"\n"; - uninst.append(QString("-$(DEL_FILE) -r") + " \"" + fileFixify(dst + wild) + "\""); - continue; - } - QString dirstr = QDir::currentDirPath(), f = wild; //wild - int slsh = f.findRev(Option::dir_sep); + QString dirstr = QDir::currentDirPath(), filestr = wild; + int slsh = filestr.findRev(Option::dir_sep); if(slsh != -1) { - dirstr = f.left(slsh+1); - f = f.right(f.length() - slsh - 1); + dirstr = filestr.left(slsh+1); + filestr = filestr.right(filestr.length() - slsh - 1); } if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep) dirstr += Option::dir_sep; + if(QFile::exists(wild)) { //real file + QString file = wild; + QFileInfo fi(wild); + if(!target.isEmpty()) + target += "\t"; + target += QString(fi.isDir() ? "-$(COPY_DIR)" : "-$(COPY_FILE)") + " \"" + + Option::fixPathToTargetOS(fileFixify(wild), FALSE) + "\" \"" + root + dst + "\"\n"; + if(!project->isActiveConfig("debug") && + !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP")) + target += QString("\t-") + var("QMAKE_STRIP") + " \"" + root + fileFixify(dst + filestr) + "\"\n"; if(!uninst.isEmpty()) uninst.append("\n\t"); - uninst.append(QString("-$(DEL_FILE) -r") + " " + fileFixify(dst + f) + ""); - - QDir dir(dirstr, f); + uninst.append( +#ifdef Q_WS_WIN + QString("-$(DEL_FILE)") +#else + QString("-$(DEL_FILE) -r") +#endif + + " \"" + root + fileFixify(dst + filestr) + "\""); + continue; + } + QDir dir(dirstr, filestr); //wild for(uint x = 0; x < dir.count(); x++) { QString file = dir[x]; if(file == "." || file == "..") //blah continue; + if(!uninst.isEmpty()) + uninst.append("\n\t"); + uninst.append( +#ifdef Q_WS_WIN + QString("-$(DEL_FILE)") +#else + QString("-$(DEL_FILE) -r") +#endif + + " \"" + root + fileFixify(dst + file) + "\""); QFileInfo fi(file); - target += QString("\t-") + (fi.isDir() ? "$(COPY_DIR)" : "$(COPY_FILE)") + - " \"" + Option::fixPathToTargetOS(fileFixify(dirstr + file), FALSE) + - "\" \"" + fileFixify(dst) + "\"\n"; + if(!target.isEmpty()) + target += "\t"; + target += QString(fi.isDir() ? "-$(COPY_DIR)" : "-$(COPY_FILE)") + " \"" + + Option::fixPathToTargetOS(fileFixify(dirstr + file), FALSE) + + "\" \"" + root + fileFixify(dst) + "\"\n"; if(!project->isActiveConfig("debug") && !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP")) - target += QString("\t") + var("QMAKE_STRIP") + " \"" + fileFixify(dst + file) + "\"\n"; + target += QString("\t-") + var("QMAKE_STRIP") + " \"" + root + fileFixify(dst + file) + "\"\n"; } } } //default? if(do_default) target = defaultInstall((*it)); if(!target.isEmpty()) { - t << "install_" << (*it) << ": " << "\n\t" - << "@test -d " << dst << " || mkdir -p " << dst << "\n\t" - << target << endl << endl; + t << "install_" << (*it) << ": " << "\n\t"; + const QStringList &dirs = project->variables()[pvar]; + for(QStringList::ConstIterator pit = dirs.begin(); pit != dirs.end(); ++pit) { + QString tmp_dst = fileFixify((*pit)); +#ifndef Q_WS_WIN + if(tmp_dst.right(1) != Option::dir_sep) + tmp_dst += Option::dir_sep; +#endif + t << mkdir_p_asstring(root+tmp_dst) << "\n\t"; + } + t << target << endl << endl; all_installs += QString("install_") + (*it) + " "; if(!uninst.isEmpty()) { t << "uninstall_" << (*it) << ": " << "\n\t" << uninst.join(" ") << "\n\t" - << "-$(DEL_DIR) \"" << dst << "\"" << endl << endl; + << "-$(DEL_DIR) \"" << ( root + dst ) << "\"" << endl << endl; all_uninstalls += "uninstall_" + (*it) + " "; } t << endl; } else { debug_msg(1, "no definition for install %s: install target not created",(*it).latin1()); } } t << "install: all " << all_installs << "\n\n"; t << "uninstall: " << all_uninstalls << "\n\n"; } QString MakefileGenerator::var(const QString &var) { return val(project->variables()[var]); } QString MakefileGenerator::val(const QStringList &varList) { return valGlue(varList, "", " ", ""); } QString MakefileGenerator::varGlue(const QString &var, const QString &before, const QString &glue, const QString &after) { return valGlue(project->variables()[var], before, glue, after); } QString MakefileGenerator::valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after) { QString ret; for(QStringList::ConstIterator it = varList.begin(); it != varList.end(); ++it) { if(!(*it).isEmpty()) { if(!ret.isEmpty()) ret += glue; ret += (*it); } } return ret.isEmpty() ? QString("") : before + ret + after; } QString MakefileGenerator::varList(const QString &var) { return valList(project->variables()[var]); } QString MakefileGenerator::valList(const QStringList &varList) { return valGlue(varList, "", " \\\n\t\t", ""); } QStringList MakefileGenerator::createObjectList(const QString &var) { QStringList &l = project->variables()[var], ret; QString objdir, dir; if(!project->variables()["OBJECTS_DIR"].isEmpty()) objdir = project->first("OBJECTS_DIR"); for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QFileInfo fi(Option::fixPathToLocalOS((*it))); if(objdir.isEmpty() && project->isActiveConfig("object_with_source")) { QString fName = Option::fixPathToTargetOS((*it), FALSE); int dl = fName.findRev(Option::dir_sep); if(dl != -1) dir = fName.left(dl + 1); } else { dir = objdir; } ret.append(dir + fi.baseName(TRUE) + Option::obj_ext); } return ret; } bool MakefileGenerator::writeMakefile(QTextStream &t) { t << "####### Compile" << endl << endl; writeObj(t, "OBJECTS", "SOURCES"); writeUicSrc(t, "FORMS"); writeObj(t, "UICOBJECTS", "UICIMPLS"); writeMocObj(t, "OBJMOC", "SRCMOC" ); writeMocSrc(t, "HEADERS"); writeMocSrc(t, "SOURCES"); writeMocSrc(t, "UICDECLS"); writeYaccSrc(t, "YACCSOURCES"); writeLexSrc(t, "LEXSOURCES"); writeImageObj(t, "IMAGEOBJECTS"); writeImageSrc(t, "QMAKE_IMAGE_COLLECTION"); t << "####### Install" << endl << endl; writeInstalls(t, "INSTALLS"); return TRUE; } QString MakefileGenerator::buildArgs() { static QString ret; if(ret.isEmpty()) { //special variables if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) ret += " QMAKE_ABSOLUTE_SOURCE_PATH=\"" + project->first("QMAKE_ABSOLUTE_SOURCE_PATH") + "\""; //warnings else if(Option::warn_level == WarnNone) ret += " -Wnone"; else if(Option::warn_level == WarnAll) ret += " -Wall"; else if(Option::warn_level & WarnParser) ret += " -Wparser"; //other options if(!Option::user_template.isEmpty()) ret += " -t " + Option::user_template; if(!Option::mkfile::do_cache) ret += " -nocache"; if(!Option::mkfile::do_deps) ret += " -nodepend"; if(!Option::mkfile::do_mocs) ret += " -nomoc"; if(!Option::mkfile::do_dep_heuristics) ret += " -nodependheuristics"; if(!Option::mkfile::qmakespec_commandline.isEmpty()) ret += " -spec " + Option::mkfile::qmakespec_commandline; //arguments for(QStringList::Iterator it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it) { if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH") ret += " \"" + (*it) + "\""; } if(Option::after_user_vars.count()) { ret += " -after "; for(QStringList::Iterator it = Option::after_user_vars.begin(); it != Option::after_user_vars.end(); ++it) { if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH") ret += " \"" + (*it) + "\""; } } } return ret; } //could get stored argv, but then it would have more options than are //probably necesary this will try to guess the bare minimum.. QString MakefileGenerator::build_args() { static QString ret; if(ret.isEmpty()) { ret = "$(QMAKE)"; // general options and arguments ret += buildArgs(); //output QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name())); if (!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE")) ret += " -o " + ofile; //inputs QStringList files = fileFixify(Option::mkfile::project_files); ret += " " + files.join(" "); } return ret; } bool MakefileGenerator::writeHeader(QTextStream &t) { time_t foo = time(NULL); t << "#############################################################################" << endl; t << "# Makefile for building: " << var("TARGET") << endl; - t << "# Generated by qmake (" << qmake_version() << ") on: " << ctime(&foo); + t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: " << ctime(&foo); t << "# Project: " << fileFixify(project->projectFile()) << endl; t << "# Template: " << var("TEMPLATE") << endl; t << "# Command: " << build_args() << endl; t << "#############################################################################" << endl; t << endl; return TRUE; } //makes my life easier.. bool MakefileGenerator::writeMakeQmake(QTextStream &t) { QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name())); - if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && + if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isActiveConfig("no_autoqmake") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) { QStringList files = fileFixify(Option::mkfile::project_files); t << project->first("QMAKE_INTERNAL_PRL_FILE") << ": " << "\n\t" << "@$(QMAKE) -prl " << buildArgs() << " " << files.join(" ") << endl; } QString pfile = project->projectFile(); if(pfile != "(stdin)") { QString qmake = build_args(); if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) { t << ofile << ": " << fileFixify(pfile) << " "; if(Option::mkfile::do_cache) t << fileFixify(Option::mkfile::cachefile) << " "; if(!specdir().isEmpty()) t << specdir() << Option::dir_sep << "qmake.conf" << " "; t << project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].join(" \\\n\t\t") << "\n\t" << qmake <<endl; } if(project->first("QMAKE_ORIG_TARGET") != "qmake") { t << "qmake: " << project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].join(" \\\n\t\t") << "\n\t" << "@" << qmake << endl << endl; } } return TRUE; } QStringList MakefileGenerator::fileFixify(const QStringList& files, const QString &out_dir, const QString &in_dir, bool force_fix) const { if(files.isEmpty()) return files; QStringList ret; for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) { if(!(*it).isEmpty()) ret << fileFixify((*it), out_dir, in_dir, force_fix); } return ret; } QString MakefileGenerator::fileFixify(const QString& file0, const QString &out_d, const QString &in_d, bool force_fix) const { + if(file0.isEmpty()) + return file0; + QString key = file0; + if(!in_d.isEmpty() || !out_d.isEmpty() || force_fix) + key.prepend(in_d + "--" + out_d + "--" + QString::number((int)force_fix) + "-"); + if(fileFixed.contains(key)) + return fileFixed[key]; + QString file = file0; - if(file.isEmpty()) - return file; int depth = 4; if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { if(project && !project->isEmpty("QMAKE_PROJECT_DEPTH")) depth = project->first("QMAKE_PROJECT_DEPTH").toInt(); else if(Option::mkfile::cachefile_depth != -1) depth = Option::mkfile::cachefile_depth; } QChar quote; if((file.startsWith("'") || file.startsWith("\"")) && file.startsWith(file.right(1))) { quote = file.at(0); file = file.mid(1, file.length() - 2); } QString orig_file = file; if(!force_fix && project->isActiveConfig("no_fixpath")) { if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) { //absoluteify it QString qfile = Option::fixPathToLocalOS(file); if(QDir::isRelativePath(file)) { //already absolute QFileInfo fi(qfile); if(!fi.convertToAbs()) //strange file = fi.filePath(); } } } else { //fix it.. QString qfile(Option::fixPathToLocalOS(file, TRUE)), in_dir(in_d), out_dir(out_d); { if(out_dir.isNull()) out_dir = Option::output_dir; if(out_dir == ".") out_dir = QDir::currentDirPath(); if(in_dir.isEmpty() || in_dir == ".") in_dir = QDir::currentDirPath(); if(!QDir::isRelativePath(in_dir) || !QDir::isRelativePath(out_dir)) { QFileInfo in_fi(in_dir); if(!in_fi.convertToAbs()) in_dir = in_fi.filePath(); QFileInfo out_fi(out_dir); if(!out_fi.convertToAbs()) out_dir = out_fi.filePath(); } + QString in_canonical_dir = QDir(in_dir).canonicalPath(), + out_canonical_dir = QDir(out_dir).canonicalPath(); + if(!in_canonical_dir.isEmpty()) + in_dir = in_canonical_dir; + if(!out_canonical_dir.isEmpty()) + out_dir = out_canonical_dir; } if(out_dir != in_dir || !QDir::isRelativePath(qfile)) { if(QDir::isRelativePath(qfile)) { if(file.left(Option::dir_sep.length()) != Option::dir_sep && in_dir.right(Option::dir_sep.length()) != Option::dir_sep) file.prepend(Option::dir_sep); file.prepend(in_dir); } file = Option::fixPathToTargetOS(file, FALSE); + if(QFile::exists(file) && file == Option::fixPathToTargetOS(file, TRUE)) { + QString real_file = QDir(file).canonicalPath(); + if(!real_file.isEmpty()) + file = real_file; + } QString match_dir = Option::fixPathToTargetOS(out_dir, FALSE); if(file == match_dir) { file = ""; } else if(file.startsWith(match_dir) && file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) { file = file.right(file.length() - (match_dir.length() + 1)); } else { for(int i = 1; i <= depth; i++) { int sl = match_dir.findRev(Option::dir_sep); if(sl == -1) break; match_dir = match_dir.left(sl); if(match_dir.isEmpty()) break; if(file.startsWith(match_dir) && file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) { //concat int remlen = file.length() - (match_dir.length() + 1); if (remlen < 0) remlen = 0; file = file.right(remlen); //prepend for(int o = 0; o < i; o++) file.prepend(".." + Option::dir_sep); } } } } } file = Option::fixPathToTargetOS(file, FALSE); + if(file.isEmpty()) + file = "."; if(!quote.isNull()) file = quote + file + quote; debug_msg(3, "Fixed %s :: to :: %s (%d)", orig_file.latin1(), file.latin1(), depth); + ((MakefileGenerator*)this)->fileFixed.insert(key, file); return file; } QString MakefileGenerator::cleanFilePath(const QString &file) const { return fileFixify(Option::fixPathToTargetOS(file)); } void MakefileGenerator::logicWarn(const QString &f, const QString &w) { if(!(Option::warn_level & WarnLogic)) return; QString file = f; int slsh = f.findRev(Option::dir_sep); if(slsh != -1) file = file.right(file.length() - slsh - 1); QStringList &l = project->variables()[w]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { QString file2((*val_it)); slsh = file2.findRev(Option::dir_sep); if(slsh != -1) file2 = file2.right(file2.length() - slsh - 1); if(file2 == file) { warn_msg(WarnLogic, "Found potential symbol conflict of %s (%s) in %s", file.latin1(), (*val_it).latin1(), w.latin1()); break; } } } QStringList &MakefileGenerator::findDependencies(const QString &file) { QString key = file; Option::fixPathToTargetOS(key); if(key.find(Option::dir_sep)) key = key.right(key.length() - key.findRev(Option::dir_sep) - 1); if(!depKeyMap.contains(key)) depKeyMap.insert(key, file); return depends[key]; } QString MakefileGenerator::specdir() { if(!spec.isEmpty()) return spec; spec = Option::mkfile::qmakespec; const char *d = getenv("QTDIR"); if(d) { QString qdir = Option::fixPathToTargetOS(QString(d)); if(qdir.endsWith(QString(QChar(QDir::separator())))) qdir.truncate(qdir.length()-1); //fix path QFileInfo fi(spec); QString absSpec(fi.absFilePath()); absSpec = Option::fixPathToTargetOS(absSpec); //replace what you can if(absSpec.startsWith(qdir)) { absSpec.replace(0, qdir.length(), "$(QTDIR)"); spec = absSpec; } } return spec; } bool MakefileGenerator::openOutput(QFile &file) const { { QString outdir; if(!file.name().isEmpty()) { QFileInfo fi(file); if(fi.isDir()) outdir = file.name() + QDir::separator(); } if(!outdir.isEmpty() || file.name().isEmpty()) { QString fname = "Makefile"; if(!project->isEmpty("MAKEFILE")) fname = project->first("MAKEFILE"); file.setName(outdir + fname); } } if(QDir::isRelativePath(file.name())) file.setName(Option::output_dir + file.name()); //pwd when qmake was run if(project->isEmpty("QMAKE_MAKEFILE")) project->variables()["QMAKE_MAKEFILE"].append(file.name()); int slsh = file.name().findRev(Option::dir_sep); if(slsh != -1) createDir(file.name().left(slsh)); if(file.open(IO_WriteOnly | IO_Translate)) { QFileInfo fi(Option::output); QString od = Option::fixPathToTargetOS((fi.isSymLink() ? fi.readLink() : fi.dirPath()) ); if(QDir::isRelativePath(od)) od.prepend(Option::output_dir); Option::output_dir = od; return TRUE; } return FALSE; } //Factory thing #include "unixmake.h" -#include "borland_bmake.h" #include "msvc_nmake.h" +#include "borland_bmake.h" +#include "mingw_make.h" #include "msvc_dsp.h" #include "msvc_vcproj.h" #include "metrowerks_xml.h" #include "pbuilder_pbx.h" #include "projectgenerator.h" MakefileGenerator * MakefileGenerator::create(QMakeProject *proj) { if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) return new ProjectGenerator(proj); MakefileGenerator *mkfile = NULL; QString gen = proj->first("MAKEFILE_GENERATOR"); if(gen.isEmpty()) { fprintf(stderr, "No generator specified in config file: %s\n", proj->projectFile().latin1()); } else if(gen == "UNIX") { mkfile = new UnixMakefileGenerator(proj); } else if(gen == "MSVC") { // Visual Studio =< v6.0 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1) mkfile = new DspMakefileGenerator(proj); else mkfile = new NmakeMakefileGenerator(proj); } else if(gen == "MSVC.NET") { // Visual Studio >= v7.0 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1) mkfile = new VcprojGenerator(proj); else mkfile = new NmakeMakefileGenerator(proj); } else if(gen == "BMAKE") { mkfile = new BorlandMakefileGenerator(proj); + } else if(gen == "MINGW") { + mkfile = new MingwMakefileGenerator(proj); } else if(gen == "METROWERKS") { mkfile = new MetrowerksMakefileGenerator(proj); } else if(gen == "PROJECTBUILDER") { mkfile = new ProjectBuilderMakefileGenerator(proj); } else { fprintf(stderr, "Unknown generator specified: %s\n", gen.latin1()); } return mkfile; } diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 1d19d98..4fdabe8 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -1,173 +1,173 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __MAKEFILE_H__ #define __MAKEFILE_H__ #include "option.h" #include "project.h" #include <qtextstream.h> class MakefileGenerator { QString spec; bool init_opath_already, init_already, moc_aware, no_io; QStringList createObjectList(const QString &var); QString build_args(); - QMap<QString, QString> depHeuristics, depKeyMap; + QMap<QString, QString> depHeuristics, depKeyMap, fileFixed; QMap<QString, QString> mocablesToMOC, mocablesFromMOC; QMap<QString, QStringList> depends; protected: void writeObj(QTextStream &, const QString &obj, const QString &src); void writeUicSrc(QTextStream &, const QString &ui); void writeMocObj(QTextStream &, const QString &obj, const QString &src); void writeMocSrc(QTextStream &, const QString &src); void writeLexSrc(QTextStream &, const QString &lex); void writeYaccSrc(QTextStream &, const QString &yac); void writeInstalls(QTextStream &t, const QString &installs); void writeImageObj(QTextStream &t, const QString &obj); void writeImageSrc(QTextStream &t, const QString &images); protected: QMakeProject *project; class MakefileDependDir { public: - MakefileDependDir(QString r, QString l) : real_dir(r), local_dir(l) { } + MakefileDependDir(const QString &r, const QString &l) : real_dir(r), local_dir(l) { } QString real_dir, local_dir; }; - bool generateDependencies(QPtrList<MakefileDependDir> &dirs, QString x, bool recurse); + bool generateDependencies(QPtrList<MakefileDependDir> &dirs, const QString &x, bool recurse); QString buildArgs(); QString specdir(); QString cleanFilePath(const QString &file) const; - bool generateMocList(QString fn); + bool generateMocList(const QString &fn); QString findMocSource(const QString &moc_file) const; QString findMocDestination(const QString &src_file) const; QStringList &findDependencies(const QString &file); void setNoIO(bool o); bool noIO() const; void setMocAware(bool o); bool mocAware() const; void logicWarn(const QString &, const QString &); virtual bool doDepends() const { return Option::mkfile::do_deps; } bool writeHeader(QTextStream &); virtual bool writeMakefile(QTextStream &); virtual bool writeMakeQmake(QTextStream &); void initOutPaths(); virtual void init(); //for installs virtual QString defaultInstall(const QString &); //for prl bool processPrlFile(QString &); virtual void processPrlVariable(const QString &, const QStringList &); virtual void processPrlFiles(); virtual void writePrlFile(QTextStream &); //make sure libraries are found virtual bool findLibraries(); QString var(const QString &var); QString varGlue(const QString &var, const QString &before, const QString &glue, const QString &after); QString varList(const QString &var); QString val(const QStringList &varList); QString valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after); QString valList(const QStringList &varList); QString fileFixify(const QString& file, const QString &out_dir=QString::null, const QString &in_dir=QString::null, bool force_fix=FALSE) const; QStringList fileFixify(const QStringList& files, const QString &out_dir=QString::null, const QString &in_dir=QString::null, bool force_fix=FALSE) const; public: MakefileGenerator(QMakeProject *p); virtual ~MakefileGenerator(); static MakefileGenerator *create(QMakeProject *); bool write(); virtual bool openOutput(QFile &) const; }; inline QString MakefileGenerator::findMocSource(const QString &moc_file) const { QString tmp = cleanFilePath(moc_file); if (mocablesFromMOC.contains(tmp)) return mocablesFromMOC[tmp]; else return QString(""); } inline QString MakefileGenerator::findMocDestination(const QString &src_file) const { QString tmp = cleanFilePath(src_file); if (mocablesToMOC.contains(tmp)) return mocablesToMOC[tmp]; else return QString(""); } inline void MakefileGenerator::setMocAware(bool o) { moc_aware = o; } inline bool MakefileGenerator::mocAware() const { return moc_aware; } inline void MakefileGenerator::setNoIO(bool o) { no_io = o; } inline bool MakefileGenerator::noIO() const { return no_io; } inline QString MakefileGenerator::defaultInstall(const QString &) { return QString(""); } inline bool MakefileGenerator::findLibraries() { return TRUE; } inline MakefileGenerator::~MakefileGenerator() { } #endif /* __MAKEFILE_H__ */ diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 5ff6250..1515216 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -1,462 +1,482 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "projectgenerator.h" #include "option.h" #include <qdir.h> #include <qfile.h> #include <qfileinfo.h> #include <qregexp.h> +QString project_builtin_regx() //calculate the builtin regular expression.. +{ + QString ret; + QStringList builtin_exts(".c"); + builtin_exts << Option::ui_ext << Option::yacc_ext << Option::lex_ext << ".ts"; + builtin_exts += Option::h_ext + Option::cpp_ext; + for(QStringList::Iterator ext_it = builtin_exts.begin(); + ext_it != builtin_exts.end(); ++ext_it) { + if(!ret.isEmpty()) + ret += "; "; + ret += QString("*") + (*ext_it); + } + return ret; +} + + ProjectGenerator::ProjectGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE) { } void ProjectGenerator::init() { if(init_flag) return; int file_count = 0; init_flag = TRUE; QMap<QString, QStringList> &v = project->variables(); QString templ = Option::user_template.isEmpty() ? QString("app") : Option::user_template; if(!Option::user_template_prefix.isEmpty()) templ.prepend(Option::user_template_prefix); v["TEMPLATE_ASSIGN"] += templ; //figure out target if(Option::output.name() == "-" || Option::output.name().isEmpty()) v["TARGET"] = QStringList("unknown"); //the scary stuff if(project->first("TEMPLATE_ASSIGN") != "subdirs") { - QString builtin_regex; - { //calculate the builtin regular expression.. - QStringList builtin_exts(".c"); - builtin_exts << Option::ui_ext << Option::yacc_ext << Option::lex_ext; - builtin_exts += Option::h_ext + Option::cpp_ext; - for(QStringList::Iterator ext_it = builtin_exts.begin(); - ext_it != builtin_exts.end(); ++ext_it) { - if(!builtin_regex.isEmpty()) - builtin_regex += "; "; - builtin_regex += QString("*") + (*ext_it); - } - } + QString builtin_regex = project_builtin_regx(); QStringList dirs = Option::projfile::project_dirs; - if(Option::projfile::do_pwd) + if(Option::projfile::do_pwd) { + if(!v["INCLUDEPATH"].contains(".")) + v["INCLUDEPATH"] += "."; dirs.prepend(QDir::currentDirPath()); + } for(QStringList::Iterator pd = dirs.begin(); pd != dirs.end(); pd++) { QString dir, regex; bool add_depend = FALSE; if(QFile::exists((*pd))) { QFileInfo fi((*pd)); if(fi.isDir()) { dir = (*pd); add_depend = TRUE; if(dir.right(1) != Option::dir_sep) dir += Option::dir_sep; if(Option::projfile::do_recursive) { QDir d(dir); d.setFilter(QDir::Dirs); for(int i = 0; i < (int)d.count(); i++) { if(d[i] != "." && d[i] != "..") dirs.append(dir + d[i] + QDir::separator() + builtin_regex); } } regex = builtin_regex; } else { QString file = (*pd); int s = file.findRev(Option::dir_sep); if(s != -1) dir = file.left(s+1); if(addFile(file)) { add_depend = TRUE; file_count++; } } } else { //regexp regex = (*pd); } if(!regex.isEmpty()) { int s = regex.findRev(Option::dir_sep); if(s != -1) { dir = regex.left(s+1); regex = regex.right(regex.length() - (s+1)); } if(Option::projfile::do_recursive) { QDir d(dir); d.setFilter(QDir::Dirs); for(int i = 0; i < (int)d.count(); i++) { if(d[i] != "." && d[i] != "..") dirs.append(dir + d[i] + QDir::separator() + regex); } } QDir d(dir, regex); for(int i = 0; i < (int)d.count(); i++) { QString file = dir + d[i]; if (addFile(file)) { add_depend = TRUE; file_count++; } } } if(add_depend && !dir.isEmpty() && !v["DEPENDPATH"].contains(dir)) { QFileInfo fi(dir); - if(fi.absFilePath() != QDir::currentDirPath()) { + if(fi.absFilePath() != QDir::currentDirPath()) v["DEPENDPATH"] += fileFixify(dir); } } } - } if(!file_count) { //shall we try a subdir? QStringList dirs = Option::projfile::project_dirs; if(Option::projfile::do_pwd) dirs.prepend("."); for(QStringList::Iterator pd = dirs.begin(); pd != dirs.end(); pd++) { if(QFile::exists((*pd))) { QString newdir = (*pd); QFileInfo fi(newdir); if(fi.isDir()) { newdir = fileFixify(newdir); QStringList &subdirs = v["SUBDIRS"]; if(QFile::exists(fi.filePath() + QDir::separator() + fi.fileName() + ".pro") && !subdirs.contains(newdir)) { subdirs.append(newdir); } else { QDir d(newdir, "*.pro"); d.setFilter(QDir::Files); for(int i = 0; i < (int)d.count(); i++) { QString nd = newdir + QDir::separator() + d[i]; fileFixify(nd); if(d[i] != "." && d[i] != ".." && !subdirs.contains(nd)) { if(newdir + d[i] != Option::output_dir + Option::output.name()) subdirs.append(nd); } } } if(Option::projfile::do_recursive) { QDir d(newdir); d.setFilter(QDir::Dirs); for(int i = 0; i < (int)d.count(); i++) { QString nd = fileFixify(newdir + QDir::separator() + d[i]); if(d[i] != "." && d[i] != ".." && !dirs.contains(nd)) dirs.append(nd); } } } } else { //regexp QString regx = (*pd), dir; int s = regx.findRev(Option::dir_sep); if(s != -1) { dir = regx.left(s+1); regx = regx.right(regx.length() - (s+1)); } QDir d(dir, regx); d.setFilter(QDir::Dirs); QStringList &subdirs = v["SUBDIRS"]; for(int i = 0; i < (int)d.count(); i++) { QString newdir(dir + d[i]); QFileInfo fi(newdir); if(fi.fileName() != "." && fi.fileName() != "..") { newdir = fileFixify(newdir); if(QFile::exists(fi.filePath() + QDir::separator() + fi.fileName() + ".pro") && !subdirs.contains(newdir)) { subdirs.append(newdir); } else { QDir d(newdir, "*.pro"); d.setFilter(QDir::Files); for(int i = 0; i < (int)d.count(); i++) { QString nd = newdir + QDir::separator() + d[i]; fileFixify(nd); if(d[i] != "." && d[i] != ".." && !subdirs.contains(nd)) { if(newdir + d[i] != Option::output_dir + Option::output.name()) subdirs.append(nd); } } } if(Option::projfile::do_recursive && !dirs.contains(newdir)) dirs.append(newdir); } } } } v["TEMPLATE_ASSIGN"] = "subdirs"; return; } QPtrList<MakefileDependDir> deplist; deplist.setAutoDelete(TRUE); { QStringList &d = v["DEPENDPATH"]; for(QStringList::Iterator it = d.begin(); it != d.end(); ++it) { QString r = (*it), l = Option::fixPathToLocalOS((*it)); deplist.append(new MakefileDependDir(r, l)); } } QStringList &h = v["HEADERS"]; bool no_qt_files = TRUE; QString srcs[] = { "SOURCES", "YACCSOURCES", "LEXSOURCES", "INTERFACES", QString::null }; for(int i = 0; !srcs[i].isNull(); i++) { QStringList &l = v[srcs[i]]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) { if(generateDependencies(deplist, (*val_it), TRUE)) { QStringList &tmp = findDependencies((*val_it)); if(!tmp.isEmpty()) { for(QStringList::Iterator dep_it = tmp.begin(); dep_it != tmp.end(); ++dep_it) { - QString file_no_path = (*dep_it).right( - (*dep_it).length() - ((*dep_it).findRev(Option::dir_sep)+1)); + QString file_dir = (*dep_it).section(Option::dir_sep, 0, -2), + file_no_path = (*dep_it).section(Option::dir_sep, -1); + if(!file_dir.isEmpty()) { + for(MakefileDependDir *mdd = deplist.first(); mdd; mdd = deplist.next()) { + if(mdd->local_dir == file_dir && !v["INCLUDEPATH"].contains(mdd->real_dir)) + v["INCLUDEPATH"] += mdd->real_dir; + } + } if(no_qt_files && file_no_path.find(QRegExp("^q[a-z_0-9].h$")) != -1) no_qt_files = FALSE; QString h_ext; - for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { + for(QStringList::Iterator hit = Option::h_ext.begin(); + hit != Option::h_ext.end(); ++hit) { if((*dep_it).endsWith((*hit))) { h_ext = (*hit); break; } } if(!h_ext.isEmpty()) { if((*dep_it).left(1).lower() == "q") { QString qhdr = (*dep_it).lower(); if(file_no_path == "qthread.h") addConfig("thread"); } for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { - QString src((*dep_it).left((*dep_it).length() - h_ext.length()) + (*cppit)); + QString src((*dep_it).left((*dep_it).length() - h_ext.length()) + + (*cppit)); if(QFile::exists(src)) { bool exists = FALSE; QStringList &srcl = v["SOURCES"]; - for(QStringList::Iterator src_it = srcl.begin(); src_it != srcl.end(); ++src_it) { + for(QStringList::Iterator src_it = srcl.begin(); + src_it != srcl.end(); ++src_it) { if((*src_it).lower() == src.lower()) { exists = TRUE; break; } } if(!exists) srcl.append(src); } } } else if((*dep_it).endsWith(Option::lex_ext) && file_no_path.startsWith(Option::lex_mod)) { addConfig("lex_included"); } if(!h.contains((*dep_it))) { if(generateMocList((*dep_it)) && !findMocDestination((*dep_it)).isEmpty()) h += (*dep_it); } } } } } } if(h.isEmpty()) addConfig("moc", FALSE); //if we find a file that matches an forms it needn't be included in the project QStringList &u = v["INTERFACES"]; QString no_ui[] = { "SOURCES", "HEADERS", QString::null }; { for(int i = 0; !no_ui[i].isNull(); i++) { QStringList &l = v[no_ui[i]]; for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ) { bool found = FALSE; for(QStringList::Iterator ui_it = u.begin(); ui_it != u.end(); ++ui_it) { QString s1 = (*val_it).right((*val_it).length() - ((*val_it).findRev(Option::dir_sep) + 1)); if(s1.findRev('.') != -1) s1 = s1.left(s1.findRev('.')) + Option::ui_ext; QString u1 = (*ui_it).right((*ui_it).length() - ((*ui_it).findRev(Option::dir_sep) + 1)); if(s1 == u1) { found = TRUE; break; } } if(!found && (*val_it).endsWith(Option::moc_ext)) found = TRUE; if(found) val_it = l.remove(val_it); else ++val_it; } } } } bool ProjectGenerator::writeMakefile(QTextStream &t) { t << "######################################################################" << endl; t << "# Automatically generated by qmake (" << qmake_version() << ") " << QDateTime::currentDateTime().toString() << endl; t << "######################################################################" << endl << endl; QStringList::Iterator it; for(it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it) t << (*it) << endl; t << getWritableVar("TEMPLATE_ASSIGN", FALSE); if(project->first("TEMPLATE_ASSIGN") == "subdirs") { t << endl << "# Directories" << "\n" << getWritableVar("SUBDIRS"); } else { t << getWritableVar("TARGET") << getWritableVar("CONFIG", FALSE) << getWritableVar("CONFIG_REMOVE", FALSE) - << getWritableVar("DEPENDPATH") << endl; + << getWritableVar("DEPENDPATH") + << getWritableVar("INCLUDEPATH") << endl; t << "# Input" << "\n"; t << getWritableVar("HEADERS") << getWritableVar("INTERFACES") << getWritableVar("LEXSOURCES") << getWritableVar("YACCSOURCES") - << getWritableVar("SOURCES"); + << getWritableVar("SOURCES") + << getWritableVar("TRANSLATIONS"); } for(it = Option::after_user_vars.begin(); it != Option::after_user_vars.end(); ++it) t << (*it) << endl; return TRUE; } bool ProjectGenerator::addConfig(const QString &cfg, bool add) { QString where = "CONFIG"; if(!add) where = "CONFIG_REMOVE"; if(!project->variables()[where].contains(cfg)) { project->variables()[where] += cfg; return TRUE; } return FALSE; } bool ProjectGenerator::addFile(QString file) { file = fileFixify(file, QDir::currentDirPath()); QString dir; int s = file.findRev(Option::dir_sep); if(s != -1) dir = file.left(s+1); if(file.mid(dir.length(), Option::moc_mod.length()) == Option::moc_mod) return FALSE; QString where; for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { if(file.endsWith((*cppit))) { if(QFile::exists(file.left(file.length() - (*cppit).length()) + Option::ui_ext)) return FALSE; else where = "SOURCES"; break; } } if(where.isEmpty()) { for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) { if(file.endsWith((*hit))) { where = "HEADERS"; break; } } } if(where.isEmpty()) { if(file.endsWith(Option::ui_ext)) where = "INTERFACES"; else if(file.endsWith(".c")) where = "SOURCES"; else if(file.endsWith(Option::lex_ext)) where = "LEXSOURCES"; else if(file.endsWith(Option::yacc_ext)) where = "YACCSOURCES"; + else if(file.endsWith(".ts")) + where = "TRANSLATIONS"; } QString newfile = fileFixify(file); if(!where.isEmpty() && !project->variables()[where].contains(file)) { project->variables()[where] += newfile; return TRUE; } return FALSE; } QString ProjectGenerator::getWritableVar(const QString &v, bool /*fixPath*/) { QStringList &vals = project->variables()[v]; if(vals.isEmpty()) return ""; QString ret; if(v.endsWith("_REMOVE")) ret = v.left(v.length() - 7) + " -= "; else if(v.endsWith("_ASSIGN")) ret = v.left(v.length() - 7) + " = "; else ret = v + " += "; QString join = vals.join(" "); if(ret.length() + join.length() > 80) { QString spaces; for(unsigned int i = 0; i < ret.length(); i++) spaces += " "; join = vals.join(" \\\n" + spaces); } // ### Commented out for now so that project generation works. // Sam: can you look at why this was needed? /* if(fixPath) join = join.replace("\\", "/");*/ return ret + join + "\n"; } bool ProjectGenerator::openOutput(QFile &file) const { QString outdir; if(!file.name().isEmpty()) { QFileInfo fi(file); if(fi.isDir()) outdir = fi.dirPath() + QDir::separator(); } if(!outdir.isEmpty() || file.name().isEmpty()) { QString dir = QDir::currentDirPath(); int s = dir.findRev('/'); if(s != -1) dir = dir.right(dir.length() - (s + 1)); file.setName(outdir + dir + ".pro"); } return MakefileGenerator::openOutput(file); } diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 7df95b2..e274481 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -1,520 +1,604 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "unixmake.h" #include "option.h" #include <qregexp.h> #include <qfile.h> #include <qdict.h> #include <qdir.h> #include <time.h> void UnixMakefileGenerator::init() { if(init_flag) return; init_flag = TRUE; if(!project->isEmpty("QMAKE_FAILED_REQUIREMENTS")) /* no point */ return; QStringList &configs = project->variables()["CONFIG"]; /* this should probably not be here, but I'm using it to wrap the .t files */ if(project->first("TEMPLATE") == "app") project->variables()["QMAKE_APP_FLAG"].append("1"); else if(project->first("TEMPLATE") == "lib") project->variables()["QMAKE_LIB_FLAG"].append("1"); else if(project->first("TEMPLATE") == "subdirs") { MakefileGenerator::init(); if(project->isEmpty("MAKEFILE")) project->variables()["MAKEFILE"].append("Makefile"); if(project->isEmpty("QMAKE")) project->variables()["QMAKE"].append("qmake"); if(project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].findIndex("qmake_all") == -1) project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].append("qmake_all"); return; /* subdirs is done */ } if( project->isEmpty("QMAKE_EXTENSION_SHLIB") ) { - QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); - if ( os == "cygwin" ) { - project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dll" ); - } else { + if ( project->isEmpty("QMAKE_CYGWIN_SHLIB") ) { project->variables()["QMAKE_EXTENSION_SHLIB"].append( "so" ); + } else { + project->variables()["QMAKE_EXTENSION_SHLIB"].append( "dll" ); } } if( project->isEmpty("QMAKE_COPY_FILE") ) project->variables()["QMAKE_COPY_FILE"].append( "$(COPY) -p" ); if( project->isEmpty("QMAKE_COPY_DIR") ) project->variables()["QMAKE_COPY_DIR"].append( "$(COPY) -pR" ); //If the TARGET looks like a path split it into DESTDIR and the resulting TARGET if(!project->isEmpty("TARGET")) { QString targ = project->first("TARGET"); int slsh = QMAX(targ.findRev('/'), targ.findRev(Option::dir_sep)); if(slsh != -1) { if(project->isEmpty("DESTDIR")) project->values("DESTDIR").append(""); else if(project->first("DESTDIR").right(1) != Option::dir_sep) project->variables()["DESTDIR"] = project->first("DESTDIR") + Option::dir_sep; project->variables()["DESTDIR"] = project->first("DESTDIR") + targ.left(slsh+1); project->variables()["TARGET"] = targ.mid(slsh+1); } } project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; bool is_qt = (project->first("TARGET") == "qt" || project->first("TARGET") == "qte" || project->first("TARGET") == "qt-mt" || project->first("TARGET") == "qte-mt"); bool extern_libs = !project->isEmpty("QMAKE_APP_FLAG") || (!project->isEmpty("QMAKE_LIB_FLAG") && project->isActiveConfig("dll")) || is_qt; if(!project->isActiveConfig("global_init_link_order")) project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; if ( (!project->isEmpty("QMAKE_LIB_FLAG") && !project->isActiveConfig("staticlib") ) || (project->isActiveConfig("qt") && project->isActiveConfig( "plugin" ) )) { if(configs.findIndex("dll") == -1) configs.append("dll"); } else if ( !project->isEmpty("QMAKE_APP_FLAG") || project->isActiveConfig("dll") ) { configs.remove("staticlib"); } if ( project->isActiveConfig("warn_off") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; } else if ( project->isActiveConfig("warn_on") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; } if ( project->isActiveConfig("debug") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; } if(!project->isEmpty("QMAKE_INCREMENTAL")) project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_INCREMENTAL"]; else if(!project->isEmpty("QMAKE_LFLAGS_PREBIND") && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() && project->isActiveConfig("dll")) project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_PREBIND"]; if(!project->isEmpty("QMAKE_INCDIR")) project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; if(!project->isEmpty("QMAKE_LIBDIR")) { if ( !project->isEmpty("QMAKE_RPATH") ) project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR", " " + var("QMAKE_RPATH"), " " + var("QMAKE_RPATH"), ""); project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue( "QMAKE_LIBDIR", "-L", " -L", "" ); } if ( extern_libs && (project->isActiveConfig("qt") || project->isActiveConfig("opengl")) ) { if(configs.findIndex("x11lib") == -1) configs.append("x11lib"); if ( project->isActiveConfig("opengl") && configs.findIndex("x11inc") == -1 ) configs.append("x11inc"); } if ( project->isActiveConfig("x11") ) { if(configs.findIndex("x11lib") == -1) configs.append("x11lib"); if(configs.findIndex("x11inc") == -1) configs.append("x11inc"); } if ( project->isActiveConfig("qt") ) { if ( project->isActiveConfig("accessibility" ) ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); if ( project->isActiveConfig("tablet") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); if(configs.findIndex("moc")) configs.append("moc"); project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; if ( !project->isActiveConfig("debug") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); if ( !is_qt ) { if ( !project->isEmpty("QMAKE_LIBDIR_QT") ) { if ( !project->isEmpty("QMAKE_RPATH") ) project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_QT", " " + var("QMAKE_RPATH"), " " + var("QMAKE_RPATH"), ""); project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_QT", "-L", " -L", ""); } if (project->isActiveConfig("thread") && !project->isEmpty("QMAKE_LIBS_QT_THREAD")) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; } } - if ( project->isActiveConfig("thread") ) { - if(project->isActiveConfig("qt")) - project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); - if ( !project->isEmpty("QMAKE_CFLAGS_THREAD")) - project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_THREAD"]; - if( !project->isEmpty("QMAKE_CXXFLAGS_THREAD")) - project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_THREAD"]; - project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_THREAD"]; - project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_THREAD"]; - if(!project->isEmpty("QMAKE_LFLAGS_THREAD")) - project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_THREAD"]; - } if ( project->isActiveConfig("opengl") ) { project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_OPENGL"]; if(!project->isEmpty("QMAKE_LIBDIR_OPENGL")) project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_OPENGL", "-L", " -L", ""); if ( is_qt ) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL_QT"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; } if(project->isActiveConfig("global_init_link_order")) project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; - if ( project->isActiveConfig("x11sm") ) - project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_X11SM"]; - if ( project->isActiveConfig("dylib") ) - project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_DYNLOAD"]; if ( project->isActiveConfig("x11inc") ) project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_X11"]; if ( project->isActiveConfig("x11lib") ) { if(!project->isEmpty("QMAKE_LIBDIR_X11")) project->variables()["QMAKE_LIBDIR_FLAGS"] += varGlue("QMAKE_LIBDIR_X11", "-L", " -L", ""); project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_X11"]; } + if ( project->isActiveConfig("x11sm") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_X11SM"]; + if ( project->isActiveConfig("dylib") ) + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_DYNLOAD"]; + if ( project->isActiveConfig("thread") ) { + if(project->isActiveConfig("qt")) + project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); + if ( !project->isEmpty("QMAKE_CFLAGS_THREAD")) + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_THREAD"]; + if( !project->isEmpty("QMAKE_CXXFLAGS_THREAD")) + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_THREAD"]; + project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_THREAD"]; + project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_THREAD"]; + if(!project->isEmpty("QMAKE_LFLAGS_THREAD")) + project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_THREAD"]; + } if ( project->isActiveConfig("moc") ) setMocAware(TRUE); if ( project->isEmpty("QMAKE_RUN_CC") ) project->variables()["QMAKE_RUN_CC"].append("$(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src"); if ( project->isEmpty("QMAKE_RUN_CC_IMP") ) project->variables()["QMAKE_RUN_CC_IMP"].append("$(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<"); if ( project->isEmpty("QMAKE_RUN_CXX") ) project->variables()["QMAKE_RUN_CXX"].append("$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src"); if ( project->isEmpty("QMAKE_RUN_CXX_IMP") ) project->variables()["QMAKE_RUN_CXX_IMP"].append("$(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<"); project->variables()["QMAKE_FILETAGS"] += QStringList::split("HEADERS SOURCES TARGET DESTDIR", " "); if ( !project->isEmpty("PRECOMPH") ) { initOutPaths(); // Need to fix MOC_DIR since we do this before init() QString allmoc = fileFixify(project->first("MOC_DIR") + "/allmoc.cpp", QDir::currentDirPath(), Option::output_dir); project->variables()["SOURCES"].prepend(allmoc); project->variables()["HEADERS_ORIG"] = project->variables()["HEADERS"]; project->variables()["HEADERS"].clear(); } if( project->isActiveConfig("GNUmake") && !project->isEmpty("QMAKE_CFLAGS_DEPS")) include_deps = TRUE; //do not generate deps MakefileGenerator::init(); if ( project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { if(!project->isEmpty("QMAKE_APP_FLAG")) { if(project->isEmpty("DESTDIR")) project->values("DESTDIR").append(""); project->variables()["DESTDIR"].first() += project->variables()["TARGET"].first() + ".app/Contents/MacOS/"; project->variables()["QMAKE_PKGINFO"].append(project->first("DESTDIR") + "../PkgInfo"); project->variables()["ALL_DEPS"] += project->first("QMAKE_PKGINFO"); QString plist = specdir() + QDir::separator() + "Info.plist." + project->first("TEMPLATE"); if(QFile::exists(Option::fixPathToLocalOS(plist))) { project->variables()["QMAKE_INFO_PLIST"].append(plist); project->variables()["QMAKE_INFO_PLIST_OUT"].append(project->first("DESTDIR") + "../Info.plist"); project->variables()["ALL_DEPS"] += project->first("QMAKE_INFO_PLIST_OUT"); if(!project->isEmpty("RC_FILE")) project->variables()["ALL_DEPS"] += project->first("DESTDIR") + "../Resources/application.icns"; } } } if(!project->isEmpty("QMAKE_INTERNAL_INCLUDED_FILES")) project->variables()["DISTFILES"] += project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"]; project->variables()["DISTFILES"] += Option::mkfile::project_files; init2(); project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "QMAKE_LIBDIR_FLAGS" << "QMAKE_LIBS"; if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) { bool ok; int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok); QStringList ar_sublibs, objs = project->variables()["OBJECTS"] + project->variables()["OBJMOC"]; if(ok && max_files > 5 && max_files < (int)objs.count()) { int obj_cnt = 0, lib_cnt = 0; QString lib; for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { if((++obj_cnt) >= max_files) { if(lib_cnt) { lib.sprintf("lib%s-tmp%d.a", project->first("QMAKE_ORIG_TARGET").latin1(), lib_cnt); ar_sublibs << lib; obj_cnt = 0; } lib_cnt++; } } } if(!ar_sublibs.isEmpty()) { project->variables()["QMAKE_AR_SUBLIBS"] = ar_sublibs; project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "QMAKE_AR_SUBLIBS"; } } } QStringList UnixMakefileGenerator::uniqueSetLFlags(const QStringList &list1, QStringList &list2) { QStringList ret; for(QStringList::ConstIterator it = list1.begin(); it != list1.end(); ++it) { bool unique = TRUE; if((*it).startsWith("-")) { if((*it).startsWith("-l") || (*it).startsWith("-L")) { unique = list2.findIndex((*it)) == -1; } else if(project->isActiveConfig("macx") && (*it).startsWith("-framework")) { int as_one = TRUE; QString framework_in; if((*it).length() > 11) { framework_in = (*it).mid(11); } else { if(it != list1.end()) { ++it; as_one = FALSE; framework_in = (*it); } } if(!framework_in.isEmpty()) { for(QStringList::ConstIterator outit = list2.begin(); outit != list2.end(); ++outit) { if((*outit).startsWith("-framework")) { QString framework_out; if((*outit).length() > 11) { framework_out = (*outit).mid(11); } else { if(it != list2.end()) { ++outit; framework_out = (*outit); } } if(framework_out == framework_in) { unique = FALSE; break; } } } if(unique) { unique = FALSE; //because I'm about to just insert it myself if(as_one) { ret.append("-framework " + framework_in); } else { ret.append("-framework"); ret.append(framework_in); } } } } else { unique = (list2.findIndex((*it)) == -1); } } else if(QFile::exists((*it))) { unique = (list2.findIndex((*it)) == -1); } if(unique) ret.append((*it)); } return ret; } void UnixMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) { if(var == "QMAKE_PRL_LIBS") project->variables()["QMAKE_CURRENT_PRL_LIBS"] += uniqueSetLFlags(l, project->variables()["QMAKE_LIBS"]); else MakefileGenerator::processPrlVariable(var, l); } +bool +UnixMakefileGenerator::findLibraries() +{ + QPtrList<MakefileDependDir> libdirs; + libdirs.setAutoDelete(TRUE); + const QString lflags[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null }; + for(int i = 0; !lflags[i].isNull(); i++) { + QStringList &l = project->variables()[lflags[i]]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QString stub, dir, extn, opt = (*it).stripWhiteSpace(); + if(opt.startsWith("-")) { + if(opt.startsWith("-L")) { + QString r = opt.right(opt.length() - 2), l = r; + fixEnvVariables(l); + libdirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + } else if(opt.startsWith("-l")) { + stub = opt.mid(2); + } else if(project->isActiveConfig("macx") && opt.startsWith("-framework")) { + if(opt.length() > 11) { + opt = opt.mid(11); + } else { + ++it; + opt = (*it); + } + extn = ""; + dir = "/System/Library/Frameworks/" + opt + ".framework/"; + stub = opt; + } + } else { + extn = dir = ""; + stub = opt; + int slsh = opt.findRev(Option::dir_sep); + if(slsh != -1) { + dir = opt.left(slsh); + stub = opt.mid(slsh+1); + } + QRegExp stub_reg("^.*lib(" + stub + "[^./=]*)\\.(.*)$"); + if(stub_reg.exactMatch(stub)) { + stub = stub_reg.cap(1); + extn = stub_reg.cap(2); + } + } + if(!stub.isEmpty()) { + const QString modifs[] = { "-mt", QString::null }; + for(int modif = 0; !modifs[modif].isNull(); modif++) { + bool found = FALSE; + QStringList extens; + if(!extn.isNull()) + extens << extn; + else + extens << project->variables()["QMAKE_EXTENSION_SHLIB"].first() << "a"; + for(QStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) { + if(dir.isNull()) { + QString lib_stub; + for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { + if(QFile::exists(mdd->local_dir + Option::dir_sep + "lib" + stub + + modifs[modif] + "." + (*extit))) { + lib_stub = stub + modifs[modif]; + break; + } + } + if(!lib_stub.isNull()) { + (*it) = "-l" + lib_stub; + found = TRUE; + break; + } + } else { + if(QFile::exists("lib" + stub + modifs[modif] + "." + (*extit))) { + (*it) = "lib" + stub + modifs[modif] + "." + (*extit); + found = TRUE; + break; + } + } + } + if(found) + break; + } + } + } + } + return FALSE; +} + void UnixMakefileGenerator::processPrlFiles() { QDict<void> processed; QPtrList<MakefileDependDir> libdirs; libdirs.setAutoDelete(TRUE); const QString lflags[] = { "QMAKE_LIBDIR_FLAGS", "QMAKE_LIBS", QString::null }; for(int i = 0; !lflags[i].isNull(); i++) { for(bool ret = FALSE; TRUE; ret = FALSE) { QStringList l_out; QStringList &l = project->variables()[lflags[i]]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { project->variables()["QMAKE_CURRENT_PRL_LIBS"].clear(); QString opt = (*it).stripWhiteSpace();; if(opt.startsWith("-")) { if(opt.startsWith("-L")) { QString r = opt.right(opt.length() - 2), l = r; fixEnvVariables(l); libdirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); } else if(opt.startsWith("-l") && !processed[opt]) { QString lib = opt.right(opt.length() - 2), prl; for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { prl = mdd->local_dir + Option::dir_sep + "lib" + lib + Option::prl_ext; if(processPrlFile(prl)) { if(prl.startsWith(mdd->local_dir)) prl.replace(0, mdd->local_dir.length(), mdd->real_dir); QRegExp reg("^.*lib(" + lib + "[^./=]*)\\..*$"); if(reg.exactMatch(prl)) prl = "-l" + reg.cap(1); opt = prl; processed.insert(opt, (void*)1); ret = TRUE; break; } } } else if(project->isActiveConfig("macx") && opt.startsWith("-framework")) { if(opt.length() > 11) { opt = opt.mid(11); } else { ++it; opt = (*it); } QString prl = "/System/Library/Frameworks/" + opt + ".framework/" + opt + Option::prl_ext; if(processPrlFile(prl)) ret = TRUE; l_out.append("-framework"); } if(!opt.isEmpty()) l_out.append(opt); l_out += uniqueSetLFlags(project->variables()["QMAKE_CURRENT_PRL_LIBS"], l_out); } else { if(!processed[opt] && processPrlFile(opt)) { processed.insert(opt, (void*)1); ret = TRUE; } if(!opt.isEmpty()) l_out.append(opt); l_out += uniqueSetLFlags(project->variables()["QMAKE_CURRENT_PRL_LIBS"], l_out); } } if(ret && l != l_out) l = l_out; else break; } } } QString UnixMakefileGenerator::defaultInstall(const QString &t) { if(t != "target" || project->first("TEMPLATE") == "subdirs") return QString(); bool resource = FALSE; + const QString root = "$(INSTALL_ROOT)"; QStringList &uninst = project->variables()[t + ".uninstall"]; - QString ret, destdir=fileFixify(project->first("DESTDIR")); + QString ret, destdir=project->first("DESTDIR"); QString targetdir = Option::fixPathToTargetOS(project->first("target.path"), FALSE); if(!destdir.isEmpty() && destdir.right(1) != Option::dir_sep) destdir += Option::dir_sep; - targetdir = "$(INSTALL_ROOT)" + Option::fixPathToTargetOS(targetdir, FALSE); + targetdir = fileFixify(targetdir); if(targetdir.right(1) != Option::dir_sep) targetdir += Option::dir_sep; QStringList links; QString target="$(TARGET)"; if(project->first("TEMPLATE") == "app") { target = "$(QMAKE_TARGET)"; if(project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) { destdir += "../../../"; target += ".app"; resource = TRUE; } } else if(project->first("TEMPLATE") == "lib") { if(project->isActiveConfig("create_prl") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) { QString dst_prl = project->first("QMAKE_INTERNAL_PRL_FILE"); int slsh = dst_prl.findRev('/'); if(slsh != -1) dst_prl = dst_prl.right(dst_prl.length() - slsh - 1); - dst_prl = targetdir + dst_prl; - ret += "-$(COPY) " + project->first("QMAKE_INTERNAL_PRL_FILE") + " " + dst_prl; + dst_prl = root + targetdir + dst_prl; + ret += "-$(COPY) \"" + project->first("QMAKE_INTERNAL_PRL_FILE") + "\" \"" + dst_prl + "\""; if(!uninst.isEmpty()) uninst.append("\n\t"); uninst.append("-$(DEL_FILE) \"" + dst_prl + "\""); } - QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); - if ( os != "cygwin" ) { + if ( project->isEmpty("QMAKE_CYGWIN_SHLIB") ) { if ( !project->isActiveConfig("staticlib") && !project->isActiveConfig("plugin") ) { - if ( os == "hpux" ) { - links << "$(TARGET0)"; - } else { + if ( project->isEmpty("QMAKE_HPUX_SHLIB") ) { links << "$(TARGET0)" << "$(TARGET1)" << "$(TARGET2)"; + } else { + links << "$(TARGET0)"; } } } } QString src_targ = target; if(!destdir.isEmpty()) src_targ = Option::fixPathToTargetOS(destdir + target, FALSE); - QString dst_targ = fileFixify(targetdir + target); + QString dst_targ = root + fileFixify(targetdir + target); if(!ret.isEmpty()) ret += "\n\t"; ret += QString(resource ? "-$(COPY_DIR)" : "-$(COPY)") + " \"" + src_targ + "\" \"" + dst_targ + "\""; - if(!project->isEmpty("QMAKE_STRIP")) { + if(!project->isActiveConfig("debug") && !project->isEmpty("QMAKE_STRIP")) { ret += "\n\t-" + var("QMAKE_STRIP"); + if(!project->isEmpty("QMAKE_STRIPFLAGS_LIB") && project->first("TEMPLATE") == "lib") + ret += " " + var("QMAKE_STRIPFLAGS_LIB"); if(resource) - ret = " \"" + dst_targ + "/Contents/MacOS/$(QMAKE_TARGET)"; + ret = " \"" + dst_targ + "/Contents/MacOS/$(QMAKE_TARGET)\""; else ret += " \"" + dst_targ + "\""; } if(!uninst.isEmpty()) uninst.append("\n\t"); if(resource) uninst.append("-$(DEL_FILE) -r \"" + dst_targ + "\""); else uninst.append("-$(DEL_FILE) \"" + dst_targ + "\""); if(!links.isEmpty()) { for(QStringList::Iterator it = links.begin(); it != links.end(); it++) { if(Option::target_mode == Option::TARG_WIN_MODE || Option::target_mode == Option::TARG_MAC9_MODE) { } else if(Option::target_mode == Option::TARG_UNIX_MODE || Option::target_mode == Option::TARG_MACX_MODE) { QString link = Option::fixPathToTargetOS(destdir + (*it), FALSE); int lslash = link.findRev(Option::dir_sep); if(lslash != -1) link = link.right(link.length() - (lslash + 1)); - QString dst_link = fileFixify(targetdir + link); + QString dst_link = root + fileFixify(targetdir + link); ret += "\n\t-$(SYMLINK) \"$(TARGET)\" \"" + dst_link + "\""; if(!uninst.isEmpty()) uninst.append("\n\t"); uninst.append("-$(DEL_FILE) \"" + dst_link + "\""); } } } return ret; } - diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index e889dcc..3d00214 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -1,71 +1,72 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __UNIXMAKE_H__ #define __UNIXMAKE_H__ #include "makefile.h" class UnixMakefileGenerator : public MakefileGenerator { bool init_flag, include_deps; bool writeMakefile(QTextStream &); QStringList uniqueSetLFlags(const QStringList &list1, QStringList &list2); public: UnixMakefileGenerator(QMakeProject *p); ~UnixMakefileGenerator(); protected: virtual bool doDepends() const { return !include_deps && MakefileGenerator::doDepends(); } virtual QString defaultInstall(const QString &); virtual void processPrlVariable(const QString &, const QStringList &); virtual void processPrlFiles(); + virtual bool findLibraries(); virtual void init(); void writeMakeParts(QTextStream &); void writeSubdirs(QTextStream &, bool=TRUE); private: void init2(); }; inline UnixMakefileGenerator::~UnixMakefileGenerator() { } #endif /* __UNIXMAKE_H__ */ diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 9bb6f6b..7fbb9f4 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1,1050 +1,1109 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "unixmake.h" #include "option.h" #include <qregexp.h> #include <qfile.h> #include <qdir.h> #include <time.h> UnixMakefileGenerator::UnixMakefileGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE), include_deps(FALSE) { } bool UnixMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { t << "all clean:" << "\n\t" << "@echo \"Some of the required modules (" << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" << "@echo \"Skipped.\"" << endl << endl; writeMakeQmake(t); return TRUE; } if (project->variables()["TEMPLATE"].first() == "app" || project->variables()["TEMPLATE"].first() == "lib") { writeMakeParts(t); return MakefileGenerator::writeMakefile(t); } else if(project->variables()["TEMPLATE"].first() == "subdirs") { writeSubdirs(t); return TRUE; } return FALSE; } void UnixMakefileGenerator::writeMakeParts(QTextStream &t) { QString deps = fileFixify(Option::output.name()), prl; bool do_incremental = (project->isActiveConfig("incremental") && !project->variables()["QMAKE_INCREMENTAL"].isEmpty() && (!project->variables()["QMAKE_APP_FLAG"].isEmpty() || !project->isActiveConfig("staticlib"))), src_incremental=FALSE, moc_incremental=FALSE; - QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); t << "####### Compiler, tools and options" << endl << endl; t << "CC = "; if (project->isActiveConfig("thread") && ! project->variables()["QMAKE_CC_THREAD"].isEmpty()) t << var("QMAKE_CC_THREAD") << endl; else t << var("QMAKE_CC") << endl; t << "CXX = "; if (project->isActiveConfig("thread") && ! project->variables()["QMAKE_CXX_THREAD"].isEmpty()) t << var("QMAKE_CXX_THREAD") << endl; else t << var("QMAKE_CXX") << endl; t << "LEX = " << var("QMAKE_LEX") << endl; t << "YACC = " << var("QMAKE_YACC") << endl; t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl; t << "YACCFLAGS= " << var("QMAKE_YACCFLAGS") << endl; - t << "INCPATH = " << varGlue("INCLUDEPATH","-I", " -I", "") << " -I" << specdir() << endl; + t << "INCPATH = " << "-I" << specdir(); + if(!project->isActiveConfig("no_include_pwd")) { + QString pwd = fileFixify(QDir::currentDirPath()); + if(pwd.isEmpty()) + pwd = "."; + t << " -I" << pwd; + } + t << varGlue("INCLUDEPATH"," -I", " -I", "") << endl; if(!project->isActiveConfig("staticlib")) { t << "LINK = "; if (project->isActiveConfig("thread") && ! project->variables()["QMAKE_LINK_THREAD"].isEmpty()) t << var("QMAKE_LINK_THREAD") << endl; else t << var("QMAKE_LINK") << endl; t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; t << "LIBS = " << "$(SUBLIBS) " << var("QMAKE_LIBDIR_FLAGS") << " " << var("QMAKE_LIBS") << endl; } t << "AR = " << var("QMAKE_AR") << endl; t << "RANLIB = " << var("QMAKE_RANLIB") << endl; t << "MOC = " << var("QMAKE_MOC") << endl; t << "UIC = " << var("QMAKE_UIC") << endl; t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; t << "TAR = " << var("QMAKE_TAR") << endl; t << "GZIP = " << var("QMAKE_GZIP") << endl; t << "COPY = " << var("QMAKE_COPY") << endl; t << "COPY_FILE= " << var("QMAKE_COPY_FILE") << endl; t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; t << "MOVE = " << var("QMAKE_MOVE") << endl; - t << "PRO = " << fileFixify(project->projectFile() )<< endl; + t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << endl; t << endl; t << "####### Output directory" << endl << endl; if (! project->variables()["OBJECTS_DIR"].isEmpty()) t << "OBJECTS_DIR = " << var("OBJECTS_DIR") << endl; else t << "OBJECTS_DIR = ./" << endl; t << endl; /* files */ t << "####### Files" << endl << endl; t << "HEADERS = " << varList("HEADERS") << endl; t << "SOURCES = " << varList("SOURCES") << endl; if(do_incremental) { QStringList &objs = project->variables()["OBJECTS"], &incrs = project->variables()["QMAKE_INCREMENTAL"], incrs_out; t << "OBJECTS = "; for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { bool increment = FALSE; for(QStringList::Iterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { if((*objit).find(QRegExp((*incrit), TRUE, TRUE)) != -1) { increment = TRUE; incrs_out.append((*objit)); break; } } if(!increment) t << "\\\n\t\t" << (*objit); } if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done! t << incrs_out.join(" \\\n\t\t") << endl; } else if(!incrs_out.count()) { t << endl; } else { src_incremental = TRUE; t << endl; t << "INCREMENTAL_OBJECTS = " << incrs_out.join(" \\\n\t\t") << endl; } } else { t << "OBJECTS = " << varList("OBJECTS") << endl; } t << "FORMS = " << varList("FORMS") << endl; t << "UICDECLS = " << varList("UICDECLS") << endl; t << "UICIMPLS = " << varList("UICIMPLS") << endl; QString srcMoc = varList("SRCMOC"), objMoc = varList("OBJMOC"); t << "SRCMOC = " << srcMoc << endl; if(do_incremental) { QStringList &objs = project->variables()["OBJMOC"], &incrs = project->variables()["QMAKE_INCREMENTAL"], incrs_out; t << "OBJMOC = "; for(QStringList::Iterator objit = objs.begin(); objit != objs.end(); ++objit) { bool increment = FALSE; for(QStringList::Iterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) { if((*objit).find(QRegExp((*incrit), TRUE, TRUE)) != -1) { increment = TRUE; incrs_out.append((*objit)); break; } } if(!increment) t << "\\\n\t\t" << (*objit); } if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done! t << incrs_out.join(" \\\n\t\t") << endl; } else if(!incrs_out.count()) { t << endl; } else { moc_incremental = TRUE; t << endl; t << "INCREMENTAL_OBJMOC = " << incrs_out.join(" \\\n\t\t") << endl; } } else { t << "OBJMOC = " << objMoc << endl; } if(do_incremental && !moc_incremental && !src_incremental) do_incremental = FALSE; - t << "DIST = " << varList("DISTFILES") << endl; - t << "PRO = " << fileFixify(project->projectFile()) << endl; + t << "DIST = " << valList(fileFixify(project->variables()["DISTFILES"])) << endl; t << "QMAKE_TARGET = " << var("QMAKE_ORIG_TARGET") << endl; t << "DESTDIR = " << var("DESTDIR") << endl; t << "TARGET = " << var("TARGET") << endl; if(project->isActiveConfig("plugin") ) { t << "TARGETD = " << var("TARGET") << endl; } else if (!project->isActiveConfig("staticlib") && project->variables()["QMAKE_APP_FLAG"].isEmpty()) { t << "TARGETA = " << var("TARGETA") << endl; - if (os == "hpux") { - t << "TARGETD = " << var("TARGET_x") << endl; - t << "TARGET0 = " << var("TARGET_") << endl; - } - else { + if (project->isEmpty("QMAKE_HPUX_SHLIB")) { t << "TARGETD = " << var("TARGET_x.y.z") << endl; t << "TARGET0 = " << var("TARGET_") << endl; t << "TARGET1 = " << var("TARGET_x") << endl; t << "TARGET2 = " << var("TARGET_x.y") << endl; + } else { + t << "TARGETD = " << var("TARGET_x") << endl; + t << "TARGET0 = " << var("TARGET_") << endl; } } t << endl; // blasted incldues QStringList &qeui = project->variables()["QMAKE_EXTRA_UNIX_INCLUDES"]; QStringList::Iterator it; for( it = qeui.begin(); it != qeui.end(); ++it) t << "include " << (*it) << endl; /* rules */ t << "first: all" << endl; t << "####### Implicit rules" << endl << endl; t << ".SUFFIXES: .c"; QStringList::Iterator cppit; for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) t << " " << (*cppit); t << endl << endl; for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) t << (*cppit) << ".o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; t << ".c.o:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; if(include_deps) { QString cmd=var("QMAKE_CFLAGS_DEPS") + " "; cmd += varGlue("DEFINES","-D"," -D","") + varGlue("PRL_EXPORT_DEFINES"," -D"," -D",""); if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) cmd += " -I" + project->first("QMAKE_ABSOLUTE_SOURCE_PATH") + " "; cmd += " $(INCPATH) " + varGlue("DEPENDPATH", "-I", " -I", ""); QString odir; if(!project->variables()["OBJECTS_DIR"].isEmpty()) odir = project->first("OBJECTS_DIR"); - t << "###### Dependancies" << endl << endl; + t << "###### Dependencies" << endl << endl; t << odir << ".deps/%.d: %.cpp\n\t" << "@echo Creating depend for $<" << "\n\t" << "@test -d $(@D) || mkdir -p $(@D)" << "\n\t" << "@$(CXX) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@" << endl << endl; t << odir << ".deps/%.d: %.c\n\t" << "@echo Creating depend for $<" << "\n\t" << "@test -d $(@D) || mkdir -p $(@D)" << "\n\t" << "@$(CC) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@" << endl << endl; QString src[] = { "SOURCES", "UICIMPLS", "SRCMOC", QString::null }; for(int x = 0; !src[x].isNull(); x++) { QStringList &l = project->variables()[src[x]]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { if(!(*it).isEmpty()) { QString d_file; if((*it).endsWith(".c")) { d_file = (*it).left((*it).length() - 2); } else { for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) { if((*it).endsWith((*cppit))) { d_file = (*it).left((*it).length() - (*cppit).length()); break; } } } if(!d_file.isEmpty()) { d_file = odir + ".deps/" + d_file + ".d"; QStringList deps = findDependencies((*it)).grep(QRegExp(Option::moc_ext + "$")); if(!deps.isEmpty()) t << d_file << ": " << deps.join(" ") << endl; t << "-include " << d_file << endl; } } } } } t << "####### Build rules" << endl << endl; if(!project->variables()["SUBLIBS"].isEmpty()) { QString libdir = "tmp/"; if(!project->isEmpty("SUBLIBS_DIR")) libdir = project->first("SUBLIBS_DIR"); t << "SUBLIBS= "; QStringList &l = project->variables()["SUBLIBS"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) t << libdir << "lib" << (*it) << ".a "; t << endl << endl; } if(project->isActiveConfig("depend_prl") && !project->isEmpty("QMAKE_PRL_INTERNAL_FILES")) { QStringList &l = project->variables()["QMAKE_PRL_INTERNAL_FILES"]; QStringList::Iterator it; for(it = l.begin(); it != l.end(); ++it) { QMakeProject proj; if(proj.read((*it), QDir::currentDirPath()) && !proj.isEmpty("QMAKE_PRL_BUILD_DIR")) { QString dir; int slsh = (*it).findRev(Option::dir_sep); if(slsh != -1) dir = (*it).left(slsh + 1); QString targ = dir + proj.first("QMAKE_PRL_TARGET"); deps += " " + targ; t << targ << ":" << "\n\t" << "@echo \"Creating '" << targ << "'\"" << "\n\t" << "(cd " << proj.first("QMAKE_PRL_BUILD_DIR") << ";" << "$(MAKE) )" << endl; } } } if(!project->variables()["QMAKE_APP_FLAG"].isEmpty()) { QString destdir = project->first("DESTDIR"); if(do_incremental) { //incremental target QString incr_target = var("TARGET") + "_incremental"; if(incr_target.find(Option::dir_sep) != -1) incr_target = incr_target.right(incr_target.length() - (incr_target.findRev(Option::dir_sep) + 1)); QString incr_deps, incr_objs; if(project->first("QMAKE_INCREMENTAL_STYLE") == "ld") { QString incr_target_dir = var("OBJECTS_DIR") + incr_target + Option::obj_ext; //actual target t << incr_target_dir << ": $(OBJECTS)" << "\n\t" << "ld -r -o "<< incr_target_dir << " $(OBJECTS)" << endl; //communicated below deps.prepend(incr_target_dir + " "); incr_deps = "$(UICDECLS) $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC) $(OBJMOC)"; if(!incr_objs.isEmpty()) incr_objs += " "; incr_objs += incr_target_dir; } else { //actual target QString incr_target_dir = var("DESTDIR") + "lib" + incr_target + "." + project->variables()["QMAKE_EXTENSION_SHLIB"].first(); QString incr_lflags = var("QMAKE_LFLAGS_SHLIB") + " "; if(project->isActiveConfig("debug")) incr_lflags += var("QMAKE_LFLAGS_DEBUG"); else incr_lflags += var("QMAKE_LFLAGS_RELEASE"); t << incr_target_dir << ": $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << "\n\t"; if(!destdir.isEmpty()) t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; t << "$(LINK) " << incr_lflags << " -o "<< incr_target_dir << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << endl; //communicated below if(!destdir.isEmpty()) { if(!incr_objs.isEmpty()) incr_objs += " "; incr_objs += "-L" + destdir; } else { if(!incr_objs.isEmpty()) incr_objs += " "; incr_objs += "-L" + QDir::currentDirPath(); } if(!incr_objs.isEmpty()) incr_objs += " "; incr_objs += " -l" + incr_target; deps.prepend(incr_target_dir + " "); incr_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; } t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" << endl << endl; //real target - t << var("TARGET") << ": " << " " << incr_deps << " " << var("TARGETDEPS") << "\n\t"; + t << var("TARGET") << ": " << var("PRE_TARGETDEPS") << " " << incr_deps + << " " << var("POST_TARGETDEPS") << "\n\t"; if(!destdir.isEmpty()) t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; if(!project->isEmpty("QMAKE_PRE_LINK")) t << var("QMAKE_PRE_LINK") << "\n\t"; t << "$(LINK) $(LFLAGS) -o $(TARGET) " << incr_deps << " " << incr_objs << " $(LIBS)"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; } else { t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" << endl << endl; - t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS") << "\n\t"; + t << "$(TARGET): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC) " + << var("POST_TARGETDEPS") << "\n\t"; if(!destdir.isEmpty()) t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; if(!project->isEmpty("QMAKE_PRE_LINK")) t << var("QMAKE_PRE_LINK") << "\n\t"; t << "$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; } } else if(!project->isActiveConfig("staticlib")) { QString destdir = project->first("DESTDIR"), incr_deps; if(do_incremental) { QString s_ext = project->variables()["QMAKE_EXTENSION_SHLIB"].first(); QString incr_target = var("QMAKE_ORIG_TARGET").replace( QRegExp("\\." + s_ext), "").replace(QRegExp("^lib"), "") + "_incremental"; if(incr_target.find(Option::dir_sep) != -1) incr_target = incr_target.right(incr_target.length() - (incr_target.findRev(Option::dir_sep) + 1)); if(project->first("QMAKE_INCREMENTAL_STYLE") == "ld") { QString incr_target_dir = var("OBJECTS_DIR") + incr_target + Option::obj_ext; //actual target const QString link_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; t << incr_target_dir << ": " << link_deps << "\n\t" << "ld -r -o " << incr_target_dir << " " << link_deps << endl; //communicated below QStringList &cmd = project->variables()["QMAKE_LINK_SHLIB_CMD"]; cmd.first().replace("$(OBJECTS) $(OBJMOC)", "$(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"); //ick cmd.append(incr_target_dir); deps.prepend(incr_target_dir + " "); incr_deps = "$(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; } else { //actual target QString incr_target_dir = var("DESTDIR") + "lib" + incr_target + "." + s_ext; QString incr_lflags = var("QMAKE_LFLAGS_SHLIB") + " "; if(!project->isEmpty("QMAKE_LFLAGS_INCREMENTAL")) incr_lflags += var("QMAKE_LFLAGS_INCREMENTAL") + " "; if(project->isActiveConfig("debug")) incr_lflags += var("QMAKE_LFLAGS_DEBUG"); else incr_lflags += var("QMAKE_LFLAGS_RELEASE"); t << incr_target_dir << ": $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << "\n\t"; if(!destdir.isEmpty()) t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; t << "$(LINK) " << incr_lflags << " -o "<< incr_target_dir << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)" << endl; //communicated below QStringList &cmd = project->variables()["QMAKE_LINK_SHLIB_CMD"]; if(!destdir.isEmpty()) cmd.append(" -L" + destdir); cmd.append(" -l" + incr_target); deps.prepend(incr_target_dir + " "); incr_deps = "$(UICDECLS) $(OBJECTS) $(OBJMOC)"; } t << "all: " << " " << deps << " " << varGlue("ALL_DEPS",""," ","") << " " << var("DESTDIR_TARGET") << endl << endl; //real target - t << var("DESTDIR_TARGET") << ": " << incr_deps << " $(SUBLIBS) " << - var("TARGETDEPS"); + t << var("DESTDIR_TARGET") << ": " << var("PRE_TARGETDEPS") << " " + << incr_deps << " $(SUBLIBS) " << var("POST_TARGETDEPS"); } else { t << "all: " << deps << " " << varGlue("ALL_DEPS",""," ","") << " " << var("DESTDIR_TARGET") << endl << endl; - t << var("DESTDIR_TARGET") << ": $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) " << - var("TARGETDEPS"); + t << var("DESTDIR_TARGET") << ": " << var("PRE_TARGETDEPS") + << " $(UICDECLS) $(OBJECTS) $(OBJMOC) $(SUBLIBS) " << var("POST_TARGETDEPS"); } if(!destdir.isEmpty()) t << "\n\t" << "test -d " << destdir << " || mkdir -p " << destdir; if(!project->isEmpty("QMAKE_PRE_LINK")) t << "\n\t" << var("QMAKE_PRE_LINK"); if(project->isActiveConfig("plugin")) { t << "\n\t" << "-$(DEL_FILE) $(TARGET)" << "\n\t" << var("QMAKE_LINK_SHLIB_CMD"); if(!destdir.isEmpty()) t << "\n\t" << "-$(MOVE) $(TARGET) " << var("DESTDIR"); if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK") << "\n\t"; t << endl << endl; - } else if ( os == "hpux" ) { + } else if(project->isEmpty("QMAKE_HPUX_SHLIB")) { t << "\n\t" - << "-$(DEL_FILE) $(TARGET) $(TARGET0)" << "\n\t" + << "-$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2)" << "\n\t" << var("QMAKE_LINK_SHLIB_CMD") << "\n\t"; - t << varGlue("QMAKE_LN_SHLIB",""," "," $(TARGET) $(TARGET0)"); + t << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET0)") << "\n\t" + << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET1)") << "\n\t" + << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET2)"); if(!destdir.isEmpty()) t << "\n\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)\n\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET0)\n\t" - << "-$(MOVE) $(TARGET) $(TARGET0) " << var("DESTDIR"); + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET1)\n\t" + << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET2)\n\t" + << "-$(MOVE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) " << var("DESTDIR"); if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; } else { t << "\n\t" - << "-$(DEL_FILE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2)" << "\n\t" + << "-$(DEL_FILE) $(TARGET) $(TARGET0)" << "\n\t" << var("QMAKE_LINK_SHLIB_CMD") << "\n\t"; - t << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET0)") << "\n\t" - << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET1)") << "\n\t" - << varGlue("QMAKE_LN_SHLIB","-"," "," $(TARGET) $(TARGET2)"); + t << varGlue("QMAKE_LN_SHLIB",""," "," $(TARGET) $(TARGET0)"); if(!destdir.isEmpty()) t << "\n\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)\n\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET0)\n\t" - << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET1)\n\t" - << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET2)\n\t" - << "-$(MOVE) $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) " << var("DESTDIR"); + << "-$(MOVE) $(TARGET) $(TARGET0) " << var("DESTDIR"); if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; } t << endl << endl; if (! project->isActiveConfig("plugin")) { t << "staticlib: $(TARGETA)" << endl << endl; - t << "$(TARGETA): $(UICDECLS) $(OBJECTS) $(OBJMOC)"; + t << "$(TARGETA): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC)"; if(do_incremental) t << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; - t << var("TARGETDEPS") << "\n\t" + t << var("POST_TARGETDEPS") << "\n\t" << "-$(DEL_FILE) $(TARGETA) " << "\n\t" << var("QMAKE_AR_CMD"); if(do_incremental) t << " $(INCREMENTAL_OBJECTS) $(INCREMENTAL_OBJMOC)"; if(!project->isEmpty("QMAKE_RANLIB")) t << "\n\t" << "$(RANLIB) $(TARGETA)"; t << endl << endl; } } else { t << "all: " << deps << " " << varGlue("ALL_DEPS",""," "," ") << var("DESTDIR") << "$(TARGET) " << varGlue("QMAKE_AR_SUBLIBS", var("DESTDIR"), " " + var("DESTDIR"), "") << "\n\n" << "staticlib: " << var("DESTDIR") << "$(TARGET)" << "\n\n"; if(project->isEmpty("QMAKE_AR_SUBLIBS")) { - t << var("DESTDIR") << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) $(TARGETDEPS) " << "\n\t"; + t << var("DESTDIR") << "$(TARGET): " << var("PRE_TARGETDEPS") + << " $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("POST_TARGETDEPS") << "\n\t"; if(!project->isEmpty("DESTDIR")) { QString destdir = project->first("DESTDIR"); t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; } t << "-$(DEL_FILE) $(TARGET)" << "\n\t" << var("QMAKE_AR_CMD") << "\n"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\t" << var("QMAKE_POST_LINK") << "\n"; if(!project->isEmpty("QMAKE_RANLIB")) t << "\t" << "$(RANLIB) $(TARGET)" << "\n"; if(!project->isEmpty("DESTDIR")) t << "\t" << "-$(DEL_FILE) " << var("DESTDIR") << "$(TARGET)" << "\n" << "\t" << "-$(MOVE) $(TARGET) " << var("DESTDIR") << "\n"; } else { - int cnt = 0, max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(); + int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(); QStringList objs = project->variables()["OBJECTS"] + project->variables()["OBJMOC"], libs = project->variables()["QMAKE_AR_SUBLIBS"]; libs.prepend("$(TARGET)"); for(QStringList::Iterator libit = libs.begin(), objit = objs.begin(); libit != libs.end(); ++libit) { QStringList build; - for(cnt = 0; cnt < max_files && objit != objs.end(); ++objit, cnt++) + for(int cnt = 0; cnt < max_files && objit != objs.end(); ++objit, cnt++) build << (*objit); QString ar; if((*libit) == "$(TARGET)") { - t << var("DESTDIR") << "$(TARGET): $(UICDECLS) " << " $(TARGETDEPS) " - << valList(build) << "\n\t"; + t << var("DESTDIR") << "$(TARGET): " << var("PRE_TARGETDEPS") + << " $(UICDECLS) " << var("POST_TARGETDEPS") << valList(build) << "\n\t"; ar = project->variables()["QMAKE_AR_CMD"].first(); ar = ar.replace("$(OBJMOC)", "").replace("$(OBJECTS)", build.join(" ")); } else { t << (*libit) << ": " << valList(build) << "\n\t"; ar = "$(AR) " + (*libit) + " " + build.join(" "); } if(!project->isEmpty("DESTDIR")) { QString destdir = project->first("DESTDIR"); t << "test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; } t << "-$(DEL_FILE) " << (*libit) << "\n\t" << ar << "\n"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\t" << var("QMAKE_POST_LINK") << "\n"; if(!project->isEmpty("QMAKE_RANLIB")) t << "\t" << "$(RANLIB) " << (*libit) << "\n"; if(!project->isEmpty("DESTDIR")) t << "\t" << "-$(DEL_FILE) " << var("DESTDIR") << (*libit) << "\n" << "\t" << "-$(MOVE) " << (*libit) << " " << var("DESTDIR") << "\n"; } } t << endl << endl; } t << "mocables: $(SRCMOC)" << endl << endl; if(!project->isActiveConfig("no_mocdepend")) { //this is an implicity depend on moc, so it will be built if necesary, however - //moc itself shouldn't have this dependancy - this is a little kludgy but it is + //moc itself shouldn't have this dependency - this is a little kludgy but it is //better than the alternative for now. QString moc = project->first("QMAKE_MOC"), target = project->first("TARGET"); fixEnvVariables(target); fixEnvVariables(moc); if(target != moc) t << "$(MOC): \n\t" << "( cd $(QTDIR)/src/moc ; $(MAKE) )" << endl << endl; } writeMakeQmake(t); if(!project->first("QMAKE_PKGINFO").isEmpty()) { QString pkginfo = project->first("QMAKE_PKGINFO"); QString destdir = project->first("DESTDIR"); t << pkginfo << ": " << "\n\t"; if(!destdir.isEmpty()) t << "@test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; t << "@$(DEL_FILE) " << pkginfo << "\n\t" << "@echo \"APPL????\" >" << pkginfo << endl; } if(!project->first("QMAKE_INFO_PLIST").isEmpty()) { QString info_plist = project->first("QMAKE_INFO_PLIST"), info_plist_out = project->first("QMAKE_INFO_PLIST_OUT"); QString destdir = project->first("DESTDIR"); t << info_plist_out << ": " << "\n\t"; if(!destdir.isEmpty()) t << "@test -d " << destdir << " || mkdir -p " << destdir << "\n\t"; t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@cp \"" << info_plist << "\" \"" << info_plist_out << "\"" << endl; if(!project->first("RC_FILE").isEmpty()) { QString dir = destdir + "../Resources/"; t << dir << "application.icns:" << "\n\t" << "@test -d " << dir << " || mkdir -p " << dir << "\n\t" << "@cp " << var("RC_FILE") << " " << dir << "application.icns" << endl; } } QString ddir = project->isEmpty("QMAKE_DISTDIR") ? project->first("QMAKE_ORIG_TARGET") : project->first("QMAKE_DISTDIR"); QString ddir_c = fileFixify((project->isEmpty("OBJECTS_DIR") ? QString(".tmp/") : project->first("OBJECTS_DIR")) + ddir); t << "dist: " << "\n\t" << "@mkdir -p " << ddir_c << " && " << "$(COPY_FILE) --parents $(SOURCES) $(HEADERS) $(FORMS) $(DIST) " << ddir_c << Option::dir_sep << " && "; if(!project->isEmpty("TRANSLATIONS")) t << "$(COPY_FILE) --parents " << var("TRANSLATIONS") << " " << ddir_c << Option::dir_sep << " && "; if(!project->isEmpty("FORMS")) { QStringList &forms = project->variables()["FORMS"], ui_headers; for(QStringList::Iterator formit = forms.begin(); formit != forms.end(); ++formit) { QString ui_h = fileFixify((*formit) + Option::h_ext.first()); if(QFile::exists(ui_h) ) ui_headers << ui_h; } if(!ui_headers.isEmpty()) t << "$(COPY_FILE) --parents " << val(ui_headers) << " " << ddir_c << Option::dir_sep << " && "; } t << "( cd `dirname " << ddir_c << "` && " << "$(TAR) " << var("QMAKE_ORIG_TARGET") << ".tar " << ddir << " && " << "$(GZIP) " << var("QMAKE_ORIG_TARGET") << ".tar ) && " << "$(MOVE) `dirname " << ddir_c << "`" << Option::dir_sep << var("QMAKE_ORIG_TARGET") << ".tar.gz . && " - << "$(DEL_DIR) " << ddir_c + << "$(DEL_FILE) -r " << ddir_c << endl << endl; QString clean_targets; if(mocAware()) { t << "mocclean:" << "\n"; if(!objMoc.isEmpty() || !srcMoc.isEmpty() || moc_incremental) { if(!objMoc.isEmpty()) t << "\t-$(DEL_FILE) $(OBJMOC)" << '\n'; if(!srcMoc.isEmpty()) t << "\t-$(DEL_FILE) $(SRCMOC)" << '\n'; if(moc_incremental) t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJMOC)" << '\n'; clean_targets += " mocclean"; } t << endl; } t << "uiclean:" << "\n"; if (!var("UICIMPLS").isEmpty() || !var("UICDECLS").isEmpty()) { t << "\t-$(DEL_FILE) $(UICIMPLS) $(UICDECLS)" << "\n"; clean_targets += " uiclean"; } t << endl; + t << "yaccclean:" << "\n"; + if(!var("YACCSOURCES").isEmpty()) { + QStringList clean, &l = project->variables()["YACCSOURCES"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QFileInfo fi((*it)); + QString dir; + if(fi.dirPath() != ".") + dir = fi.dirPath() + Option::dir_sep; + dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); + if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) + dir += Option::dir_sep; + clean << dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first(); + clean << dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first(); + } + if(!clean.isEmpty()) { + t << "\t-$(DEL_FILE) " << clean.join(" ") << "\n"; + clean_targets += " yaccclean"; + } + } + + t << "lexclean:" << "\n"; + if(!var("LEXSOURCES").isEmpty()) { + QStringList clean, &l = project->variables()["LEXSOURCES"]; + for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { + QFileInfo fi((*it)); + QString dir; + if(fi.dirPath() != ".") + dir = fi.dirPath() + Option::dir_sep; + dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir); + if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep) + dir += Option::dir_sep; + clean << dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first(); + } + if(!clean.isEmpty()) { + t << "\t-$(DEL_FILE) " << clean.join(" ") << "\n"; + clean_targets += " lexclean"; + } + } + if(do_incremental) { t << "incrclean:" << "\n"; if(src_incremental) t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJECTS)" << "\n"; if(moc_incremental) t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJMOC)" << '\n'; t << endl; } t << "clean:" << clean_targets << "\n\t"; if(!project->isEmpty("OBJECTS")) t << "-$(DEL_FILE) $(OBJECTS) " << "\n\t"; if(!project->isEmpty("IMAGES")) t << varGlue("QMAKE_IMAGE_COLLECTION", "\t-$(DEL_FILE) ", " ", "") << "\n\t"; if(src_incremental) t << "-$(DEL_FILE) $(INCREMENTAL_OBJECTS)" << "\n\t"; t << varGlue("QMAKE_CLEAN","-$(DEL_FILE) "," ","\n\t") << "-$(DEL_FILE) *~ core *.core" << "\n" << varGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << endl << endl; t << "####### Sub-libraries" << endl << endl; if ( !project->variables()["SUBLIBS"].isEmpty() ) { QString libdir = "tmp/"; if(!project->isEmpty("SUBLIBS_DIR")) libdir = project->first("SUBLIBS_DIR"); QStringList &l = project->variables()["SUBLIBS"]; for(it = l.begin(); it != l.end(); ++it) t << libdir << "lib" << (*it) << ".a" << ":\n\t" << var(QString("MAKELIB") + (*it)) << endl << endl; } QString destdir = project->first("DESTDIR"); if(!destdir.isEmpty() && destdir.right(1) != Option::dir_sep) destdir += Option::dir_sep; - t << "distclean: " << "clean\n\t" - << "-$(DEL_FILE) " << destdir << "$(TARGET)" << " " << "$(TARGET)" << "\n"; + t << "distclean: " << "clean\n"; + if(project->first("TEMPLATE") == "app" && + project->isActiveConfig("resource_fork") && !project->isActiveConfig("console")) + t << "\t-$(DEL_FILE) -r " << destdir.section(Option::dir_sep, 0, -4) << "\n"; + else + t << "\t-$(DEL_FILE) " << destdir << "$(TARGET)" << " " << "$(TARGET)" << "\n"; if(!project->isActiveConfig("staticlib") && project->variables()["QMAKE_APP_FLAG"].isEmpty() && !project->isActiveConfig("plugin")) t << "\t-$(DEL_FILE) " << destdir << "$(TARGET0) " << destdir << "$(TARGET1) " << destdir << "$(TARGET2) $(TARGETA)" << "\n"; t << endl << endl; if ( !project->isEmpty("PRECOMPH") ) { QString outdir = project->first("MOC_DIR"); QString qt_dot_h = Option::fixPathToLocalOS(project->first("PRECOMPH")); t << "###### Combined headers" << endl << endl; //XXX t << outdir << "allmoc.cpp: " << qt_dot_h << " " << varList("HEADERS_ORIG") << "\n\t" << "echo '#include \"" << qt_dot_h << "\"' >" << outdir << "allmoc.cpp" << "\n\t" << "$(CXX) -E -DQT_MOC_CPP -DQT_NO_STL $(CXXFLAGS) $(INCPATH) >" << outdir << "allmoc.h " << outdir << "allmoc.cpp" << "\n\t" << "$(MOC) -o " << outdir << "allmoc.cpp " << outdir << "allmoc.h" << "\n\t" << "perl -pi -e 's{#include \"allmoc.h\"}{#define QT_H_CPP\\n#include \"" << qt_dot_h << "\"}' " << outdir << "allmoc.cpp" << "\n\t" << "$(DEL_FILE) " << outdir << "allmoc.h" << endl << endl; } // blasted user defined targets QStringList &qut = project->variables()["QMAKE_EXTRA_UNIX_TARGETS"]; for(it = qut.begin(); it != qut.end(); ++it) { QString targ = var((*it) + ".target"), cmd = var((*it) + ".commands"), deps; if(targ.isEmpty()) targ = (*it); QStringList &deplist = project->variables()[(*it) + ".depends"]; for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { QString dep = var((*dep_it) + ".target"); if(dep.isEmpty()) dep = (*dep_it); deps += " " + dep; } t << targ << ":" << deps << "\n\t" << cmd << endl << endl; } t <<"FORCE:" << endl << endl; } struct SubDir { QString directory, profile, target, makefile; }; void UnixMakefileGenerator::writeSubdirs(QTextStream &t, bool direct) { QPtrList<SubDir> subdirs; { QStringList subdirs_in = project->variables()["SUBDIRS"]; for(QStringList::Iterator it = subdirs_in.begin(); it != subdirs_in.end(); ++it) { QString file = (*it); fileFixify(file); SubDir *sd = new SubDir; subdirs.append(sd); sd->makefile = "$(MAKEFILE)"; if((*it).right(4) == ".pro") { int slsh = file.findRev(Option::dir_sep); if(slsh != -1) { sd->directory = file.left(slsh+1); sd->profile = file.mid(slsh+1); } else { sd->profile = file; } } else { sd->directory = file; } while(sd->directory.right(1) == Option::dir_sep) sd->directory = sd->directory.left(sd->directory.length() - 1); if(!sd->profile.isEmpty()) { QString basename = sd->directory; int new_slsh = basename.findRev(Option::dir_sep); if(new_slsh != -1) basename = basename.mid(new_slsh+1); if(sd->profile != basename + ".pro") sd->makefile += "." + sd->profile.left(sd->profile.length() - 4); //no need for the .pro } sd->target = "sub-" + (*it); sd->target.replace('/', '-'); sd->target.replace('.', '_'); } } QPtrListIterator<SubDir> it(subdirs); QString ofile = Option::output.name(); if(ofile.findRev(Option::dir_sep) != -1) ofile = ofile.right(ofile.length() - ofile.findRev(Option::dir_sep) -1); t << "MAKEFILE = " << var("MAKEFILE") << endl; t << "QMAKE = " << var("QMAKE") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "SUBTARGETS = "; // subdirectory targets are sub-directory for( it.toFirst(); it.current(); ++it) t << " \\\n\t\t" << it.current()->target; t << endl << endl; t << "first: all\n\nall: " << ofile << " $(SUBTARGETS)" << endl << endl; // generate target rules for( it.toFirst(); it.current(); ++it) { bool have_dir = !(*it)->directory.isEmpty(); QString mkfile = (*it)->makefile, out; if(have_dir) mkfile.prepend((*it)->directory + Option::dir_sep); if(direct || (*it)->makefile != "$(MAKEFILE)") out = " -o " + (*it)->makefile; //qmake it t << mkfile << ": " << "\n\t"; if(have_dir) t << "cd " << (*it)->directory << " && "; t << "$(QMAKE) " << (*it)->profile << buildArgs() << out << endl; //actually compile t << (*it)->target << ": " << mkfile << " FORCE" << "\n\t"; if(have_dir) t << "cd " << (*it)->directory << " && "; t << "$(MAKE) -f " << (*it)->makefile << endl << endl; } if (project->isActiveConfig("ordered")) { // generate dependencies for( it.toFirst(); it.current(); ) { QString tar = it.current()->target; ++it; if (it.current()) t << it.current()->target << ": " << tar << endl; } t << endl; } writeMakeQmake(t); if(project->isEmpty("SUBDIRS")) { - t << "all qmake_all distclean install uiclean mocclean clean: FORCE" << endl; + t << "all qmake_all distclean install uiclean mocclean lexclean yaccclean clean: FORCE" << endl; } else { t << "all: $(SUBTARGETS)" << endl; t << "qmake_all:"; for( it.toFirst(); it.current(); ++it) { t << " "; if(!(*it)->directory.isEmpty()) t << (*it)->directory << Option::dir_sep; t << (*it)->makefile; } for( it.toFirst(); it.current(); ++it) { t << "\n\t ( "; if(!(*it)->directory.isEmpty()) t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; t << "grep \"^qmake_all:\" " << (*it)->makefile << " && $(MAKE) -f " << (*it)->makefile << " qmake_all" << "; ) || true"; } t << endl; - t << "clean uninstall install uiclean mocclean: qmake_all FORCE"; + t << "clean uninstall install uiclean mocclean lexclean yaccclean: qmake_all FORCE"; for( it.toFirst(); it.current(); ++it) { t << "\n\t ( "; if(!(*it)->directory.isEmpty()) t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; t << "$(MAKE) -f " << (*it)->makefile << " $@" << "; ) || true"; } t << endl; t << "distclean: qmake_all FORCE"; for( it.toFirst(); it.current(); ++it) { t << "\n\t ( "; if(!(*it)->directory.isEmpty()) t << "[ -d " << (*it)->directory << " ] && cd " << (*it)->directory << " ; "; t << "$(MAKE) -f " << (*it)->makefile << " $@; $(DEL_FILE) " << (*it)->makefile << "; ) || true"; } t << endl << endl; } t <<"FORCE:" << endl << endl; } void UnixMakefileGenerator::init2() { //version handling if(project->variables()["VERSION"].isEmpty()) project->variables()["VERSION"].append("1.0." + (project->isEmpty("VER_PAT") ? QString("0") : project->first("VER_PAT")) ); QStringList l = QStringList::split('.', project->first("VERSION")); l << "0" << "0"; //make sure there are three project->variables()["VER_MAJ"].append(l[0]); project->variables()["VER_MIN"].append(l[1]); project->variables()["VER_PAT"].append(l[2]); if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { #if 0 if ( project->isActiveConfig("dll") ) { project->variables()["TARGET"] += project->variables()["TARGET.so"]; if(project->variables()["QMAKE_LFLAGS_SHAPP"].isEmpty()) project->variables()["QMAKE_LFLAGS_SHAPP"] += project->variables()["QMAKE_LFLAGS_SHLIB"]; if(!project->variables()["QMAKE_LFLAGS_SONAME"].isEmpty()) project->variables()["QMAKE_LFLAGS_SONAME"].first() += project->first("TARGET"); } #endif project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); + if ( !project->variables()["QMAKE_CYGWIN_EXE"].isEmpty() ) + project->variables()["TARGET_EXT"].append(".exe"); } else if ( project->isActiveConfig("staticlib") ) { project->variables()["TARGET"].first().prepend("lib"); project->variables()["TARGET"].first() += ".a"; if(project->variables()["QMAKE_AR_CMD"].isEmpty()) project->variables()["QMAKE_AR_CMD"].append("$(AR) $(TARGET) $(OBJECTS) $(OBJMOC)"); } else { project->variables()["TARGETA"].append(project->first("DESTDIR") + "lib" + project->first("TARGET") + ".a"); if ( !project->variables()["QMAKE_AR_CMD"].isEmpty() ) project->variables()["QMAKE_AR_CMD"].first().replace("(TARGET)","(TARGETA)"); else project->variables()["QMAKE_AR_CMD"].append("$(AR) $(TARGETA) $(OBJECTS) $(OBJMOC)"); - QString os = project->variables()["QMAKESPEC"].first().section( '-', 0, 0 ); if( project->isActiveConfig("plugin") ) { project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB")); if(project->isActiveConfig("lib_version_first")) project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("QMAKE_EXTENSION_SHLIB")); else project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ")); project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; if(project->isActiveConfig("qt")) project->variables()["DEFINES"].append("QT_PLUGIN"); - } else if ( os == "hpux" ) { + } else if ( !project->isEmpty("QMAKE_HPUX_SHLIB") ) { project->variables()["TARGET_"].append("lib" + project->first("TARGET") + ".sl"); if(project->isActiveConfig("lib_version_first")) project->variables()["TARGET_x"].append("lib" + project->first("VER_MAJ") + "." + project->first("TARGET")); else project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ")); project->variables()["TARGET"] = project->variables()["TARGET_x"]; - } else if ( os == "aix" ) { + } else if ( !project->isEmpty("QMAKE_AIX_SHLIB") ) { project->variables()["TARGET_"].append("lib" + project->first("TARGET") + ".a"); if(project->isActiveConfig("lib_version_first")) { project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("VER_PAT") + "." + project->first("QMAKE_EXTENSION_SHLIB")); } else { project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ")); project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN")); project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("VER_PAT")); } project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; } else { project->variables()["TARGET_"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB")); if(project->isActiveConfig("lib_version_first")) { project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("QMAKE_EXTENSION_SHLIB")); project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("VER_PAT") + "." + project->variables()["QMAKE_EXTENSION_SHLIB"].first()); } else { project->variables()["TARGET_x"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ")); project->variables()["TARGET_x.y"].append("lib" + project->first("TARGET") + "." + project->first("QMAKE_EXTENSION_SHLIB") + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN")); project->variables()["TARGET_x.y.z"].append("lib" + project->first("TARGET") + "." + project->variables()[ "QMAKE_EXTENSION_SHLIB"].first() + "." + project->first("VER_MAJ") + "." + project->first("VER_MIN") + "." + project->first("VER_PAT")); } project->variables()["TARGET"] = project->variables()["TARGET_x.y.z"]; } if(project->isEmpty("QMAKE_LN_SHLIB")) project->variables()["QMAKE_LN_SHLIB"].append("ln -s"); project->variables()["DESTDIR_TARGET"].append("$(TARGET)"); if ( !project->variables()["DESTDIR"].isEmpty() ) project->variables()["DESTDIR_TARGET"].first().prepend(project->first("DESTDIR")); - if ( !project->variables()["QMAKE_LFLAGS_SONAME"].isEmpty() && !project->variables()["TARGET_x"].isEmpty() ) + if ( !project->variables()["QMAKE_LFLAGS_SONAME"].isEmpty()) { + if(project->isActiveConfig("plugin")) { + if(!project->variables()["TARGET"].isEmpty() ) + project->variables()["QMAKE_LFLAGS_SONAME"].first() += project->first("TARGET"); + } else { + if(!project->variables()["TARGET_x"].isEmpty() ) project->variables()["QMAKE_LFLAGS_SONAME"].first() += project->first("TARGET_x"); + } + } if ( project->variables()["QMAKE_LINK_SHLIB_CMD"].isEmpty() ) project->variables()["QMAKE_LINK_SHLIB_CMD"].append( "$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)"); } if(project->isEmpty("QMAKE_SYMBOLIC_LINK")) project->variables()["QMAKE_SYMBOLIC_LINK"].append("ln -sf"); if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SHAPP"]; } else if ( project->isActiveConfig("dll") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_SHLIB"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_SHLIB"]; if ( project->isActiveConfig("plugin") ) { project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_PLUGIN"]; if( !project->isActiveConfig("plugin_no_soname") ) project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SONAME"]; } else { project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SHLIB"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_SONAME"]; } QString destdir = project->first("DESTDIR"); if ( !destdir.isEmpty() && !project->variables()["QMAKE_RPATH"].isEmpty() ) { QString rpath_destdir = destdir; if(QDir::isRelativePath(rpath_destdir)) { QFileInfo fi(Option::fixPathToLocalOS(rpath_destdir)); if(fi.convertToAbs()) //strange, shouldn't really happen rpath_destdir = Option::fixPathToTargetOS(rpath_destdir, FALSE); else rpath_destdir = fi.filePath(); } else { rpath_destdir = Option::fixPathToTargetOS(rpath_destdir, FALSE); } project->variables()["QMAKE_LFLAGS"] += project->first("QMAKE_RPATH") + rpath_destdir; } } } diff --git a/qmake/generators/win32/borland_bmake.cpp b/qmake/generators/win32/borland_bmake.cpp index ae7b47b..26eea88 100644 --- a/qmake/generators/win32/borland_bmake.cpp +++ b/qmake/generators/win32/borland_bmake.cpp @@ -1,477 +1,509 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "borland_bmake.h" #include "option.h" #include <qdir.h> #include <qregexp.h> #include <time.h> #include <stdlib.h> BorlandMakefileGenerator::BorlandMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) { } bool BorlandMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { t << "all clean:" << "\n\t" << "@echo \"Some of the required modules (" << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" << "@echo \"Skipped.\"" << endl << endl; return TRUE; } if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { writeBorlandParts(t); return MakefileGenerator::writeMakefile(t); } else if(project->first("TEMPLATE") == "subdirs") { writeSubDirs(t); return TRUE; } return FALSE; } void BorlandMakefileGenerator::writeBorlandParts(QTextStream &t) { t << "!if !$d(BCB)" << endl; t << "BCB = $(MAKEDIR)\\.." << endl; t << "!endif" << endl << endl; t << "####### Compiler, tools and options" << endl << endl; t << "CC = " << var("QMAKE_CC") << endl; t << "CXX = " << var("QMAKE_CXX") << endl; t << "LEX = " << var("QMAKE_LEX") << endl; t << "YACC = " << var("QMAKE_YACC") << endl; t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "CXXFLAGS= " << var("QMAKE_CXXFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "LEXFLAGS=" << var("QMAKE_LEXFLAGS") << endl; t << "YACCFLAGS=" << var("QMAKE_YACCFLAGS") << endl; t << "INCPATH = "; QStringList &incs = project->variables()["INCLUDEPATH"]; for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit); inc.replace(QRegExp("\\\\*$"), ""); inc.replace("\"", ""); t << " -I\"" << inc << "\""; } t << " -I\"" << specdir() << "\"" << endl; if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { t << "LINK = " << var("QMAKE_LINK") << endl; t << "LFLAGS = "; if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) t << varGlue("QMAKE_LIBDIR","-L",";","") << " "; t << var("QMAKE_LFLAGS") << endl; t << "LIBS = " << var("QMAKE_LIBS") << endl; } else { t << "LIB = " << var("QMAKE_LIB") << endl; } t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") : Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl; t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") : Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl; t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl; t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl; t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl; t << "ZIP = " << var("QMAKE_ZIP") << endl; t << "DEF_FILE = " << varList("DEF_FILE") << endl; t << "RES_FILE = " << varList("RES_FILE") << endl; t << "COPY_FILE = " << var("QMAKE_COPY") << endl; t << "COPY_DIR = " << var("QMAKE_COPY") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << endl; t << endl; t << "####### Files" << endl << endl; t << "HEADERS = " << varList("HEADERS") << endl; t << "SOURCES = " << varList("SOURCES") << endl; t << "OBJECTS = " << varList("OBJECTS") << endl; t << "FORMS = " << varList("FORMS") << endl; t << "UICDECLS = " << varList("UICDECLS") << endl; t << "UICIMPLS = " << varList("UICIMPLS") << endl; t << "SRCMOC = " << varList("SRCMOC") << endl; t << "OBJMOC = " << varList("OBJMOC") << endl; t << "DIST = " << varList("DISTFILES") << endl; t << "TARGET = " << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT")) << endl; t << endl; t << "####### Implicit rules" << endl << endl; - t << ".SUFFIXES: .cpp .cxx .cc .c" << endl << endl; - t << ".cpp.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".cxx.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".cc.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".c.obj:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + t << ".SUFFIXES: .c"; + QStringList::Iterator cppit; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << " " << (*cppit); + t << endl << endl; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".c" << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; t << "####### Build rules" << endl << endl; t << "all: " << varGlue("ALL_DEPS",""," "," ") << " $(TARGET)" << endl << endl; - t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS"); + t << "$(TARGET): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC) " + << var("POST_TARGETDEPS"); if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { t << "\n\t" << "$(LINK) @&&|" << "\n\t" << "$(LFLAGS) $(OBJECTS) $(OBJMOC),$(TARGET),,$(LIBS),$(DEF_FILE),$(RES_FILE)"; } else { t << "\n\t-del $(TARGET)" << "\n\t" << "$(LIB) $(TARGET) @&&|" << " \n+" << project->variables()["OBJECTS"].join(" \\\n+") << " \\\n+" << project->variables()["OBJMOC"].join(" \\\n+"); } t << endl << "|" << endl; + + if ( !project->variables()["QMAKE_POST_LINK"].isEmpty() ) + t << "\t" <<var("QMAKE_POST_LINK") << endl; + if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) { QStringList dlldirs = project->variables()["DLLDESTDIR"]; for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { t << "\n\t" << "-copy $(TARGET) " << *dlldir; } } QString targetfilename = project->variables()["TARGET"].first(); if(project->isActiveConfig("activeqt")) { QString version = project->variables()["VERSION"].first(); if ( version.isEmpty() ) version = "1.0"; if ( project->isActiveConfig("dll")) { t << "\n\t" << ("-$(IDC) $(TARGET) /idl tmp\\" + targetfilename + ".idl -version " + version); t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" ); } else { t << "\n\t" << ("-$(TARGET) -dumpidl tmp\\" + targetfilename + ".idl -version " + version); t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); t << "\n\t" << ("-$(TARGET) -regserver"); } } t << endl << endl; if(!project->variables()["RC_FILE"].isEmpty()) { t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t" << var("QMAKE_RC") << " " << var("RC_FILE") << endl << endl; } t << "mocables: $(SRCMOC)" << endl << endl; writeMakeQmake(t); t << "dist:" << "\n\t" << "$(ZIP) " << var("PROJECT") << ".zip " << var("PROJECT") << ".pro $(SOURCES) $(HEADERS) $(DIST) $(FORMS)" << endl << endl; t << "clean:\n" << varGlue("OBJECTS","\t-del ","\n\t-del ","") << varGlue("SRCMOC" ,"\n\t-del ","\n\t-del ","") << varGlue("OBJMOC" ,"\n\t-del ","\n\t-del ","") << varGlue("UICDECLS" ,"\n\t-del ","\n\t-del ","") << varGlue("UICIMPLS" ,"\n\t-del ","\n\t-del ","") - << "\n\t-del $(TARGET)" << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ","") << varGlue("CLEAN_FILES","\n\t-del ","\n\t-del ",""); if ( project->isActiveConfig("activeqt")) { t << ("\n\t-del tmp\\" + targetfilename + ".*"); t << "\n\t-del tmp\\dump.*"; } - if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) - t << "\n\t-del " << var("DLLDESTDIR") << "\\" << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first(); if(!project->isEmpty("IMAGES")) t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-del ", "\n\t-del ", ""); // blasted user defined targets QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"]; for(QStringList::Iterator it = qut.begin(); it != qut.end(); ++it) { QString targ = var((*it) + ".target"), cmd = var((*it) + ".commands"), deps; if(targ.isEmpty()) targ = (*it); QStringList &deplist = project->variables()[(*it) + ".depends"]; for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { QString dep = var((*dep_it) + ".target"); if(dep.isEmpty()) dep = (*dep_it); deps += " " + dep; } t << "\n\n" << targ << ":" << deps << "\n\t" << cmd; } t << endl << endl; + + t << "distclean: clean" + << "\n\t-del $(TARGET)" + << endl << endl; } void BorlandMakefileGenerator::init() { if(init_flag) return; init_flag = TRUE; project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; /* this should probably not be here, but I'm using it to wrap the .t files */ if(project->first("TEMPLATE") == "app") project->variables()["QMAKE_APP_FLAG"].append("1"); else if(project->first("TEMPLATE") == "lib") project->variables()["QMAKE_LIB_FLAG"].append("1"); else if(project->first("TEMPLATE") == "subdirs") { MakefileGenerator::init(); if(project->variables()["MAKEFILE"].isEmpty()) project->variables()["MAKEFILE"].append("Makefile"); if(project->variables()["QMAKE"].isEmpty()) project->variables()["QMAKE"].append("qmake"); return; } bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qtmt"QTDLL_POSTFIX); QStringList &configs = project->variables()["CONFIG"]; if (project->isActiveConfig("shared")) project->variables()["DEFINES"].append("QT_DLL"); if (project->isActiveConfig("qt_dll")) if(configs.findIndex("qt") == -1) configs.append("qt"); if ( project->isActiveConfig("qt") ) { if ( project->isActiveConfig("plugin") ) { project->variables()["CONFIG"].append("dll"); project->variables()["DEFINES"].append("QT_PLUGIN"); } if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { project->variables()["QMAKE_QT_DLL"].append("1"); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) project->variables()["CONFIG"].append("dll"); } } if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["CONFIG"].remove("staticlib"); project->variables()["QMAKE_APP_OR_DLL"].append("1"); } else { project->variables()["CONFIG"].append("staticlib"); } if ( project->isActiveConfig("warn_off") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; } else if ( project->isActiveConfig("warn_on") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; } if(project->isActiveConfig("qt")) { if ( project->isActiveConfig("thread") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); if ( project->isActiveConfig("accessibility" ) ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); if ( project->isActiveConfig("tablet") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); } if ( project->isActiveConfig("debug") ) { if ( project->isActiveConfig("thread") ) { if ( project->isActiveConfig("dll") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; } } project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; } else { if ( project->isActiveConfig("thread") ) { if ( project->isActiveConfig("dll") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"]; } } project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; } if ( !project->variables()["QMAKE_INCDIR"].isEmpty()) { project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; } if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) { project->variables()["CONFIG"].append("windows"); } if ( project->isActiveConfig("qt") ) { project->variables()["CONFIG"].append("moc"); project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; if ( !project->isActiveConfig("debug") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) { project->variables()["DEFINES"].append("QT_MAKEDLL"); project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"]; } } else { if(project->isActiveConfig("thread")) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); if ( hver == -1 ) - hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); + hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qtmt"); if(hver != -1) { QString ver; ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "mt" : ""), hver); QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) (*libit).replace(QRegExp("qt(mt)?\\.lib"), ver); } } if ( project->isActiveConfig( "activeqt" ) ) { project->variables().remove("QMAKE_LIBS_QT_ENTRY"); project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; if ( project->isActiveConfig( "dll" ) ) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; } if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; } } } if ( project->isActiveConfig("opengl") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; } if ( project->isActiveConfig("dll") ) { project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"]; if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) { project->variables()["TARGET_EXT"].append( QStringList::split('.',project->first("VERSION")).join("") + ".dll"); } else { project->variables()["TARGET_EXT"].append(".dll"); } } else { project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"]; project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"]; project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"]; project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"]; if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) { project->variables()["TARGET_EXT"].append(".exe"); } else { project->variables()["TARGET_EXT"].append(".lib"); } } if ( project->isActiveConfig("windows") ) { if ( project->isActiveConfig("console") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; } else { project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"]; } project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; } + if ( project->isActiveConfig("stl") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_OFF"]; + } + if ( project->isActiveConfig("exceptions") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_OFF"]; + } + if ( project->isActiveConfig("rtti") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_OFF"]; + } + if ( project->isActiveConfig("thread") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_RTMT"]; } else { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_RT"]; } if ( project->isActiveConfig("moc") ) { setMocAware(TRUE); } project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); QStringList &l = project->variables()["QMAKE_FILETAGS"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QStringList &gdmf = project->variables()[(*it)]; for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) (*inner) = Option::fixPathToTargetOS((*inner), FALSE); } if ( !project->variables()["RC_FILE"].isEmpty()) { if ( !project->variables()["RES_FILE"].isEmpty()) { fprintf(stderr, "Both .rc and .res file specified.\n"); fprintf(stderr, "Please specify one of them, not both."); exit(666); } project->variables()["RES_FILE"] = project->variables()["RC_FILE"]; project->variables()["RES_FILE"].first().replace(".rc",".res"); - project->variables()["TARGETDEPS"] += project->variables()["RES_FILE"]; + project->variables()["POST_TARGETDEPS"] += project->variables()["RES_FILE"]; } MakefileGenerator::init(); if ( !project->variables()["VERSION"].isEmpty()) { QStringList l = QStringList::split('.', project->first("VERSION")); project->variables()["VER_MAJ"].append(l[0]); project->variables()["VER_MIN"].append(l[1]); } if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { // bcc does not generate a .tds file for static libs QString tdsPostfix; if ( !project->variables()["VERSION"].isEmpty() ) { tdsPostfix = QStringList::split( '.', project->first("VERSION") ).join("") + ".tds"; } else { tdsPostfix = ".tds"; } project->variables()["QMAKE_CLEAN"].append( project->first("DESTDIR") + project->first("TARGET") + tdsPostfix ); } } - diff --git a/qmake/generators/win32/borland_bmake.h b/qmake/generators/win32/borland_bmake.h index 90f8229..5ffed58 100644 --- a/qmake/generators/win32/borland_bmake.h +++ b/qmake/generators/win32/borland_bmake.h @@ -1,59 +1,58 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef __BORLANDMAKE_H__ -#define __BORLANDMAKE_H__ +#ifndef __BORLAND_BMAKE_H__ +#define __BORLAND_BMAKE_H__ #include "winmakefile.h" class BorlandMakefileGenerator : public Win32MakefileGenerator { bool init_flag; void writeBorlandParts(QTextStream &); bool writeMakefile(QTextStream &); void init(); public: BorlandMakefileGenerator(QMakeProject *p); ~BorlandMakefileGenerator(); }; inline BorlandMakefileGenerator::~BorlandMakefileGenerator() { } - -#endif /* __BORLANDMAKE_H__ */ +#endif /* __BORLAND_BMAKE_H__ */ diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp new file mode 100644 index 0000000..7f58a55 --- a/dev/null +++ b/qmake/generators/win32/mingw_make.cpp @@ -0,0 +1,524 @@ +/****************************************************************************
+** $Id$
+**
+** Definition of ________ class.
+**
+** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the network module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition licenses may use this
+** file in accordance with the Qt Commercial License Agreement provided
+** with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "mingw_make.h"
+#include "option.h"
+#include <qregexp.h>
+#include <qdir.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+MingwMakefileGenerator::MingwMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE)
+{
+ Option::obj_ext = ".o";
+}
+
+bool
+MingwMakefileGenerator::writeMakefile(QTextStream &t)
+{
+ writeHeader(t);
+ if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
+ t << "all clean:" << "\n\t"
+ << "@echo \"Some of the required modules ("
+ << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
+ << "@echo \"Skipped.\"" << endl << endl;
+ writeMakeQmake(t);
+ return TRUE;
+ }
+
+ if(project->first("TEMPLATE") == "app" ||
+ project->first("TEMPLATE") == "lib") {
+ writeMingwParts(t);
+ return MakefileGenerator::writeMakefile(t);
+ }
+ else if(project->first("TEMPLATE") == "subdirs") {
+ writeSubDirs(t);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+MingwMakefileGenerator::writeMingwParts(QTextStream &t)
+{
+ t << "####### Compiler, tools and options" << endl << endl;
+ t << "CC = " << var("QMAKE_CC") << endl;
+ t << "CXX = " << var("QMAKE_CXX") << endl;
+ t << "LEX = " << var("QMAKE_LEX") << endl;
+ t << "YACC = " << var("QMAKE_YACC") << endl;
+ t << "CFLAGS = " << var("QMAKE_CFLAGS") << " "
+ << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " "
+ << varGlue("DEFINES","-D"," -D","") << endl;
+ t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " "
+ << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " "
+ << varGlue("DEFINES","-D"," -D","") << endl;
+ t << "LEXFLAGS =" << var("QMAKE_LEXFLAGS") << endl;
+ t << "YACCFLAGS =" << var("QMAKE_YACCFLAGS") << endl;
+
+ t << "INCPATH = ";
+ QStringList &incs = project->variables()["INCLUDEPATH"];
+ for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
+ QString inc = (*incit);
+ inc.replace(QRegExp("\\\\$"), "\\\\");
+ inc.replace(QRegExp("\""), "");
+ t << " -I" << inc ;
+ }
+ t << " -I" << specdir()
+ << endl;
+ if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) {
+ t << "LINK = " << var("QMAKE_LINK") << endl;
+ t << "LFLAGS = ";
+ if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() )
+ t << varGlue("QMAKE_LIBDIR","-L",";","") << " ";
+ t << var("QMAKE_LFLAGS") << endl;
+ t << "LIBS = " << var("QMAKE_LIBS").replace(QRegExp("(\\slib|^lib)")," -l") << endl;
+ }
+ else {
+ t << "LIB = " << var("QMAKE_LIB") << endl;
+ }
+ t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") :
+ Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl;
+ t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") :
+ Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl;
+ t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") :
+ Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl;
+ t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") :
+ Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl;
+ t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") :
+ Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl;
+ t << "ZIP = " << var("QMAKE_ZIP") << endl;
+ t << "DEF_FILE = " << varList("DEF_FILE") << endl;
+ t << "COPY_FILE = " << var("QMAKE_COPY") << endl;
+ t << "COPY_DIR = " << var("QMAKE_COPY") << endl;
+ t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
+ t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
+ t << "MOVE = " << var("QMAKE_MOVE") << endl;
+ t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl;
+ t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
+ t << endl;
+
+ t << "####### Output directory" << endl << endl;
+ if (! project->variables()["OBJECTS_DIR"].isEmpty())
+ t << "OBJECTS_DIR = " << var("OBJECTS_DIR").replace(QRegExp("\\\\$"),"") << endl;
+ else
+ t << "OBJECTS_DIR = . " << endl;
+ if (! project->variables()["MOC_DIR"].isEmpty())
+ t << "MOC_DIR = " << var("MOC_DIR").replace(QRegExp("\\\\$"),"") << endl;
+ else
+ t << "MOC_DIR = . " << endl;
+ t << endl;
+
+ t << "####### Files" << endl << endl;
+ t << "HEADERS = " << varList("HEADERS") << endl;
+ t << "SOURCES = " << varList("SOURCES") << endl;
+// t << "OBJECTS = " << varList("OBJECTS").replace(QRegExp("\\.obj"),".o") << endl;
+ t << "OBJECTS = " << varList("OBJECTS") << endl;
+ t << "FORMS = " << varList("FORMS") << endl;
+ t << "UICDECLS = " << varList("UICDECLS") << endl;
+ t << "UICIMPLS = " << varList("UICIMPLS") << endl;
+ t << "SRCMOC = " << varList("SRCMOC") << endl;
+ t << "OBJMOC = " << varList("OBJMOC") << endl;
+// t << "OBJMOC = " << varList("OBJMOC").replace(QRegExp("\\.obj"),".o") << endl;
+ t << "DIST = " << varList("DISTFILES") << endl;
+ t << "TARGET = ";
+ if( !project->variables()[ "DESTDIR" ].isEmpty() )
+ t << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT"));
+ else
+ t << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first();
+ t << endl;
+ t << endl;
+
+ t << "####### Implicit rules" << endl << endl;
+ t << ".SUFFIXES: .cpp .cxx .cc .C .c" << endl << endl;
+ t << ".cpp.o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ t << ".cxx.o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ t << ".cc.o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ t << ".C.o:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
+ t << ".c.o:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl;
+
+ t << "####### Build rules" << endl << endl;
+ t << "all: " << "$(OBJECTS_DIR) " << "$(MOC_DIR) " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" << endl << endl;
+ t << "$(TARGET): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC) "
+ << var("POST_TARGETDEPS");
+ if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) {
+ t << "\n\t" << "$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)";
+ } else {
+ t << "\n\t" << "$(LIB) $(TARGET) $(OBJECTS) $(OBJMOC)";
+ }
+
+ if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) {
+ QStringList dlldirs = project->variables()["DLLDESTDIR"];
+ for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) {
+ t << "\n\t" << "copy $(TARGET) " << *dlldir;
+ }
+ }
+ QString targetfilename = project->variables()["TARGET"].first();
+ if(project->isActiveConfig("activeqt")) {
+ QString version = project->variables()["VERSION"].first();
+ if ( version.isEmpty() )
+ version = "1.0";
+
+ if ( project->isActiveConfig("dll")) {
+ t << "\n\t" << ("-$(IDC) $(TARGET) /idl tmp\\" + targetfilename + ".idl -version " + version);
+ t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl");
+ t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb");
+ t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" );
+ } else {
+ t << "\n\t" << ("-$(TARGET) -dumpidl tmp\\" + targetfilename + ".idl -version " + version);
+ t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl");
+ t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb");
+ t << "\n\t" << "-$(TARGET) -regserver";
+ }
+ }
+ t << endl << endl;
+
+ if(!project->variables()["RC_FILE"].isEmpty()) {
+ t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t"
+ << var("QMAKE_RC") << " -i " << var("RC_FILE") << " -o " << var("RC_FILE").replace(QRegExp("\\.rc"),".o") << endl << endl;
+ }
+ project->variables()["RES_FILE"].first().replace(QRegExp("\\.rc"),".o");
+
+ t << "mocables: $(SRCMOC)" << endl << endl;
+
+ t << "$(OBJECTS_DIR):" << "\n\t"
+ << "@if not exist $(OBJECTS_DIR) mkdir $(OBJECTS_DIR)" << endl << endl;
+
+ t << "$(MOC_DIR):" << "\n\t"
+ << "@if not exist $(MOC_DIR) mkdir $(MOC_DIR)" << endl << endl;
+
+ writeMakeQmake(t);
+
+ t << "dist:" << "\n\t"
+ << "$(ZIP) " << var("PROJECT") << ".zip "
+ << var("PROJECT") << ".pro $(SOURCES) $(HEADERS) $(DIST) $(FORMS)" << endl << endl;
+
+ t << "clean:"
+ << varGlue("OBJECTS","\n\t-del ","\n\t-del ","").replace(QRegExp("\\.obj"),".o")
+ << varGlue("SRCMOC" ,"\n\t-del ","\n\t-del ","")
+ << varGlue("OBJMOC" ,"\n\t-del ","\n\t-del ","").replace(QRegExp("\\.obj"),".o")
+ << varGlue("UICDECLS" ,"\n\t-del ","\n\t-del ","")
+ << varGlue("UICIMPLS" ,"\n\t-del ","\n\t-del ","")
+ << "\n\t-del $(TARGET)"
+ << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ","")
+ << varGlue("CLEAN_FILES","\n\t-del ","\n\t-del ","");
+ if ( project->isActiveConfig("activeqt")) {
+ t << ("\n\t-del tmp\\" + targetfilename + ".*");
+ t << "\n\t-del tmp\\dump.*";
+ }
+ if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty())
+ t << "\n\t-del " << var("DLLDESTDIR") << "\\" << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first();
+ if(!project->isEmpty("IMAGES"))
+ t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-del ", "\n\t-del ", "");
+
+ // blasted user defined targets
+ QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"];
+ for(QStringList::Iterator it = qut.begin(); it != qut.end(); ++it) {
+ QString targ = var((*it) + ".target"),
+ cmd = var((*it) + ".commands"), deps;
+ if(targ.isEmpty())
+ targ = (*it);
+ QStringList &deplist = project->variables()[(*it) + ".depends"];
+ for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) {
+ QString dep = var((*dep_it) + ".target");
+ if(dep.isEmpty())
+ dep = (*dep_it);
+ deps += " " + dep;
+ }
+ t << "\n\n" << targ << ":" << deps << "\n\t"
+ << cmd;
+ }
+
+ t << endl << endl;
+}
+
+
+void
+MingwMakefileGenerator::init()
+{
+ if(init_flag)
+ return;
+ init_flag = TRUE;
+
+ /* this should probably not be here, but I'm using it to wrap the .t files */
+ if(project->first("TEMPLATE") == "app")
+ project->variables()["QMAKE_APP_FLAG"].append("1");
+ else if(project->first("TEMPLATE") == "lib")
+ project->variables()["QMAKE_LIB_FLAG"].append("1");
+ else if(project->first("TEMPLATE") == "subdirs") {
+ MakefileGenerator::init();
+ if(project->variables()["MAKEFILE"].isEmpty())
+ project->variables()["MAKEFILE"].append("Makefile");
+ if(project->variables()["QMAKE"].isEmpty())
+ project->variables()["QMAKE"].append("qmake");
+ return;
+ }
+
+ bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX);
+ project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"];
+
+ // LIBS defined in Profile comes first for gcc
+ project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"];
+
+ QString targetfilename = project->variables()["TARGET"].first();
+ QStringList &configs = project->variables()["CONFIG"];
+ if (project->isActiveConfig("qt") && project->isActiveConfig("shared"))
+ project->variables()["DEFINES"].append("QT_DLL");
+ if (project->isActiveConfig("qt_dll"))
+ if(configs.findIndex("qt") == -1) configs.append("qt");
+ if ( project->isActiveConfig("qt") ) {
+ if ( project->isActiveConfig( "plugin" ) ) {
+ project->variables()["CONFIG"].append("dll");
+ if(project->isActiveConfig("qt"))
+ project->variables()["DEFINES"].append("QT_PLUGIN");
+ }
+ if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) &&
+ ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 ||
+ project->variables()["DEFINES"].findIndex("QT_DLL") != -1) ||
+ (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) {
+ project->variables()["QMAKE_QT_DLL"].append("1");
+ if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() )
+ project->variables()["CONFIG"].append("dll");
+ }
+ if ( project->isActiveConfig("thread") )
+ project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT");
+ if ( project->isActiveConfig("accessibility" ) )
+ project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT");
+ if ( project->isActiveConfig("tablet") )
+ project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT");
+ }
+ if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) {
+ project->variables()["CONFIG"].remove("staticlib");
+ project->variables()["QMAKE_APP_OR_DLL"].append("1");
+ } else {
+ project->variables()["CONFIG"].append("staticlib");
+ }
+ if ( project->isActiveConfig("warn_off") ) {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"];
+ } else if ( project->isActiveConfig("warn_on") ) {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"];
+ }
+ if ( project->isActiveConfig("debug") ) {
+ if ( project->isActiveConfig("thread") ) {
+ // use the DLL RT even here
+ if ( project->variables()["DEFINES"].contains("QT_DLL") ) {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"];
+ } else {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"];
+ }
+ }
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"];
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"];
+ } else {
+ if ( project->isActiveConfig("thread") ) {
+ if ( project->variables()["DEFINES"].contains("QT_DLL") ) {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"];
+ } else {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"];
+ }
+ }
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"];
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"];
+ }
+
+ if ( !project->variables()["QMAKE_INCDIR"].isEmpty())
+ project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"];
+ if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") )
+ project->variables()["CONFIG"].append("windows");
+ if ( project->isActiveConfig("qt") ) {
+ project->variables()["CONFIG"].append("moc");
+ project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"];
+ project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"];
+ if ( !project->isActiveConfig("debug") )
+ project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG");
+ if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) {
+ if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) {
+ project->variables()["DEFINES"].append("QT_MAKEDLL");
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"];
+ }
+ } else {
+ if(project->isActiveConfig("thread"))
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"];
+ else
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"];
+ if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) {
+ int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt");
+ if ( hver == -1 )
+ hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt");
+ if(hver != -1) {
+ QString ver;
+ ver.sprintf("libqt-%s" QTDLL_POSTFIX "%d.a", (project->isActiveConfig("thread") ? "-mt" : ""), hver);
+ QStringList &libs = project->variables()["QMAKE_LIBS"];
+// @@@HGTODO maybe we must change the replace regexp if we understand what's going on
+ for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit)
+ (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver);
+ }
+ }
+ if ( project->isActiveConfig( "activeqt" ) ) {
+ project->variables().remove("QMAKE_LIBS_QT_ENTRY");
+ project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib";
+ if ( project->isActiveConfig( "dll" ) )
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"];
+ }
+ if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) {
+ project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"];
+ }
+ }
+ }
+ if ( project->isActiveConfig("opengl") ) {
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"];
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"];
+ }
+ if ( project->isActiveConfig("dll") ) {
+ project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"];
+ project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"];
+ project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"];
+ project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"];
+ if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) {
+ project->variables()["TARGET_EXT"].append(
+ QStringList::split('.',project->first("VERSION")).join("") + ".dll");
+ } else {
+ project->variables()["TARGET_EXT"].append(".dll");
+ }
+ } else {
+ project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"];
+ project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"];
+ project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"];
+ project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"];
+ if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) {
+ project->variables()["TARGET_EXT"].append(".exe");
+ } else {
+ project->variables()["TARGET_EXT"].append(".a");
+ project->variables()["QMAKE_LFLAGS"].append("-static");
+ if(project->variables()["TARGET"].first().left(3) != "lib")
+ project->variables()["TARGET"].first().prepend("lib");
+ }
+ }
+ if ( project->isActiveConfig("windows") ) {
+ if ( project->isActiveConfig("console") ) {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"];
+ } else {
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"];
+ }
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"];
+ } else {
+ project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"];
+ project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"];
+ }
+
+ if ( project->isActiveConfig("moc") )
+ setMocAware(TRUE);
+ project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ',
+ "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH");
+ QStringList &l = project->variables()["QMAKE_FILETAGS"];
+ for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
+ QStringList &gdmf = project->variables()[(*it)];
+ for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner)
+ (*inner) = Option::fixPathToTargetOS((*inner), FALSE);
+ }
+
+ if ( project->isActiveConfig("dll") )
+ project->variables()["QMAKE_LFLAGS"].append(QString("-Wl,--out-implib,") + project->first("DESTDIR") + "\\lib"+ project->first("TARGET") + ".a");
+
+ if ( !project->variables()["DEF_FILE"].isEmpty() )
+ project->variables()["QMAKE_LFLAGS"].append(QString("-Wl,--output-def,") + project->first("DEF_FILE"));
+// if(!project->isActiveConfig("incremental"))
+// project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no"));
+
+#if 0
+ if ( !project->variables()["VERSION"].isEmpty() ) {
+ QString version = project->variables()["VERSION"][0];
+ int firstDot = version.find( "." );
+ QString major = version.left( firstDot );
+ QString minor = version.right( version.length() - firstDot - 1 );
+ minor.replace( ".", "" );
+ project->variables()["QMAKE_LFLAGS"].append( "/VERSION:" + major + "." + minor );
+ }
+#endif
+ if ( !project->variables()["RC_FILE"].isEmpty()) {
+ if ( !project->variables()["RES_FILE"].isEmpty()) {
+ fprintf(stderr, "Both .rc and .res file specified.\n");
+ fprintf(stderr, "Please specify one of them, not both.");
+ exit(666);
+ }
+ project->variables()["RES_FILE"] = project->variables()["RC_FILE"];
+ project->variables()["RES_FILE"].first().replace(".rc",".o");
+ project->variables()["POST_TARGETDEPS"] += project->variables()["RES_FILE"];
+ }
+ if ( !project->variables()["RES_FILE"].isEmpty())
+ project->variables()["QMAKE_LIBS"] += project->variables()["RES_FILE"];
+
+ MakefileGenerator::init();
+ if ( !project->variables()["VERSION"].isEmpty()) {
+ QStringList l = QStringList::split('.', project->first("VERSION"));
+ project->variables()["VER_MAJ"].append(l[0]);
+ project->variables()["VER_MIN"].append(l[1]);
+ }
+ if(project->isActiveConfig("dll")) {
+ project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") +"lib" + project->first("TARGET") + ".a");
+ }
+}
+
+void
+MingwMakefileGenerator::writeSubDirs(QTextStream &t)
+{
+ QString qs ;
+ QTextStream ts (&qs, IO_WriteOnly) ;
+ Win32MakefileGenerator::writeSubDirs( ts ) ;
+ QRegExp rx("(\\n\\tcd [^\\n\\t]+)(\\n\\t.+)\\n\\t@cd ..") ;
+ rx.setMinimal(true);
+ int pos = 0 ;
+ while ( -1 != (pos = rx.search( qs, pos)))
+ {
+ QString qsMatch = rx.cap(2);
+ qsMatch.replace("\n\t"," && \\\n\t");
+ qs.replace(pos+rx.cap(1).length(), rx.cap(2).length(), qsMatch );
+ pos += (rx.cap(1).length()+qsMatch.length());
+ }
+ t << qs ;
+}
diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h new file mode 100644 index 0000000..c00bf1b --- a/dev/null +++ b/qmake/generators/win32/mingw_make.h @@ -0,0 +1,58 @@ +/****************************************************************************
+** $Id$
+**
+** Definition of ________ class.
+**
+** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the network module of the Qt GUI Toolkit.
+**
+** This file may be distributed under the terms of the Q Public License
+** as defined by Trolltech AS of Norway and appearing in the file
+** LICENSE.QPL included in the packaging of this file.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** Licensees holding valid Qt Enterprise Edition licenses may use this
+** file in accordance with the Qt Commercial License Agreement provided
+** with the Software.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
+** See http://www.trolltech.com/qpl/ for QPL licensing information.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef __MINGW_MAKE_H__
+#define __MINGW_MAKE_H__
+
+#include "winmakefile.h"
+
+class MingwMakefileGenerator : public Win32MakefileGenerator
+{
+ bool init_flag;
+ void writeMingwParts(QTextStream &);
+ void writeSubDirs(QTextStream &t) ;
+
+ bool writeMakefile(QTextStream &);
+ void init();
+
+public:
+ MingwMakefileGenerator(QMakeProject *p);
+ ~MingwMakefileGenerator();
+
+};
+
+inline MingwMakefileGenerator::~MingwMakefileGenerator()
+{ }
+
+#endif /* __MINGW_MAKE_H__ */
diff --git a/qmake/generators/win32/msvc_dsp.cpp b/qmake/generators/win32/msvc_dsp.cpp index 8b08c78..3fa0496 100644 --- a/qmake/generators/win32/msvc_dsp.cpp +++ b/qmake/generators/win32/msvc_dsp.cpp @@ -127,829 +127,872 @@ DspMakefileGenerator::writeDspParts(QTextStream &t) t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF " << endl << endl; } t << "# End Source File" << endl; } endGroups(t); } else if(variable == "MSVCDSP_IMAGES") { if(project->variables()["IMAGES"].isEmpty()) continue; t << "# Begin Source File\n\nSOURCE=" << project->first("QMAKE_IMAGE_COLLECTION") << endl; t << "# End Source File" << endl; } else if(variable == "MSVCDSP_HEADERS") { if(project->variables()["HEADERS"].isEmpty()) continue; QStringList list = project->variables()["HEADERS"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { // beginGroupForFile((*it), t); t << "# Begin Source File\n\nSOURCE=" << (*it) << endl << endl; if ( project->isActiveConfig("moc") && !findMocDestination((*it)).isEmpty()) { QString base = (*it); base.replace(QRegExp("\\..*$"), "").upper(); base.replace(QRegExp("[^a-zA-Z]"), "_"); QString mocpath = var( "QMAKE_MOC" ); mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; QString build = "\n\n# Begin Custom Build - Moc'ing " + (*it) + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + findMocDestination((*it)) + "\"" " : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n" "\t" + mocpath + (*it) + " -o " + findMocDestination((*it)) + "\n\n" "# End Custom Build\n\n"; t << "USERDEP_" << base << "=\"$(QTDIR)\\bin\\moc.exe\"" << endl << endl; t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF " << endl << endl; } t << "# End Source File" << endl; } // endGroups(t); } else if(variable == "MSVCDSP_FORMSOURCES" || variable == "MSVCDSP_FORMHEADERS") { if(project->variables()["FORMS"].isEmpty()) continue; QString uiSourcesDir; QString uiHeadersDir; if(!project->variables()["UI_DIR"].isEmpty()) { uiSourcesDir = project->first("UI_DIR"); uiHeadersDir = project->first("UI_DIR"); } else { if ( !project->variables()["UI_SOURCES_DIR"].isEmpty() ) uiSourcesDir = project->first("UI_SOURCES_DIR"); else uiSourcesDir = ""; if ( !project->variables()["UI_HEADERS_DIR"].isEmpty() ) uiHeadersDir = project->first("UI_HEADERS_DIR"); else uiHeadersDir = ""; } QStringList list = project->variables()["FORMS"]; if(!project->isActiveConfig("flat")) list.sort(); QString ext = variable == "MSVCDSP_FORMSOURCES" ? ".cpp" : ".h"; for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { QString base = (*it); int dot = base.findRev("."); base.replace( dot, base.length() - dot, ext ); QString fname = base; int lbs = fname.findRev( "\\" ); QString fpath; if ( lbs != -1 ) fpath = fname.left( lbs + 1 ); fname = fname.right( fname.length() - lbs - 1 ); if ( ext == ".cpp" && !uiSourcesDir.isEmpty() ) fname.prepend(uiSourcesDir); else if ( ext == ".h" && !uiHeadersDir.isEmpty() ) fname.prepend(uiHeadersDir); else fname = base; // beginGroupForFile(fname, t); t << "# Begin Source File\n\nSOURCE=" << fname << "\n# End Source File" << endl; } // endGroups(t); } else if(variable == "MSVCDSP_TRANSLATIONS" ) { if(project->variables()["TRANSLATIONS"].isEmpty()) continue; t << "# Begin Group \"Translations\"\n"; t << "# Prop Default_Filter \"ts\"\n"; QStringList list = project->variables()["TRANSLATIONS"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { QString sify = *it; sify.replace('/', '\\' ); QString base = (*it); base.replace(QRegExp("\\..*$"), "").upper(); base.replace(QRegExp("[^a-zA-Z]"), "_"); // beginGroupForFile(sify, t); t << "# Begin Source File\n\nSOURCE=" << sify << endl; t << "\n# End Source File" << endl; } // endGroups(t); t << "\n# End Group\n"; } else if (variable == "MSVCDSP_MOCSOURCES" && project->isActiveConfig("moc")) { if ( project->variables()["SRCMOC"].isEmpty()) continue; QString mocpath = var( "QMAKE_MOC" ); mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; QStringList list = project->variables()["SRCMOC"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { // beginGroupForFile((*it), t); t << "# Begin Source File\n\nSOURCE=" << (*it) << endl; if ( project->isActiveConfig("moc") && (*it).endsWith(Option::moc_ext)) { QString base = (*it); base.replace(QRegExp("\\..*$"), "").upper(); base.replace(QRegExp("[^a-zA-Z]"), "_"); QString build = "\n\n# Begin Custom Build - Moc'ing " + findMocSource((*it)) + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + (*it) + "\"" " : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n" "\t" + mocpath + findMocSource((*it)) + " -o " + (*it) + "\n\n" "# End Custom Build\n\n"; t << "USERDEP_" << base << "=\".\\" << findMocSource((*it)) << "\" \"$(QTDIR)\\bin\\moc.exe\"" << endl << endl; t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF " << endl << endl; } t << "# End Source File" << endl; } // endGroups(t); } else if(variable == "MSVCDSP_PICTURES") { if(project->variables()["IMAGES"].isEmpty()) continue; t << "# Begin Group \"Images\"\n" << "# Prop Default_Filter \"png jpeg bmp xpm\"\n"; QStringList list = project->variables()["IMAGES"]; if(!project->isActiveConfig("flat")) list.sort(); QStringList::Iterator it; // dump the image list to a file UIC can read. QFile f( "images.tmp" ); f.open( IO_WriteOnly ); QTextStream ts( &f ); for( it = list.begin(); it != list.end(); ++it ) ts << " " << *it; f.close(); // create an output step for images not more than once bool imagesBuildDone = FALSE; for( it = list.begin(); it != list.end(); ++it ) { // beginGroupForFile((*it), t); t << "# Begin Source File\n\nSOURCE=" << (*it) << endl; QString base = (*it); QString uicpath = var("QMAKE_UIC"); uicpath = uicpath.replace(QRegExp("\\..*$"), "") + " "; if ( !imagesBuildDone ) { imagesBuildDone = TRUE; QString build = "\n\n# Begin Custom Build - Creating image collection...\n" "InputPath=.\\" + base + "\n\n"; build += "\"" + project->first("QMAKE_IMAGE_COLLECTION") + "\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n"; build += "\t" + uicpath + "-embed " + project->first("QMAKE_ORIG_TARGET") + " -f images.tmp -o " + project->first("QMAKE_IMAGE_COLLECTION") + "\n\n"; build.append("# End Custom Build\n\n"); t << "USERDEP_" << base << "="; QStringList::Iterator it2 = list.begin(); while ( it2 != list.end() ) { t << "\"" << (*it2) << "\""; it2++; if ( it2 != list.end() ) t << "\\\n"; } t << endl << endl; t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF \n\n" << endl; } t << "# End Source File" << endl; } // endGroups(t); t << "\n# End Group\n"; } else if(variable == "MSVCDSP_FORMS") { if(project->variables()["FORMS"].isEmpty()) continue; t << "# Begin Group \"Forms\"\n" << "# Prop Default_Filter \"ui\"\n"; QString uicpath = var("QMAKE_UIC"); uicpath = uicpath.replace(QRegExp("\\..*$"), "") + " "; QString mocpath = var( "QMAKE_MOC" ); mocpath = mocpath.replace( QRegExp( "\\..*$" ), "" ) + " "; QStringList list = project->variables()["FORMS"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { QString base = (*it); // beginGroupForFile(base, t); t << "# Begin Source File\n\nSOURCE=" << base << endl; QString fname = base; fname.replace(".ui", ""); int lbs = fname.findRev( "\\" ); QString fpath; if ( lbs != -1 ) fpath = fname.left( lbs + 1 ); fname = fname.right( fname.length() - lbs - 1 ); QString mocFile; if(!project->variables()["MOC_DIR"].isEmpty()) mocFile = project->first("MOC_DIR"); else mocFile = fpath; QString uiSourcesDir; QString uiHeadersDir; if(!project->variables()["UI_DIR"].isEmpty()) { uiSourcesDir = project->first("UI_DIR"); uiHeadersDir = project->first("UI_DIR"); } else { if ( !project->variables()["UI_SOURCES_DIR"].isEmpty() ) uiSourcesDir = project->first("UI_SOURCES_DIR"); else uiSourcesDir = fpath; if ( !project->variables()["UI_HEADERS_DIR"].isEmpty() ) uiHeadersDir = project->first("UI_HEADERS_DIR"); else uiHeadersDir = fpath; } t << "USERDEP_" << base << "=\"$(QTDIR)\\bin\\moc.exe\" \"$(QTDIR)\\bin\\uic.exe\"" << endl << endl; QString build = "\n\n# Begin Custom Build - Uic'ing " + base + "...\n" "InputPath=.\\" + base + "\n\n" "BuildCmds= \\\n\t" + uicpath + base + " -o " + uiHeadersDir + fname + ".h \\\n" "\t" + uicpath + base + " -i " + fname + ".h -o " + uiSourcesDir + fname + ".cpp \\\n" "\t" + mocpath + uiHeadersDir + fname + ".h -o " + mocFile + "moc_" + fname + ".cpp \\\n"; build.append("\n\"" + uiHeadersDir + fname + ".h\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" "\t$(BuildCmds)\n\n" "\"" + uiSourcesDir + fname + ".cpp\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" "\t$(BuildCmds)\n\n" "\"" + mocFile + "moc_" + fname + ".cpp\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" "\t$(BuildCmds)\n\n"); build.append("# End Custom Build\n\n"); t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF \n\n" << "# End Source File" << endl; } // endGroups(t); t << "\n# End Group\n"; } else if(variable == "MSVCDSP_LEXSOURCES") { if(project->variables()["LEXSOURCES"].isEmpty()) continue; t << "# Begin Group \"Lexables\"\n" << "# Prop Default_Filter \"l\"\n"; QString lexpath = var("QMAKE_LEX") + varGlue("QMAKE_LEXFLAGS", " ", " ", "") + " "; QStringList list = project->variables()["LEXSOURCES"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { QString fname = (*it); // beginGroupForFile(fname, t); t << "# Begin Source File\n\nSOURCE=" << fname << endl; fname.replace(".l", Option::lex_mod + Option::cpp_ext.first()); QString build = "\n\n# Begin Custom Build - Lex'ing " + (*it) + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + fname + "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" "\t" + lexpath + (*it) + "\\\n" "\tdel " + fname + "\\\n" "\tcopy lex.yy.c " + fname + "\n\n" + "# End Custom Build\n\n"; t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF \n\n" << build << "# End Source File" << endl; } // endGroups(t); t << "\n# End Group\n"; } else if(variable == "MSVCDSP_YACCSOURCES") { if(project->variables()["YACCSOURCES"].isEmpty()) continue; t << "# Begin Group \"Yaccables\"\n" << "# Prop Default_Filter \"y\"\n"; QString yaccpath = var("QMAKE_YACC") + varGlue("QMAKE_YACCFLAGS", " ", " ", "") + " "; QStringList list = project->variables()["YACCSOURCES"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { QString fname = (*it); // beginGroupForFile(fname, t); t << "# Begin Source File\n\nSOURCE=" << fname << endl; fname.replace(".y", Option::yacc_mod); QString build = "\n\n# Begin Custom Build - Yacc'ing " + (*it) + "...\n" "InputPath=.\\" + (*it) + "\n\n" "\"" + fname + Option::cpp_ext.first() + "\" : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"" "\n" "\t" + yaccpath + (*it) + "\\\n" "\tdel " + fname + Option::h_ext.first() + "\\\n" "\tmove y.tab.h " + fname + Option::h_ext.first() + "\n\n" + "\tdel " + fname + Option::cpp_ext.first() + "\\\n" "\tmove y.tab.c " + fname + Option::cpp_ext.first() + "\n\n" + "# End Custom Build\n\n"; t << "!IF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Release\"" << build << "!ELSEIF \"$(CFG)\" == \"" << var("MSVCDSP_PROJECT") << " - Win32 Debug\"" << build << "!ENDIF \n\n" << "# End Source File" << endl; } // endGroups(t); t << "\n# End Group\n"; } else if( variable == "MSVCDSP_CONFIGMODE" ) { if( project->isActiveConfig( "debug" ) ) t << "Debug"; else t << "Release"; } else if( variable == "MSVCDSP_IDLSOURCES" ) { QStringList list = project->variables()["MSVCDSP_IDLSOURCES"]; if(!project->isActiveConfig("flat")) list.sort(); for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) { t << "# Begin Source File" << endl << endl; t << "SOURCE=" << (*it) << endl; t << "# PROP Exclude_From_Build 1" << endl; t << "# End Source File" << endl << endl; } } else t << var(variable); } t << line << endl; } t << endl; file.close(); return TRUE; } void DspMakefileGenerator::init() { if(init_flag) return; QStringList::Iterator it; init_flag = TRUE; + const bool thread = project->isActiveConfig("thread"); + + if ( project->isActiveConfig("stl") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_OFF"]; + } + if ( project->isActiveConfig("exceptions") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_OFF"]; + } + if ( project->isActiveConfig("rtti") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_OFF"]; + } + /* this should probably not be here, but I'm using it to wrap the .t files */ if(project->first("TEMPLATE") == "vcapp" ) project->variables()["QMAKE_APP_FLAG"].append("1"); else if(project->first("TEMPLATE") == "vclib") project->variables()["QMAKE_LIB_FLAG"].append("1"); if ( project->variables()["QMAKESPEC"].isEmpty() ) project->variables()["QMAKESPEC"].append( getenv("QMAKESPEC") ); bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX); project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; QStringList &configs = project->variables()["CONFIG"]; if (project->isActiveConfig("shared")) project->variables()["DEFINES"].append("QT_DLL"); if (project->isActiveConfig("qt_dll")) if(configs.findIndex("qt") == -1) configs.append("qt"); if ( project->isActiveConfig("qt") ) { if ( project->isActiveConfig( "plugin" ) ) { project->variables()["CONFIG"].append("dll"); project->variables()["DEFINES"].append("QT_PLUGIN"); } if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { project->variables()["QMAKE_QT_DLL"].append("1"); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) project->variables()["CONFIG"].append("dll"); } } if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["CONFIG"].remove("staticlib"); project->variables()["QMAKE_APP_OR_DLL"].append("1"); } else { project->variables()["CONFIG"].append("staticlib"); } if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) { project->variables()["CONFIG"].append("windows"); } if ( !project->variables()["VERSION"].isEmpty() ) { QString version = project->variables()["VERSION"][0]; int firstDot = version.find( "." ); QString major = version.left( firstDot ); QString minor = version.right( version.length() - firstDot - 1 ); minor.replace( ".", "" ); project->variables()["MSVCDSP_VERSION"].append( "/VERSION:" + major + "." + minor ); } if ( project->isActiveConfig("qt") ) { project->variables()["CONFIG"].append("moc"); project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { project->variables()["DEFINES"].append("QT_MAKEDLL"); project->variables()["QMAKE_LFLAGS"].append("/base:\"0x39D00000\""); } } else { - if(project->isActiveConfig("thread")) + if( thread ) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); if ( hver == -1 ) hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); if(hver != -1) { QString ver; - ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); + ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (thread ? "-mt" : ""), hver); QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); } } if ( project->isActiveConfig( "activeqt" ) ) { project->variables().remove("QMAKE_LIBS_QT_ENTRY"); project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; if ( project->isActiveConfig( "dll" ) ) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; } if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; } } } if ( project->isActiveConfig("debug") ) { if ( !project->first("OBJECTS_DIR").isEmpty() ) project->variables()["MSVCDSP_OBJECTSDIRDEB"] = project->first("OBJECTS_DIR"); else project->variables()["MSVCDSP_OBJECTSDIRDEB"] = "Debug"; project->variables()["MSVCDSP_OBJECTSDIRREL"] = "Release"; if ( !project->first("DESTDIR").isEmpty() ) project->variables()["MSVCDSP_TARGETDIRDEB"] = project->first("DESTDIR"); else project->variables()["MSVCDSP_TARGETDIRDEB"] = "Debug"; project->variables()["MSVCDSP_TARGETDIRREL"] = "Release"; } else { if ( !project->first("OBJECTS_DIR").isEmpty() ) project->variables()["MSVCDSP_OBJECTSDIRREL"] = project->first("OBJECTS_DIR"); project->variables()["MSVCDSP_OBJECTSDIRDEB"] = "Debug"; if ( !project->first("DESTDIR").isEmpty() ) project->variables()["MSVCDSP_TARGETDIRREL"] = project->first("DESTDIR"); else project->variables()["MSVCDSP_TARGETDIRREL"] = "Release"; project->variables()["MSVCDSP_TARGETDIRDEB"] = "Debug"; } if ( project->isActiveConfig("opengl") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; } - if ( project->isActiveConfig("thread") ) { + if ( thread ) { if(project->isActiveConfig("qt")) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT" ); if ( project->isActiveConfig("dll") || project->first("TARGET") == "qtmain" || !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { project->variables()["MSVCDSP_MTDEFD"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; project->variables()["MSVCDSP_MTDEF"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; } else { // YES we want to use the DLL even in a static build project->variables()["MSVCDSP_MTDEFD"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; project->variables()["MSVCDSP_MTDEF"] += project->variables()["QMAKE_CXXFLAGS_MT"]; } if ( !project->variables()["DEFINES"].contains("QT_DLL") && is_qt && project->first("TARGET") != "qtmain" ) project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:\"libc\""); } if(project->isActiveConfig("qt")) { if ( project->isActiveConfig("accessibility" ) ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); if ( project->isActiveConfig("tablet") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); } if ( project->isActiveConfig("dll") ) { if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { QString ver_xyz(project->first("VERSION")); ver_xyz.replace(".", ""); project->variables()["TARGET_EXT"].append(ver_xyz + ".dll"); } else { project->variables()["TARGET_EXT"].append(".dll"); } } else { if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) project->variables()["TARGET_EXT"].append(".exe"); else project->variables()["TARGET_EXT"].append(".lib"); } project->variables()["MSVCDSP_VER"] = "6.00"; project->variables()["MSVCDSP_DEBUG_OPT"] = "/GZ /ZI"; if(!project->isActiveConfig("incremental")) { project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); if ( is_qt ) project->variables()["MSVCDSP_DEBUG_OPT"] = "/GZ /Zi"; } QString msvcdsp_project; if ( project->variables()["TARGET"].count() ) msvcdsp_project = project->variables()["TARGET"].first(); QString targetfilename = project->variables()["TARGET"].first(); project->variables()["TARGET"].first() += project->first("TARGET_EXT"); if ( project->isActiveConfig("moc") ) setMocAware(TRUE); project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); QStringList &l = project->variables()["QMAKE_FILETAGS"]; for(it = l.begin(); it != l.end(); ++it) { QStringList &gdmf = project->variables()[(*it)]; for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) (*inner) = Option::fixPathToTargetOS((*inner), FALSE); } MakefileGenerator::init(); if ( msvcdsp_project.isEmpty() ) msvcdsp_project = Option::output.name(); msvcdsp_project = msvcdsp_project.right( msvcdsp_project.length() - msvcdsp_project.findRev( "\\" ) - 1 ); msvcdsp_project = msvcdsp_project.left( msvcdsp_project.findRev( "." ) ); msvcdsp_project.replace("-", ""); project->variables()["MSVCDSP_PROJECT"].append(msvcdsp_project); QStringList &proj = project->variables()["MSVCDSP_PROJECT"]; for(it = proj.begin(); it != proj.end(); ++it) (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["MSVCDSP_TEMPLATE"].append("win32app" + project->first( "DSP_EXTENSION" ) ); if ( project->isActiveConfig("console") ) { project->variables()["MSVCDSP_CONSOLE"].append("Console"); project->variables()["MSVCDSP_WINCONDEF"].append("_CONSOLE"); project->variables()["MSVCDSP_DSPTYPE"].append("0x0103"); project->variables()["MSVCDSP_SUBSYSTEM"].append("console"); } else { project->variables()["MSVCDSP_CONSOLE"].clear(); project->variables()["MSVCDSP_WINCONDEF"].append("_WINDOWS"); project->variables()["MSVCDSP_DSPTYPE"].append("0x0101"); project->variables()["MSVCDSP_SUBSYSTEM"].append("windows"); } } else { if ( project->isActiveConfig("dll") ) { project->variables()["MSVCDSP_TEMPLATE"].append("win32dll" + project->first( "DSP_EXTENSION" ) ); } else { project->variables()["MSVCDSP_TEMPLATE"].append("win32lib" + project->first( "DSP_EXTENSION" ) ); } } project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; project->variables()["MSVCDSP_LFLAGS" ] += project->variables()["QMAKE_LFLAGS"]; if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) project->variables()["MSVCDSP_LFLAGS" ].append(varGlue("QMAKE_LIBDIR","/LIBPATH:\"","\" /LIBPATH:\"","\"")); project->variables()["MSVCDSP_CXXFLAGS" ] += project->variables()["QMAKE_CXXFLAGS"]; project->variables()["MSVCDSP_DEFINES"].append(varGlue("DEFINES","/D ","" " /D ","")); project->variables()["MSVCDSP_DEFINES"].append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ","")); + processPrlFiles(); QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) { QString lib = (*libit); lib.replace(QRegExp("\""), ""); project->variables()["MSVCDSP_LIBS"].append(" \"" + lib + "\""); } QStringList &incs = project->variables()["INCLUDEPATH"]; for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit); inc.replace("\"", ""); project->variables()["MSVCDSP_INCPATH"].append("/I \"" + inc + "\""); } project->variables()["MSVCDSP_INCPATH"].append("/I \"" + specdir() + "\""); if ( project->isActiveConfig("qt") ) { project->variables()["MSVCDSP_RELDEFS"].append("/D \"QT_NO_DEBUG\""); } else { project->variables()["MSVCDSP_RELDEFS"].clear(); } QString dest; + QString postLinkStep; + QString copyDllStep; + QString activeQtStepPreCopyDll; + QString activeQtStepPostCopyDll; + QString activeQtStepPreCopyDllDebug; + QString activeQtStepPostCopyDllDebug; + QString activeQtStepPreCopyDllRelease; + QString activeQtStepPostCopyDllRelease; + + if ( !project->variables()["QMAKE_POST_LINK"].isEmpty() ) + postLinkStep += var("QMAKE_POST_LINK"); + if ( !project->variables()["DESTDIR"].isEmpty() ) { project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); Option::fixPathToTargetOS(project->first("TARGET")); dest = project->first("TARGET"); if ( project->first("TARGET").startsWith("$(QTDIR)") ) dest.replace( "$(QTDIR)", getenv("QTDIR") ); project->variables()["MSVCDSP_TARGET"].append( QString("/out:\"") + dest + "\""); if ( project->isActiveConfig("dll") ) { QString imp = dest; imp.replace(".dll", ".lib"); project->variables()["MSVCDSP_TARGET"].append(QString(" /implib:\"") + imp + "\""); } } if ( project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty() ) { QStringList dlldirs = project->variables()["DLLDESTDIR"]; - QString copydll = "# Begin Special Build Tool\n" - "TargetPath=" + dest + "\n" - "SOURCE=$(InputPath)\n" - "PostBuild_Desc=Copy DLL to " + project->first("DLLDESTDIR") + "\n" - "PostBuild_Cmds="; - + if ( dlldirs.count() ) + copyDllStep += "\t"; for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { - copydll += "copy \"" + dest + "\" \"" + *dlldir + "\"\t"; + copyDllStep += "copy \"$(TargetPath)\" \"" + *dlldir + "\"\t"; } - - copydll += "\n# End Special Build Tool"; - project->variables()["MSVCDSP_COPY_DLL_REL"].append( copydll ); - project->variables()["MSVCDSP_COPY_DLL_DBG"].append( copydll ); } + if ( project->isActiveConfig("activeqt") ) { QString idl = project->variables()["QMAKE_IDL"].first(); QString idc = project->variables()["QMAKE_IDC"].first(); QString version = project->variables()["VERSION"].first(); if ( version.isEmpty() ) version = "1.0"; project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".idl" ); project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".tlb" ); project->variables()["MSVCDSP_IDLSOURCES"].append( "tmp\\" + targetfilename + ".midl" ); if ( project->isActiveConfig( "dll" ) ) { - QString regcmd = "# Begin Special Build Tool\n" - "TargetPath=" + targetfilename + "\n" - "SOURCE=$(InputPath)\n" - "PostBuild_Desc=Finalizing ActiveQt server...\n" - "PostBuild_Cmds=" + - idc + " %1 -idl tmp\\" + targetfilename + ".idl -version " + version + + activeQtStepPreCopyDll += + "\t" + idc + " %1 -idl tmp\\" + targetfilename + ".idl -version " + version + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" - "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" - "\t" + idc + " %1 /regserver\n" - "# End Special Build Tool"; + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb"; + activeQtStepPostCopyDll += + "\t" + idc + " %1 /regserver\n"; - QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); - project->variables()["MSVCDSP_COPY_DLL_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + targetfilename + ".dll"; + activeQtStepPreCopyDllRelease = activeQtStepPreCopyDll.arg(executable).arg(executable); + activeQtStepPostCopyDllRelease = activeQtStepPostCopyDll.arg(executable); - executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); - project->variables()["MSVCDSP_COPY_DLL_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + targetfilename + ".dll"; + activeQtStepPreCopyDllDebug = activeQtStepPreCopyDll.arg(executable).arg(executable); + activeQtStepPostCopyDllDebug = activeQtStepPostCopyDll.arg(executable); } else { - QString regcmd = "# Begin Special Build Tool\n" - "TargetPath=" + targetfilename + "\n" - "SOURCE=$(InputPath)\n" - "PostBuild_Desc=Finalizing ActiveQt server...\n" - "PostBuild_Cmds=" - "%1 -dumpidl tmp\\" + targetfilename + ".idl -version " + version + + activeQtStepPreCopyDll += + "\t%1 -dumpidl tmp\\" + targetfilename + ".idl -version " + version + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" - "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" - "\t%1 -regserver\n" - "# End Special Build Tool"; + "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb"; + activeQtStepPostCopyDll += + "\t%1 -regserver\n"; + QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + targetfilename + ".exe"; + activeQtStepPreCopyDllRelease = activeQtStepPreCopyDll.arg(executable).arg(executable); + activeQtStepPostCopyDllRelease = activeQtStepPostCopyDll.arg(executable); - QString executable = project->variables()["MSVCDSP_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); - project->variables()["MSVCDSP_REGSVR_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); + executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + targetfilename + ".exe"; + activeQtStepPreCopyDllDebug = activeQtStepPreCopyDll.arg(executable).arg(executable); + activeQtStepPostCopyDllDebug = activeQtStepPostCopyDll.arg(executable); + } - executable = project->variables()["MSVCDSP_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); - project->variables()["MSVCDSP_REGSVR_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); } + + if ( !postLinkStep.isEmpty() || !copyDllStep.isEmpty() || !activeQtStepPreCopyDllDebug.isEmpty() || !activeQtStepPreCopyDllRelease.isEmpty() ) { + project->variables()["MSVCDSP_POST_LINK_DBG"].append( + "# Begin Special Build Tool\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Post Build Step\n" + "PostBuild_Cmds=" + postLinkStep + activeQtStepPreCopyDllDebug + copyDllStep + activeQtStepPostCopyDllDebug + "\n" + "# End Special Build Tool\n" ); + project->variables()["MSVCDSP_POST_LINK_REL"].append( + "# Begin Special Build Tool\n" + "SOURCE=$(InputPath)\n" + "PostBuild_Desc=Post Build Step\n" + "PostBuild_Cmds=" + postLinkStep + activeQtStepPreCopyDllRelease + copyDllStep + activeQtStepPostCopyDllRelease + "\n" + "# End Special Build Tool\n" ); } + if ( !project->variables()["SOURCES"].isEmpty() || !project->variables()["RC_FILE"].isEmpty() ) { project->variables()["SOURCES"] += project->variables()["RC_FILE"]; } QStringList &list = project->variables()["FORMS"]; for( it = list.begin(); it != list.end(); ++it ) { if ( QFile::exists( *it + ".h" ) ) project->variables()["SOURCES"].append( *it + ".h" ); } project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "MSVCDSP_LIBS"; } QString -DspMakefileGenerator::findTemplate(QString file) +DspMakefileGenerator::findTemplate(const QString &file) { QString ret; if(!QFile::exists((ret = file)) && !QFile::exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) && !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/win32-msvc/" + file)) && !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) return ""; return ret; } void DspMakefileGenerator::processPrlVariable(const QString &var, const QStringList &l) { if(var == "QMAKE_PRL_DEFINES") { QStringList &out = project->variables()["MSVCDSP_DEFINES"]; for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if(out.findIndex((*it)) == -1) out.append((" /D \"" + *it + "\"")); } } else { MakefileGenerator::processPrlVariable(var, l); } } -int +void DspMakefileGenerator::beginGroupForFile(QString file, QTextStream &t, - QString filter) + const QString& filter) { if(project->isActiveConfig("flat")) - return 0; + return; fileFixify(file, QDir::currentDirPath(), QDir::currentDirPath(), TRUE); file = file.section(Option::dir_sep, 0, -2); if(file.right(Option::dir_sep.length()) != Option::dir_sep) file += Option::dir_sep; if(file == currentGroup) - return 0; + return; if(file.isEmpty() || !QDir::isRelativePath(file)) { endGroups(t); - return 0; + return; } if(file.startsWith(currentGroup)) file = file.mid(currentGroup.length()); - else - endGroups(t); - int lvl = file.contains(Option::dir_sep), old_lvl = currentGroup.contains(Option::dir_sep); - if(lvl > old_lvl) { - QStringList dirs = QStringList::split(Option::dir_sep, file); + int dirSep = currentGroup.findRev( Option::dir_sep ); + while( !file.startsWith( currentGroup ) && dirSep != -1 ) { + currentGroup.truncate( dirSep ); + dirSep = currentGroup.findRev( Option::dir_sep ); + if ( !file.startsWith( currentGroup ) && dirSep != -1 ) + t << "\n# End Group\n"; + } + if ( !file.startsWith( currentGroup ) ) { + t << "\n# End Group\n"; + currentGroup = ""; + } + QStringList dirs = QStringList::split(Option::dir_sep, file.right( file.length() - currentGroup.length() ) ); for(QStringList::Iterator dir_it = dirs.begin(); dir_it != dirs.end(); ++dir_it) { t << "# Begin Group \"" << (*dir_it) << "\"\n" << "# Prop Default_Filter \"" << filter << "\"\n"; } - } else { - for(int x = old_lvl - lvl; x; x--) - t << "\n# End Group\n"; - } currentGroup = file; - return lvl - old_lvl; } -int +void DspMakefileGenerator::endGroups(QTextStream &t) { if(project->isActiveConfig("flat")) - return 0; + return; else if(currentGroup.isEmpty()) - return 0; + return; QStringList dirs = QStringList::split(Option::dir_sep, currentGroup); for(QStringList::Iterator dir_it = dirs.end(); dir_it != dirs.begin(); --dir_it) { t << "\n# End Group\n"; } currentGroup = ""; - return dirs.count(); } bool DspMakefileGenerator::openOutput(QFile &file) const { QString outdir; if(!file.name().isEmpty()) { QFileInfo fi(file); if(fi.isDir()) outdir = file.name() + QDir::separator(); } if(!outdir.isEmpty() || file.name().isEmpty()) file.setName(outdir + project->first("TARGET") + project->first("DSP_EXTENSION")); if(QDir::isRelativePath(file.name())) { QString ofile; ofile = file.name(); int slashfind = ofile.findRev('\\'); if (slashfind == -1) { ofile = ofile.replace(QRegExp("-"), "_"); } else { int hypenfind = ofile.find('-', slashfind); while (hypenfind != -1 && slashfind < hypenfind) { ofile = ofile.replace(hypenfind, 1, "_"); hypenfind = ofile.find('-', hypenfind + 1); } } file.setName(Option::fixPathToLocalOS(QDir::currentDirPath() + Option::dir_sep + ofile)); } return Win32MakefileGenerator::openOutput(file); } diff --git a/qmake/generators/win32/msvc_dsp.h b/qmake/generators/win32/msvc_dsp.h index a7fc3e7..3a7d18e 100644 --- a/qmake/generators/win32/msvc_dsp.h +++ b/qmake/generators/win32/msvc_dsp.h @@ -1,73 +1,73 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef __DSPMAKE_H__ -#define __DSPMAKE_H__ +#ifndef __MSVC_DSP_H__ +#define __MSVC_DSP_H__ #include "winmakefile.h" #include <qvaluestack.h> class DspMakefileGenerator : public Win32MakefileGenerator { QString currentGroup; - int beginGroupForFile(QString file, QTextStream &, const QString filter=""); - int endGroups(QTextStream &); + void beginGroupForFile(QString file, QTextStream &, const QString& filter=""); + void endGroups(QTextStream &); bool init_flag; bool writeDspParts(QTextStream &); bool writeMakefile(QTextStream &); - QString findTemplate(QString file); + QString findTemplate(const QString &file); void init(); public: DspMakefileGenerator(QMakeProject *p); ~DspMakefileGenerator(); bool openOutput(QFile &file) const; protected: virtual void processPrlVariable(const QString &, const QStringList &); virtual bool findLibraries(); }; inline DspMakefileGenerator::~DspMakefileGenerator() { } inline bool DspMakefileGenerator::findLibraries() { return Win32MakefileGenerator::findLibraries("MSVCDSP_LIBS"); } -#endif /* __DSPMAKE_H__ */ +#endif /* __MSVC_DSP_H__ */ diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 9cc9a69..ecef34d 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -1,488 +1,562 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "msvc_nmake.h" #include "option.h" #include <qregexp.h> +#include <qdict.h> #include <qdir.h> #include <stdlib.h> #include <time.h> NmakeMakefileGenerator::NmakeMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) { } bool NmakeMakefileGenerator::writeMakefile(QTextStream &t) { writeHeader(t); if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { t << "all clean:" << "\n\t" << "@echo \"Some of the required modules (" << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t" << "@echo \"Skipped.\"" << endl << endl; writeMakeQmake(t); return TRUE; } if(project->first("TEMPLATE") == "app" || project->first("TEMPLATE") == "lib") { writeNmakeParts(t); return MakefileGenerator::writeMakefile(t); } else if(project->first("TEMPLATE") == "subdirs") { writeSubDirs(t); return TRUE; } return FALSE; } void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t) { t << "####### Compiler, tools and options" << endl << endl; t << "CC = " << var("QMAKE_CC") << endl; t << "CXX = " << var("QMAKE_CXX") << endl; t << "LEX = " << var("QMAKE_LEX") << endl; t << "YACC = " << var("QMAKE_YACC") << endl; t << "CFLAGS = " << var("QMAKE_CFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " " << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " " << varGlue("DEFINES","-D"," -D","") << endl; t << "LEXFLAGS =" << var("QMAKE_LEXFLAGS") << endl; t << "YACCFLAGS =" << var("QMAKE_YACCFLAGS") << endl; t << "INCPATH = "; QStringList &incs = project->variables()["INCLUDEPATH"]; for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit); inc.replace(QRegExp("\\\\$"), "\\\\"); inc.replace("\"", ""); t << " -I\"" << inc << "\""; } t << " -I\"" << specdir() << "\"" << endl; if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { t << "LINK = " << var("QMAKE_LINK") << endl; t << "LFLAGS = " << var("QMAKE_LFLAGS"); if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) t << " " << varGlue("QMAKE_LIBDIR","/LIBPATH:\"","\" /LIBPATH:\"","\""); t << endl; t << "LIBS = "; QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) { QString lib = (*libit); lib.replace(QRegExp("\\\\$"), "\\\\"); lib.replace(QRegExp("\""), ""); t << " \"" << lib << "\""; } t << endl; } else { t << "LIB = " << var("QMAKE_LIB") << endl; } t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") : Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl; t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") : Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl; t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl; t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl; t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl; t << "ZIP = " << var("QMAKE_ZIP") << endl; t << "COPY_FILE = " << var("QMAKE_COPY") << endl; t << "COPY_DIR = " << var("QMAKE_COPY") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << endl; t << endl; t << "####### Files" << endl << endl; t << "HEADERS = " << varList("HEADERS") << endl; t << "SOURCES = " << varList("SOURCES") << endl; t << "OBJECTS = " << varList("OBJECTS") << endl; t << "FORMS = " << varList("FORMS") << endl; t << "UICDECLS = " << varList("UICDECLS") << endl; t << "UICIMPLS = " << varList("UICIMPLS") << endl; t << "SRCMOC = " << varList("SRCMOC") << endl; t << "OBJMOC = " << varList("OBJMOC") << endl; t << "DIST = " << varList("DISTFILES") << endl; t << "TARGET = "; if( !project->variables()[ "DESTDIR" ].isEmpty() ) t << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT")); else t << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first(); t << endl; t << endl; t << "####### Implicit rules" << endl << endl; - t << ".SUFFIXES: .cpp .cxx .cc .c" << endl << endl; - t << ".cpp.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".cxx.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".cc.obj:\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; - t << ".c.obj:\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + t << ".SUFFIXES: .c"; + QStringList::Iterator cppit; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << " " << (*cppit); + t << endl << endl; + if(!project->isActiveConfig("no_batch")) { + // Batchmode doesn't use the non implicit rules QMAKE_RUN_CXX & QMAKE_RUN_CC + project->variables().remove("QMAKE_RUN_CXX"); + project->variables().remove("QMAKE_RUN_CC"); + + QDict<void> source_directories; + source_directories.insert(".", (void*)1); + if(!project->isEmpty("MOC_DIR")) + source_directories.insert(project->first("MOC_DIR"), (void*)1); + if(!project->isEmpty("UI_SOURCES_DIR")) + source_directories.insert(project->first("UI_SOURCES_DIR"), (void*)1); + else if(!project->isEmpty("UI_DIR")) + source_directories.insert(project->first("UI_DIR"), (void*)1); + QString srcs[] = { QString("SOURCES"), QString("UICIMPLS"), QString("SRCMOC"), QString::null }; + for(int x = 0; !srcs[x].isNull(); x++) { + QStringList &l = project->variables()[srcs[x]]; + for(QStringList::Iterator sit = l.begin(); sit != l.end(); ++sit) { + QString sep = "\\"; + if((*sit).find(sep) == -1) + sep = "/"; + QString dir = (*sit).section(sep, 0, -2); + if(!dir.isEmpty() && !source_directories[dir]) + source_directories.insert(dir, (void*)1); + } + } + + for(QDictIterator<void> it(source_directories); it.current(); ++it) { + if(it.currentKey().isEmpty()) + continue; + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << "{" << it.currentKey() << "}" << (*cppit) << "{" << var("OBJECTS_DIR") << "}" << Option::obj_ext << "::\n\t" + << var("QMAKE_RUN_CXX_IMP_BATCH").replace( QRegExp( "\\$@" ), var("OBJECTS_DIR") ) << endl << "\t$<" << endl << "<<" << endl << endl; + t << "{" << it.currentKey() << "}" << ".c{" << var("OBJECTS_DIR") << "}" << Option::obj_ext << "::\n\t" + << var("QMAKE_RUN_CC_IMP_BATCH").replace( QRegExp( "\\$@" ), var("OBJECTS_DIR") ) << endl << "\t$<" << endl << "<<" << endl << endl; + } + } else { + for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) + t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << ".c" << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + } t << "####### Build rules" << endl << endl; t << "all: " << varGlue("ALL_DEPS",""," "," ") << "$(TARGET)" << endl << endl; - t << "$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC) " << var("TARGETDEPS"); + t << "$(TARGET): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC) " + << var("POST_TARGETDEPS"); if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) { t << "\n\t" << "$(LINK) $(LFLAGS) /OUT:$(TARGET) @<< " << "\n\t " << "$(OBJECTS) $(OBJMOC) $(LIBS)"; } else { t << "\n\t" << "$(LIB) /OUT:$(TARGET) @<<" << "\n\t " << "$(OBJECTS) $(OBJMOC)"; } t << endl << "<<" << endl; + if ( !project->variables()["QMAKE_POST_LINK"].isEmpty() ) + t << "\t" << var( "QMAKE_POST_LINK" ) << endl; if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) { QStringList dlldirs = project->variables()["DLLDESTDIR"]; for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { t << "\n\t" << "-copy $(TARGET) " << *dlldir; } } QString targetfilename = project->variables()["TARGET"].first(); if(project->isActiveConfig("activeqt")) { QString version = project->variables()["VERSION"].first(); if ( version.isEmpty() ) version = "1.0"; if ( project->isActiveConfig("dll")) { t << "\n\t" << ("-$(IDC) $(TARGET) /idl tmp\\" + targetfilename + ".idl -version " + version); t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" ); } else { t << "\n\t" << ("-$(TARGET) -dumpidl tmp\\" + targetfilename + ".idl -version " + version); t << "\n\t" << ("-$(IDL) tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl"); t << "\n\t" << ("-$(IDC) $(TARGET) /tlb tmp\\" + targetfilename + ".tlb"); t << "\n\t" << "-$(TARGET) -regserver"; } } t << endl << endl; if(!project->variables()["RC_FILE"].isEmpty()) { t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t" << var("QMAKE_RC") << " " << var("RC_FILE") << endl << endl; } t << "mocables: $(SRCMOC)" << endl << endl; writeMakeQmake(t); t << "dist:" << "\n\t" << "$(ZIP) " << var("PROJECT") << ".zip " << var("PROJECT") << ".pro $(SOURCES) $(HEADERS) $(DIST) $(FORMS)" << endl << endl; t << "clean:" << varGlue("OBJECTS","\n\t-del ","\n\t-del ","") << varGlue("SRCMOC" ,"\n\t-del ","\n\t-del ","") << varGlue("OBJMOC" ,"\n\t-del ","\n\t-del ","") << varGlue("UICDECLS" ,"\n\t-del ","\n\t-del ","") << varGlue("UICIMPLS" ,"\n\t-del ","\n\t-del ","") << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ","") << varGlue("CLEAN_FILES","\n\t-del ","\n\t-del ",""); + if ( project->isActiveConfig("activeqt")) { t << ("\n\t-del tmp\\" + targetfilename + ".*"); t << "\n\t-del tmp\\dump.*"; } if(!project->isEmpty("IMAGES")) t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-del ", "\n\t-del ", ""); // blasted user defined targets QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"]; for(QStringList::Iterator it = qut.begin(); it != qut.end(); ++it) { QString targ = var((*it) + ".target"), cmd = var((*it) + ".commands"), deps; if(targ.isEmpty()) targ = (*it); QStringList &deplist = project->variables()[(*it) + ".depends"]; for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { QString dep = var((*dep_it) + ".target"); if(dep.isEmpty()) dep = (*dep_it); deps += " " + dep; } t << "\n\n" << targ << ":" << deps << "\n\t" << cmd; } t << endl << endl; + + t << "distclean: clean" + << "\n\t-del $(TARGET)" + << endl << endl; } void NmakeMakefileGenerator::init() { if(init_flag) return; init_flag = TRUE; /* this should probably not be here, but I'm using it to wrap the .t files */ if(project->first("TEMPLATE") == "app") project->variables()["QMAKE_APP_FLAG"].append("1"); else if(project->first("TEMPLATE") == "lib") project->variables()["QMAKE_LIB_FLAG"].append("1"); else if(project->first("TEMPLATE") == "subdirs") { MakefileGenerator::init(); if(project->variables()["MAKEFILE"].isEmpty()) project->variables()["MAKEFILE"].append("Makefile"); if(project->variables()["QMAKE"].isEmpty()) project->variables()["QMAKE"].append("qmake"); return; } bool is_qt = (project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX); project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; QString targetfilename = project->variables()["TARGET"].first(); QStringList &configs = project->variables()["CONFIG"]; if (project->isActiveConfig("qt") && project->isActiveConfig("shared")) project->variables()["DEFINES"].append("QT_DLL"); if (project->isActiveConfig("qt_dll")) if(configs.findIndex("qt") == -1) configs.append("qt"); if ( project->isActiveConfig("qt") ) { if ( project->isActiveConfig( "plugin" ) ) { project->variables()["CONFIG"].append("dll"); if(project->isActiveConfig("qt")) project->variables()["DEFINES"].append("QT_PLUGIN"); } if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) && ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 || project->variables()["DEFINES"].findIndex("QT_DLL") != -1) || (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) { project->variables()["QMAKE_QT_DLL"].append("1"); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) project->variables()["CONFIG"].append("dll"); } if ( project->isActiveConfig("thread") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT"); if ( project->isActiveConfig("accessibility" ) ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); if ( project->isActiveConfig("tablet") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); } if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["CONFIG"].remove("staticlib"); project->variables()["QMAKE_APP_OR_DLL"].append("1"); } else { project->variables()["CONFIG"].append("staticlib"); } if ( project->isActiveConfig("warn_off") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"]; } else if ( project->isActiveConfig("warn_on") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"]; } if ( project->isActiveConfig("debug") ) { if ( project->isActiveConfig("thread") ) { // use the DLL RT even here if ( project->variables()["DEFINES"].contains("QT_DLL") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"]; } } project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"]; } else { if ( project->isActiveConfig("thread") ) { if ( project->variables()["DEFINES"].contains("QT_DLL") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"]; } } project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"]; } if ( project->isActiveConfig("thread") && !project->variables()["DEFINES"].contains("QT_DLL") && !is_qt && project->first("TARGET") != "qtmain") { project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:\"libc\""); } if ( !project->variables()["QMAKE_INCDIR"].isEmpty()) project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"]; if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") ) project->variables()["CONFIG"].append("windows"); if ( project->isActiveConfig("qt") ) { project->variables()["CONFIG"].append("moc"); project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; if ( !project->isActiveConfig("debug") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG"); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) { project->variables()["DEFINES"].append("QT_MAKEDLL"); project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"]; } } else { if(project->isActiveConfig("thread")) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); if ( hver == -1 ) hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt"); if(hver != -1) { QString ver; ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); } } if ( project->isActiveConfig( "activeqt" ) ) { project->variables().remove("QMAKE_LIBS_QT_ENTRY"); project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; if ( project->isActiveConfig( "dll" ) ) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; } if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; } } } if ( project->isActiveConfig("opengl") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; } if ( project->isActiveConfig("dll") ) { project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"]; project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"]; if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) { project->variables()["TARGET_EXT"].append( QStringList::split('.',project->first("VERSION")).join("") + ".dll"); } else { project->variables()["TARGET_EXT"].append(".dll"); } } else { project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"]; project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"]; project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"]; project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"]; if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) { project->variables()["TARGET_EXT"].append(".exe"); } else { project->variables()["TARGET_EXT"].append(".lib"); } } if ( project->isActiveConfig("windows") ) { if ( project->isActiveConfig("console") ) { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; } else { project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"]; } project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; } else { project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"]; project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"]; } + if ( project->isActiveConfig("stl") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_OFF"]; + } + if ( project->isActiveConfig("exceptions") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_OFF"]; + } + if ( project->isActiveConfig("rtti") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_OFF"]; + } + if ( project->isActiveConfig("moc") ) setMocAware(TRUE); project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); QStringList &l = project->variables()["QMAKE_FILETAGS"]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QStringList &gdmf = project->variables()[(*it)]; for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) (*inner) = Option::fixPathToTargetOS((*inner), FALSE); } if ( !project->variables()["DEF_FILE"].isEmpty() ) project->variables()["QMAKE_LFLAGS"].append(QString("/DEF:") + project->first("DEF_FILE")); if(!project->isActiveConfig("incremental")) project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); if ( !project->variables()["VERSION"].isEmpty() ) { QString version = project->variables()["VERSION"][0]; int firstDot = version.find( "." ); QString major = version.left( firstDot ); QString minor = version.right( version.length() - firstDot - 1 ); minor.replace( ".", "" ); project->variables()["QMAKE_LFLAGS"].append( "/VERSION:" + major + "." + minor ); } if ( !project->variables()["RC_FILE"].isEmpty()) { if ( !project->variables()["RES_FILE"].isEmpty()) { fprintf(stderr, "Both .rc and .res file specified.\n"); fprintf(stderr, "Please specify one of them, not both."); exit(666); } project->variables()["RES_FILE"] = project->variables()["RC_FILE"]; project->variables()["RES_FILE"].first().replace(".rc",".res"); - project->variables()["TARGETDEPS"] += project->variables()["RES_FILE"]; + project->variables()["POST_TARGETDEPS"] += project->variables()["RES_FILE"]; } if ( !project->variables()["RES_FILE"].isEmpty()) project->variables()["QMAKE_LIBS"] += project->variables()["RES_FILE"]; MakefileGenerator::init(); if ( !project->variables()["VERSION"].isEmpty()) { QStringList l = QStringList::split('.', project->first("VERSION")); project->variables()["VER_MAJ"].append(l[0]); project->variables()["VER_MIN"].append(l[1]); } + + QString version = QStringList::split('.', project->first("VERSION")).join(""); if(project->isActiveConfig("dll")) { - project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".lib"); - project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".exp"); + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".exp"); } if(project->isActiveConfig("debug")) { - project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".pdb"); - project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + ".ilk"); + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".pdb"); + project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".ilk"); project->variables()["QMAKE_CLEAN"].append("vc*.pdb"); } } diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h index d3e170f..579fc35 100644 --- a/qmake/generators/win32/msvc_nmake.h +++ b/qmake/generators/win32/msvc_nmake.h @@ -1,59 +1,59 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef __NMAKEMAKE_H__ -#define __NMAKEMAKE_H__ +#ifndef __MSVC_NMAKE_H__ +#define __MSVC_NMAKE_H__ #include "winmakefile.h" class NmakeMakefileGenerator : public Win32MakefileGenerator { bool init_flag; void writeNmakeParts(QTextStream &); bool writeMakefile(QTextStream &); void init(); public: NmakeMakefileGenerator(QMakeProject *p); ~NmakeMakefileGenerator(); }; inline NmakeMakefileGenerator::~NmakeMakefileGenerator() { } -#endif /* __NMAKEMAKE_H__ */ +#endif /* __MSVC_NMAKE_H__ */ diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index c2b9e30..7ffe4f7 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2,1954 +2,1991 @@ ** $Id$ ** ** Definition of ________ class. ** ** Copyright (C) 2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "msvc_objectmodel.h" #include "msvc_vcproj.h" #include <qtextstream.h> #include <qstringlist.h> #include <quuid.h> #if defined(Q_OS_WIN32) #include <objbase.h> #ifndef GUID_DEFINED #define GUID_DEFINED typedef struct _GUID { ulong Data1; ushort Data2; ushort Data3; uchar Data4[8]; } GUID; #endif #endif // XML Tags --------------------------------------------------------- const char* _xmlInit = "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>"; const char* _begConfiguration = "\n\t\t<Configuration"; const char* _begConfigurations = "\n\t<Configurations>"; const char* _begFile = "\n\t\t\t<File"; const char* _begFileConfiguration = "\n\t\t\t\t<FileConfiguration"; const char* _begFiles = "\n\t<Files>"; const char* _begFilter = "\n\t\t<Filter"; const char* _begGlobals = "\n\t<Globals>"; const char* _begPlatform = "\n\t\t<Platform"; const char* _begPlatforms = "\n\t<Platforms>"; const char* _begTool3 = "\n\t\t\t<Tool"; const char* _begTool5 = "\n\t\t\t\t\t<Tool"; const char* _begVisualStudioProject = "\n<VisualStudioProject"; const char* _endConfiguration = "\n\t\t</Configuration>"; const char* _endConfigurations = "\n\t</Configurations>"; const char* _endFile = "\n\t\t\t</File>"; const char* _endFileConfiguration = "\n\t\t\t\t</FileConfiguration>"; const char* _endFiles = "\n\t</Files>"; const char* _endFilter = "\n\t\t</Filter>"; const char* _endGlobals = "\n\t</Globals>"; const char* _endPlatforms = "\n\t</Platforms>"; const char* _endVisualStudioProject = "\n</VisualStudioProject>"; // XML Properties --------------------------------------------------- const char* _AddModuleNamesToAssembly = "\n\t\t\t\tAddModuleNamesToAssembly=\""; const char* _AdditionalDependencies4 = "\n\t\t\t\tAdditionalDependencies=\""; const char* _AdditionalDependencies6 = "\n\t\t\t\t\t\tAdditionalDependencies=\""; const char* _AdditionalIncludeDirectories = "\n\t\t\t\tAdditionalIncludeDirectories=\""; const char* _AdditionalLibraryDirectories = "\n\t\t\t\tAdditionalLibraryDirectories=\""; const char* _AdditionalOptions = "\n\t\t\t\tAdditionalOptions=\""; const char* _AdditionalUsingDirectories = "\n\t\t\t\tAdditionalUsingDirectories=\""; const char* _AssemblerListingLocation = "\n\t\t\t\tAssemblerListingLocation=\""; const char* _AssemblerOutput = "\n\t\t\t\tAssemblerOutput=\""; const char* _ATLMinimizesCRunTimeLibraryUsage = "\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\""; const char* _BaseAddress = "\n\t\t\t\tBaseAddress=\""; const char* _BasicRuntimeChecks = "\n\t\t\t\tBasicRuntimeChecks=\""; const char* _BrowseInformation = "\n\t\t\t\tBrowseInformation=\""; const char* _BrowseInformationFile = "\n\t\t\t\tBrowseInformationFile=\""; const char* _BufferSecurityCheck = "\n\t\t\t\tBufferSecurityCheck=\""; const char* _BuildBrowserInformation = "\n\t\t\tBuildBrowserInformation=\""; const char* _CPreprocessOptions = "\n\t\t\t\tCPreprocessOptions=\""; const char* _CallingConvention = "\n\t\t\t\tCallingConvention=\""; const char* _CharacterSet = "\n\t\t\tCharacterSet=\""; const char* _CommandLine4 = "\n\t\t\t\tCommandLine=\""; const char* _CommandLine6 = "\n\t\t\t\t\t\tCommandLine=\""; const char* _CompileAs = "\n\t\t\t\tCompileAs=\""; const char* _CompileAsManaged = "\n\t\t\t\tCompileAsManaged=\""; const char* _CompileOnly = "\n\t\t\t\tCompileOnly=\""; const char* _ConfigurationType = "\n\t\t\tConfigurationType=\""; const char* _Culture = "\n\t\t\t\tCulture=\""; const char* _DLLDataFileName = "\n\t\t\t\tDLLDataFileName=\""; const char* _DebugInformationFormat = "\n\t\t\t\tDebugInformationFormat=\""; const char* _DefaultCharIsUnsigned = "\n\t\t\t\tDefaultCharIsUnsigned=\""; const char* _DefaultCharType = "\n\t\t\t\tDefaultCharType=\""; const char* _DelayLoadDLLs = "\n\t\t\t\tDelayLoadDLLs=\""; const char* _DeleteExtensionsOnClean = "\n\t\t\tDeleteExtensionsOnClean=\""; const char* _Description4 = "\n\t\t\t\tDescription=\""; const char* _Description6 = "\n\t\t\t\t\t\tDescription=\""; const char* _Detect64BitPortabilityProblems = "\n\t\t\t\tDetect64BitPortabilityProblems=\""; const char* _DisableLanguageExtensions = "\n\t\t\t\tDisableLanguageExtensions=\""; const char* _DisableSpecificWarnings = "\n\t\t\t\tDisableSpecificWarnings=\""; const char* _EnableCOMDATFolding = "\n\t\t\t\tEnableCOMDATFolding=\""; const char* _EnableErrorChecks = "\n\t\t\t\tEnableErrorChecks=\""; const char* _EnableFiberSafeOptimizations = "\n\t\t\t\tEnableFiberSafeOptimizations=\""; const char* _EnableFunctionLevelLinking = "\n\t\t\t\tEnableFunctionLevelLinking=\""; const char* _EnableIntrinsicFunctions = "\n\t\t\t\tEnableIntrinsicFunctions=\""; const char* _EntryPointSymbol = "\n\t\t\t\tEntryPointSymbol=\""; const char* _ErrorCheckAllocations = "\n\t\t\t\tErrorCheckAllocations=\""; const char* _ErrorCheckBounds = "\n\t\t\t\tErrorCheckBounds=\""; const char* _ErrorCheckEnumRange = "\n\t\t\t\tErrorCheckEnumRange=\""; const char* _ErrorCheckRefPointers = "\n\t\t\t\tErrorCheckRefPointers=\""; const char* _ErrorCheckStubData = "\n\t\t\t\tErrorCheckStubData=\""; const char* _ExceptionHandling = "\n\t\t\t\tExceptionHandling=\""; const char* _ExcludedFromBuild = "\n\t\t\t\tExcludedFromBuild=\""; const char* _ExpandAttributedSource = "\n\t\t\t\tExpandAttributedSource=\""; const char* _ExportNamedFunctions = "\n\t\t\t\tExportNamedFunctions=\""; const char* _FavorSizeOrSpeed = "\n\t\t\t\tFavorSizeOrSpeed=\""; const char* _Filter = "\n\t\t\tFilter=\""; const char* _ForceConformanceInForLoopScope = "\n\t\t\t\tForceConformanceInForLoopScope=\""; const char* _ForceSymbolReferences = "\n\t\t\t\tForceSymbolReferences=\""; const char* _ForcedIncludeFiles = "\n\t\t\t\tForcedIncludeFiles=\""; const char* _ForcedUsingFiles = "\n\t\t\t\tForcedUsingFiles=\""; const char* _FullIncludePath = "\n\t\t\t\tFullIncludePath=\""; const char* _FunctionOrder = "\n\t\t\t\tFunctionOrder=\""; const char* _GenerateDebugInformation = "\n\t\t\t\tGenerateDebugInformation=\""; const char* _GenerateMapFile = "\n\t\t\t\tGenerateMapFile=\""; const char* _GeneratePreprocessedFile = "\n\t\t\t\tGeneratePreprocessedFile=\""; const char* _GenerateStublessProxies = "\n\t\t\t\tGenerateStublessProxies=\""; const char* _GenerateTypeLibrary = "\n\t\t\t\tGenerateTypeLibrary=\""; const char* _GlobalOptimizations = "\n\t\t\t\tGlobalOptimizations=\""; const char* _HeaderFileName = "\n\t\t\t\tHeaderFileName=\""; const char* _HeapCommitSize = "\n\t\t\t\tHeapCommitSize=\""; const char* _HeapReserveSize = "\n\t\t\t\tHeapReserveSize=\""; const char* _IgnoreAllDefaultLibraries = "\n\t\t\t\tIgnoreAllDefaultLibraries=\""; const char* _IgnoreDefaultLibraryNames = "\n\t\t\t\tIgnoreDefaultLibraryNames=\""; const char* _IgnoreEmbeddedIDL = "\n\t\t\t\tIgnoreEmbeddedIDL=\""; const char* _IgnoreImportLibrary = "\n\t\t\t\tIgnoreImportLibrary=\""; const char* _IgnoreStandardIncludePath = "\n\t\t\t\tIgnoreStandardIncludePath=\""; const char* _ImportLibrary = "\n\t\t\t\tImportLibrary=\""; const char* _ImproveFloatingPointConsistency = "\n\t\t\t\tImproveFloatingPointConsistency=\""; const char* _InlineFunctionExpansion = "\n\t\t\t\tInlineFunctionExpansion=\""; const char* _InterfaceIdentifierFileName = "\n\t\t\t\tInterfaceIdentifierFileName=\""; const char* _IntermediateDirectory = "\n\t\t\tIntermediateDirectory=\""; const char* _KeepComments = "\n\t\t\t\tKeepComments=\""; const char* _LargeAddressAware = "\n\t\t\t\tLargeAddressAware=\""; const char* _LinkDLL = "\n\t\t\t\tLinkDLL=\""; const char* _LinkIncremental = "\n\t\t\t\tLinkIncremental=\""; const char* _LinkTimeCodeGeneration = "\n\t\t\t\tLinkTimeCodeGeneration=\""; const char* _LinkToManagedResourceFile = "\n\t\t\t\tLinkToManagedResourceFile=\""; const char* _MapExports = "\n\t\t\t\tMapExports=\""; const char* _MapFileName = "\n\t\t\t\tMapFileName=\""; const char* _MapLines = "\n\t\t\t\tMapLines =\""; const char* _MergeSections = "\n\t\t\t\tMergeSections=\""; const char* _MergedIDLBaseFileName = "\n\t\t\t\tMergedIDLBaseFileName=\""; const char* _MidlCommandFile = "\n\t\t\t\tMidlCommandFile=\""; const char* _MinimalRebuild = "\n\t\t\t\tMinimalRebuild=\""; const char* _MkTypLibCompatible = "\n\t\t\t\tMkTypLibCompatible=\""; const char* _ModuleDefinitionFile = "\n\t\t\t\tModuleDefinitionFile=\""; const char* _Name1 = "\n\tName=\""; const char* _Name2 = "\n\t\tName=\""; const char* _Name3 = "\n\t\t\tName=\""; const char* _Name4 = "\n\t\t\t\tName=\""; const char* _Name5 = "\n\t\t\t\t\tName=\""; const char* _ObjectFile = "\n\t\t\t\tObjectFile=\""; const char* _OmitFramePointers = "\n\t\t\t\tOmitFramePointers=\""; const char* _Optimization = "\n\t\t\t\tOptimization =\""; const char* _OptimizeForProcessor = "\n\t\t\t\tOptimizeForProcessor=\""; const char* _OptimizeForWindows98 = "\n\t\t\t\tOptimizeForWindows98=\""; const char* _OptimizeForWindowsApplication = "\n\t\t\t\tOptimizeForWindowsApplication=\""; const char* _OptimizeReferences = "\n\t\t\t\tOptimizeReferences=\""; const char* _OutputDirectory3 = "\n\t\t\tOutputDirectory=\""; const char* _OutputDirectory4 = "\n\t\t\t\tOutputDirectory=\""; const char* _OutputFile = "\n\t\t\t\tOutputFile=\""; const char* _Outputs4 = "\n\t\t\t\tOutputs=\""; const char* _Outputs6 = "\n\t\t\t\t\t\tOutputs=\""; const char* _ParseFiles = "\n\t\t\tParseFiles=\""; const char* _PrecompiledHeaderFile = "\n\t\t\t\tPrecompiledHeaderFile=\""; const char* _PrecompiledHeaderThrough = "\n\t\t\t\tPrecompiledHeaderThrough=\""; const char* _PreprocessorDefinitions = "\n\t\t\t\tPreprocessorDefinitions=\""; const char* _PrimaryOutput = "\n\t\t\tPrimaryOutput=\""; const char* _ProjectGUID = "\n\tProjectGUID=\""; const char* _ProjectType = "\n\tProjectType=\"Visual C++\""; const char* _ProgramDatabase = "\n\t\t\tProgramDatabase=\""; const char* _ProgramDataBaseFileName = "\n\t\t\t\tProgramDataBaseFileName=\""; const char* _ProgramDatabaseFile = "\n\t\t\t\tProgramDatabaseFile=\""; const char* _ProxyFileName = "\n\t\t\t\tProxyFileName=\""; const char* _RedirectOutputAndErrors = "\n\t\t\t\tRedirectOutputAndErrors=\""; const char* _RegisterOutput = "\n\t\t\t\tRegisterOutput=\""; const char* _RelativePath = "\n\t\t\t\tRelativePath=\""; const char* _ResourceOnlyDLL = "\n\t\t\t\tResourceOnlyDLL=\""; const char* _ResourceOutputFileName = "\n\t\t\t\tResourceOutputFileName=\""; const char* _RuntimeLibrary = "\n\t\t\t\tRuntimeLibrary=\""; const char* _RuntimeTypeInfo = "\n\t\t\t\tRuntimeTypeInfo=\""; const char* _SccProjectName = "\n\tSccProjectName=\""; const char* _SccLocalPath = "\n\tSccLocalPath=\""; const char* _SetChecksum = "\n\t\t\t\tSetChecksum=\""; const char* _ShowIncludes = "\n\t\t\t\tShowIncludes=\""; const char* _ShowProgress = "\n\t\t\t\tShowProgress=\""; const char* _SmallerTypeCheck = "\n\t\t\t\tSmallerTypeCheck=\""; const char* _StackCommitSize = "\n\t\t\t\tStackCommitSize=\""; const char* _StackReserveSize = "\n\t\t\t\tStackReserveSize=\""; const char* _StringPooling = "\n\t\t\t\tStringPooling=\""; const char* _StripPrivateSymbols = "\n\t\t\t\tStripPrivateSymbols=\""; const char* _StructMemberAlignment = "\n\t\t\t\tStructMemberAlignment=\""; const char* _SubSystem = "\n\t\t\t\tSubSystem=\""; const char* _SupportUnloadOfDelayLoadedDLL = "\n\t\t\t\tSupportUnloadOfDelayLoadedDLL=\""; const char* _SuppressStartupBanner = "\n\t\t\t\tSuppressStartupBanner=\""; const char* _SwapRunFromCD = "\n\t\t\t\tSwapRunFromCD=\""; const char* _SwapRunFromNet = "\n\t\t\t\tSwapRunFromNet=\""; const char* _TargetEnvironment = "\n\t\t\t\tTargetEnvironment=\""; const char* _TargetMachine = "\n\t\t\t\tTargetMachine=\""; const char* _TerminalServerAware = "\n\t\t\t\tTerminalServerAware=\""; const char* _ToolName = "\n\t\t\t\tName=\""; const char* _ToolPath = "\n\t\t\t\tPath=\""; const char* _TreatWChar_tAsBuiltInType = "\n\t\t\t\tTreatWChar_tAsBuiltInType=\""; const char* _TurnOffAssemblyGeneration = "\n\t\t\t\tTurnOffAssemblyGeneration=\""; const char* _TypeLibraryFile = "\n\t\t\t\tTypeLibraryFile=\""; const char* _TypeLibraryName = "\n\t\t\t\tTypeLibraryName=\""; const char* _TypeLibraryResourceID = "\n\t\t\t\tTypeLibraryResourceID=\""; const char* _UndefineAllPreprocessorDefinitions = "\n\t\t\t\tUndefineAllPreprocessorDefinitions=\""; const char* _UndefinePreprocessorDefinitions = "\n\t\t\t\tUndefinePreprocessorDefinitions=\""; const char* _UseOfATL = "\n\t\t\tUseOfATL=\""; const char* _UseOfMfc = "\n\t\t\tUseOfMfc=\""; const char* _UsePrecompiledHeader = "\n\t\t\t\tUsePrecompiledHeader=\""; const char* _ValidateParameters = "\n\t\t\t\tValidateParameters=\""; const char* _VCCLCompilerToolName = "\n\t\t\t\tName=\"VCCLCompilerTool\""; const char* _VCCustomBuildTool = "\n\t\t\t\t\t\tName=\"VCCustomBuildTool\""; const char* _VCLinkerToolName = "\n\t\t\t\tName=\"VCLinkerTool\""; const char* _VCResourceCompilerToolName = "\n\t\t\t\tName=\"VCResourceCompilerTool\""; const char* _VCMIDLToolName = "\n\t\t\t\tName=\"VCMIDLTool\""; const char* _Version1 = "\n\tVersion=\""; const char* _Version4 = "\n\t\t\t\tVersion=\""; const char* _WarnAsError = "\n\t\t\t\tWarnAsError=\""; const char* _WarnLevel = "\n\t\t\t\tWarnLevel=\""; const char* _WarningLevel = "\n\t\t\t\tWarningLevel=\""; const char* _WholeProgramOptimization = "\n\t\t\t\tWholeProgramOptimization=\""; // Property name and value as Pairs --------------------------------- struct TPair { TPair( const char* n, const triState v ) : name(n), value(v) {}; const char* name; const triState value; }; struct EPair { EPair( const char* n, const int v ) : name(n), value(v) {}; const char* name; const int value; }; struct LPair { LPair( const char* n, const long v ) : name(n), value(v) {}; const char* name; const long value; }; struct SPair { SPair( const char* n, const QString& v ) : name(n), value(v) {}; const char* name; const QString& value; }; struct XPair { XPair( const char* n, const QStringList& v, const char* s = "," ) : name(n), value(v), sep(s) {}; const char* name; const QStringList& value; const char* sep; }; // void streamSPair( QTextStream &strm, const char *n, const QString &s ) // Streaming operators for property Pairs --------------------------- QTextStream &operator<<( QTextStream &strm, const TPair &prop ) { switch( prop.value ) { case _False: strm << prop.name << "FALSE\""; break; case _True: strm << prop.name << "TRUE\""; break; case unset: default: break; } return strm; } /* Be sure to check that each enum is not set to default before streaming it out. Defaults seem to not be in the XML file. */ QTextStream &operator<<( QTextStream &strm, const EPair &prop ) { strm << prop.name << prop.value << "\""; return strm; } QTextStream &operator<<( QTextStream &strm, const LPair &prop ) { strm << prop.name << prop.value << "\""; return strm; } QTextStream &operator<<( QTextStream &strm, const SPair &prop ) { if ( !prop.value.isEmpty() ) strm << prop.name << prop.value.latin1() << "\""; return strm; } QTextStream &operator<<( QTextStream &strm, const XPair &prop ) { if ( !prop.value.isEmpty() ) strm << prop.name << prop.value.join(prop.sep).latin1() << "\""; return strm; } // VCCLCompilerTool ------------------------------------------------- VCCLCompilerTool::VCCLCompilerTool() : AssemblerOutput( asmListingNone ), BasicRuntimeChecks( runtimeBasicCheckNone ), BrowseInformation( brInfoNone ), BufferSecurityCheck( unset ), CallingConvention( callConventionDefault ), CompileAs( compileAsDefault ), CompileAsManaged( managedDefault ), CompileOnly( unset ), DebugInformationFormat( debugDisabled ), DefaultCharIsUnsigned( unset ), Detect64BitPortabilityProblems( unset ), DisableLanguageExtensions( unset ), EnableFiberSafeOptimizations( unset ), EnableFunctionLevelLinking( unset ), EnableIntrinsicFunctions( unset ), ExceptionHandling( unset ), ExpandAttributedSource( unset ), FavorSizeOrSpeed( favorNone ), ForceConformanceInForLoopScope( unset ), GeneratePreprocessedFile( preprocessNo ), GlobalOptimizations( unset ), IgnoreStandardIncludePath( unset ), ImproveFloatingPointConsistency( unset ), InlineFunctionExpansion( expandOnlyInline ), KeepComments( unset ), MinimalRebuild( unset ), OmitFramePointers( unset ), Optimization( optimizeDisabled ), OptimizeForProcessor( procOptimizeBlended ), OptimizeForWindowsApplication( unset ), RuntimeLibrary( rtMultiThreaded ), RuntimeTypeInfo( unset ), ShowIncludes( unset ), SmallerTypeCheck( unset ), StringPooling( unset ), StructMemberAlignment( alignNotSet ), SuppressStartupBanner( unset ), TreatWChar_tAsBuiltInType( unset ), TurnOffAssemblyGeneration( unset ), UndefineAllPreprocessorDefinitions( unset ), UsePrecompiledHeader( pchGenerateAuto ), WarnAsError( unset ), WarningLevel( warningLevel_0 ), WholeProgramOptimization( unset ) { } QTextStream &operator<<( QTextStream &strm, const VCCLCompilerTool &tool ) { strm << _begTool3; strm << _VCCLCompilerToolName; strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); - strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions, " " ); strm << XPair( _AdditionalUsingDirectories, tool.AdditionalUsingDirectories ); strm << SPair( _AssemblerListingLocation, tool.AssemblerListingLocation ); if ( tool.AssemblerOutput != asmListingNone ) strm << EPair( _AssemblerOutput, tool.AssemblerOutput ); if ( tool.BasicRuntimeChecks != runtimeBasicCheckNone ) strm << EPair( _BasicRuntimeChecks, tool.BasicRuntimeChecks ); if ( tool.BrowseInformation != brInfoNone ) strm << EPair( _BrowseInformation, tool.BrowseInformation ); strm << SPair( _BrowseInformationFile, tool.BrowseInformationFile ); strm << TPair( _BufferSecurityCheck, tool.BufferSecurityCheck ); if ( tool.CallingConvention != callConventionDefault ) strm << EPair( _CallingConvention, tool.CallingConvention ); if ( tool.CompileAs != compileAsDefault ) strm << EPair( _CompileAs, tool.CompileAs ); if ( tool.CompileAsManaged != managedDefault ) strm << EPair( _CompileAsManaged, tool.CompileAsManaged ); strm << TPair( _CompileOnly, tool.CompileOnly ); strm << EPair( _DebugInformationFormat, tool.DebugInformationFormat ); strm << TPair( _DefaultCharIsUnsigned, tool.DefaultCharIsUnsigned ); strm << TPair( _Detect64BitPortabilityProblems, tool.Detect64BitPortabilityProblems ); strm << TPair( _DisableLanguageExtensions, tool.DisableLanguageExtensions ); strm << XPair( _DisableSpecificWarnings, tool.DisableSpecificWarnings ); strm << TPair( _EnableFiberSafeOptimizations, tool.EnableFiberSafeOptimizations ); strm << TPair( _EnableFunctionLevelLinking, tool.EnableFunctionLevelLinking ); strm << TPair( _EnableIntrinsicFunctions, tool.EnableIntrinsicFunctions ); strm << TPair( _ExceptionHandling, tool.ExceptionHandling ); strm << TPair( _ExpandAttributedSource, tool.ExpandAttributedSource ); if ( tool.FavorSizeOrSpeed != favorNone ) strm << EPair( _FavorSizeOrSpeed, tool.FavorSizeOrSpeed ); strm << TPair( _ForceConformanceInForLoopScope, tool.ForceConformanceInForLoopScope ); strm << XPair( _ForcedIncludeFiles, tool.ForcedIncludeFiles ); strm << XPair( _ForcedUsingFiles, tool.ForcedUsingFiles ); strm << EPair( _GeneratePreprocessedFile, tool.GeneratePreprocessedFile ); strm << TPair( _GlobalOptimizations, tool.GlobalOptimizations ); strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); strm << TPair( _ImproveFloatingPointConsistency, tool.ImproveFloatingPointConsistency ); strm << EPair( _InlineFunctionExpansion, tool.InlineFunctionExpansion ); strm << TPair( _KeepComments, tool.KeepComments ); strm << TPair( _MinimalRebuild, tool.MinimalRebuild ); strm << SPair( _ObjectFile, tool.ObjectFile ); strm << TPair( _OmitFramePointers, tool.OmitFramePointers ); strm << EPair( _Optimization, tool.Optimization ); if ( tool.OptimizeForProcessor != procOptimizeBlended ) strm << EPair( _OptimizeForProcessor, tool.OptimizeForProcessor ); strm << TPair( _OptimizeForWindowsApplication, tool.OptimizeForWindowsApplication ); strm << SPair( _OutputFile, tool.OutputFile ); strm << SPair( _PrecompiledHeaderFile, tool.PrecompiledHeaderFile ); strm << SPair( _PrecompiledHeaderThrough, tool.PrecompiledHeaderThrough ); strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); strm << SPair( _ProgramDataBaseFileName, tool.ProgramDataBaseFileName ); strm << EPair( _RuntimeLibrary, tool.RuntimeLibrary ); strm << TPair( _RuntimeTypeInfo, tool.RuntimeTypeInfo ); strm << TPair( _ShowIncludes, tool.ShowIncludes ); strm << TPair( _SmallerTypeCheck, tool.SmallerTypeCheck ); strm << TPair( _StringPooling, tool.StringPooling ); if ( tool.StructMemberAlignment != alignNotSet ) strm << EPair( _StructMemberAlignment, tool.StructMemberAlignment ); strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); strm << TPair( _TreatWChar_tAsBuiltInType, tool.TreatWChar_tAsBuiltInType ); strm << TPair( _TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration ); strm << TPair( _UndefineAllPreprocessorDefinitions, tool.UndefineAllPreprocessorDefinitions ); strm << XPair( _UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions ); if ( !tool.PrecompiledHeaderFile.isEmpty() || !tool.PrecompiledHeaderThrough.isEmpty() ) strm << EPair( _UsePrecompiledHeader, tool.UsePrecompiledHeader ); strm << TPair( _WarnAsError, tool.WarnAsError ); strm << EPair( _WarningLevel, tool.WarningLevel ); strm << TPair( _WholeProgramOptimization, tool.WholeProgramOptimization ); strm << "/>"; return strm; } bool VCCLCompilerTool::parseOption( const char* option ) { // skip index 0 ('/' or '-') char first = option[1]; char second = option[2]; char third = option[3]; char fourth = option[4]; + bool found = TRUE; switch ( first ) { case '?': case 'h': qWarning( "Generator: Option '/?', '/help': MSVC.NET projects do not support outputting help info" ); - return FALSE; + found = FALSE; + break; case '@': qWarning( "Generator: Option '/@': MSVC.NET projects do not support the use of a response file" ); - return FALSE; + found = FALSE; + break; case 'l': qWarning( "Generator: Option '/link': qmake generator does not support passing link options through the compiler tool" ); - return FALSE; - + found = FALSE; + break; case 'A': - if ( second != 'I' ) - return FALSE; + if ( second != 'I' ) { + found = FALSE; break; + } AdditionalUsingDirectories += option+2; break; case 'C': KeepComments = _True; break; case 'D': PreprocessorDefinitions += option+1; break; case 'E': if ( second == 'H' ) { if ( third == 'a' || third == 'c' || third == 's' ) { // ExceptionHandling must be false, or it will override // with an /EHsc option ExceptionHandling = _False; AdditionalOptions += option; break; } - return FALSE; + found = FALSE; break; } GeneratePreprocessedFile = preprocessYes; break; case 'F': if ( second <= '9' && second >= '0' ) { AdditionalOptions += option; break; } else { switch ( second ) { case 'A': if ( third == 'c' ) { AssemblerOutput = asmListingAsmMachine; if ( fourth == 's' ) AssemblerOutput = asmListingAsmMachineSrc; } else if ( third == 's' ) { AssemblerOutput = asmListingAsmSrc; } else { AssemblerOutput = asmListingAssemblyOnly; } break; case 'a': AssemblerListingLocation = option+3; break; case 'I': ForcedIncludeFiles += option+3; break; case 'R': BrowseInformation = brAllInfo; BrowseInformationFile = option+3; break; case 'r': BrowseInformation = brNoLocalSymbols; BrowseInformationFile = option+3; break; case 'U': ForcedUsingFiles += option+3; break; case 'd': ProgramDataBaseFileName = option+3; break; case 'e': OutputFile = option+3; break; case 'm': AdditionalOptions += option; break; case 'o': ObjectFile = option+3; break; case 'p': PrecompiledHeaderFile = option+3; break; case 'x': ExpandAttributedSource = _True; break; default: - return FALSE; + found = FALSE; break; } } break; case 'G': switch ( second ) { case '3': case '4': qWarning( "Option '/G3' and '/G4' were phased out in Visual C++ 5.0" ); - return FALSE; + found = FALSE; break; case '5': OptimizeForProcessor = procOptimizePentium; break; case '6': case 'B': OptimizeForProcessor = procOptimizePentiumProAndAbove; break; case 'A': OptimizeForWindowsApplication = _True; break; case 'F': StringPooling = _True; break; case 'H': AdditionalOptions += option; break; case 'L': WholeProgramOptimization = _True; if ( third == '-' ) WholeProgramOptimization = _False; break; case 'R': RuntimeTypeInfo = _True; if ( third == '-' ) RuntimeTypeInfo = _False; break; case 'S': BufferSecurityCheck = _True; break; case 'T': EnableFiberSafeOptimizations = _True; break; case 'X': case 'Z': case 'e': case 'h': AdditionalOptions += option; break; case 'd': CallingConvention = callConventionCDecl; break; case 'f': StringPooling = _True; AdditionalOptions += option; break; case 'm': MinimalRebuild = _True; if ( third == '-' ) MinimalRebuild = _False; break; case 'r': CallingConvention = callConventionFastCall; break; case 's': // Warning: following [num] is not used, // were should we put it? BufferSecurityCheck = _True; break; case 'y': EnableFunctionLevelLinking = _True; break; case 'z': CallingConvention = callConventionStdCall; break; default: - return FALSE; + found = FALSE; break; } break; case 'H': AdditionalOptions += option; break; case 'I': AdditionalIncludeDirectories += option+2; break; case 'L': if ( second == 'D' ) { AdditionalOptions += option; break; } - return FALSE; + found = FALSE; break; case 'M': if ( second == 'D' ) { RuntimeLibrary = rtMultiThreadedDLL; if ( third == 'd' ) RuntimeLibrary = rtMultiThreadedDebugDLL; break; } else if ( second == 'L' ) { RuntimeLibrary = rtSingleThreaded; if ( third == 'd' ) RuntimeLibrary = rtSingleThreadedDebug; break; } else if ( second == 'T' ) { RuntimeLibrary = rtMultiThreaded; if ( third == 'd' ) RuntimeLibrary = rtMultiThreadedDebug; break; } - return FALSE; + found = FALSE; break; case 'O': switch ( second ) { case '1': Optimization = optimizeMinSpace; break; case '2': Optimization = optimizeMaxSpeed; break; case 'a': AdditionalOptions += option; break; case 'b': if ( third == '0' ) InlineFunctionExpansion = expandDisable; else if ( third == '1' ) InlineFunctionExpansion = expandOnlyInline; else if ( third == '2' ) InlineFunctionExpansion = expandAnySuitable; else - return FALSE; + found = FALSE; break; case 'd': Optimization = optimizeDisabled; break; case 'g': GlobalOptimizations = _True; break; case 'i': EnableIntrinsicFunctions = _True; break; case 'p': ImproveFloatingPointConsistency = _True; if ( third == '-' ) ImproveFloatingPointConsistency = _False; break; case 's': FavorSizeOrSpeed = favorSize; break; case 't': FavorSizeOrSpeed = favorSpeed; break; case 'w': AdditionalOptions += option; break; case 'x': Optimization = optimizeFull; break; case 'y': OmitFramePointers = _True; if ( third == '-' ) OmitFramePointers = _False; break; default: - return FALSE; + found = FALSE; break; } break; case 'P': GeneratePreprocessedFile = preprocessYes; break; case 'Q': if ( second == 'I' ) { AdditionalOptions += option; break; } - return FALSE; + found = FALSE; break; case 'R': if ( second == 'T' && third == 'C' ) { if ( fourth == '1' ) BasicRuntimeChecks = runtimeBasicCheckAll; else if ( fourth == 'c' ) SmallerTypeCheck = _True; else if ( fourth == 's' ) BasicRuntimeChecks = runtimeCheckStackFrame; else if ( fourth == 'u' ) BasicRuntimeChecks = runtimeCheckUninitVariables; else - return FALSE; + found = FALSE; break; } break; case 'T': if ( second == 'C' ) { CompileAs = compileAsC; } else if ( second == 'P' ) { CompileAs = compileAsCPlusPlus; } else { qWarning( "Generator: Options '/Tp<filename>' and '/Tc<filename>' are not supported by qmake" ); - return FALSE; + found = FALSE; break; } break; case 'U': UndefinePreprocessorDefinitions += option+2; break; case 'V': AdditionalOptions += option; break; case 'W': switch ( second ) { case 'a': case '4': WarningLevel = warningLevel_4; break; case '3': WarningLevel = warningLevel_3; break; case '2': WarningLevel = warningLevel_2; break; case '1': WarningLevel = warningLevel_1; break; case '0': WarningLevel = warningLevel_0; break; case 'L': AdditionalOptions += option; break; case 'X': WarnAsError = _True; break; case 'p': if ( third == '6' && fourth == '4' ) { Detect64BitPortabilityProblems = _True; break; } // Fallthrough default: - return FALSE; + found = FALSE; break; } break; case 'X': IgnoreStandardIncludePath = _True; break; case 'Y': switch ( second ) { case '\0': case '-': AdditionalOptions += option; break; case 'X': UsePrecompiledHeader = pchGenerateAuto; PrecompiledHeaderFile = option+3; break; case 'c': UsePrecompiledHeader = pchCreateUsingSpecific; PrecompiledHeaderFile = option+3; break; case 'd': case 'l': AdditionalOptions =+ option; break; case 'u': UsePrecompiledHeader = pchUseUsingSpecific; PrecompiledHeaderFile = option+3; break; default: - return FALSE; + found = FALSE; break; } break; case 'Z': switch ( second ) { case '7': DebugInformationFormat = debugOldStyleInfo; break; case 'I': DebugInformationFormat = debugEditAndContinue; break; case 'd': DebugInformationFormat = debugLineInfoOnly; break; case 'i': DebugInformationFormat = debugEnabled; break; case 'l': DebugInformationFormat = debugEditAndContinue; break; case 'a': DisableLanguageExtensions = _True; break; case 'e': DisableLanguageExtensions = _False; break; case 'c': if ( third == ':' ) { if ( fourth == 'f' ) ForceConformanceInForLoopScope = _True; else if ( fourth == 'w' ) TreatWChar_tAsBuiltInType = _True; else - return FALSE; + found = FALSE; } else { - return FALSE; + found = FALSE; break; } break; case 'g': case 'm': case 's': AdditionalOptions += option; break; case 'p': switch ( third ) { case '\0': case '1': StructMemberAlignment = alignSingleByte; if ( fourth == '6' ) StructMemberAlignment = alignSixteenBytes; break; case '2': StructMemberAlignment = alignTwoBytes; break; case '4': StructMemberAlignment = alignFourBytes; break; case '8': StructMemberAlignment = alignEightBytes; break; default: - return FALSE; + found = FALSE; break; } break; default: - return FALSE; + found = FALSE; break; } break; case 'c': if ( second == '\0' ) { CompileOnly = _True; } else if ( second == 'l' ) { if ( *(option+5) == 'n' ) { CompileAsManaged = managedAssembly; TurnOffAssemblyGeneration = _True; } else { CompileAsManaged = managedAssembly; } } else { - return FALSE; + found = FALSE; break; } break; case 'd': - if ( second != 'r' ) - return FALSE; + if ( second != 'r' ) { + found = FALSE; break; + } CompileAsManaged = managedAssembly; break; case 'n': if ( second == 'o' && third == 'B' && fourth == 'o' ) { AdditionalOptions += "/noBool"; break; } if ( second == 'o' && third == 'l' && fourth == 'o' ) { SuppressStartupBanner = _True; break; } - return FALSE; + found = FALSE; break; case 's': if ( second == 'h' && third == 'o' && fourth == 'w' ) { ShowIncludes = _True; break; } - return FALSE; + found = FALSE; break; case 'u': UndefineAllPreprocessorDefinitions = _True; break; case 'v': if ( second == 'd' || second == 'm' ) { AdditionalOptions += option; break; } - return FALSE; + found = FALSE; break; case 'w': switch ( second ) { case '\0': WarningLevel = warningLevel_0; break; case 'd': DisableSpecificWarnings += option+3; break; default: AdditionalOptions += option; } break; default: - return FALSE; + found = FALSE; break; } + if( !found ) + warn_msg( WarnLogic, "Could not parse Compiler option: %s", option ); return TRUE; } // VCLinkerTool ----------------------------------------------------- VCLinkerTool::VCLinkerTool() : EnableCOMDATFolding( optFoldingDefault ), GenerateDebugInformation( unset ), GenerateMapFile( unset ), HeapCommitSize( -1 ), HeapReserveSize( -1 ), IgnoreAllDefaultLibraries( unset ), IgnoreEmbeddedIDL( unset ), IgnoreImportLibrary( unset ), LargeAddressAware( addrAwareDefault ), LinkDLL( unset ), LinkIncremental( linkIncrementalYes ), LinkTimeCodeGeneration( unset ), MapExports( unset ), MapLines( unset ), OptimizeForWindows98( optWin98Default ), OptimizeReferences( optReferencesDefault ), RegisterOutput( unset ), ResourceOnlyDLL( unset ), SetChecksum( unset ), ShowProgress( linkProgressNotSet ), StackCommitSize( -1 ), StackReserveSize( -1 ), SubSystem( subSystemNotSet ), SupportUnloadOfDelayLoadedDLL( unset ), SuppressStartupBanner( unset ), SwapRunFromCD( unset ), SwapRunFromNet( unset ), TargetMachine( machineNotSet ), TerminalServerAware( termSvrAwareDefault ), TurnOffAssemblyGeneration( unset ), TypeLibraryResourceID( 0 ) { } QTextStream &operator<<( QTextStream &strm, const VCLinkerTool &tool ) { strm << _begTool3; strm << _VCLinkerToolName; strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies, " " ); strm << XPair( _AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories ); - strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions, " " ); strm << XPair( _AddModuleNamesToAssembly, tool.AddModuleNamesToAssembly ); strm << SPair( _BaseAddress, tool.BaseAddress ); strm << XPair( _DelayLoadDLLs, tool.DelayLoadDLLs ); if ( tool.EnableCOMDATFolding != optFoldingDefault ) strm << EPair( _EnableCOMDATFolding, tool.EnableCOMDATFolding ); strm << SPair( _EntryPointSymbol, tool.EntryPointSymbol ); strm << XPair( _ForceSymbolReferences, tool.ForceSymbolReferences ); strm << SPair( _FunctionOrder, tool.FunctionOrder ); strm << TPair( _GenerateDebugInformation, tool.GenerateDebugInformation ); strm << TPair( _GenerateMapFile, tool.GenerateMapFile ); if ( tool.HeapCommitSize != -1 ) strm << LPair( _HeapCommitSize, tool.HeapCommitSize ); if ( tool.HeapReserveSize != -1 ) strm << LPair( _HeapReserveSize, tool.HeapReserveSize ); strm << TPair( _IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries ); strm << XPair( _IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames ); strm << TPair( _IgnoreEmbeddedIDL, tool.IgnoreEmbeddedIDL ); strm << TPair( _IgnoreImportLibrary, tool.IgnoreImportLibrary ); strm << SPair( _ImportLibrary, tool.ImportLibrary ); if ( tool.LargeAddressAware != addrAwareDefault ) strm << EPair( _LargeAddressAware, tool.LargeAddressAware ); strm << TPair( _LinkDLL, tool.LinkDLL ); if ( tool.LinkIncremental != linkIncrementalDefault ) strm << EPair( _LinkIncremental, tool.LinkIncremental ); strm << TPair( _LinkTimeCodeGeneration, tool.LinkTimeCodeGeneration ); strm << SPair( _LinkToManagedResourceFile, tool.LinkToManagedResourceFile ); strm << TPair( _MapExports, tool.MapExports ); strm << SPair( _MapFileName, tool.MapFileName ); strm << TPair( _MapLines, tool.MapLines ); strm << SPair( _MergedIDLBaseFileName, tool.MergedIDLBaseFileName ); strm << SPair( _MergeSections, tool.MergeSections ); strm << SPair( _MidlCommandFile, tool.MidlCommandFile ); strm << SPair( _ModuleDefinitionFile, tool.ModuleDefinitionFile ); if ( tool.OptimizeForWindows98 != optWin98Default ) strm << EPair( _OptimizeForWindows98, tool.OptimizeForWindows98 ); if ( tool.OptimizeReferences != optReferencesDefault ) strm << EPair( _OptimizeReferences, tool.OptimizeReferences ); strm << SPair( _OutputFile, tool.OutputFile ); strm << SPair( _ProgramDatabaseFile, tool.ProgramDatabaseFile ); strm << TPair( _RegisterOutput, tool.RegisterOutput ); strm << TPair( _ResourceOnlyDLL, tool.ResourceOnlyDLL ); strm << TPair( _SetChecksum, tool.SetChecksum ); if ( tool.ShowProgress != linkProgressNotSet ) strm << EPair( _ShowProgress, tool.ShowProgress ); if ( tool.StackCommitSize != -1 ) strm << LPair( _StackCommitSize, tool.StackCommitSize ); if ( tool.StackReserveSize != -1 ) strm << LPair( _StackReserveSize, tool.StackReserveSize ); strm << SPair( _StripPrivateSymbols, tool.StripPrivateSymbols ); strm << EPair( _SubSystem, tool.SubSystem ); strm << TPair( _SupportUnloadOfDelayLoadedDLL, tool.SupportUnloadOfDelayLoadedDLL ); strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); strm << TPair( _SwapRunFromCD, tool.SwapRunFromCD ); strm << TPair( _SwapRunFromNet, tool.SwapRunFromNet ); if ( tool.TargetMachine != machineNotSet ) strm << EPair( _TargetMachine, tool.TargetMachine ); if ( tool.TerminalServerAware != termSvrAwareDefault ) strm << EPair( _TerminalServerAware, tool.TerminalServerAware ); strm << TPair( _TurnOffAssemblyGeneration, tool.TurnOffAssemblyGeneration ); strm << SPair( _TypeLibraryFile, tool.TypeLibraryFile ); if ( tool.TypeLibraryResourceID != rcUseDefault ) strm << LPair( _TypeLibraryResourceID, tool.TypeLibraryResourceID ); strm << SPair( _Version4, tool.Version ); strm << "/>"; return strm; } // Hashing routine to do fast option lookups ---- // Slightly rewritten to stop on ':' ',' and '\0' // Original routine in qtranslator.cpp ---------- static uint elfHash( const char* name ) { const uchar *k; uint h = 0; uint g; if ( name ) { k = (const uchar *) name; while ( (*k) && (*k)!= ':' && (*k)!=',' && (*k)!=' ' ) { h = ( h << 4 ) + *k++; if ( (g = (h & 0xf0000000)) != 0 ) h ^= g >> 24; h &= ~g; } } if ( !h ) h = 1; return h; } + +//#define USE_DISPLAY_HASH +#ifdef USE_DISPLAY_HASH static void displayHash( const char* str ) { printf( "case 0x%07x: // %s\n break;\n", elfHash(str), str ); } +#endif bool VCLinkerTool::parseOption( const char* option ) { -#if 0 +#ifdef USE_DISPLAY_HASH // Main options displayHash( "/ALIGN" ); displayHash( "/ALLOWBIND" ); displayHash( "/ASSEMBLYMODULE" ); displayHash( "/ASSEMBLYRESOURCE" ); displayHash( "/BASE" ); displayHash( "/DEBUG" ); displayHash( "/DEF" ); displayHash( "/DEFAULTLIB" ); displayHash( "/DELAY" ); displayHash( "/DELAYLOAD" ); displayHash( "/DLL" ); displayHash( "/DRIVER" ); displayHash( "/ENTRY" ); displayHash( "/EXETYPE" ); displayHash( "/EXPORT" ); displayHash( "/FIXED" ); displayHash( "/FORCE" ); displayHash( "/HEAP" ); displayHash( "/IDLOUT" ); displayHash( "/IGNOREIDL" ); displayHash( "/IMPLIB" ); displayHash( "/INCLUDE" ); displayHash( "/INCREMENTAL" ); displayHash( "/LARGEADDRESSAWARE" ); displayHash( "/LIBPATH" ); displayHash( "/LTCG" ); displayHash( "/MACHINE" ); displayHash( "/MAP" ); displayHash( "/MAPINFO" ); displayHash( "/MERGE" ); displayHash( "/MIDL" ); displayHash( "/NOASSEMBLY" ); displayHash( "/NODEFAULTLIB" ); displayHash( "/NOENTRY" ); displayHash( "/NOLOGO" ); displayHash( "/OPT" ); displayHash( "/ORDER" ); displayHash( "/OUT" ); displayHash( "/PDB" ); displayHash( "/PDBSTRIPPED" ); displayHash( "/RELEASE" ); displayHash( "/SECTION" ); displayHash( "/STACK" ); displayHash( "/STUB" ); displayHash( "/SUBSYSTEM" ); displayHash( "/SWAPRUN" ); displayHash( "/TLBID" ); displayHash( "/TLBOUT" ); displayHash( "/TSAWARE" ); displayHash( "/VERBOSE" ); displayHash( "/VERSION" ); displayHash( "/VXD" ); displayHash( "/WS " ); #endif -#if 0 +#ifdef USE_DISPLAY_HASH // Sub options displayHash( "UNLOAD" ); displayHash( "NOBIND" ); displayHash( "no" ); displayHash( "NOSTATUS" ); displayHash( "STATUS" ); displayHash( "AM33" ); displayHash( "ARM" ); displayHash( "CEE" ); displayHash( "IA64" ); displayHash( "X86" ); displayHash( "M32R" ); displayHash( "MIPS" ); displayHash( "MIPS16" ); displayHash( "MIPSFPU" ); displayHash( "MIPSFPU16" ); displayHash( "MIPSR41XX" ); displayHash( "PPC" ); displayHash( "SH3" ); displayHash( "SH4" ); displayHash( "SH5" ); displayHash( "THUMB" ); displayHash( "TRICORE" ); displayHash( "EXPORTS" ); displayHash( "LINES" ); displayHash( "REF" ); displayHash( "NOREF" ); displayHash( "ICF" ); displayHash( "WIN98" ); displayHash( "NOWIN98" ); displayHash( "CONSOLE" ); displayHash( "EFI_APPLICATION" ); displayHash( "EFI_BOOT_SERVICE_DRIVER" ); displayHash( "EFI_ROM" ); displayHash( "EFI_RUNTIME_DRIVER" ); displayHash( "NATIVE" ); displayHash( "POSIX" ); displayHash( "WINDOWS" ); displayHash( "WINDOWSCE" ); displayHash( "NET" ); displayHash( "CD" ); displayHash( "NO" ); #endif - + bool found = TRUE; switch ( elfHash(option) ) { case 0x3360dbe: // /ALIGN[:number] case 0x1485c34: // /ALLOWBIND[:NO] case 0x6b21972: // /DEFAULTLIB:library case 0x396ea92: // /DRIVER[:UPONLY | :WDM] case 0xaca9d75: // /EXETYPE[:DYNAMIC | :DEV386] case 0x3ad5444: // /EXPORT:entryname[,@ordinal[,NONAME]][,DATA] case 0x33aec94: // /FIXED[:NO] case 0x33b4675: // /FORCE:[MULTIPLE|UNRESOLVED] case 0x7988f7e: // /SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#] case 0x0348992: // /STUB:filename case 0x0034bc4: // /VXD case 0x0034c50: // /WS AdditionalOptions += option; break; case 0x679c075: // /ASSEMBLYMODULE:filename AddModuleNamesToAssembly += option+15; break; case 0x062d065: // /ASSEMBLYRESOURCE:filename LinkToManagedResourceFile = option+18; break; case 0x0336675: // /BASE:{address | @filename,key} // Do we need to do a manual lookup when '@filename,key'? // Seems BaseAddress only can contain the location... // We don't use it in Qt, so keep it simple for now BaseAddress = option+6; break; case 0x3389797: // /DEBUG GenerateDebugInformation = _True; break; case 0x0033896: // /DEF:filename ModuleDefinitionFile = option+5; break; case 0x338a069: // /DELAY:{UNLOAD | NOBIND} // MS documentation does not specify what to do with // this option, so we'll put it in AdditionalOptions AdditionalOptions += option; break; case 0x06f4bf4: // /DELAYLOAD:dllname DelayLoadDLLs += option+11; break; // case 0x003390c: // /DLL // This option is not used for vcproj files // break; case 0x33a3979: // /ENTRY:function EntryPointSymbol = option+7; break; case 0x033c960: // /HEAP:reserve[,commit] { QStringList both = QStringList::split( ",", option+6 ); HeapReserveSize = both[0].toLong(); if ( both.count() == 2 ) HeapCommitSize = both[1].toLong(); } break; case 0x3d91494: // /IDLOUT:[path\]filename MergedIDLBaseFileName = option+8; break; case 0x345a04c: // /IGNOREIDL IgnoreEmbeddedIDL = _True; break; case 0x3e250e2: // /IMPLIB:filename ImportLibrary = option+8; break; case 0xe281ab5: // /INCLUDE:symbol ForceSymbolReferences += option+9; break; case 0xb28103c: // /INCREMENTAL[:no] if ( *(option+12) == ':' && *(option+13) == 'n' ) LinkIncremental = linkIncrementalNo; else LinkIncremental = linkIncrementalYes; break; case 0x26e4675: // /LARGEADDRESSAWARE[:no] if ( *(option+18) == ':' && *(option+19) == 'n' ) LargeAddressAware = addrAwareNoLarge; else LargeAddressAware = addrAwareLarge; break; case 0x0d745c8: // /LIBPATH:dir AdditionalLibraryDirectories += option+9; break; case 0x0341877: // /LTCG[:NOSTATUS|:STATUS] config->WholeProgramOptimization = _True; LinkTimeCodeGeneration = _True; if ( *(option+5) == ':' && *(option+6) == 'S' ) ShowProgress = linkProgressAll; break; case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE} switch ( elfHash(option+9) ) { // Very limited documentation on all options but X86, // so we put the others in AdditionalOptions... case 0x0046063: // AM33 case 0x000466d: // ARM case 0x0004795: // CEE case 0x004d494: // IA64 case 0x0050672: // M32R case 0x0051e53: // MIPS case 0x51e5646: // MIPS16 case 0x1e57b05: // MIPSFPU case 0x57b09a6: // MIPSFPU16 case 0x5852738: // MIPSR41XX case 0x0005543: // PPC case 0x00057b3: // SH3 case 0x00057b4: // SH4 case 0x00057b5: // SH5 case 0x058da12: // THUMB case 0x96d8435: // TRICORE AdditionalOptions += option; break; case 0x0005bb6: // X86 TargetMachine = machineX86; break; default: - return FALSE; + found = FALSE; } break; case 0x0034160: // /MAP[:filename] GenerateMapFile = _True; MapFileName = option+5; break; case 0x164e1ef: // /MAPINFO:{EXPORTS|LINES} if ( *(option+9) == 'E' ) MapExports = _True; else if ( *(option+9) == 'L' ) MapLines = _True; break; case 0x341a6b5: // /MERGE:from=to MergeSections = option+7; break; case 0x0341d8c: // /MIDL:@file MidlCommandFile = option+7; break; case 0x84e2679: // /NOASSEMBLY TurnOffAssemblyGeneration = _True; break; case 0x2b21942: // /NODEFAULTLIB[:library] if ( *(option+13) == '\0' ) IgnoreAllDefaultLibraries = _True; else IgnoreDefaultLibraryNames += option+14; break; case 0x33a3a39: // /NOENTRY ResourceOnlyDLL = _True; break; case 0x434138f: // /NOLOGO SuppressStartupBanner = _True; break; case 0x0034454: // /OPT:{REF | NOREF | ICF[=iterations] | NOICF | WIN98 | NOWIN98} { char third = *(option+7); switch ( third ) { case 'F': // REF if ( *(option+5) == 'R' ) { OptimizeReferences = optReferences; } else { // ICF[=iterations] EnableCOMDATFolding = optFolding; // [=iterations] case is not documented } break; case 'R': // NOREF OptimizeReferences = optNoReferences; break; case 'I': // NOICF EnableCOMDATFolding = optNoFolding; break; case 'N': // WIN98 OptimizeForWindows98 = optWin98Yes; break; case 'W': // NOWIN98 OptimizeForWindows98 = optWin98No; break; default: - return FALSE; + found = FALSE; } } break; case 0x34468a2: // /ORDER:@filename FunctionOrder = option+8; break; case 0x00344a4: // /OUT:filename OutputFile = option+5; break; case 0x0034482: // /PDB:filename ProgramDatabaseFile = option+5; break; case 0xa2ad314: // /PDBSTRIPPED:pdb_file_name StripPrivateSymbols = option+13; break; case 0x6a09535: // /RELEASE SetChecksum = _True; break; case 0x348857b: // /STACK:reserve[,commit] { QStringList both = QStringList::split( ",", option+7 ); StackReserveSize = both[0].toLong(); if ( both.count() == 2 ) StackCommitSize = both[1].toLong(); } break; case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]] { // Split up in subsystem, and version number QStringList both = QStringList::split( ",", option+11 ); switch ( elfHash(both[0].latin1()) ) { case 0x8438445: // CONSOLE SubSystem = subSystemConsole; break; case 0xbe29493: // WINDOWS SubSystem = subSystemWindows; break; // The following are undocumented, so add them to AdditionalOptions case 0x240949e: // EFI_APPLICATION case 0xe617652: // EFI_BOOT_SERVICE_DRIVER case 0x9af477d: // EFI_ROM case 0xd34df42: // EFI_RUNTIME_DRIVER case 0x5268ea5: // NATIVE case 0x05547e8: // POSIX case 0x2949c95: // WINDOWSCE AdditionalOptions += option; break; default: - return FALSE; + found = FALSE; } } break; case 0x8b654de: // /SWAPRUN:{NET | CD} if ( *(option+9) == 'N' ) SwapRunFromNet = _True; else if ( *(option+9) == 'C' ) SwapRunFromCD = _True; else - return FALSE; + found = FALSE; break; case 0x34906d4: // /TLBID:id TypeLibraryResourceID = QString( option+7 ).toLong(); break; case 0x4907494: // /TLBOUT:[path\]filename TypeLibraryFile = option+8; break; case 0x976b525: // /TSAWARE[:NO] if ( *(option+8) == ':' ) TerminalServerAware = termSvrAwareNo; else TerminalServerAware = termSvrAwareYes; break; case 0xaa67735: // /VERBOSE[:lib] if ( *(option+9) == ':' ) { ShowProgress = linkProgressLibs; AdditionalOptions += option; } else { ShowProgress = linkProgressAll; } break; case 0xaa77f7e: // /VERSION:major[.minor] Version = option+9; break; default: - return FALSE; + found = FALSE; } - return TRUE; + if( !found ) + warn_msg( WarnLogic, "Could not parse Linker options: %s", option ); + return found; } // VCMIDLTool ------------------------------------------------------- VCMIDLTool::VCMIDLTool() : DefaultCharType( midlCharUnsigned ), EnableErrorChecks( midlDisableAll ), ErrorCheckAllocations( unset ), ErrorCheckBounds( unset ), ErrorCheckEnumRange( unset ), ErrorCheckRefPointers( unset ), ErrorCheckStubData( unset ), GenerateStublessProxies( unset ), GenerateTypeLibrary( unset ), IgnoreStandardIncludePath( unset ), MkTypLibCompatible( unset ), StructMemberAlignment( midlAlignNotSet ), SuppressStartupBanner( unset ), TargetEnvironment( midlTargetNotSet ), ValidateParameters( unset ), WarnAsError( unset ), WarningLevel( midlWarningLevel_0 ) { } QTextStream &operator<<( QTextStream &strm, const VCMIDLTool &tool ) { strm << _begTool3; strm << _VCMIDLToolName; strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); - strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions, " " ); strm << XPair( _CPreprocessOptions, tool.CPreprocessOptions ); strm << EPair( _DefaultCharType, tool.DefaultCharType ); strm << SPair( _DLLDataFileName, tool.DLLDataFileName ); strm << EPair( _EnableErrorChecks, tool.EnableErrorChecks ); strm << TPair( _ErrorCheckAllocations, tool.ErrorCheckAllocations ); strm << TPair( _ErrorCheckBounds, tool.ErrorCheckBounds ); strm << TPair( _ErrorCheckEnumRange, tool.ErrorCheckEnumRange ); strm << TPair( _ErrorCheckRefPointers, tool.ErrorCheckRefPointers ); strm << TPair( _ErrorCheckStubData, tool.ErrorCheckStubData ); strm << XPair( _FullIncludePath, tool.FullIncludePath ); strm << TPair( _GenerateStublessProxies, tool.GenerateStublessProxies ); strm << TPair( _GenerateTypeLibrary, tool.GenerateTypeLibrary ); strm << SPair( _HeaderFileName, tool.HeaderFileName ); strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); strm << SPair( _InterfaceIdentifierFileName, tool.InterfaceIdentifierFileName ); strm << TPair( _MkTypLibCompatible, tool.MkTypLibCompatible ); strm << SPair( _OutputDirectory4, tool.OutputDirectory ); strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); strm << SPair( _ProxyFileName, tool.ProxyFileName ); strm << SPair( _RedirectOutputAndErrors, tool.RedirectOutputAndErrors ); if ( tool.StructMemberAlignment != midlAlignNotSet) strm << EPair( _StructMemberAlignment, tool.StructMemberAlignment ); strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); if ( tool.TargetEnvironment != midlTargetNotSet ) strm << EPair( _TargetEnvironment, tool.TargetEnvironment ); strm << SPair( _TypeLibraryName, tool.TypeLibraryName ); strm << XPair( _UndefinePreprocessorDefinitions, tool.UndefinePreprocessorDefinitions ); strm << TPair( _ValidateParameters, tool.ValidateParameters ); strm << TPair( _WarnAsError, tool.WarnAsError ); strm << EPair( _WarningLevel, tool.WarningLevel ); strm << "/>"; return strm; } bool VCMIDLTool::parseOption( const char* option ) { -#if 0 +#ifdef USE_DISPLAY_HASH displayHash( "/D name[=def]" ); displayHash( "/I directory-list" ); displayHash( "/Oi" ); displayHash( "/Oic" ); displayHash( "/Oicf" ); displayHash( "/Oif" ); displayHash( "/Os" ); displayHash( "/U name" ); displayHash( "/WX" ); displayHash( "/W{0|1|2|3|4}" ); displayHash( "/Zp {N}" ); displayHash( "/Zs" ); displayHash( "/acf filename" ); displayHash( "/align {N}" ); displayHash( "/app_config" ); displayHash( "/c_ext" ); displayHash( "/char ascii7" ); displayHash( "/char signed" ); displayHash( "/char unsigned" ); displayHash( "/client none" ); displayHash( "/client stub" ); displayHash( "/confirm" ); displayHash( "/cpp_cmd cmd_line" ); displayHash( "/cpp_opt options" ); displayHash( "/cstub filename" ); displayHash( "/dlldata filename" ); displayHash( "/env win32" ); displayHash( "/env win64" ); displayHash( "/error all" ); displayHash( "/error allocation" ); displayHash( "/error bounds_check" ); displayHash( "/error enum" ); displayHash( "/error none" ); displayHash( "/error ref" ); displayHash( "/error stub_data" ); displayHash( "/h filename" ); displayHash( "/header filename" ); displayHash( "/iid filename" ); displayHash( "/lcid" ); displayHash( "/mktyplib203" ); displayHash( "/ms_ext" ); displayHash( "/ms_union" ); displayHash( "/msc_ver <nnnn>" ); displayHash( "/newtlb" ); displayHash( "/no_cpp" ); displayHash( "/no_def_idir" ); displayHash( "/no_default_epv" ); displayHash( "/no_format_opt" ); displayHash( "/no_warn" ); displayHash( "/nocpp" ); displayHash( "/nologo" ); displayHash( "/notlb" ); displayHash( "/o filename" ); displayHash( "/oldnames" ); displayHash( "/oldtlb" ); displayHash( "/osf" ); displayHash( "/out directory" ); displayHash( "/pack {N}" ); displayHash( "/prefix all" ); displayHash( "/prefix client" ); displayHash( "/prefix server" ); displayHash( "/prefix switch" ); displayHash( "/protocol all" ); displayHash( "/protocol dce" ); displayHash( "/protocol ndr64" ); displayHash( "/proxy filename" ); displayHash( "/robust" ); displayHash( "/rpcss" ); displayHash( "/savePP" ); displayHash( "/server none" ); displayHash( "/server stub" ); displayHash( "/sstub filename" ); displayHash( "/syntax_check" ); displayHash( "/target {system}" ); displayHash( "/tlb filename" ); displayHash( "/use_epv" ); displayHash( "/win32" ); displayHash( "/win64" ); #endif + bool found = TRUE; int offset = 0; switch( elfHash(option) ) { case 0x0000334: // /D name[=def] PreprocessorDefinitions += option+3; break; case 0x0000339: // /I directory-list AdditionalIncludeDirectories += option+3; break; case 0x0345f96: // /Oicf case 0x00345f6: // /Oif GenerateStublessProxies = _True; break; case 0x0000345: // /U name UndefinePreprocessorDefinitions += option+3; break; case 0x00034c8: // /WX WarnAsError = _True; break; case 0x3582fde: // /align {N} offset = 3; // Fallthrough case 0x0003510: // /Zp {N} switch ( *(option+offset+4) ) { case '1': StructMemberAlignment = ( *(option+offset+5) == '\0' ) ? midlAlignSingleByte : midlAlignSixteenBytes; break; case '2': StructMemberAlignment = midlAlignTwoBytes; break; case '4': StructMemberAlignment = midlAlignFourBytes; break; case '8': StructMemberAlignment = midlAlignEightBytes; break; default: - return FALSE; + found = FALSE; } break; case 0x0359e82: // /char {ascii7|signed|unsigned} switch( *(option+6) ) { case 'a': DefaultCharType = midlCharAscii7; break; case 's': DefaultCharType = midlCharSigned; break; case 'u': DefaultCharType = midlCharUnsigned; break; default: - return FALSE; + found = FALSE; } break; case 0xa766524: // /cpp_opt options CPreprocessOptions += option+9; break; case 0xb32abf1: // /dlldata filename DLLDataFileName = option + 9; break; case 0x0035c56: // /env {win32|win64} TargetEnvironment = ( *(option+8) == '6' ) ? midlTargetWin64 : midlTargetWin32; break; case 0x35c9962: // /error {all|allocation|bounds_check|enum|none|ref|stub_data} EnableErrorChecks = midlEnableCustom; switch ( *(option+7) ) { case 'a': if ( *(option+10) == '\0' ) EnableErrorChecks = midlEnableAll; else ErrorCheckAllocations = _True; break; case 'b': ErrorCheckBounds = _True; break; case 'e': ErrorCheckEnumRange = _True; break; case 'n': EnableErrorChecks = midlDisableAll; break; case 'r': - break; ErrorCheckRefPointers = _True; - case 's': break; + case 's': ErrorCheckStubData = _True; + break; default: - return FALSE; + found = FALSE; } break; case 0x5eb7af2: // /header filename offset = 5; case 0x0000358: // /h filename HeaderFileName = option + offset + 3; break; case 0x0035ff4: // /iid filename InterfaceIdentifierFileName = option+5; break; case 0x64b7933: // /mktyplib203 MkTypLibCompatible = _True; break; case 0x8e0b0a2: // /no_def_idir IgnoreStandardIncludePath = _True; break; case 0x65635ef: // /nologo SuppressStartupBanner = _True; break; case 0x3656b22: // /notlb GenerateTypeLibrary = _True; break; case 0x000035f: // /o filename RedirectOutputAndErrors = option+3; break; case 0x00366c4: // /out directory OutputDirectory = option+5; break; case 0x36796f9: // /proxy filename ProxyFileName = option+7; break; case 0x6959c94: // /robust ValidateParameters = _True; break; case 0x6a88df4: // /target {system} if ( *(option+11) == '6' ) TargetEnvironment = midlTargetWin64; else TargetEnvironment = midlTargetWin32; break; case 0x0036b22: // /tlb filename TypeLibraryName = option+5; break; case 0x36e0162: // /win32 TargetEnvironment = midlTargetWin32; break; case 0x36e0194: // /win64 TargetEnvironment = midlTargetWin64; break; case 0x0003459: // /Oi case 0x00345f3: // /Oic case 0x0003463: // /Os case 0x0003513: // /Zs case 0x0035796: // /acf filename case 0x5b1cb97: // /app_config case 0x3595cf4: // /c_ext case 0x5a2fc64: // /client {none|stub} case 0xa64d3dd: // /confirm case 0xa765b64: // /cpp_cmd cmd_line case 0x35aabb2: // /cstub filename case 0x03629f4: // /lcid case 0x6495cc4: // /ms_ext case 0x96c7a1e: // /ms_union case 0x4996fa2: // /msc_ver <nnnn> case 0x64ceb12: // /newtlb case 0x6555a40: // /no_cpp case 0xf64d6a6: // /no_default_epv case 0x6dd9384: // /no_format_opt case 0x556dbee: // /no_warn case 0x3655a70: // /nocpp case 0x2b455a3: // /oldnames case 0x662bb12: // /oldtlb case 0x0036696: // /osf case 0x036679b: // /pack {N} case 0x678bd38: // /prefix {all|client|server|switch} case 0x96b702c: // /protocol {all|dce|ndr64} case 0x3696aa3: // /rpcss case 0x698ca60: // /savePP case 0x69c9cf2: // /server {none|stub} case 0x36aabb2: // /sstub filename case 0xce9b12b: // /syntax_check case 0xc9b5f16: // /use_epv AdditionalOptions += option; break; default: // /W{0|1|2|3|4} case if ( *(option+1) == 'W' ) { switch ( *(option+2) ) { case '0': WarningLevel = midlWarningLevel_0; break; case '1': WarningLevel = midlWarningLevel_1; break; case '2': WarningLevel = midlWarningLevel_2; break; case '3': WarningLevel = midlWarningLevel_3; break; case '4': WarningLevel = midlWarningLevel_4; break; default: - return FALSE; + found = FALSE; } } break; } + if( !found ) + warn_msg( WarnLogic, "Could not parse MIDL option: %s", option ); return TRUE; } // VCLibrarianTool -------------------------------------------------- VCLibrarianTool::VCLibrarianTool() : IgnoreAllDefaultLibraries( unset ), SuppressStartupBanner( _True ) { } QTextStream &operator<<( QTextStream &strm, const VCLibrarianTool &tool ) { strm << _begTool3; strm << SPair( _ToolName, QString( "VCLibrarianTool" ) ); strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies ); strm << XPair( _AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories ); - strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions, " " ); strm << XPair( _ExportNamedFunctions, tool.ExportNamedFunctions ); strm << XPair( _ForceSymbolReferences, tool.ForceSymbolReferences ); strm << TPair( _IgnoreAllDefaultLibraries, tool.IgnoreAllDefaultLibraries ); strm << XPair( _IgnoreDefaultLibraryNames, tool.IgnoreDefaultLibraryNames ); strm << SPair( _ModuleDefinitionFile, tool.ModuleDefinitionFile ); strm << SPair( _OutputFile, tool.OutputFile ); strm << TPair( _SuppressStartupBanner, tool.SuppressStartupBanner ); strm << "/>"; return strm; } // VCCustomBuildTool ------------------------------------------------ VCCustomBuildTool::VCCustomBuildTool() { ToolName = "VCCustomBuildTool"; } QTextStream &operator<<( QTextStream &strm, const VCCustomBuildTool &tool ) { strm << _begTool3; strm << SPair( _ToolName, tool.ToolName ); strm << XPair( _AdditionalDependencies4, tool.AdditionalDependencies, ";" ); strm << SPair( _CommandLine4, tool.CommandLine ); strm << SPair( _Description4, tool.Description ); strm << SPair( _Outputs4, tool.Outputs ); strm << SPair( _ToolPath, tool.ToolPath ); strm << "/>"; return strm; } // VCResourceCompilerTool ------------------------------------------- VCResourceCompilerTool::VCResourceCompilerTool() : Culture( rcUseDefault ), IgnoreStandardIncludePath( unset ), ShowProgress( linkProgressNotSet ) { PreprocessorDefinitions = "NDEBUG"; } QTextStream &operator<<( QTextStream &strm, const VCResourceCompilerTool &tool ) { strm << _begTool3; strm << _VCResourceCompilerToolName; strm << SPair( _ToolPath, tool.ToolPath ); strm << XPair( _AdditionalIncludeDirectories, tool.AdditionalIncludeDirectories ); - strm << XPair( _AdditionalOptions, tool.AdditionalOptions ); + strm << XPair( _AdditionalOptions, tool.AdditionalOptions, " " ); if ( tool.Culture != rcUseDefault ) strm << EPair( _Culture, tool.Culture ); strm << XPair( _FullIncludePath, tool.FullIncludePath ); strm << TPair( _IgnoreStandardIncludePath, tool.IgnoreStandardIncludePath ); strm << XPair( _PreprocessorDefinitions, tool.PreprocessorDefinitions ); strm << SPair( _ResourceOutputFileName, tool.ResourceOutputFileName ); if ( tool.ShowProgress != linkProgressNotSet ) strm << EPair( _ShowProgress, tool.ShowProgress ); strm << "/>"; return strm; } // VCEventTool ------------------------------------------------- QTextStream &operator<<( QTextStream &strm, const VCEventTool &tool ) { strm << _begTool3; strm << SPair( _ToolName, tool.ToolName ); strm << SPair( _ToolPath, tool.ToolPath ); strm << SPair( _CommandLine4, tool.CommandLine ); strm << SPair( _Description4, tool.Description ); strm << TPair( _ExcludedFromBuild, tool.ExcludedFromBuild ); strm << "/>"; return strm; } // VCPostBuildEventTool --------------------------------------------- VCPostBuildEventTool::VCPostBuildEventTool() { ToolName = "VCPostBuildEventTool"; } // VCPreBuildEventTool ---------------------------------------------- VCPreBuildEventTool::VCPreBuildEventTool() { ToolName = "VCPreBuildEventTool"; } // VCPreLinkEventTool ----------------------------------------------- VCPreLinkEventTool::VCPreLinkEventTool() { ToolName = "VCPreLinkEventTool"; } // VCConfiguration -------------------------------------------------- VCConfiguration::VCConfiguration() : ATLMinimizesCRunTimeLibraryUsage( unset ), BuildBrowserInformation( unset ), CharacterSet( charSetNotSet ), ConfigurationType( typeApplication ), RegisterOutput( unset ), UseOfATL( useATLNotSet ), UseOfMfc( useMfcStdWin ), WholeProgramOptimization( unset ) { compiler.config = this; linker.config = this; idl.config = this; } QTextStream &operator<<( QTextStream &strm, const VCConfiguration &tool ) { strm << _begConfiguration; strm << SPair( _Name3, tool.Name ); strm << SPair( _OutputDirectory3, tool.OutputDirectory ); strm << TPair( _ATLMinimizesCRunTimeLibraryUsage, tool.ATLMinimizesCRunTimeLibraryUsage ); strm << TPair( _BuildBrowserInformation, tool.BuildBrowserInformation ); if ( tool.CharacterSet != charSetNotSet) strm << EPair( _CharacterSet, tool.CharacterSet ); strm << EPair( _ConfigurationType, tool.ConfigurationType ); strm << SPair( _DeleteExtensionsOnClean, tool.DeleteExtensionsOnClean ); strm << SPair( _ImportLibrary, tool.ImportLibrary ); strm << SPair( _IntermediateDirectory, tool.IntermediateDirectory ); strm << SPair( _PrimaryOutput, tool.PrimaryOutput ); strm << SPair( _ProgramDatabase, tool.ProgramDatabase ); strm << TPair( _RegisterOutput, tool.RegisterOutput ); if ( tool.UseOfATL != useATLNotSet) strm << EPair( _UseOfATL, tool.UseOfATL ); strm << EPair( _UseOfMfc, tool.UseOfMfc ); strm << TPair( _WholeProgramOptimization, tool.WholeProgramOptimization ); strm << ">"; strm << tool.compiler; strm << tool.custom; if ( tool.ConfigurationType == typeStaticLibrary ) strm << tool.librarian; else strm << tool.linker; strm << tool.idl; strm << tool.postBuild; strm << tool.preBuild; strm << tool.preLink; strm << tool.resource; strm << _endConfiguration; return strm; } // VCFilter --------------------------------------------------------- VCFilter::VCFilter() : ParseFiles( unset ) { } void VCFilter::generateMOC( QTextStream &strm, QString str ) const { QString mocOutput = Project->findMocDestination( str ); QString mocApp = Project->var( "QMAKE_MOC" ); if( mocOutput.isEmpty() ) { // In specialcases we DO moc .cpp files // when the result is an .moc file if ( !str.endsWith(".moc") ) return; mocOutput = str; str = Project->findMocSource( mocOutput ); } strm << _begFileConfiguration; strm << _Name5; strm << Config->Name; strm << "\">"; strm << _begTool5; strm << _VCCustomBuildTool; strm << _Description6; strm << "Moc'ing " << str << "...\""; strm << _CommandLine6; strm << mocApp; strm << " " << str << " -o " << mocOutput << "\""; strm << _AdditionalDependencies6; strm << mocApp << "\""; strm << _Outputs6; strm << mocOutput << "\""; strm << "/>"; strm << _endFileConfiguration; } void VCFilter::generateUIC( QTextStream &strm, const QString& str ) const { QString uicApp = Project->var("QMAKE_UIC"); QString mocApp = Project->var( "QMAKE_MOC" ); QString fname = str.section( '\\', -1 ); QString mocDir = Project->var( "MOC_DIR" ); - int dot = fname.findRev( '.' ); - if( dot != -1 ) - fname.truncate( dot ); + QString uiDir = Project->var( "UI_DIR" ); + QString uiHeaders; + QString uiSources; + // Determining the paths for the output files. int slash = str.findRev( '\\' ); QString pname = ( slash != -1 ) ? str.left( slash+1 ) : QString(".\\"); + if( !uiDir.isEmpty() ) { + uiHeaders = uiDir; + uiSources = uiDir; + } else { + uiHeaders = Project->var( "UI_HEADERS_DIR" ); + uiSources = Project->var( "UI_SOURCES_DIR" ); + if( uiHeaders.isEmpty() ) + uiHeaders = pname; + if( uiSources.isEmpty() ) + uiSources = pname; + } + if( !uiHeaders.endsWith( "\\" ) ) + uiHeaders += "\\"; + if( !uiSources.endsWith( "\\" ) ) + uiSources += "\\"; + + // Determine the file name. + int dot = fname.findRev( '.' ); + if( dot != -1 ) + fname.truncate( dot ); strm << _begFileConfiguration; strm << _Name5; strm << Config->Name; strm << "\">"; strm << _begTool5; strm << _VCCustomBuildTool; strm << _Description6; strm << "Uic'ing " << str << "...\""; strm << _CommandLine6; - strm << uicApp << " " << str << " -o " << pname << fname << ".h && "; // Create .h from .ui file - strm << uicApp << " " << str << " -i " << fname << ".h -o " << pname << fname << ".cpp && "; // Create .cpp from .ui file - strm << mocApp << " " << pname << fname << ".h -o " << mocDir << "moc_" << fname << ".cpp\""; + strm << uicApp << " " << str << " -o " << uiHeaders << fname << ".h && "; // Create .h from .ui file + strm << uicApp << " " << str << " -i " << fname << ".h -o " << uiSources << fname << ".cpp && "; // Create .cpp from .ui file + strm << mocApp << " " << uiHeaders << fname << ".h -o " << mocDir << "moc_" << fname << ".cpp\""; strm << _AdditionalDependencies6; strm << mocApp << ";" << uicApp << "\""; strm << _Outputs6; - strm << pname << fname << ".h;" << pname << fname << ".cpp;" << mocDir << "moc_" << fname << ".cpp\""; + strm << uiHeaders << fname << ".h;" << uiSources << fname << ".cpp;" << mocDir << "moc_" << fname << ".cpp\""; strm << "/>"; strm << _endFileConfiguration; } QTextStream &operator<<( QTextStream &strm, const VCFilter &tool ) { if ( tool.Files.count() == 0 ) return strm; strm << _begFilter; strm << SPair( _Name3, tool.Name ); strm << TPair( _ParseFiles, tool.ParseFiles ); strm << SPair( _Filter, tool.Filter ); strm << ">"; for ( QStringList::ConstIterator it = tool.Files.begin(); it != tool.Files.end(); ++it ) { strm << _begFile; strm << SPair( _RelativePath, *it ); strm << ">"; if ( tool.CustomBuild == moc ) tool.generateMOC( strm, *it ); else if ( tool.CustomBuild == uic ) tool.generateUIC( strm, *it ); strm << _endFile; } strm << _endFilter; return strm; } // VCProject -------------------------------------------------------- VCProject::VCProject() { - QUuid uniqueId; #if defined(Q_WS_WIN32) GUID guid; + QUuid uniqueId; HRESULT h = CoCreateGuid( &guid ); if ( h == S_OK ) uniqueId = QUuid( guid ); ProjectGUID = uniqueId.toString(); #else // Qt doesn't support GUID on other platforms yet ProjectGUID = ""; #endif } QTextStream &operator<<( QTextStream &strm, const VCProject &tool ) { strm << _xmlInit; strm << _begVisualStudioProject; strm << _ProjectType; strm << SPair( _Version1, tool.Version ); strm << SPair( _Name1, tool.Name ); strm << SPair( _ProjectGUID, tool.ProjectGUID ); strm << SPair( _SccProjectName, tool.SccProjectName ); strm << SPair( _SccLocalPath, tool.SccLocalPath ); strm << ">"; strm << _begPlatforms; strm << _begPlatform; strm << SPair( _Name3, tool.PlatformName ); strm << "/>"; strm << _endPlatforms; strm << _begConfigurations; strm << tool.Configuration; strm << _endConfigurations; strm << _begFiles; strm << tool.SourceFiles; strm << tool.HeaderFiles; strm << tool.MOCFiles; strm << tool.UICFiles; strm << tool.FormFiles; strm << tool.TranslationFiles; strm << tool.LexYaccFiles; strm << tool.ResourceFiles; strm << _endFiles; strm << _begGlobals; strm << _endGlobals; strm << _endVisualStudioProject; return strm; } diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 2d09280..1dca68d 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -9,767 +9,765 @@ ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __MSVC_OBJECTMODEL_H__ #define __MSVC_OBJECTMODEL_H__ #include "project.h" #include <qstring.h> #include <qstringlist.h> /* This Object model is of course VERY simplyfied, and does not actually follow the original MSVC object model. However, it fulfilles the basic needs for qmake */ /* If a triState value is 'unset' then the corresponding property is not in the output, forcing the tool to utilize default values. False/True values will be in the output... */ enum customBuildCheck { none, moc, uic, lexyacc }; enum triState { unset = -1, _False = 0, _True = 1 }; enum addressAwarenessType { addrAwareDefault, addrAwareNoLarge, addrAwareLarge }; enum asmListingOption { asmListingNone, asmListingAssemblyOnly, asmListingAsmMachineSrc, asmListingAsmMachine, asmListingAsmSrc }; enum basicRuntimeCheckOption { runtimeBasicCheckNone, runtimeCheckStackFrame, runtimeCheckUninitVariables, runtimeBasicCheckAll }; enum browseInfoOption { brInfoNone, brAllInfo, brNoLocalSymbols }; enum callingConventionOption { callConventionDefault = -1, callConventionCDecl, callConventionFastCall, callConventionStdCall }; enum charSet { charSetNotSet, charSetUnicode, charSetMBCS }; enum compileAsManagedOptions { managedDefault = -1, managedAssembly = 2 }; enum CompileAsOptions{ compileAsDefault, compileAsC, compileAsCPlusPlus }; enum ConfigurationTypes { typeUnknown = 0, typeApplication = 1, typeDynamicLibrary = 2, typeStaticLibrary = 4, typeGeneric = 10 }; enum debugOption { debugDisabled, debugOldStyleInfo, debugLineInfoOnly, debugEnabled, debugEditAndContinue }; enum eAppProtectionOption { eAppProtectUnchanged, eAppProtectLow, eAppProtectMedium, eAppProtectHigh }; enum enumResourceLangID { rcUseDefault = 0, rcAfrikaans = 1078, rcAlbanian = 1052, rcArabicAlgeria = 5121, rcArabicBahrain = 15361, rcArabicEgypt = 3073, rcArabicIraq = 2049, rcArabicJordan = 11265, rcArabicKuwait = 13313, rcArabicLebanon = 12289, rcArabicLibya = 4097, rcArabicMorocco = 6145, rcArabicOman = 8193, rcArabicQatar = 16385, rcArabicSaudi = 1025, rcArabicSyria = 10241, rcArabicTunisia = 7169, rcArabicUnitedArabEmirates = 14337, rcArabicYemen = 9217, rcBasque = 1069, rcBulgarian = 1026, rcByelorussian = 1059, rcCatalan = 1027, rcChineseHongKong = 3076, rcChinesePRC = 2052, rcChineseSingapore = 4100, rcChineseTaiwan = 1028, rcCroatian = 1050, rcCzech = 1029, rcDanish = 1030, rcDutchBelgium = 2067, rcDutchStandard = 1043, rcEnglishAustralia = 3081, rcEnglishBritain = 2057, rcEnglishCanada = 4105, RcEnglishCaribbean = 9225, rcEnglishIreland = 6153, rcEnglishJamaica = 8201, rcEnglishNewZealand = 5129, rcEnglishSouthAfrica = 7177, rcEnglishUS = 1033, rcEstonian = 1061, rcFarsi = 1065, rcFinnish = 1035, rcFrenchBelgium = 2060, rcFrenchCanada = 3084, rcFrenchLuxembourg = 5132, rcFrenchStandard = 1036, rcFrenchSwitzerland = 4108, rcGermanAustria = 3079, rcGermanLichtenstein = 5127, rcGermanLuxembourg = 4103, rcGermanStandard = 1031, rcGermanSwitzerland = 2055, rcGreek = 1032, rcHebrew = 1037, rcHungarian = 1038, rcIcelandic = 1039, rcIndonesian = 1057, rcItalianStandard = 1040, rcItalianSwitzerland = 2064, rcJapanese = 1041, rcKorean = 1042, rcKoreanJohab = 2066, rcLatvian = 1062, rcLithuanian = 1063, rcNorwegianBokmal = 1044, rcNorwegianNynorsk = 2068, rcPolish = 1045, rcPortugueseBrazilian = 1046, rcPortugueseStandard = 2070, rcRomanian = 1048, rcRussian = 1049, rcSerbian = 2074, rcSlovak = 1051, rcSpanishArgentina = 11274, rcSpanishBolivia = 16394, rcSpanishChile = 13322, rcSpanishColombia = 9226, rcSpanishCostaRica = 5130, rcSpanishDominicanRepublic = 7178, rcSpanishEcuador = 12298, rcSpanishGuatemala = 4106, rcSpanishMexico = 2058, rcSpanishModern = 3082, rcSpanishPanama = 6154, rcSpanishParaguay = 15370, rcSpanishPeru = 10250, rcSpanishTraditional = 1034, rcSpanishUruguay = 14346, rcSpanishVenezuela = 8202, rcSwedish = 1053, rcThai = 1054, rcTurkish = 1055, rcUkrainian = 1058, rcUrdu = 1056 }; enum enumSccEvent { eProjectInScc, ePreDirtyNotification }; enum favorSizeOrSpeedOption { favorNone, favorSpeed, favorSize }; enum genProxyLanguage { genProxyNative, genProxyManaged }; enum inlineExpansionOption { expandDisable, expandOnlyInline, expandAnySuitable }; enum linkIncrementalType { linkIncrementalDefault, linkIncrementalNo, linkIncrementalYes }; enum linkProgressOption { linkProgressNotSet, linkProgressAll, linkProgressLibs }; enum machineTypeOption { machineNotSet, machineX86 }; enum midlCharOption { midlCharUnsigned, midlCharSigned, midlCharAscii7 }; enum midlErrorCheckOption { midlEnableCustom, midlDisableAll, midlEnableAll }; enum midlStructMemberAlignOption { midlAlignNotSet, midlAlignSingleByte, midlAlignTwoBytes, midlAlignFourBytes, midlAlignEightBytes, midlAlignSixteenBytes }; enum midlTargetEnvironment { midlTargetNotSet, midlTargetWin32, midlTargetWin64 }; enum midlWarningLevelOption { midlWarningLevel_0, midlWarningLevel_1, midlWarningLevel_2, midlWarningLevel_3, midlWarningLevel_4 }; enum optFoldingType { optFoldingDefault, optNoFolding, optFolding }; enum optimizeOption { optimizeDisabled, optimizeMinSpace, optimizeMaxSpeed, optimizeFull, optimizeCustom }; enum optRefType { optReferencesDefault, optNoReferences, optReferences }; enum optWin98Type { optWin98Default, optWin98No, optWin98Yes }; enum pchOption { pchNone, pchCreateUsingSpecific, pchGenerateAuto, pchUseUsingSpecific }; enum preprocessOption { preprocessNo, preprocessYes, preprocessNoLineNumbers }; enum ProcessorOptimizeOption { procOptimizeBlended, procOptimizePentium, procOptimizePentiumProAndAbove }; enum RemoteDebuggerType { DbgLocal, DbgRemote, DbgRemoteTCPIP }; enum runtimeLibraryOption { rtMultiThreaded, rtMultiThreadedDebug, rtMultiThreadedDLL, rtMultiThreadedDebugDLL, rtSingleThreaded, rtSingleThreadedDebug }; enum structMemberAlignOption { alignNotSet, alignSingleByte, alignTwoBytes, alignFourBytes, alignEightBytes, alignSixteenBytes }; enum subSystemOption { subSystemNotSet, subSystemConsole, subSystemWindows }; enum termSvrAwarenessType { termSvrAwareDefault, termSvrAwareNo, termSvrAwareYes }; enum toolSetType { toolSetUtility, toolSetMakefile, toolSetLinker, toolSetLibrarian, toolSetAll }; enum TypeOfDebugger { DbgNativeOnly, DbgManagedOnly, DbgMixed, DbgAuto }; enum useOfATL { useATLNotSet, useATLStatic, useATLDynamic }; enum useOfMfc { useMfcStdWin, useMfcStatic, useMfcDynamic }; enum warningLevelOption { warningLevel_0, warningLevel_1, warningLevel_2, warningLevel_3, warningLevel_4 }; class VCToolBase { protected: // Functions VCToolBase(){}; - ~VCToolBase(){}; + virtual ~VCToolBase(){} virtual bool parseOption( const char* option ) = 0; public: - bool parseOptions( QStringList& options ) { - bool result = TRUE; - for ( QStringList::ConstIterator it=options.begin(); (it!=options.end()) && result; it++ ) - result = parseOption( (*it).latin1() ); - return result; + void parseOptions( QStringList& options ) { + for ( QStringList::ConstIterator it=options.begin(); (it!=options.end()); it++ ) + parseOption( (*it).latin1() ); } }; class VCConfiguration; class VCProject; class VCCLCompilerTool : public VCToolBase { public: // Functions VCCLCompilerTool(); - ~VCCLCompilerTool(){}; - virtual bool parseOption( const char* option ); + virtual ~VCCLCompilerTool(){} + bool parseOption( const char* option ); // Variables QStringList AdditionalIncludeDirectories; QStringList AdditionalOptions; QStringList AdditionalUsingDirectories; QString AssemblerListingLocation; asmListingOption AssemblerOutput; basicRuntimeCheckOption BasicRuntimeChecks; browseInfoOption BrowseInformation; QString BrowseInformationFile; triState BufferSecurityCheck; callingConventionOption CallingConvention; CompileAsOptions CompileAs; compileAsManagedOptions CompileAsManaged; triState CompileOnly; debugOption DebugInformationFormat; triState DefaultCharIsUnsigned; triState Detect64BitPortabilityProblems; triState DisableLanguageExtensions; QStringList DisableSpecificWarnings; triState EnableFiberSafeOptimizations; triState EnableFunctionLevelLinking; triState EnableIntrinsicFunctions; triState ExceptionHandling; triState ExpandAttributedSource; favorSizeOrSpeedOption FavorSizeOrSpeed; triState ForceConformanceInForLoopScope; QStringList ForcedIncludeFiles; QStringList ForcedUsingFiles; preprocessOption GeneratePreprocessedFile; triState GlobalOptimizations; triState IgnoreStandardIncludePath; triState ImproveFloatingPointConsistency; inlineExpansionOption InlineFunctionExpansion; triState KeepComments; triState MinimalRebuild; QString ObjectFile; triState OmitFramePointers; optimizeOption Optimization; ProcessorOptimizeOption OptimizeForProcessor; triState OptimizeForWindowsApplication; QString OutputFile; QString PrecompiledHeaderFile; QString PrecompiledHeaderThrough; QStringList PreprocessorDefinitions; QString ProgramDataBaseFileName; runtimeLibraryOption RuntimeLibrary; triState RuntimeTypeInfo; triState ShowIncludes; triState SmallerTypeCheck; triState StringPooling; structMemberAlignOption StructMemberAlignment; triState SuppressStartupBanner; triState TreatWChar_tAsBuiltInType; triState TurnOffAssemblyGeneration; triState UndefineAllPreprocessorDefinitions; QStringList UndefinePreprocessorDefinitions; pchOption UsePrecompiledHeader; triState WarnAsError; warningLevelOption WarningLevel; triState WholeProgramOptimization; VCConfiguration* config; }; class VCLinkerTool : public VCToolBase { public: // Functions VCLinkerTool(); - ~VCLinkerTool(){}; - virtual bool parseOption( const char* option ); + virtual ~VCLinkerTool(){} + bool parseOption( const char* option ); // Variables QStringList AdditionalDependencies; QStringList AdditionalLibraryDirectories; QStringList AdditionalOptions; QStringList AddModuleNamesToAssembly; QString BaseAddress; QStringList DelayLoadDLLs; optFoldingType EnableCOMDATFolding; QString EntryPointSymbol; QStringList ForceSymbolReferences; QString FunctionOrder; triState GenerateDebugInformation; triState GenerateMapFile; long HeapCommitSize; long HeapReserveSize; triState IgnoreAllDefaultLibraries; QStringList IgnoreDefaultLibraryNames; triState IgnoreEmbeddedIDL; triState IgnoreImportLibrary; QString ImportLibrary; addressAwarenessType LargeAddressAware; triState LinkDLL; linkIncrementalType LinkIncremental; triState LinkTimeCodeGeneration; QString LinkToManagedResourceFile; triState MapExports; QString MapFileName; triState MapLines; QString MergedIDLBaseFileName; QString MergeSections; // Should be list? QString MidlCommandFile; QString ModuleDefinitionFile; // Should be list? optWin98Type OptimizeForWindows98; optRefType OptimizeReferences; QString OutputFile; QString ProgramDatabaseFile; triState RegisterOutput; triState ResourceOnlyDLL; triState SetChecksum; linkProgressOption ShowProgress; long StackCommitSize; long StackReserveSize; QString StripPrivateSymbols; // Should be list? subSystemOption SubSystem; triState SupportUnloadOfDelayLoadedDLL; triState SuppressStartupBanner; triState SwapRunFromCD; triState SwapRunFromNet; machineTypeOption TargetMachine; termSvrAwarenessType TerminalServerAware; triState TurnOffAssemblyGeneration; QString TypeLibraryFile; long TypeLibraryResourceID; QString Version; VCConfiguration* config; }; class VCMIDLTool : public VCToolBase { public: // Functions VCMIDLTool(); - ~VCMIDLTool(){}; - virtual bool parseOption( const char* option ); + virtual ~VCMIDLTool(){} + bool parseOption( const char* option ); // Variables QStringList AdditionalIncludeDirectories; QStringList AdditionalOptions; QStringList CPreprocessOptions; midlCharOption DefaultCharType; QString DLLDataFileName; // Should be list? midlErrorCheckOption EnableErrorChecks; triState ErrorCheckAllocations; triState ErrorCheckBounds; triState ErrorCheckEnumRange; triState ErrorCheckRefPointers; triState ErrorCheckStubData; QStringList FullIncludePath; triState GenerateStublessProxies; triState GenerateTypeLibrary; QString HeaderFileName; triState IgnoreStandardIncludePath; QString InterfaceIdentifierFileName; triState MkTypLibCompatible; QString OutputDirectory; QStringList PreprocessorDefinitions; QString ProxyFileName; QString RedirectOutputAndErrors; midlStructMemberAlignOption StructMemberAlignment; triState SuppressStartupBanner; midlTargetEnvironment TargetEnvironment; QString TypeLibraryName; QStringList UndefinePreprocessorDefinitions; triState ValidateParameters; triState WarnAsError; midlWarningLevelOption WarningLevel; VCConfiguration* config; }; class VCLibrarianTool : public VCToolBase { public: // Functions VCLibrarianTool(); - ~VCLibrarianTool(){}; - virtual bool parseOption( const char* option ){ return FALSE; }; + virtual ~VCLibrarianTool(){} + bool parseOption( const char* ){ return FALSE; }; // Variables QStringList AdditionalDependencies; QStringList AdditionalLibraryDirectories; QStringList AdditionalOptions; QStringList ExportNamedFunctions; QStringList ForceSymbolReferences; triState IgnoreAllDefaultLibraries; QStringList IgnoreDefaultLibraryNames; QString ModuleDefinitionFile; QString OutputFile; triState SuppressStartupBanner; }; class VCCustomBuildTool : public VCToolBase { public: // Functions VCCustomBuildTool(); - ~VCCustomBuildTool(){}; - virtual bool parseOption( const char* option ){ return FALSE; }; + virtual ~VCCustomBuildTool(){} + bool parseOption( const char* ){ return FALSE; }; // Variables QStringList AdditionalDependencies; QString CommandLine; QString Description; QString Outputs; QString ToolName; QString ToolPath; }; class VCResourceCompilerTool : public VCToolBase { public: // Functions VCResourceCompilerTool(); - ~VCResourceCompilerTool(){}; - virtual bool parseOption( const char* option ){ return FALSE; }; + virtual ~VCResourceCompilerTool(){} + bool parseOption( const char* ){ return FALSE; }; // Variables QStringList AdditionalIncludeDirectories; QStringList AdditionalOptions; enumResourceLangID Culture; QStringList FullIncludePath; triState IgnoreStandardIncludePath; QStringList PreprocessorDefinitions; QString ResourceOutputFileName; linkProgressOption ShowProgress; QString ToolPath; }; class VCEventTool : public VCToolBase { protected: // Functions VCEventTool() : ExcludedFromBuild( unset ){}; - ~VCEventTool(){}; - virtual bool parseOption( const char* option ){ return FALSE; }; + virtual ~VCEventTool(){} + bool parseOption( const char* ){ return FALSE; }; public: // Variables QString CommandLine; QString Description; triState ExcludedFromBuild; QString ToolName; QString ToolPath; }; class VCPostBuildEventTool : public VCEventTool { public: VCPostBuildEventTool(); - ~VCPostBuildEventTool(){}; + ~VCPostBuildEventTool(){} }; class VCPreBuildEventTool : public VCEventTool { public: VCPreBuildEventTool(); - ~VCPreBuildEventTool(){}; + ~VCPreBuildEventTool(){} }; class VCPreLinkEventTool : public VCEventTool { public: VCPreLinkEventTool(); - ~VCPreLinkEventTool(){}; + ~VCPreLinkEventTool(){} }; class VCConfiguration { public: // Functions VCConfiguration(); - ~VCConfiguration(){}; + ~VCConfiguration(){} // Variables triState ATLMinimizesCRunTimeLibraryUsage; triState BuildBrowserInformation; charSet CharacterSet; ConfigurationTypes ConfigurationType; QString DeleteExtensionsOnClean; QString ImportLibrary; QString IntermediateDirectory; QString Name; QString OutputDirectory; QString PrimaryOutput; QString ProgramDatabase; triState RegisterOutput; useOfATL UseOfATL; useOfMfc UseOfMfc; triState WholeProgramOptimization; // XML sub-parts VCCLCompilerTool compiler; VCLinkerTool linker; VCLibrarianTool librarian; VCCustomBuildTool custom; VCMIDLTool idl; VCPostBuildEventTool postBuild; VCPreBuildEventTool preBuild; VCPreLinkEventTool preLink; VCResourceCompilerTool resource; }; class VcprojGenerator; class VCFilter { public: // Functions VCFilter(); - ~VCFilter(){}; + ~VCFilter(){} void generateMOC( QTextStream &strm, QString str ) const; void generateUIC( QTextStream &strm, const QString& str ) const; // Variables QString Name; QString Filter; triState ParseFiles; QStringList Files; VcprojGenerator* Project; VCConfiguration* Config; customBuildCheck CustomBuild; }; class VCProject { public: // Functions VCProject(); - ~VCProject(){}; + ~VCProject(){} // Variables QString Name; QString Version; QString ProjectGUID; QString SccProjectName; QString SccLocalPath; QString PlatformName; // XML sub-parts VCConfiguration Configuration; VCFilter SourceFiles; VCFilter HeaderFiles; VCFilter MOCFiles; VCFilter UICFiles; VCFilter FormFiles; VCFilter TranslationFiles; VCFilter LexYaccFiles; VCFilter ResourceFiles; }; QTextStream &operator<<( QTextStream &, const VCCLCompilerTool & ); QTextStream &operator<<( QTextStream &, const VCLinkerTool & ); QTextStream &operator<<( QTextStream &, const VCMIDLTool & ); QTextStream &operator<<( QTextStream &, const VCCustomBuildTool & ); QTextStream &operator<<( QTextStream &, const VCLibrarianTool & ); QTextStream &operator<<( QTextStream &, const VCResourceCompilerTool & ); QTextStream &operator<<( QTextStream &, const VCEventTool & ); QTextStream &operator<<( QTextStream &, const VCConfiguration & ); QTextStream &operator<<( QTextStream &, const VCFilter & ); QTextStream &operator<<( QTextStream &, const VCProject & ); #endif //__MSVC_OBJECTMODEL_H__ diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index a2bb6e9..d2cbc31 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1,1050 +1,1214 @@ /**************************************************************************** ** $Id$ ** ** Definition of VcprojGenerator class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "msvc_vcproj.h" #include "option.h" #include <qdir.h> -#include <stdlib.h> #include <qregexp.h> +#include <qdict.h> +#include <quuid.h> +#include <stdlib.h> #if defined(Q_OS_WIN32) #include <objbase.h> +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + ulong Data1; + ushort Data2; + ushort Data3; + uchar Data4[8]; +} GUID; +#endif #endif +// Flatfile Tags ---------------------------------------------------- +const char* _snlHeader = "Microsoft Visual Studio Solution File, Format Version 7.00"; + // The following UUID _may_ change for later servicepacks... + // If so we need to search through the registry at + // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects + // to find the subkey that contains a "PossibleProjectExtension" + // containing "vcproj"... + // Use the hardcoded value for now so projects generated on other + // platforms are actually usable. +const char* _snlMSVCvcprojGUID = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; +const char* _snlProjectBeg = "\nProject(\""; +const char* _snlProjectMid = "\") = "; +const char* _snlProjectEnd = "\nEndProject"; +const char* _snlGlobalBeg = "\nGlobal"; +const char* _snlGlobalEnd = "\nEndGlobal"; +const char* _snlSolutionConf = "\n\tGlobalSection(SolutionConfiguration) = preSolution" + "\n\t\tConfigName.0 = Release" + "\n\tEndGlobalSection"; +const char* _snlProjDepBeg = "\n\tGlobalSection(ProjectDependencies) = postSolution"; +const char* _snlProjDepEnd = "\n\tEndGlobalSection"; +const char* _snlProjConfBeg = "\n\tGlobalSection(ProjectConfiguration) = postSolution"; +const char* _snlProjConfTag1 = ".Release.ActiveCfg = Release|Win32"; +const char* _snlProjConfTag2 = ".Release.Build.0 = Release|Win32"; +const char* _snlProjConfEnd = "\n\tEndGlobalSection"; +const char* _snlExtSections = "\n\tGlobalSection(ExtensibilityGlobals) = postSolution" + "\n\tEndGlobalSection" + "\n\tGlobalSection(ExtensibilityAddIns) = postSolution" + "\n\tEndGlobalSection"; +// ------------------------------------------------------------------ + VcprojGenerator::VcprojGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE) { } /* \internal Generates a project file for the given profile. Options are either a Visual Studio projectfiles, or - recursive projectfiles.. Maybe we can make .sln files - someday? + solutionfiles by parsing recursive projectdirectories. */ bool VcprojGenerator::writeMakefile(QTextStream &t) { // Check if all requirements are fullfilled if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) { fprintf(stderr, "Project file not generated because all requirements not met:\n\t%s\n", var("QMAKE_FAILED_REQUIREMENTS").latin1()); return TRUE; } - // Generate full project file + // Generate project file if(project->first("TEMPLATE") == "vcapp" || project->first("TEMPLATE") == "vclib") { debug_msg(1, "Generator: MSVC.NET: Writing project file" ); t << vcProject; return TRUE; - } else if(project->first("TEMPLATE") == "vcsubdirs") { // Generate recursive project + } + // Generate solution file + else if(project->first("TEMPLATE") == "vcsubdirs") { debug_msg(1, "Generator: MSVC.NET: Writing solution file" ); writeSubDirs(t); return TRUE; } return FALSE; } struct VcsolutionDepend { + QString uuid; QString vcprojFile, orig_target, target; + ::target targetType; QStringList dependencies; }; +QUuid VcprojGenerator::increaseUUID( const QUuid &id ) +{ + QUuid result( id ); + Q_LONG dataFirst = (result.data4[0] << 24) + + (result.data4[1] << 16) + + (result.data4[2] << 8) + + result.data4[3]; + Q_LONG dataLast = (result.data4[4] << 24) + + (result.data4[5] << 16) + + (result.data4[6] << 8) + + result.data4[7]; + + if ( !(dataLast++) ) + dataFirst++; + + result.data4[0] = uchar((dataFirst >> 24) & 0xff); + result.data4[1] = uchar((dataFirst >> 16) & 0xff); + result.data4[2] = uchar((dataFirst >> 8) & 0xff); + result.data4[3] = uchar( dataFirst & 0xff); + result.data4[4] = uchar((dataLast >> 24) & 0xff); + result.data4[5] = uchar((dataLast >> 16) & 0xff); + result.data4[6] = uchar((dataLast >> 8) & 0xff); + result.data4[7] = uchar( dataLast & 0xff); + return result; +} + void VcprojGenerator::writeSubDirs(QTextStream &t) { if(project->first("TEMPLATE") == "subdirs") { writeHeader(t); Win32MakefileGenerator::writeSubDirs(t); return; } - QPtrList<VcsolutionDepend> solution_depends; - solution_depends.setAutoDelete(TRUE); + t << _snlHeader; + QUuid solutionGUID; +#if defined(Q_WS_WIN32) + GUID guid; + HRESULT h = CoCreateGuid( &guid ); + if ( h == S_OK ) + solutionGUID = QUuid( guid ); +#else + // Qt doesn't support GUID on other platforms yet, + // so we use the all-zero uuid, and increase that. +#endif + + + QDict<VcsolutionDepend> solution_depends; + QPtrList<VcsolutionDepend> solution_cleanup; + solution_cleanup.setAutoDelete(TRUE); QStringList subdirs = project->variables()["SUBDIRS"]; QString oldpwd = QDir::currentDirPath(); for(QStringList::Iterator it = subdirs.begin(); it != subdirs.end(); ++it) { QFileInfo fi(Option::fixPathToLocalOS((*it), TRUE)); if(fi.exists()) { if(fi.isDir()) { QString profile = (*it); if(!profile.endsWith(Option::dir_sep)) profile += Option::dir_sep; profile += fi.baseName() + ".pro"; subdirs.append(profile); } else { QMakeProject tmp_proj; QString dir = fi.dirPath(), fn = fi.fileName(); if(!dir.isEmpty()) { if(!QDir::setCurrent(dir)) fprintf(stderr, "Cannot find directory: %s\n", dir.latin1()); } if(tmp_proj.read(fn, oldpwd)) { if(tmp_proj.first("TEMPLATE") == "vcsubdirs") { QStringList tmp_subdirs = fileFixify(tmp_proj.variables()["SUBDIRS"]); subdirs += tmp_subdirs; - } else if(tmp_proj.first("TEMPLATE") == "vcapp" || - tmp_proj.first("TEMPLATE") == "vclib") { - QString vcproj = fi.baseName() + project->first("VCPROJ_EXTENSION"); - if(QFile::exists(vcproj) || 1) { - VcprojGenerator tmp_dsp(&tmp_proj); - tmp_dsp.setNoIO(TRUE); - tmp_dsp.init(); + } else if(tmp_proj.first("TEMPLATE") == "vcapp" || tmp_proj.first("TEMPLATE") == "vclib") { + // Initialize a 'fake' project to get the correct variables + // and to be able to extract all the dependencies + VcprojGenerator tmp_vcproj(&tmp_proj); + tmp_vcproj.setNoIO(TRUE); + tmp_vcproj.init(); if(Option::debug_level) { QMap<QString, QStringList> &vars = tmp_proj.variables(); for(QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it) { if(it.key().left(1) != "." && !it.data().isEmpty()) debug_msg(1, "%s: %s === %s", fn.latin1(), it.key().latin1(), it.data().join(" :: ").latin1()); } } + + // We assume project filename is [QMAKE_ORIG_TARGET].vcproj + QString vcproj = fixFilename(tmp_vcproj.project->first("QMAKE_ORIG_TARGET")) + project->first("VCPROJ_EXTENSION"); + + // If file doesn't exsist, then maybe the users configuration + // doesn't allow it to be created. Skip to next... + if(!QFile::exists(QDir::currentDirPath() + Option::dir_sep + vcproj)) { + qDebug( "Ignored (not found) '%s'", QString(QDir::currentDirPath() + Option::dir_sep + vcproj).latin1() ); + goto nextfile; // # Dirty! + } + VcsolutionDepend *newDep = new VcsolutionDepend; newDep->vcprojFile = fileFixify(vcproj); newDep->orig_target = tmp_proj.first("QMAKE_ORIG_TARGET"); newDep->target = tmp_proj.first("TARGET").section(Option::dir_sep, -1); + newDep->targetType = tmp_vcproj.projectTarget; + { + static QUuid uuid = solutionGUID; + uuid = increaseUUID( uuid ); + newDep->uuid = uuid.toString().upper(); + } if(newDep->target.endsWith(".dll")) newDep->target = newDep->target.left(newDep->target.length()-3) + "lib"; if(!tmp_proj.isEmpty("FORMS")) newDep->dependencies << "uic.exe"; { QStringList where("QMAKE_LIBS"); if(!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS")) where = tmp_proj.variables()["QMAKE_INTERNAL_PRL_LIBS"]; for(QStringList::iterator wit = where.begin(); wit != where.end(); ++wit) { QStringList &l = tmp_proj.variables()[(*wit)]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString opt = (*it); if(!opt.startsWith("/")) //Not a switch newDep->dependencies << opt.section(Option::dir_sep, -1); } } } - solution_depends.append(newDep); + solution_cleanup.append(newDep); + solution_depends.insert(newDep->target, newDep); + { + QRegExp libVersion("[0-9]{3,3}\\.lib$"); + if(libVersion.search(newDep->target) != -1) + solution_depends.insert(newDep->target.left(newDep->target.length() - + libVersion.matchedLength()) + ".lib", newDep); } + t << _snlProjectBeg << _snlMSVCvcprojGUID << _snlProjectMid + << "\"" << newDep->orig_target << "\", \"" << newDep->vcprojFile + << "\", \"" << newDep->uuid << "\""; + t << _snlProjectEnd; } } +nextfile: QDir::setCurrent(oldpwd); } } } - + t << _snlGlobalBeg; + t << _snlSolutionConf; + t << _snlProjDepBeg; + for(solution_cleanup.first(); solution_cleanup.current(); solution_cleanup.next()) { + int cnt = 0; + for(QStringList::iterator dit = solution_cleanup.current()->dependencies.begin(); + dit != solution_cleanup.current()->dependencies.end(); + ++dit) { VcsolutionDepend *vc; - QMap<QString, int> uuids; - QRegExp libVersion("[0-9]{3,3}\\.lib$"); - for(vc = solution_depends.first(); vc; vc = solution_depends.next()) { - static int uuid = 666; - uuids.insert(vc->target, uuid); - if(libVersion.match(vc->target) != -1) - uuids.insert(vc->target.left(vc->target.length() - libVersion.matchedLength()) + ".lib", - uuid); - t << "\"" << vc->orig_target << "\" \"" << vc->vcprojFile << "\" { " << uuid << " }" << endl; - uuid++; + if((vc=solution_depends[*dit])) { + if(solution_cleanup.current()->targetType != StaticLib || vc->targetType == Application) + t << "\n\t\t" << solution_cleanup.current()->uuid << "." << cnt++ << " = " << vc->uuid; } - for(vc = solution_depends.first(); vc; vc = solution_depends.next()) { - int uuid = uuids[vc->target], cnt = 0; - for(QStringList::iterator dit = vc->dependencies.begin(); dit != vc->dependencies.end(); ++dit) { - if(uuids.contains((*dit))) - t << uuid << "." << cnt++ << " = " << uuids[(*dit)] << endl; } } + t << _snlProjDepEnd; + t << _snlProjConfBeg; + for(solution_cleanup.first(); solution_cleanup.current(); solution_cleanup.next()) { + t << "\n\t\t" << solution_cleanup.current()->uuid << _snlProjConfTag1; + t << "\n\t\t" << solution_cleanup.current()->uuid << _snlProjConfTag2; + } + t << _snlProjConfEnd; + t << _snlExtSections; + t << _snlGlobalEnd; } // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ void VcprojGenerator::init() { if( init_flag ) return; if(project->first("TEMPLATE") == "vcsubdirs") { //too much work for subdirs init_flag = TRUE; return; } debug_msg(1, "Generator: MSVC.NET: Initializing variables" ); /* // Once to be nice and clean code... // Wouldn't life be great? // Are we building Qt? bool is_qt = ( project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX ); // Are we using Qt? bool isQtActive = project->isActiveConfig("qt"); if ( isQtActive ) { project->variables()["CONFIG"] += "moc"; project->variables()["CONFIG"] += "windows"; project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; if( projectTarget == SharedLib ) project->variables()["DEFINES"] += "QT_DLL"; if( project->isActiveConfig("accessibility" ) ) project->variables()["DEFINES"] += "QT_ACCESSIBILITY_SUPPORT"; if ( project->isActiveConfig("plugin")) { project->variables()["DEFINES"] += "QT_PLUGIN"; project->variables()["CONFIG"] += "dll"; } if( project->isActiveConfig("thread") ) { project->variables()["DEFINES"] += "QT_THREAD_SUPPORT"; project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; } else { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; } } if ( project->isActiveConfig("opengl") ) { project->variables()["CONFIG"] += "windows"; // <-- Also in 'qt' above project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; } */ initOld(); // Currently calling old DSP code to set variables. CLEAN UP! // Figure out what we're trying to build if ( project->first("TEMPLATE") == "vcapp" ) { projectTarget = Application; } else if ( project->first("TEMPLATE") == "vclib") { if ( project->isActiveConfig( "staticlib" ) ) projectTarget = StaticLib; else projectTarget = SharedLib; } initProject(); // Fills the whole project with proper data } void VcprojGenerator::initProject() { // Initialize XML sub elements // - Do this first since project elements may need // - to know of certain configuration options initConfiguration(); initSourceFiles(); initHeaderFiles(); initMOCFiles(); initUICFiles(); initFormsFiles(); initTranslationFiles(); initLexYaccFiles(); initResourceFiles(); // Own elements ----------------------------- vcProject.Name = project->first("QMAKE_ORIG_TARGET"); vcProject.Version = "7.00"; vcProject.PlatformName = ( vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32" ); // These are not used by Qt, but may be used by customers vcProject.SccProjectName = project->first("SCCPROJECTNAME"); vcProject.SccLocalPath = project->first("SCCLOCALPATH"); } void VcprojGenerator::initConfiguration() { // Initialize XML sub elements // - Do this first since main configuration elements may need // - to know of certain compiler/linker options initCompilerTool(); if ( projectTarget == StaticLib ) initLibrarianTool(); else initLinkerTool(); initIDLTool(); // Own elements ----------------------------- QString temp = project->first("BuildBrowserInformation"); switch ( projectTarget ) { case SharedLib: vcProject.Configuration.ConfigurationType = typeDynamicLibrary; break; case StaticLib: vcProject.Configuration.ConfigurationType = typeStaticLibrary; break; case Application: default: vcProject.Configuration.ConfigurationType = typeApplication; break; } - vcProject.Configuration.Name = ( project->isActiveConfig( "release" ) ? "Release|" : "Debug|" ); + vcProject.Configuration.Name = ( project->isActiveConfig( "debug" ) ? "Debug|" : "Release|" ); vcProject.Configuration.Name += ( vcProject.Configuration.idl.TargetEnvironment == midlTargetWin64 ? "Win64" : "Win32" ); vcProject.Configuration.ATLMinimizesCRunTimeLibraryUsage = ( project->first("ATLMinimizesCRunTimeLibraryUsage").isEmpty() ? _False : _True ); - vcProject.Configuration.BuildBrowserInformation = triState( temp.isEmpty() ? unset : temp.toShort() ); + vcProject.Configuration.BuildBrowserInformation = triState( temp.isEmpty() ? (short)unset : temp.toShort() ); temp = project->first("CharacterSet"); - vcProject.Configuration.CharacterSet = charSet( temp.isEmpty() ? charSetNotSet : temp.toShort() ); + vcProject.Configuration.CharacterSet = charSet( temp.isEmpty() ? (short)charSetNotSet : temp.toShort() ); vcProject.Configuration.DeleteExtensionsOnClean = project->first("DeleteExtensionsOnClean"); vcProject.Configuration.ImportLibrary = vcProject.Configuration.linker.ImportLibrary; vcProject.Configuration.IntermediateDirectory = project->first("OBJECTS_DIR"); // temp = (projectTarget == StaticLib) ? project->first("DESTDIR"):project->first("DLLDESTDIR"); vcProject.Configuration.OutputDirectory = "."; //( temp.isEmpty() ? QString(".") : temp ); vcProject.Configuration.PrimaryOutput = project->first("PrimaryOutput"); vcProject.Configuration.WholeProgramOptimization = vcProject.Configuration.compiler.WholeProgramOptimization; temp = project->first("UseOfATL"); if ( !temp.isEmpty() ) vcProject.Configuration.UseOfATL = useOfATL( temp.toShort() ); temp = project->first("UseOfMfc"); if ( !temp.isEmpty() ) vcProject.Configuration.UseOfMfc = useOfMfc( temp.toShort() ); // Configuration does not need parameters from // these sub XML items; initCustomBuildTool(); initPreBuildEventTools(); initPostBuildEventTools(); initPreLinkEventTools(); } void VcprojGenerator::initCompilerTool() { QString placement = project->first("OBJECTS_DIR"); if ( placement.isEmpty() ) - placement = project->isActiveConfig( "release" )? ".\\Release\\":".\\Debug\\"; + placement = ".\\"; vcProject.Configuration.compiler.AssemblerListingLocation = placement ; vcProject.Configuration.compiler.ProgramDataBaseFileName = placement ; vcProject.Configuration.compiler.ObjectFile = placement ; vcProject.Configuration.compiler.PrecompiledHeaderFile = placement + project->first("QMAKE_ORIG_TARGET") + ".pch"; if ( project->isActiveConfig("debug") ){ // Debug version vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS"] ); vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_DEBUG"] ); if ( project->isActiveConfig("thread") ) { if ( (projectTarget == Application) || (projectTarget == StaticLib) ) vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DBG"] ); else vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"] ); } else { vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_ST_DBG"] ); } } else { // Release version vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS"] ); vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_RELEASE"] ); vcProject.Configuration.compiler.PreprocessorDefinitions += "QT_NO_DEBUG"; + vcProject.Configuration.compiler.PreprocessorDefinitions += "NDEBUG"; if ( project->isActiveConfig("thread") ) { if ( (projectTarget == Application) || (projectTarget == StaticLib) ) vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT"] ); else vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_MT_DLL"] ); } else { vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_ST"] ); } } // Common for both release and debug if ( project->isActiveConfig("warn_off") ) vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_WARN_OFF"] ); - else + else if ( project->isActiveConfig("warn_on") ) vcProject.Configuration.compiler.parseOptions( project->variables()["QMAKE_CXXFLAGS_WARN_ON"] ); if ( project->isActiveConfig("windows") ) vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["MSVCPROJ_WINCONDEF"]; // Can this be set for ALL configs? // If so, use qmake.conf! if ( projectTarget == SharedLib ) vcProject.Configuration.compiler.PreprocessorDefinitions += "_WINDOWS"; vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["DEFINES"]; vcProject.Configuration.compiler.PreprocessorDefinitions += project->variables()["PRL_EXPORT_DEFINES"]; vcProject.Configuration.compiler.parseOptions( project->variables()["MSVCPROJ_INCPATH"] ); } void VcprojGenerator::initLibrarianTool() { vcProject.Configuration.librarian.OutputFile = project->first( "DESTDIR" ); if( vcProject.Configuration.librarian.OutputFile.isEmpty() ) vcProject.Configuration.librarian.OutputFile = ".\\"; if( !vcProject.Configuration.librarian.OutputFile.endsWith("\\") ) vcProject.Configuration.librarian.OutputFile += '\\'; vcProject.Configuration.librarian.OutputFile += project->first("MSVCPROJ_TARGET"); } void VcprojGenerator::initLinkerTool() { vcProject.Configuration.linker.parseOptions( project->variables()["MSVCPROJ_LFLAGS"] ); vcProject.Configuration.linker.AdditionalDependencies += project->variables()["MSVCPROJ_LIBS"]; switch ( projectTarget ) { case Application: vcProject.Configuration.linker.OutputFile = project->first( "DESTDIR" ); break; case SharedLib: vcProject.Configuration.linker.parseOptions( project->variables()["MSVCPROJ_LIBOPTIONS"] ); vcProject.Configuration.linker.OutputFile = project->first( "DLLDESTDIR" ); break; + case StaticLib: //unhandled - added to remove warnings.. + break; } if( vcProject.Configuration.linker.OutputFile.isEmpty() ) vcProject.Configuration.linker.OutputFile = ".\\"; if( !vcProject.Configuration.linker.OutputFile.endsWith("\\") ) vcProject.Configuration.linker.OutputFile += '\\'; vcProject.Configuration.linker.OutputFile += project->first("MSVCPROJ_TARGET"); vcProject.Configuration.linker.ProgramDatabaseFile = project->first("OBJECTS_DIR") + project->first("QMAKE_ORIG_TARGET") + ".pdb"; if ( project->isActiveConfig("debug") ){ vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_DEBUG"] ); } else { vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_RELEASE"] ); } if ( project->isActiveConfig("dll") ){ vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_QT_DLL"] ); } if ( project->isActiveConfig("console") ){ vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_CONSOLE"] ); } else { vcProject.Configuration.linker.parseOptions( project->variables()["QMAKE_LFLAGS_WINDOWS"] ); } } void VcprojGenerator::initIDLTool() { } void VcprojGenerator::initCustomBuildTool() { } void VcprojGenerator::initPreBuildEventTools() { QString collectionName = project->first("QMAKE_IMAGE_COLLECTION"); if( !collectionName.isEmpty() ) { QStringList& list = project->variables()["IMAGES"]; vcProject.Configuration.preBuild.Description = "Generate imagecollection"; //vcProject.Configuration.preBuild.AdditionalDependencies += list; - vcProject.Configuration.preBuild.CommandLine = project->first("QMAKE_UIC") + " -embed " + project->first("QMAKE_ORIG_TARGET") + " " + list.join(" ") + " -o " + collectionName; + + QFile imgs( ".imgcol" ); + imgs.open( IO_WriteOnly ); + QTextStream s( &imgs ); + QStringList::ConstIterator it = list.begin(); + while( it!=list.end() ) { + s << *it << " "; + it++; + } + + vcProject.Configuration.preBuild.CommandLine = project->first("QMAKE_UIC") + " -embed " + project->first("QMAKE_ORIG_TARGET") + " -f .imgcol -o " + collectionName; //vcProject.Configuration.preBuild.Outputs = collectionName; } } void VcprojGenerator::initPostBuildEventTools() { + if ( !project->variables()["QMAKE_POST_LINK"].isEmpty() ) { + vcProject.Configuration.postBuild.Description = var("QMAKE_POST_LINK"); + vcProject.Configuration.postBuild.CommandLine = var("QMAKE_POST_LINK"); + } if( project->isActiveConfig( "activeqt" ) ) { QString name = project->first( "QMAKE_ORIG_TARGET" ); QString nameext = project->first( "TARGET" ); QString objdir = project->first( "OBJECTS_DIR" ); QString idc = project->first( "QMAKE_IDC" ); vcProject.Configuration.postBuild.Description = "Finalizing ActiveQt server..."; + if ( !vcProject.Configuration.postBuild.CommandLine.isEmpty() ) + vcProject.Configuration.postBuild.CommandLine += " && "; if( project->isActiveConfig( "dll" ) ) { // In process - vcProject.Configuration.postBuild.CommandLine = + vcProject.Configuration.postBuild.CommandLine += // call idc to generate .idl file from .dll idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " -idl " + objdir + name + ".idl -version 1.0 && " + // call midl to create implementations of the .idl file project->first( "QMAKE_IDL" ) + " " + objdir + name + ".idl /nologo /o " + objdir + name + ".midl /tlb " + objdir + name + ".tlb /iid " + objdir + "dump.midl /dlldata " + objdir + "dump.midl /cstub " + objdir + "dump.midl /header " + objdir + "dump.midl /proxy " + objdir + "dump.midl /sstub " + objdir + "dump.midl && " + // call idc to replace tlb... idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /tlb " + objdir + name + ".tlb && " + // register server idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /regserver"; } else { // out of process vcProject.Configuration.postBuild.CommandLine = // call application to dump idl vcProject.Configuration.OutputDirectory + "\\" + nameext + " -dumpidl " + objdir + name + ".idl -version 1.0 && " + // call midl to create implementations of the .idl file project->first( "QMAKE_IDL" ) + " " + objdir + name + ".idl /nologo /o " + objdir + name + ".midl /tlb " + objdir + name + ".tlb /iid " + objdir + "dump.midl /dlldata " + objdir + "dump.midl /cstub " + objdir + "dump.midl /header " + objdir + "dump.midl /proxy " + objdir + "dump.midl /sstub " + objdir + "dump.midl && " + // call idc to replace tlb... idc + " " + vcProject.Configuration.OutputDirectory + "\\" + nameext + " /tlb " + objdir + name + ".tlb && " + // call app to register vcProject.Configuration.OutputDirectory + "\\" + nameext + " -regserver"; } } } void VcprojGenerator::initPreLinkEventTools() { } void VcprojGenerator::initSourceFiles() { vcProject.SourceFiles.Name = "Source Files"; vcProject.SourceFiles.Filter = "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"; vcProject.SourceFiles.Files += project->variables()["SOURCES"]; vcProject.SourceFiles.Files.sort(); vcProject.SourceFiles.Project = this; vcProject.SourceFiles.Config = &(vcProject.Configuration); vcProject.SourceFiles.CustomBuild = none; } void VcprojGenerator::initHeaderFiles() { vcProject.HeaderFiles.Name = "Header Files"; vcProject.HeaderFiles.Filter = "h;hpp;hxx;hm;inl"; vcProject.HeaderFiles.Files += project->variables()["HEADERS"]; vcProject.HeaderFiles.Files.sort(); vcProject.HeaderFiles.Project = this; vcProject.HeaderFiles.Config = &(vcProject.Configuration); vcProject.HeaderFiles.CustomBuild = moc; } void VcprojGenerator::initMOCFiles() { vcProject.MOCFiles.Name = "Generated MOC Files"; vcProject.MOCFiles.Filter = "cpp;c;cxx;moc"; vcProject.MOCFiles.Files += project->variables()["SRCMOC"]; vcProject.MOCFiles.Files.sort(); vcProject.MOCFiles.Project = this; vcProject.MOCFiles.Config = &(vcProject.Configuration); vcProject.MOCFiles.CustomBuild = moc; } void VcprojGenerator::initUICFiles() { vcProject.UICFiles.Name = "Generated UI Files"; vcProject.UICFiles.Filter = "cpp;c;cxx;h;hpp;hxx;"; vcProject.UICFiles.Project = this; vcProject.UICFiles.Files += project->variables()["UICDECLS"]; vcProject.UICFiles.Files += project->variables()["UICIMPLS"]; vcProject.UICFiles.Files.sort(); vcProject.UICFiles.Config = &(vcProject.Configuration); vcProject.UICFiles.CustomBuild = none; } void VcprojGenerator::initFormsFiles() { vcProject.FormFiles.Name = "Forms"; vcProject.FormFiles.ParseFiles = _False; vcProject.FormFiles.Filter = "ui"; vcProject.FormFiles.Files += project->variables()["FORMS"]; vcProject.FormFiles.Files.sort(); vcProject.FormFiles.Project = this; vcProject.FormFiles.Config = &(vcProject.Configuration); vcProject.FormFiles.CustomBuild = uic; } void VcprojGenerator::initTranslationFiles() { vcProject.TranslationFiles.Name = "Translations Files"; vcProject.TranslationFiles.ParseFiles = _False; vcProject.TranslationFiles.Filter = "ts"; vcProject.TranslationFiles.Files += project->variables()["TRANSLATIONS"]; vcProject.TranslationFiles.Files.sort(); vcProject.TranslationFiles.Project = this; vcProject.TranslationFiles.Config = &(vcProject.Configuration); vcProject.TranslationFiles.CustomBuild = none; } void VcprojGenerator::initLexYaccFiles() { vcProject.LexYaccFiles.Name = "Lex / Yacc Files"; vcProject.LexYaccFiles.ParseFiles = _False; vcProject.LexYaccFiles.Filter = "l;y"; vcProject.LexYaccFiles.Files += project->variables()["LEXSOURCES"]; vcProject.LexYaccFiles.Files += project->variables()["YACCSOURCES"]; vcProject.LexYaccFiles.Files.sort(); vcProject.LexYaccFiles.Project = this; vcProject.LexYaccFiles.CustomBuild = lexyacc; } void VcprojGenerator::initResourceFiles() { vcProject.ResourceFiles.Name = "Resources"; vcProject.ResourceFiles.ParseFiles = _False; vcProject.ResourceFiles.Filter = "cpp;ico;png;jpg;jpeg;gif;xpm;bmp;rc;ts"; vcProject.ResourceFiles.Files += project->variables()["RC_FILE"]; vcProject.ResourceFiles.Files += project->variables()["QMAKE_IMAGE_COLLECTION"]; vcProject.ResourceFiles.Files += project->variables()["IMAGES"]; vcProject.ResourceFiles.Files += project->variables()["IDLSOURCES"]; vcProject.ResourceFiles.Files.sort(); vcProject.ResourceFiles.Project = this; vcProject.ResourceFiles.CustomBuild = none; } -/* -// $$MSVCPROJ_IDLSOURCES --------------------------------------------- -void VcprojGenerator::writeIDLs( QTextStream &t ) -{ - QStringList &l = project->variables()["MSVCPROJ_IDLSOURCES"]; - for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - t << "# Begin Source File" << endl << endl; - t << "SOURCE=" << (*it) << endl; - t << "# PROP Exclude_From_Build 1" << endl; - t << "# End Source File" << endl << endl; - } - debug_msg(3, "Generator: MSVC.NET: Added IDLs" ); -} -*/ - /* \internal Sets up all needed variables from the environment and all the different caches and .conf files */ void VcprojGenerator::initOld() { if( init_flag ) return; init_flag = TRUE; QStringList::Iterator it; + if ( project->isActiveConfig("stl") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_OFF"]; + } + if ( project->isActiveConfig("exceptions") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_OFF"]; + } + if ( project->isActiveConfig("rtti") ) { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_ON"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_ON"]; + } else { + project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_OFF"]; + project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_OFF"]; + } + // this should probably not be here, but I'm using it to wrap the .t files if(project->first("TEMPLATE") == "vcapp" ) project->variables()["QMAKE_APP_FLAG"].append("1"); else if(project->first("TEMPLATE") == "vclib") project->variables()["QMAKE_LIB_FLAG"].append("1"); if ( project->variables()["QMAKESPEC"].isEmpty() ) project->variables()["QMAKESPEC"].append( getenv("QMAKESPEC") ); bool is_qt = ( project->first("TARGET") == "qt"QTDLL_POSTFIX || project->first("TARGET") == "qt-mt"QTDLL_POSTFIX ); QStringList &configs = project->variables()["CONFIG"]; if ( project->isActiveConfig( "shared" ) ) project->variables()["DEFINES"].append( "QT_DLL" ); if ( project->isActiveConfig( "qt_dll" ) && configs.findIndex("qt") == -1 ) configs.append("qt"); if ( project->isActiveConfig( "qt" ) ) { if ( project->isActiveConfig( "plugin" ) ) { project->variables()["CONFIG"].append( "dll" ); project->variables()["DEFINES"].append( "QT_PLUGIN" ); } if ( ( project->variables()["DEFINES"].findIndex( "QT_NODLL" ) == -1 ) && (( project->variables()["DEFINES"].findIndex( "QT_MAKEDLL" ) != -1 || project->variables()["DEFINES"].findIndex( "QT_DLL" ) != -1 ) || ( getenv( "QT_DLL" ) && !getenv( "QT_NODLL" ))) ) { project->variables()["QMAKE_QT_DLL"].append( "1" ); if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) project->variables()["CONFIG"].append( "dll" ); } } // If we are a dll, then we cannot be a staticlib at the same time... if ( project->isActiveConfig( "dll" ) || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["CONFIG"].remove( "staticlib" ); project->variables()["QMAKE_APP_OR_DLL"].append( "1" ); } else { project->variables()["CONFIG"].append( "staticlib" ); } // If we need 'qt' and/or 'opengl', then we need windows and not console if ( project->isActiveConfig( "qt" ) || project->isActiveConfig( "opengl" ) ) { project->variables()["CONFIG"].append( "windows" ); } // Decode version, and add it to $$MSVCPROJ_VERSION -------------- if ( !project->variables()["VERSION"].isEmpty() ) { QString version = project->variables()["VERSION"][0]; int firstDot = version.find( "." ); QString major = version.left( firstDot ); QString minor = version.right( version.length() - firstDot - 1 ); minor.replace( QRegExp( "\\." ), "" ); project->variables()["MSVCPROJ_VERSION"].append( "/VERSION:" + major + "." + minor ); } // QT ------------------------------------------------------------ if ( project->isActiveConfig("qt") ) { project->variables()["CONFIG"].append("moc"); project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"]; project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"]; if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { project->variables()["DEFINES"].append("QT_MAKEDLL"); project->variables()["QMAKE_LFLAGS"].append("/BASE:0x39D00000"); } } else { if(project->isActiveConfig("thread")) project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"]; else project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"]; if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) { int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt"); if( hver==-1 ) { hver = findHighestVersion( project->first("QMAKE_LIBDIR_QT"), "qt-mt" ); } if(hver != -1) { QString ver; ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver); QStringList &libs = project->variables()["QMAKE_LIBS"]; for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver); } } if ( project->isActiveConfig( "activeqt" ) ) { project->variables().remove("QMAKE_LIBS_QT_ENTRY"); project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib"; if ( project->isActiveConfig( "dll" ) ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"]; project->variables()["MSVCPROJ_LFLAGS"].append("/DEF:"+project->first("DEF_FILE")); } } if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) { project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"]; } } } // Set target directories ---------------------------------------- // if ( !project->first("OBJECTS_DIR").isEmpty() ) //project->variables()["MSVCPROJ_OBJECTSDIR"] = project->first("OBJECTS_DIR"); // else //project->variables()["MSVCPROJ_OBJECTSDIR"] = project->isActiveConfig( "release" )?"Release":"Debug"; // if ( !project->first("DESTDIR").isEmpty() ) //project->variables()["MSVCPROJ_TARGETDIR"] = project->first("DESTDIR"); // else //project->variables()["MSVCPROJ_TARGETDIR"] = project->isActiveConfig( "release" )?"Release":"Debug"; // OPENGL -------------------------------------------------------- if ( project->isActiveConfig("opengl") ) { project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"]; project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"]; } // THREAD -------------------------------------------------------- if ( project->isActiveConfig("thread") ) { if(project->isActiveConfig("qt")) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT" ); if ( !project->variables()["DEFINES"].contains("QT_DLL") && is_qt && project->first("TARGET") != "qtmain" ) project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:libc"); } // ACCESSIBILITY ------------------------------------------------- if(project->isActiveConfig("qt")) { if ( project->isActiveConfig("accessibility" ) ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT"); if ( project->isActiveConfig("tablet") ) project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT"); } // DLL ----------------------------------------------------------- if ( project->isActiveConfig("dll") ) { if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) { QString ver_xyz(project->first("VERSION")); ver_xyz.replace(QRegExp("\\."), ""); project->variables()["TARGET_EXT"].append(ver_xyz + ".dll"); } else { project->variables()["TARGET_EXT"].append(".dll"); } } // EXE / LIB ----------------------------------------------------- else { if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) project->variables()["TARGET_EXT"].append(".exe"); else project->variables()["TARGET_EXT"].append(".lib"); } project->variables()["MSVCPROJ_VER"] = "7.00"; project->variables()["MSVCPROJ_DEBUG_OPT"] = "/GZ /ZI"; // INCREMENTAL:NO ------------------------------------------------ if(!project->isActiveConfig("incremental")) { - project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no")); + project->variables()["QMAKE_LFLAGS"].append(QString("/INCREMENTAL:no")); if ( is_qt ) project->variables()["MSVCPROJ_DEBUG_OPT"] = "/GZ /Zi"; } // MOC ----------------------------------------------------------- if ( project->isActiveConfig("moc") ) setMocAware(TRUE); project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"]; + // Update -lname to name.lib, and -Ldir to + QStringList &libList = project->variables()["QMAKE_LIBS"]; + for( it = libList.begin(); it != libList.end(); ) { + QString s = *it; + if( s.startsWith( "-l" ) ) { + it = libList.remove( it ); + it = libList.insert( it, s.mid( 2 ) + ".lib" ); + } else if( s.startsWith( "-L" ) ) { + it = libList.remove( it ); + } else { + it++; + } + } // Run through all variables containing filepaths, and ----------- // slash-slosh them correctly depending on current OS ----------- project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ', "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH"); QStringList &l = project->variables()["QMAKE_FILETAGS"]; for(it = l.begin(); it != l.end(); ++it) { QStringList &gdmf = project->variables()[(*it)]; for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner) (*inner) = Option::fixPathToTargetOS((*inner), FALSE); } // Get filename w/o extention ----------------------------------- QString msvcproj_project = ""; QString targetfilename = ""; if ( project->variables()["TARGET"].count() ) { msvcproj_project = project->variables()["TARGET"].first(); targetfilename = msvcproj_project; } // Save filename w/o extention in $$QMAKE_ORIG_TARGET ------------ project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"]; - // TARGET (add extention to $$TARGET) ---------------------------- - project->variables()["TARGET"].first() += project->first("TARGET_EXT"); + // TARGET (add extention to $$TARGET) + //project->variables()["MSVCPROJ_DEFINES"].append(varGlue(".first() += project->first("TARGET_EXT"); // Init base class too ------------------------------------------- MakefileGenerator::init(); if ( msvcproj_project.isEmpty() ) msvcproj_project = Option::output.name(); msvcproj_project = msvcproj_project.right( msvcproj_project.length() - msvcproj_project.findRev( "\\" ) - 1 ); msvcproj_project = msvcproj_project.left( msvcproj_project.findRev( "." ) ); msvcproj_project.replace(QRegExp("-"), ""); project->variables()["MSVCPROJ_PROJECT"].append(msvcproj_project); QStringList &proj = project->variables()["MSVCPROJ_PROJECT"]; for(it = proj.begin(); it != proj.end(); ++it) (*it).replace(QRegExp("\\.[a-zA-Z0-9_]*$"), ""); // SUBSYSTEM ----------------------------------------------------- if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) { project->variables()["MSVCPROJ_TEMPLATE"].append("win32app" + project->first( "VCPROJ_EXTENSION" ) ); if ( project->isActiveConfig("console") ) { project->variables()["MSVCPROJ_CONSOLE"].append("CONSOLE"); project->variables()["MSVCPROJ_WINCONDEF"].append("_CONSOLE"); project->variables()["MSVCPROJ_VCPROJTYPE"].append("0x0103"); project->variables()["MSVCPROJ_SUBSYSTEM"].append("CONSOLE"); } else { project->variables()["MSVCPROJ_CONSOLE"].clear(); project->variables()["MSVCPROJ_WINCONDEF"].append("_WINDOWS"); project->variables()["MSVCPROJ_VCPROJTYPE"].append("0x0101"); project->variables()["MSVCPROJ_SUBSYSTEM"].append("WINDOWS"); } } else { if ( project->isActiveConfig("dll") ) { project->variables()["MSVCPROJ_TEMPLATE"].append("win32dll" + project->first( "VCPROJ_EXTENSION" ) ); } else { project->variables()["MSVCPROJ_TEMPLATE"].append("win32lib" + project->first( "VCPROJ_EXTENSION" ) ); } } // $$QMAKE.. -> $$MSVCPROJ.. ------------------------------------- project->variables()["MSVCPROJ_LIBS"] += project->variables()["QMAKE_LIBS"]; project->variables()["MSVCPROJ_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"]; project->variables()["MSVCPROJ_LFLAGS" ] += project->variables()["QMAKE_LFLAGS"]; - if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) - project->variables()["MSVCPROJ_LFLAGS" ].append(varGlue("QMAKE_LIBDIR","/LIBPATH:"," /LIBPATH:","")); + if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() ) { + QStringList strl = project->variables()["QMAKE_LIBDIR"]; + QStringList::iterator stri; + for ( stri = strl.begin(); stri != strl.end(); ++stri ) { + if ( !(*stri).startsWith("/LIBPATH:") ) + (*stri).prepend( "/LIBPATH:" ); + } + project->variables()["MSVCPROJ_LFLAGS"] += strl; + } project->variables()["MSVCPROJ_CXXFLAGS" ] += project->variables()["QMAKE_CXXFLAGS"]; // We don't use this... Direct manipulation of compiler object //project->variables()["MSVCPROJ_DEFINES"].append(varGlue("DEFINES","/D ","" " /D ","")); //project->variables()["MSVCPROJ_DEFINES"].append(varGlue("PRL_EXPORT_DEFINES","/D ","" " /D ","")); QStringList &incs = project->variables()["INCLUDEPATH"]; for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) { QString inc = (*incit); inc.replace(QRegExp("\""), ""); project->variables()["MSVCPROJ_INCPATH"].append("/I" + inc ); } project->variables()["MSVCPROJ_INCPATH"].append("/I" + specdir()); QString dest; project->variables()["MSVCPROJ_TARGET"] = project->first("TARGET"); - if ( !project->variables()["DESTDIR"].isEmpty() ) { - project->variables()["TARGET"].first().prepend(project->first("DESTDIR")); Option::fixPathToTargetOS(project->first("TARGET")); - dest = project->first("TARGET"); + dest = project->first("TARGET") + project->first( "TARGET_EXT" ); if ( project->first("TARGET").startsWith("$(QTDIR)") ) dest.replace( QRegExp("\\$\\(QTDIR\\)"), getenv("QTDIR") ); - project->variables()["MSVCPROJ_TARGET"].append( - QString("/OUT:") + dest ); + project->variables()["MSVCPROJ_TARGET"] = dest; if ( project->isActiveConfig("dll") ) { - QString imp = dest; + QString imp = project->first( "DESTDIR" ); + if( !imp.isNull() && !imp.endsWith( "\\" ) ) + imp += "\\"; + imp += dest; imp.replace(QRegExp("\\.dll"), ".lib"); - project->variables()["MSVCPROJ_LIBOPTIONS"] += (QString("/IMPLIB:") + imp ); - } + project->variables()["MSVCPROJ_LIBOPTIONS"] += QString("/IMPLIB:") + imp; } // DLL COPY ------------------------------------------------------ if ( project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty() ) { QStringList dlldirs = project->variables()["DLLDESTDIR"]; QString copydll = "# Begin Special Build Tool\n" "TargetPath=" + dest + "\n" "SOURCE=$(InputPath)\n" "PostBuild_Desc=Copy DLL to " + project->first("DLLDESTDIR") + "\n" "PostBuild_Cmds="; for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) { copydll += "copy \"" + dest + "\" \"" + *dlldir + "\"\t"; } copydll += "\n# End Special Build Tool"; project->variables()["MSVCPROJ_COPY_DLL_REL"].append( copydll ); project->variables()["MSVCPROJ_COPY_DLL_DBG"].append( copydll ); } // ACTIVEQT ------------------------------------------------------ if ( project->isActiveConfig("activeqt") ) { QString idl = project->variables()["QMAKE_IDL"].first(); QString idc = project->variables()["QMAKE_IDC"].first(); QString version = project->variables()["VERSION"].first(); if ( version.isEmpty() ) version = "1.0"; project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".idl" ); project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".tlb" ); project->variables()["MSVCPROJ_IDLSOURCES"].append( "tmp\\" + targetfilename + ".midl" ); if ( project->isActiveConfig( "dll" ) ) { QString regcmd = "# Begin Special Build Tool\n" "TargetPath=" + targetfilename + "\n" "SOURCE=$(InputPath)\n" "PostBuild_Desc=Finalizing ActiveQt server...\n" "PostBuild_Cmds=" + idc + " %1 -idl tmp\\" + targetfilename + ".idl -version " + version + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" "\tregsvr32 /s %1\n" "# End Special Build Tool"; QString executable = project->variables()["MSVCPROJ_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); project->variables()["MSVCPROJ_COPY_DLL_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); executable = project->variables()["MSVCPROJ_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); project->variables()["MSVCPROJ_COPY_DLL_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); } else { QString regcmd = "# Begin Special Build Tool\n" "TargetPath=" + targetfilename + "\n" "SOURCE=$(InputPath)\n" "PostBuild_Desc=Finalizing ActiveQt server...\n" "PostBuild_Cmds=" "%1 -dumpidl tmp\\" + targetfilename + ".idl -version " + version + "\t" + idl + " tmp\\" + targetfilename + ".idl /nologo /o tmp\\" + targetfilename + ".midl /tlb tmp\\" + targetfilename + ".tlb /iid tmp\\dump.midl /dlldata tmp\\dump.midl /cstub tmp\\dump.midl /header tmp\\dump.midl /proxy tmp\\dump.midl /sstub tmp\\dump.midl" "\t" + idc + " %1 /tlb tmp\\" + targetfilename + ".tlb" "\t%1 -regserver\n" "# End Special Build Tool"; QString executable = project->variables()["MSVCPROJ_TARGETDIRREL"].first() + "\\" + project->variables()["TARGET"].first(); project->variables()["MSVCPROJ_REGSVR_REL"].append( regcmd.arg(executable).arg(executable).arg(executable) ); executable = project->variables()["MSVCPROJ_TARGETDIRDEB"].first() + "\\" + project->variables()["TARGET"].first(); project->variables()["MSVCPROJ_REGSVR_DBG"].append( regcmd.arg(executable).arg(executable).arg(executable) ); } } // FORMS --------------------------------------------------------- QStringList &list = project->variables()["FORMS"]; for( it = list.begin(); it != list.end(); ++it ) { if ( QFile::exists( *it + ".h" ) ) project->variables()["SOURCES"].append( *it + ".h" ); } project->variables()["QMAKE_INTERNAL_PRL_LIBS"] << "MSVCPROJ_LFLAGS" << "MSVCPROJ_LIBS"; // Verbose output if "-d -d"... outputVariables(); } // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ bool VcprojGenerator::openOutput(QFile &file) const { QString outdir; if(!file.name().isEmpty()) { QFileInfo fi(file); if(fi.isDir()) outdir = file.name() + QDir::separator(); } if(!outdir.isEmpty() || file.name().isEmpty()) { QString ext = project->first("VCPROJ_EXTENSION"); if(project->first("TEMPLATE") == "vcsubdirs") ext = project->first("VCSOLUTION_EXTENSION"); file.setName(outdir + project->first("TARGET") + ext); } if(QDir::isRelativePath(file.name())) { - QString ofile; - ofile = file.name(); + file.setName( Option::fixPathToLocalOS(QDir::currentDirPath() + Option::dir_sep + fixFilename(file.name())) ); + } + return Win32MakefileGenerator::openOutput(file); +} + +QString VcprojGenerator::fixFilename(QString ofile) const +{ int slashfind = ofile.findRev('\\'); if (slashfind == -1) { - ofile = ofile.replace("-", "_"); + ofile = ofile.replace('-', '_'); } else { int hypenfind = ofile.find('-', slashfind); while (hypenfind != -1 && slashfind < hypenfind) { - ofile = ofile.replace(hypenfind, 1, "_"); + ofile = ofile.replace(hypenfind, 1, '_'); hypenfind = ofile.find('-', hypenfind + 1); } } - file.setName(Option::fixPathToLocalOS(QDir::currentDirPath() + Option::dir_sep + ofile)); - } - return Win32MakefileGenerator::openOutput(file); + return ofile; } QString VcprojGenerator::findTemplate(QString file) { QString ret; if(!QFile::exists((ret = file)) && !QFile::exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) && !QFile::exists((ret = QString(getenv("QTDIR")) + "/mkspecs/win32-msvc.net/" + file)) && !QFile::exists((ret = (QString(getenv("HOME")) + "/.tmake/" + file)))) return ""; debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.latin1() ); return ret; } void VcprojGenerator::processPrlVariable(const QString &var, const QStringList &l) { if(var == "QMAKE_PRL_DEFINES") { QStringList &out = project->variables()["MSVCPROJ_DEFINES"]; for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if(out.findIndex((*it)) == -1) out.append((" /D " + *it )); } } else { MakefileGenerator::processPrlVariable(var, l); } } void VcprojGenerator::outputVariables() { #if 0 - debug_msg(3, "Generator: MSVC.NET: List of current variables:" ); + qDebug( "Generator: MSVC.NET: List of current variables:" ); for ( QMap<QString, QStringList>::ConstIterator it = project->variables().begin(); it != project->variables().end(); ++it) { - debug_msg(3, "Generator: MSVC.NET: %s => %s", it.key().latin1(), it.data().join(" | ").latin1() ); + qDebug( "Generator: MSVC.NET: %s => %s", it.key().latin1(), it.data().join(" | ").latin1() ); } #endif } diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h index 583b164..69e0c02 100644 --- a/qmake/generators/win32/msvc_vcproj.h +++ b/qmake/generators/win32/msvc_vcproj.h @@ -1,129 +1,115 @@ /**************************************************************************** ** $Id$ ** ** Definition of VcprojGenerator class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef __VCPROJMAKE_H__ -#define __VCPROJMAKE_H__ +#ifndef __MSVC_VCPROJ_H__ +#define __MSVC_VCPROJ_H__ #include "winmakefile.h" #include "msvc_objectmodel.h" enum target { Application, SharedLib, StaticLib }; +struct QUuid; class VcprojGenerator : public Win32MakefileGenerator { bool init_flag; bool writeVcprojParts(QTextStream &); bool writeMakefile(QTextStream &); virtual void writeSubDirs(QTextStream &t); QString findTemplate(QString file); void init(); public: VcprojGenerator(QMakeProject *p); ~VcprojGenerator(); QString defaultMakefile() const; virtual bool doDepends() const { return FALSE; } //never necesary protected: virtual bool openOutput(QFile &file) const; virtual void processPrlVariable(const QString &, const QStringList &); virtual bool findLibraries(); virtual void outputVariables(); + QString fixFilename(QString ofile) const; void initOld(); void initProject(); void initConfiguration(); void initCompilerTool(); void initLinkerTool(); void initLibrarianTool(); void initIDLTool(); void initCustomBuildTool(); void initPreBuildEventTools(); void initPostBuildEventTools(); void initPreLinkEventTools(); void initSourceFiles(); void initHeaderFiles(); void initMOCFiles(); void initUICFiles(); void initFormsFiles(); void initTranslationFiles(); void initLexYaccFiles(); void initResourceFiles(); - /* - void writeGuid( QTextStream &t ); - void writeAdditionalOptions( QTextStream &t ); - void writeHeaders( QTextStream &t ); - void writeSources( QTextStream &t ); - void writeMocs( QTextStream &t ); - void writeLexs( QTextStream &t ); - void writeYaccs( QTextStream &t ); - void writePictures( QTextStream &t ); - void writeImages( QTextStream &t ); - void writeIDLs( QTextStream &t ); - - void writeForms( QTextStream &t ); - void writeFormsSourceHeaders( QString &variable, QTextStream &t ); - void writeTranslations( QTextStream &t ); - void writeStrippedTranslations( QTextStream &t ); - */ - VCProject vcProject; target projectTarget; +private: + QUuid increaseUUID(const QUuid &id); friend class VCFilter; }; inline VcprojGenerator::~VcprojGenerator() { } inline QString VcprojGenerator::defaultMakefile() const { return project->first("TARGET") + project->first("VCPROJ_EXTENSION"); } inline bool VcprojGenerator::findLibraries() { return Win32MakefileGenerator::findLibraries("MSVCVCPROJ_LIBS"); } -#endif /* __VCPROJMAKE_H__ */ +#endif /* __MSVC_VCPROJ_H__ */ diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index a07c921..bc3fed9 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -1,360 +1,400 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "winmakefile.h" #include "option.h" #include "project.h" #include <qtextstream.h> #include <qstring.h> #include <qdict.h> #include <qregexp.h> #include <qstringlist.h> #include <qdir.h> Win32MakefileGenerator::Win32MakefileGenerator(QMakeProject *p) : MakefileGenerator(p) { } struct SubDir { QString directory, profile, target, makefile; }; void Win32MakefileGenerator::writeSubDirs(QTextStream &t) { QPtrList<SubDir> subdirs; { QStringList subdirs_in = project->variables()["SUBDIRS"]; for(QStringList::Iterator it = subdirs_in.begin(); it != subdirs_in.end(); ++it) { QString file = (*it); file = fileFixify(file); SubDir *sd = new SubDir; subdirs.append(sd); sd->makefile = "$(MAKEFILE)"; if((*it).right(4) == ".pro") { int slsh = file.findRev(Option::dir_sep); if(slsh != -1) { sd->directory = file.left(slsh+1); sd->profile = file.mid(slsh+1); } else { sd->profile = file; } } else { sd->directory = file; } while(sd->directory.right(1) == Option::dir_sep) sd->directory = sd->directory.left(sd->directory.length() - 1); if(!sd->profile.isEmpty()) { QString basename = sd->directory; int new_slsh = basename.findRev(Option::dir_sep); if(new_slsh != -1) basename = basename.mid(new_slsh+1); if(sd->profile != basename + ".pro") sd->makefile += "." + sd->profile.left(sd->profile.length() - 4); //no need for the .pro } sd->target = "sub-" + (*it); sd->target.replace('/', '-'); sd->target.replace('.', '_'); } } QPtrListIterator<SubDir> it(subdirs); if(!project->isEmpty("MAKEFILE")) t << "MAKEFILE= " << var("MAKEFILE") << endl; t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl; t << "SUBTARGETS = "; for( it.toFirst(); it.current(); ++it) t << " \\\n\t\t" << it.current()->target; t << endl << endl; t << "all: qmake_all $(SUBTARGETS)" << endl << endl; for( it.toFirst(); it.current(); ++it) { bool have_dir = !(*it)->directory.isEmpty(); //make the makefile QString mkfile = (*it)->makefile; if(have_dir) mkfile.prepend((*it)->directory + Option::dir_sep); t << mkfile << ":"; if(project->variables()["QMAKE_NOFORCE"].isEmpty()) t << " FORCE"; if(have_dir) t << "\n\t" << "cd " << (*it)->directory; t << "\n\t" << "$(QMAKE) " << (*it)->profile << " " << buildArgs(); - if((*it)->makefile != "$(MAKEFILE)") t << " -o " << (*it)->makefile; if(have_dir) { int subLevels = it.current()->directory.contains(Option::dir_sep) + 1; t << "\n\t" << "@cd .."; for(int i = 1; i < subLevels; i++ ) t << Option::dir_sep << ".."; } t << endl; //now actually build t << (*it)->target << ": " << mkfile; if(project->variables()["QMAKE_NOFORCE"].isEmpty()) t << " FORCE"; if(have_dir) t << "\n\t" << "cd " << (*it)->directory; t << "\n\t" << "$(MAKE)"; - if((*it)->makefile != "$(MAKEFILE)") t << " -f " << (*it)->makefile; if(have_dir) { int subLevels = it.current()->directory.contains(Option::dir_sep) + 1; t << "\n\t" << "@cd .."; for(int i = 1; i < subLevels; i++ ) t << Option::dir_sep << ".."; } t << endl << endl; } if(project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].findIndex("qmake_all") == -1) project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].append("qmake_all"); writeMakeQmake(t); t << "qmake_all:"; if ( !subdirs.isEmpty() ) { for( it.toFirst(); it.current(); ++it) { QString subdir = (*it)->directory; + QString profile = (*it)->profile; int subLevels = subdir.contains(Option::dir_sep) + 1; t << "\n\t" << "cd " << subdir << "\n\t"; int lastSlash = subdir.findRev(Option::dir_sep); if(lastSlash != -1) subdir = subdir.mid( lastSlash + 1 ); - t << "$(QMAKE) " << subdir << ".pro" - << (!project->isEmpty("MAKEFILE") ? QString(" -o ") + var("MAKEFILE") : QString("")) + t << "$(QMAKE) " + << ( !profile.isEmpty() ? profile : subdir + ".pro" ) + << " -o " << (*it)->makefile << " " << buildArgs() << "\n\t" << "@cd .."; for(int i = 1; i < subLevels; i++ ) t << Option::dir_sep << ".."; } } else { // Borland make does not like empty an empty command section, so insert // a dummy command. t << "\n\t" << "@cd ."; } t << endl << endl; QString targs[] = { QString("clean"), QString("install"), QString("mocclean"), QString::null }; for(int x = 0; targs[x] != QString::null; x++) { t << targs[x] << ": qmake_all"; if(targs[x] == "clean") t << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ", ""); if (!subdirs.isEmpty()) { for( it.toFirst(); it.current(); ++it) { int subLevels = (*it)->directory.contains(Option::dir_sep) + 1; bool have_dir = !(*it)->directory.isEmpty(); if(have_dir) t << "\n\t" << "cd " << (*it)->directory; - QString in_file; - if((*it)->makefile != "$(MAKEFILE)") - in_file = " -f " + (*it)->makefile; + QString in_file = " -f " + (*it)->makefile; t << "\n\t" << "$(MAKE) " << in_file << " " << targs[x]; if(have_dir) { t << "\n\t" << "@cd .."; for(int i = 1; i < subLevels; i++ ) t << Option::dir_sep << ".."; } } } else { // Borland make does not like empty an empty command section, so // insert a dummy command. t << "\n\t" << "@cd ."; } t << endl << endl; } if(project->variables()["QMAKE_NOFORCE"].isEmpty()) t << "FORCE:" << endl << endl; } int -Win32MakefileGenerator::findHighestVersion(const QString &d, const - QString &stem) +Win32MakefileGenerator::findHighestVersion(const QString &d, const QString &stem) { - if(!QFile::exists(Option::fixPathToLocalOS(d))) + QString bd = Option::fixPathToLocalOS(d, TRUE); + if(!QFile::exists(bd)) return -1; - if(!project->variables()["QMAKE_" + stem.upper() + - "_VERSION_OVERRIDE"].isEmpty()) - return project->variables()["QMAKE_" + stem.upper() + - "_VERSION_OVERRIDE"].first().toInt(); - QString bd = d; - fixEnvVariables(bd); + if(!project->variables()["QMAKE_" + stem.upper() + "_VERSION_OVERRIDE"].isEmpty()) + return project->variables()["QMAKE_" + stem.upper() + "_VERSION_OVERRIDE"].first().toInt(); + QDir dir(bd); int biggest=-1; QStringList entries = dir.entryList(); - QRegExp regx( "(" + stem + "([0-9]*)).lib", FALSE ); - for(QStringList::Iterator it = entries.begin(); it != entries.end(); - ++it) { + QString dllStem = stem + QTDLL_POSTFIX; + QRegExp regx( "(" + dllStem + "([0-9]*)).lib", FALSE ); + for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) { if(regx.exactMatch((*it))) - biggest = QMAX(biggest, (regx.cap(1) == stem || + biggest = QMAX(biggest, (regx.cap(1) == dllStem || regx.cap(2).isEmpty()) ? -1 : regx.cap(2).toInt()); } + if(dir.exists(dllStem + Option::prl_ext)) { + QMakeProject proj; + if(proj.read(bd + dllStem + Option::prl_ext, QDir::currentDirPath(), TRUE)) { + if(!proj.isEmpty("QMAKE_PRL_VERSION")) + biggest = QMAX(biggest, proj.first("QMAKE_PRL_VERSION").replace(".", "").toInt()); + } + } return biggest; } bool Win32MakefileGenerator::findLibraries(const QString &where) { QStringList &l = project->variables()[where]; QPtrList<MakefileDependDir> dirs; + { + QStringList &libpaths = project->variables()["QMAKE_LIBDIR"]; + for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit) { + QString r = (*libpathit), l = r; + fixEnvVariables(l); + dirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); + } + } dirs.setAutoDelete(TRUE); for(QStringList::Iterator it = l.begin(); it != l.end(); ) { - QString opt = (*it); - bool remove = FALSE; - if(opt.startsWith("-L") || opt.startsWith("/L")) { - QString r = opt.right(opt.length() - 2), l = Option::fixPathToLocalOS(r); + QChar quote; + bool modified_opt = FALSE, remove = FALSE; + QString opt = (*it).stripWhiteSpace(); + if((opt[0] == '\'' || opt[0] == '"') && opt[(int)opt.length()-1] == opt[0]) { + quote = opt[0]; + opt = opt.mid(1, opt.length()-2); + } + if(opt.startsWith("/LIBPATH:")) { + QString r = opt.mid(9), l = Option::fixPathToLocalOS(r); + dirs.append(new MakefileDependDir(r.replace("\"",""), + l.replace("\"",""))); + } else if(opt.startsWith("-L") || opt.startsWith("/L")) { + QString r = opt.mid(2), l = Option::fixPathToLocalOS(r); dirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); - remove = TRUE; + remove = TRUE; //we eat this switch } else if(opt.startsWith("-l") || opt.startsWith("/l")) { QString lib = opt.right(opt.length() - 2), out; if(!lib.isEmpty()) { for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) { + QString extension; int ver = findHighestVersion(mdd->local_dir, lib); if(ver > 0) - lib += QString::number(ver); - lib += ".lib"; - if(QFile::exists(mdd->local_dir + Option::dir_sep + lib)) { - out = mdd->real_dir + Option::dir_sep + lib; + extension += QString::number(ver); + extension += ".lib"; + if(QFile::exists(mdd->local_dir + Option::dir_sep + lib + Option::prl_ext) || + QFile::exists(mdd->local_dir + Option::dir_sep + lib + extension)) { + out = mdd->real_dir + Option::dir_sep + lib + extension; break; } } } - if(out.isEmpty()) - remove = TRUE; - else + if(out.isEmpty()) { + remove = TRUE; //just eat it since we cannot find one.. + } else { + modified_opt = TRUE; (*it) = out; + } } else if(!QFile::exists(Option::fixPathToLocalOS(opt))) { - QString dir, file = opt; + QPtrList<MakefileDependDir> lib_dirs; + QString file = opt; int slsh = file.findRev(Option::dir_sep); if(slsh != -1) { - dir = file.left(slsh+1); + QString r = file.left(slsh+1), l = r; + fixEnvVariables(l); + lib_dirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); file = file.right(file.length() - slsh - 1); + } else { + lib_dirs = dirs; } - if ( !(project->variables()["QMAKE_QT_DLL"].isEmpty() && (file == "qt.lib" || file == "qt-mt.lib")) ) { if(file.endsWith(".lib")) { file = file.left(file.length() - 4); if(!file.at(file.length()-1).isNumber()) { - int ver = findHighestVersion(dir, file); + for(MakefileDependDir *mdd = lib_dirs.first(); mdd; mdd = lib_dirs.next() ) { + QString lib_tmpl(file + "%1" + ".lib"); + int ver = findHighestVersion(mdd->local_dir, file); if(ver != -1) { - file = QString(dir + file + "%1" + ".lib"); if(ver) - (*it) = file.arg(ver); + lib_tmpl = lib_tmpl.arg(ver); else - (*it) = file.arg(""); + lib_tmpl = lib_tmpl.arg(""); + if(slsh != -1) { + QString dir = mdd->real_dir; + if(!dir.endsWith(Option::dir_sep)) + dir += Option::dir_sep; + lib_tmpl.prepend(dir); + } + modified_opt = TRUE; + (*it) = lib_tmpl; + break; } } } } } - if(remove) + if(remove) { it = l.remove(it); - else + } else { + if(!quote.isNull() && modified_opt) + (*it) = quote + (*it) + quote; ++it; } + } return TRUE; } void Win32MakefileGenerator::processPrlFiles() { QDict<void> processed; QPtrList<MakefileDependDir> libdirs; libdirs.setAutoDelete(TRUE); { QStringList &libpaths = project->variables()["QMAKE_LIBDIR"]; for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit) { QString r = (*libpathit), l = r; fixEnvVariables(l); libdirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); } } for(bool ret = FALSE; TRUE; ret = FALSE) { //read in any prl files included.. QStringList l_out; QString where = "QMAKE_LIBS"; if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) where = project->first("QMAKE_INTERNAL_PRL_LIBS"); QStringList &l = project->variables()[where]; for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) { QString opt = (*it); - if(opt.left(1) == "/") { - if(opt.left(9) == "/LIBPATH:") { + if(opt.startsWith("/")) { + if(opt.startsWith("/LIBPATH:")) { QString r = opt.mid(9), l = r; fixEnvVariables(l); libdirs.append(new MakefileDependDir(r.replace("\"",""), l.replace("\"",""))); } } else { if(!processed[opt]) { if(processPrlFile(opt)) { processed.insert(opt, (void*)1); ret = TRUE; } else { for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) { QString prl = mdd->local_dir + Option::dir_sep + opt; if(processed[prl]) { break; } else if(processPrlFile(prl)) { processed.insert(prl, (void*)1); ret = TRUE; break; } } } } } if(!opt.isEmpty()) l_out.append(opt); } if(ret) l = l_out; else break; } } diff --git a/qmake/include/private/qapplication_p.h b/qmake/include/private/qapplication_p.h index 6fab6b3..280992e 100644 --- a/qmake/include/private/qapplication_p.h +++ b/qmake/include/private/qapplication_p.h @@ -1,87 +1,88 @@ /**************************************************************************** ** $Id$ ** ** Definition of some Qt private functions. ** ** Created : 000228 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QAPPLICATION_P_H #define QAPPLICATION_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qapplication_*.cpp, qwidget*.cpp, qcolor_x11.cpp, qfiledialog.cpp // and many other. This header file may change from version to version // without notice, or even be removed. // // We mean it. // // #ifndef QT_H #endif // QT_H class QWidget; class QObject; class QClipboard; class QKeyEvent; class QMouseEvent; class QWheelEvent; extern Q_EXPORT bool qt_modal_state(); extern Q_EXPORT void qt_enter_modal( QWidget* ); extern Q_EXPORT void qt_leave_modal( QWidget* ); extern bool qt_is_gui_used; #ifndef QT_NO_CLIPBOARD extern QClipboard *qt_clipboard; #endif #if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) extern Qt::WindowsVersion qt_winver; +#elif defined (Q_OS_MAC) +extern Qt::MacintoshVersion qt_macver; #endif #if defined (Q_WS_X11) extern int qt_ncols_option; #endif extern void qt_dispatchEnterLeave( QWidget*, QWidget* ); - - +extern bool qt_tryModalHelper( QWidget *, QWidget ** = 0 ); #endif diff --git a/qmake/include/private/qcom_p.h b/qmake/include/private/qcom_p.h index 6e7e1c8..5bed8c8c 100644 --- a/qmake/include/private/qcom_p.h +++ b/qmake/include/private/qcom_p.h @@ -1,337 +1,337 @@ /**************************************************************************** ** $Id$ ** ** ... ** ** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QCOM_H -#define QCOM_H +#ifndef QCOM_P_H +#define QCOM_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qstringlist.h" #include "quuid.h" #endif // QT_H #ifndef QT_NO_COMPONENT class QObject; struct QUInterfaceDescription; struct QUObject; #define QRESULT unsigned long #define QS_OK (QRESULT)0x00000000 #define QS_FALSE (QRESULT)0x00000001 #define QE_NOTIMPL (QRESULT)0x80000001 #define QE_OUTOFMEMORY (QRESULT)0x80000002 #define QE_INVALIDARG (QRESULT)0x80000003 #define QE_NOINTERFACE (QRESULT)0x80000004 #define QE_NOCOMPONENT (QRESULT)0x80000005 // {1D8518CD-E8F5-4366-99E8-879FD7E482DE} #ifndef IID_QUnknown #define IID_QUnknown QUuid(0x1d8518cd, 0xe8f5, 0x4366, 0x99, 0xe8, 0x87, 0x9f, 0xd7, 0xe4, 0x82, 0xde) #endif struct Q_EXPORT QUnknownInterface { virtual QRESULT queryInterface( const QUuid&, QUnknownInterface** ) = 0; virtual ulong addRef() = 0; virtual ulong release() = 0; }; // {FBAC965E-A441-413F-935E-CDF582573FAB} #ifndef IID_QDispatch #define IID_QDispatch QUuid( 0xfbac965e, 0xa441, 0x413f, 0x93, 0x5e, 0xcd, 0xf5, 0x82, 0x57, 0x3f, 0xab) #endif // the dispatch interface that inherits the unknown interface.. It is // used to explore interfaces during runtime and to do dynamic calls. struct Q_EXPORT QDispatchInterface : public QUnknownInterface { // returns the interface description of this dispatch interface. virtual const QUInterfaceDescription* interfaceDescription() const = 0; // returns the event description of this dispatch interface. virtual const QUInterfaceDescription* eventsDescription() const = 0; // invokes method id with parameters V*. Returns some sort of // exception code. virtual QRESULT invoke( int id, QUObject* o ) = 0; // installs listener as event listener virtual void installListener( QDispatchInterface* listener ) = 0; // remove listener as event listener virtual void removeListener( QDispatchInterface* listener ) = 0; }; template <class T> class QInterfacePtr { public: QInterfacePtr():iface(0){} QInterfacePtr( T* i) { if ( (iface = i) ) iface->addRef(); } QInterfacePtr(const QInterfacePtr<T> &p) { if ( (iface = p.iface) ) iface->addRef(); } ~QInterfacePtr() { if ( iface ) iface->release(); } QInterfacePtr<T> &operator=(const QInterfacePtr<T> &p) { if ( iface != p.iface ) { if ( iface ) iface->release(); if ( (iface = p.iface) ) iface->addRef(); } return *this; } QInterfacePtr<T> &operator=(T* i) { if (iface != i ) { if ( iface ) iface->release(); if ( (iface = i) ) iface->addRef(); } return *this; } bool operator==( const QInterfacePtr<T> &p ) const { return iface == p.iface; } bool operator!= ( const QInterfacePtr<T>& p ) const { return !( *this == p ); } bool isNull() const { return !iface; } T* operator->() const { return iface; } T& operator*() const { return *iface; } operator T*() const { return iface; } QUnknownInterface** operator &() const { if( iface ) iface->release(); return (QUnknownInterface**)&iface; } T** operator &() { if ( iface ) iface->release(); return &iface; } private: T* iface; }; // {10A1501B-4C5F-4914-95DD-C400486CF900} #ifndef IID_QObject #define IID_QObject QUuid( 0x10a1501b, 0x4c5f, 0x4914, 0x95, 0xdd, 0xc4, 0x00, 0x48, 0x6c, 0xf9, 0x00) #endif struct Q_EXPORT QObjectInterface { virtual QObject* qObject() = 0; }; // {5F3968A5-F451-45b1-96FB-061AD98F926E} #ifndef IID_QComponentInformation #define IID_QComponentInformation QUuid(0x5f3968a5, 0xf451, 0x45b1, 0x96, 0xfb, 0x6, 0x1a, 0xd9, 0x8f, 0x92, 0x6e) #endif struct Q_EXPORT QComponentInformationInterface : public QUnknownInterface { virtual QString name() const = 0; virtual QString description() const = 0; virtual QString author() const = 0; virtual QString version() const = 0; }; // {6CAA771B-17BB-4988-9E78-BA5CDDAAC31E} #ifndef IID_QComponentFactory #define IID_QComponentFactory QUuid( 0x6caa771b, 0x17bb, 0x4988, 0x9e, 0x78, 0xba, 0x5c, 0xdd, 0xaa, 0xc3, 0x1e) #endif struct Q_EXPORT QComponentFactoryInterface : public QUnknownInterface { virtual QRESULT createInstance( const QUuid &cid, const QUuid &iid, QUnknownInterface** instance, QUnknownInterface *outer ) = 0; }; // {D16111D4-E1E7-4C47-8599-24483DAE2E07} #ifndef IID_QLibrary #define IID_QLibrary QUuid( 0xd16111d4, 0xe1e7, 0x4c47, 0x85, 0x99, 0x24, 0x48, 0x3d, 0xae, 0x2e, 0x07) #endif struct Q_EXPORT QLibraryInterface : public QUnknownInterface { virtual bool init() = 0; virtual void cleanup() = 0; virtual bool canUnload() const = 0; }; // {3F8FDC44-3015-4f3e-B6D6-E4AAAABDEAAD} #ifndef IID_QFeatureList #define IID_QFeatureList QUuid(0x3f8fdc44, 0x3015, 0x4f3e, 0xb6, 0xd6, 0xe4, 0xaa, 0xaa, 0xbd, 0xea, 0xad) #endif struct Q_EXPORT QFeatureListInterface : public QUnknownInterface { virtual QStringList featureList() const = 0; }; // {B5FEB5DE-E0CD-4E37-B0EB-8A812499A0C1} #ifndef IID_QComponentRegistration #define IID_QComponentRegistration QUuid( 0xb5feb5de, 0xe0cd, 0x4e37, 0xb0, 0xeb, 0x8a, 0x81, 0x24, 0x99, 0xa0, 0xc1) #endif struct Q_EXPORT QComponentRegistrationInterface : public QUnknownInterface { virtual bool registerComponents( const QString &filepath ) const = 0; virtual bool unregisterComponents() const = 0; }; // internal class that wraps an initialized ulong struct Q_EXPORT QtULong { QtULong() : ref( 0 ) { } operator unsigned long () const { return ref; } unsigned long& operator++() { return ++ref; } unsigned long operator++( int ) { return ref++; } unsigned long& operator--() { return --ref; } unsigned long operator--( int ) { return ref--; } unsigned long ref; }; // default implementation of ref counting. A variable "ulong ref" has to be a member #define Q_REFCOUNT \ private: \ QtULong qtrefcount; \ public: \ ulong addRef() {return qtrefcount++;} \ ulong release() {if(!--qtrefcount){delete this;return 0;}return qtrefcount;} #ifndef Q_EXPORT_COMPONENT #if defined(QT_THREAD_SUPPORT) #define QT_THREADED_BUILD 1 #define Q_UCM_FLAGS_STRING "11" #else #define QT_THREADED_BUILD 0 #define Q_UCM_FLAGS_STRING "01" #endif #ifndef Q_EXTERN_C #ifdef __cplusplus #define Q_EXTERN_C extern "C" #else #define Q_EXTERN_C extern #endif #endif // this is duplicated at Q_PLUGIN_VERIFICATION_DATA in qgplugin.h // NOTE: if you change pattern, you MUST change the pattern in // qcomlibrary.cpp as well. changing the pattern will break all // backwards compatibility as well (no old plugins will be loaded). #ifndef Q_UCM_VERIFICATION_DATA # define Q_UCM_VERIFICATION_DATA \ static const char *qt_ucm_verification_data = \ "pattern=""QT_UCM_VERIFICATION_DATA""\n" \ "version="QT_VERSION_STR"\n" \ "flags="Q_UCM_FLAGS_STRING"\n" \ "buildkey="QT_BUILD_KEY"\0"; #endif // Q_UCM_VERIFICATION_DATA // This macro expands to the default implementation of ucm_instantiate. #ifndef Q_CREATE_INSTANCE # define Q_CREATE_INSTANCE( IMPLEMENTATION ) \ IMPLEMENTATION *i = new IMPLEMENTATION; \ QUnknownInterface* iface = 0; \ i->queryInterface( IID_QUnknown, &iface ); \ return iface; #endif // Q_CREATE_INSTANCE # ifdef Q_WS_WIN # ifdef Q_CC_BOR # define Q_EXPORT_COMPONENT() \ Q_UCM_VERIFICATION_DATA \ Q_EXTERN_C __declspec(dllexport) \ const char * __stdcall qt_ucm_query_verification_data() \ { return qt_ucm_verification_data; } \ Q_EXTERN_C __declspec(dllexport) QUnknownInterface* \ __stdcall ucm_instantiate() # else # define Q_EXPORT_COMPONENT() \ Q_UCM_VERIFICATION_DATA \ Q_EXTERN_C __declspec(dllexport) \ const char *qt_ucm_query_verification_data() \ { return qt_ucm_verification_data; } \ Q_EXTERN_C __declspec(dllexport) QUnknownInterface* ucm_instantiate() # endif # else # define Q_EXPORT_COMPONENT() \ Q_UCM_VERIFICATION_DATA \ Q_EXTERN_C \ const char *qt_ucm_query_verification_data() \ { return qt_ucm_verification_data; } \ Q_EXTERN_C QUnknownInterface* ucm_instantiate() # endif # define Q_EXPORT_INTERFACE() Q_EXPORT_COMPONENT() #endif #endif //QT_NO_COMPONENT -#endif //QCOM_H +#endif //QCOM_P_H diff --git a/qmake/include/private/qcomlibrary_p.h b/qmake/include/private/qcomlibrary_p.h index f52f679..3f440c0 100644 --- a/qmake/include/private/qcomlibrary_p.h +++ b/qmake/include/private/qcomlibrary_p.h @@ -1,79 +1,79 @@ /**************************************************************************** ** $Id$ ** ** Definition of QComLibrary class ** ** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QUCOMLIBRARY_H -#define QUCOMLIBRARY_H +#ifndef QCOMLIBRARY_P_H +#define QCOMLIBRARY_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qcom_p.h" #include "qlibrary.h" #endif // QT_H #ifndef QT_NO_COMPONENT class Q_EXPORT QComLibrary : public QLibrary { public: QComLibrary( const QString &filename ); ~QComLibrary(); bool unload(); QRESULT queryInterface( const QUuid &iid, QUnknownInterface **iface ); uint qtVersion(); private: void createInstanceInternal(); QUnknownInterface *entry; QLibraryInterface *libiface; uint qt_version; }; #endif //QT_NO_COMPONENT -#endif // QUCOMLIBRARY_H +#endif diff --git a/qmake/include/private/qcomplextext_p.h b/qmake/include/private/qcomplextext_p.h index 2132522..c3aeeb1 100644 --- a/qmake/include/private/qcomplextext_p.h +++ b/qmake/include/private/qcomplextext_p.h @@ -1,123 +1,121 @@ /**************************************************************************** ** $Id$ ** ** Internal header file. ** -** Created : -** -** Copyright (C) 2001 Trolltech AS. All rights reserved. +** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QCOMPLEXTEXT_H -#define QCOMPLEXTEXT_H +#ifndef QCOMPLEXTEXT_P_H +#define QCOMPLEXTEXT_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of Qt Remote Control. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include <qstring.h> #include <qpointarray.h> #include <qfont.h> #include <qpainter.h> #include <qptrlist.h> #include <qshared.h> #endif // QT_H #ifndef QT_NO_COMPLEXTEXT // bidi helper classes. Internal to Qt struct Q_EXPORT QBidiStatus { QBidiStatus() { eor = QChar::DirON; lastStrong = QChar::DirON; last = QChar:: DirON; } QChar::Direction eor; QChar::Direction lastStrong; QChar::Direction last; }; struct Q_EXPORT QBidiContext : public QShared { // ### ref and deref parent? QBidiContext( uchar level, QChar::Direction embedding, QBidiContext *parent = 0, bool override = FALSE ); ~QBidiContext(); unsigned char level; bool override : 1; QChar::Direction dir : 5; QBidiContext *parent; }; struct Q_EXPORT QBidiControl { QBidiControl() { context = 0; } QBidiControl( QBidiContext *c, QBidiStatus s) { context = c; if( context ) context->ref(); status = s; } ~QBidiControl() { if ( context && context->deref() ) delete context; } void setContext( QBidiContext *c ) { if ( context == c ) return; if ( context && context->deref() ) delete context; context = c; context->ref(); } QBidiContext *context; QBidiStatus status; }; struct Q_EXPORT QTextRun { QTextRun(int _start, int _stop, QBidiContext *context, QChar::Direction dir); int start; int stop; // explicit + implicit levels here uchar level; }; class Q_EXPORT QComplexText { public: static QString shapedString( const QString &str, int from = 0, int len = -1, QPainter::TextDirection dir = QPainter::Auto, const QFontMetrics *fm = 0); static QChar shapedCharacter(const QString &str, int pos, const QFontMetrics *fm = 0); // positions non spacing marks relative to the base character at position pos. static QPointArray positionMarks( QFontPrivate *f, const QString &str, int pos, QRect *boundingRect = 0 ); static QPtrList<QTextRun> *bidiReorderLine( QBidiControl *control, const QString &str, int start, int len, QChar::Direction basicDir = QChar::DirON ); static QString bidiReorderString( const QString &str, QChar::Direction basicDir = QChar::DirON ); }; #endif //QT_NO_COMPLEXTEXT #endif diff --git a/qmake/include/private/qcomponentfactory_p.h b/qmake/include/private/qcomponentfactory_p.h index 1ac973f..d5c1743 100644 --- a/qmake/include/private/qcomponentfactory_p.h +++ b/qmake/include/private/qcomponentfactory_p.h @@ -1,73 +1,73 @@ /**************************************************************************** ** $Id$ ** ** Definition of the QComponentFactory class ** ** Created : 990101 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QCOMPONENTFACTORY_H -#define QCOMPONENTFACTORY_H +#ifndef QCOMPONENTFACTORY_P_H +#define QCOMPONENTFACTORY_P_H #ifndef QT_H #include "qcom_p.h" #endif // QT_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_NO_COMPONENT class Q_EXPORT QComponentFactory { public: static QRESULT createInstance( const QString &cid, const QUuid &iid, QUnknownInterface** instance, QUnknownInterface *outer = 0 ); static QRESULT registerServer( const QString &filename ); static QRESULT unregisterServer( const QString &filename ); static bool registerComponent( const QUuid &cid, const QString &filename, const QString &name = QString::null, int version = 0, const QString &description = QString::null ); static bool unregisterComponent( const QUuid &cid ); }; #endif // QT_NO_COMPONENT -#endif // QCOMPONENTFACTORY_H +#endif // QCOMPONENTFACTORY_P_H diff --git a/qmake/include/private/qcriticalsection_p.h b/qmake/include/private/qcriticalsection_p.h index 7d9feca..8dacc62 100644 --- a/qmake/include/private/qcriticalsection_p.h +++ b/qmake/include/private/qcriticalsection_p.h @@ -1,80 +1,80 @@ /**************************************************************************** ** $Id$ ** ** Definition of QCriticalSection class ** ** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QCRITICALSECTION_H -#define QCRITICALSECTION_H +#ifndef QCRITICALSECTION_P_H +#define QCRITICALSECTION_P_H #ifndef QT_H #endif // QT_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of Qt Remote Control. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // #if defined(QT_THREAD_SUPPORT) #if defined(Q_WS_WIN) /* QCriticalSection */ class QCriticalSectionPrivate; class QCriticalSection { public: QCriticalSection(); ~QCriticalSection(); void enter(); void leave(); private: QCriticalSectionPrivate *d; }; #endif #endif #endif diff --git a/qmake/include/private/qdir_p.h b/qmake/include/private/qdir_p.h index 35dba28..a6c7c91 100644 --- a/qmake/include/private/qdir_p.h +++ b/qmake/include/private/qdir_p.h @@ -1,78 +1,79 @@ /**************************************************************************** ** $Id$ ** ** Definition of some private QDir functions. ** -** Created : 2000.11.06 +** Created : 001106 ** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QDIR_P_H #define QDIR_P_H - // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qdir.cpp and qdir_*.cpp. // This header file may change from version to version without notice, // or even be removed. // // We mean it. // // #ifndef QT_H +#include "qregexp.h" +#include "qvaluelist.h" #endif // QT_H -extern QStringList qt_makeFilterList( const QString & ); - +extern QValueList<QRegExp> qt_makeFilterList( const QString & ); +extern bool qt_matchFilterList( const QValueList<QRegExp> &, const QString & ); extern int qt_cmp_si_sortSpec; #if defined(Q_C_CALLBACKS) extern "C" { #endif #ifdef Q_OS_TEMP extern int __cdecl qt_cmp_si( const void *, const void * ); #else extern int qt_cmp_si( const void *, const void * ); #endif #if defined(Q_C_CALLBACKS) } #endif #endif // QDIR_P_H diff --git a/qmake/include/private/qeffects_p.h b/qmake/include/private/qeffects_p.h index 4178b6f..3b6c212 100644 --- a/qmake/include/private/qeffects_p.h +++ b/qmake/include/private/qeffects_p.h @@ -1,78 +1,78 @@ /**************************************************************************** ** $Id$ ** ** Definition of QEffects functions ** -** Created : 2000.06.21 +** Created : 000621 ** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of the widgets module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QEFFECTS_P_H #define QEFFECTS_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qeffects.cpp, qcombobox.cpp, qpopupmenu.cpp and qtooltip.cpp. // This header file may change from version to version without notice, // or even be removed. // // We mean it. // // #ifndef QT_H #include "qnamespace.h" #endif // QT_H #ifndef QT_NO_EFFECTS class QWidget; struct QEffects { enum Direction { LeftScroll = 0x0001, RightScroll = 0x0002, UpScroll = 0x0004, DownScroll = 0x0008 }; typedef uint DirFlags; }; extern void Q_EXPORT qScrollEffect( QWidget*, QEffects::DirFlags dir = QEffects::DownScroll, int time = -1 ); extern void Q_EXPORT qFadeEffect( QWidget*, int time = -1 ); #endif // QT_NO_EFFECTS #endif // QEFFECTS_P_H diff --git a/qmake/include/private/qeventloop_p.h b/qmake/include/private/qeventloop_p.h index b64d0df..3a5350e 100644 --- a/qmake/include/private/qeventloop_p.h +++ b/qmake/include/private/qeventloop_p.h @@ -1,74 +1,138 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QEventLoop class +** +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + #ifndef QEVENTLOOP_P_H #define QEVENTLOOP_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + #include "qplatformdefs.h" + +// SCO OpenServer redefines raise -> kill +#if defined(raise) +# undef raise +#endif + #include "qwindowdefs.h" class QSocketNotifier; -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) || defined (Q_WS_WIN) #include <qptrlist.h> +#endif // Q_OS_UNIX || Q_WS_WIN +#if defined(Q_OS_UNIX) struct QSockNot { QSocketNotifier *obj; int fd; fd_set *queue; }; class QSockNotType { public: QSockNotType(); ~QSockNotType(); QPtrList<QSockNot> *list; fd_set select_fds; fd_set enabled_fds; fd_set pending_fds; }; #endif // Q_OS_UNIX +#if defined(Q_WS_WIN) +struct QSockNot { + QSocketNotifier *obj; + int fd; +}; +#endif // Q_WS_WIN class QEventLoopPrivate { public: QEventLoopPrivate() { reset(); } void reset() { looplevel = 0; quitcode = 0; quitnow = FALSE; exitloop = FALSE; + shortcut = FALSE; } int looplevel; int quitcode; - bool quitnow; - bool exitloop; + unsigned int quitnow : 1; + unsigned int exitloop : 1; + unsigned int shortcut : 1; #if defined(Q_WS_MAC) EventLoopTimerRef select_timer; #endif #if defined(Q_WS_X11) int xfd; #endif // Q_WS_X11 #if defined(Q_OS_UNIX) int thread_pipe[2]; // pending socket notifiers list QPtrList<QSockNot> sn_pending_list; // highest fd for all socket notifiers int sn_highest; // 3 socket notifier types - read, write and exception QSockNotType sn_vec[3]; #endif + +#ifdef Q_WS_WIN + // pending socket notifiers list + QPtrList<QSockNot> sn_pending_list; +#endif // Q_WS_WIN + }; #endif // QEVENTLOOP_P_H diff --git a/qmake/include/private/qfontcodecs_p.h b/qmake/include/private/qfontcodecs_p.h index 8222f98..54b0ac1 100644 --- a/qmake/include/private/qfontcodecs_p.h +++ b/qmake/include/private/qfontcodecs_p.h @@ -1,368 +1,368 @@ /**************************************************************************** ** $Id$ ** ** Font utilities for X11 ** ** Created : 20001101 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QFONTCODECS_P_H #define QFONTCODECS_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qfontencodings_x11.cpp and qfont_x11.cpp. This header file may // change from version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H -#include <qglobal.h> -#include <qtextcodec.h> +#include "qglobal.h" +#include "qtextcodec.h" #endif // QT_H #ifndef QT_NO_CODECS #ifndef QT_NO_BIG_CODECS class QJpUnicodeConv; class QFontJis0201Codec : public QTextCodec { public: QFontJis0201Codec(); const char *name() const; int mibEnum() const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; int heuristicNameMatch(const char* hint) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; }; class QFontJis0208Codec : public QTextCodec { public: QFontJis0208Codec(); ~QFontJis0208Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; int heuristicNameMatch(const char* hint) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; private: QJpUnicodeConv *convJP; }; class QFontKsc5601Codec : public QTextCodec { public: QFontKsc5601Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; }; class QFontGb2312Codec : public QTextCodec { public: QFontGb2312Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; bool canEncode( QChar ) const; }; class QFontGbkCodec : public QTextCodec { public: QFontGbkCodec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; int heuristicNameMatch(const char* hint) const; bool canEncode( QChar ) const; }; class QFontGb18030_0Codec : public QTextCodec { public: QFontGb18030_0Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; }; class QFontBig5Codec : public QTextCodec { public: QFontBig5Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif int heuristicNameMatch(const char* hint) const; bool canEncode( QChar ) const; }; class QFontBig5hkscsCodec : public QTextCodec { public: QFontBig5hkscsCodec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; int heuristicNameMatch(const char* hint) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; }; // ------------------------------------------------------------------ // the shaping codec for iso8859-6.8x fonts (see www.langbox.com) class QFontArabic68Codec : public QTextCodec { public: QFontArabic68Codec(); // Return the official name for the encoding. const char* name() const ; // Return the MIB enum for the encoding if it is listed in the // IANA character-sets encoding file. int mibEnum() const ; // Converts len characters from chars to Unicode. QString toUnicode(const char* chars, int len) const ; // Converts lenInOut characters (of type QChar) from the start of // the string uc, returning a QCString result, and also returning // the length of the result in lenInOut. QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; QByteArray fromUnicode( const QString &str, int from, int len ) const; unsigned short characterFromUnicode(const QString &str, int pos) const; }; class QFontLaoCodec : public QTextCodec { public: QFontLaoCodec(); const char *name() const; int mibEnum() const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::fromUnicode; #endif QCString fromUnicode(const QString& uc, int& lenInOut ) const; int heuristicContentMatch(const char *, int) const; #if !defined(Q_NO_USING_KEYWORD) using QTextCodec::canEncode; #endif bool canEncode( QChar ) const; }; #endif // QT_NO_BIG_CODECS #endif // QT_NO_CODECS #endif // QFONTCODECS_P_H diff --git a/qmake/include/private/qfontdata_p.h b/qmake/include/private/qfontdata_p.h index 917d14f..1eaf80c 100644 --- a/qmake/include/private/qfontdata_p.h +++ b/qmake/include/private/qfontdata_p.h @@ -1,479 +1,480 @@ /**************************************************************************** ** $Id$ ** ** Definition of internal QFontData struct ** ** Created : 941229 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QFONTDATA_P_H #define QFONTDATA_P_H #ifndef QT_H #include <qcache.h> #include <qobject.h> #include <qpaintdevice.h> #endif // QT_H #include <limits.h> // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of internal files. This header file may change from version to version // without notice, or even be removed. // // We mean it. // // class QPaintDevice; #ifdef Q_WS_WIN #include <qt_windows.h> #endif #ifdef Q_WS_X11 #include <qt_x11.h> class QCharStruct; #endif // font description struct QFontDef { QFontDef() : pixelSize(0), pointSize(0), lbearing(SHRT_MIN), rbearing(SHRT_MIN), styleStrategy(QFont::PreferDefault), styleHint(QFont::AnyStyle), weight(0), italic(FALSE), underline(FALSE), strikeOut(FALSE), fixedPitch(FALSE), hintSetByUser(FALSE), rawMode(FALSE), dirty(TRUE) { ; } QString family; QString addStyle; int pixelSize; int pointSize; short lbearing; short rbearing; ushort styleStrategy; uchar styleHint; uchar weight; bool italic; bool underline; bool strikeOut; bool fixedPitch; bool hintSetByUser; bool rawMode; bool dirty; }; class QTextCodec; #ifdef Q_WS_X11 // this is a shared wrapper for XFontStruct (to prevent a font being freed by // the cache while it's being used) class QFontStruct : public QShared { public: QFontStruct(Qt::HANDLE h, Qt::HANDLE xfth, Qt::HANDLE xftp, QCString n, QTextCodec *c, int a) : QShared(), handle(h), xfthandle(xfth), xftpattern(xftp), name(n), codec(c), cache_cost(a), scale( 1. ) { ; } ~QFontStruct(); Qt::HANDLE handle, xfthandle, xftpattern; QCString name; QTextCodec *codec; int cache_cost; float scale; // needed for printing, to correctly scale font metrics for bitmap fonts }; enum { widthCacheSize = 0x500 }; class QFontX11Data // used as a QFontPrivate member { public: // X fontstruct handles for each character set QFontStruct *fontstruct[QFont::LastPrivateScript]; uchar widthCache[widthCacheSize]; QFontX11Data(); ~QFontX11Data(); }; #endif // Q_WS_X11 #ifdef Q_WS_WIN class QFontStruct : public QShared { public: QFontStruct( const QString &key ); ~QFontStruct() { reset(); } bool dirty() const { return hfont == 0; } HDC dc() const; HFONT font() const { return hfont; } const TEXTMETRICA *textMetricA() const { return &tm.a; } const TEXTMETRICW *textMetricW() const { return &tm.w; } QString key() const { return k; } void reset(); QString k; HDC hdc; HFONT hfont; uint stockFont:1; uint paintDevice:1; + uint useTextOutA:1; union { TEXTMETRICW w; TEXTMETRICA a; } tm; int lw; int cache_cost; // friend void QFont::initFontInfo() const; }; #endif // Q_WS_WIN #if defined( Q_WS_MAC ) #if defined( Q_WS_MACX ) # define QMAC_FONT_ATSUI #endif #include "qt_mac.h" class QMacFontInfo; class QFontStruct : public QShared { public: inline QFontStruct() : QShared(), info(NULL), fnum(-1), cache_cost(0), internal_fi(NULL) { } #if defined( QMAC_FONT_ATSUI ) && 0 ATSFontMetrics *info; int maxWidth() const { return (int)info->maxAdvanceWidth; } #else FontInfo *info; int maxWidth() const { return info->widMax; } #endif int ascent() const { return (int)info->ascent; } int descent() const { return (int)info->descent; } int leading() const { return (int)info->leading; } int minLeftBearing() const { return 0; } int minRightBearing() const { return 0; } short fnum; int psize, cache_cost; QMacFontInfo *internal_fi; }; #endif #ifdef Q_WS_QWS class QFontStruct; class QGfx; #endif typedef QCacheIterator<QFontStruct> QFontCacheIterator; class QFontCache : public QObject, public QCache<QFontStruct> { public: QFontCache(); ~QFontCache(); bool insert(const QString &, const QFontStruct *, int c); #ifndef Q_WS_MAC void deleteItem(Item d); #endif void timerEvent(QTimerEvent *); protected: private: int timer_id; bool fast; }; // QFontPrivate - holds all data on which a font operates class QFontPrivate : public QShared { public: static QFontCache *fontCache; public: QFontPrivate(); QFontPrivate(const QFontPrivate &fp); QFontPrivate( const QFontPrivate &fp, QPaintDevice *pd ); ~QFontPrivate(); // requested font QFontDef request; // actual font QFontDef actual; bool exactMatch; int lineWidth; // common functions QString defaultFamily() const; QString lastResortFamily() const; QString lastResortFont() const; QString key() const; static int getFontWeight(const QCString &, bool = FALSE); QRect boundingRect( const QChar &ch ); struct TextRun { TextRun() { xoff = 0; yoff = 0; x2off = 0; script = QFont::NoScript; string = 0; length = 0; next = 0; } ~TextRun() { if ( next ) delete next; } void setParams( int x, int y, int x2, const QChar *s, int len, QFont::Script sc = QFont::NoScript ) { xoff = x; yoff = y; x2off = x2; string = s; length = len; script = sc; } int xoff; int yoff; int x2off; QFont::Script script; const QChar *string; int length; TextRun *next; #ifdef Q_WS_X11 QByteArray mapped; #endif }; // some replacement functions for native calls. This is needed, because shaping and // non spacing marks can change the extents of a string to draw. At the same time // drawing needs to take care to correctly position non spacing marks. int textWidth( const QString &str, int pos, int len ); // returns the script a certain character is in. Needed to separate the string // into runs of different scripts as required for X11 and opentype. QFont::Script scriptForChar(const QChar &c); #ifdef Q_WS_X11 QFont::Script hanHack( const QChar & c ); static char **getXFontNames(const char *, int *); static bool fontExists(const QString &); static bool parseXFontName(char *, char **); static QCString fixXLFD( const QCString & ); static bool fillFontDef(XFontStruct *, QFontDef *, int); static bool fillFontDef(const QCString &, QFontDef *, int); static inline bool isZero(char *x) { return (x[0] == '0' && x[1] == 0); } static inline bool isScalable( char **tokens ) { return (isZero(tokens[PixelSize]) && isZero(tokens[PointSize]) && isZero(tokens[AverageWidth])); } static inline bool isSmoothlyScalable( char **tokens ) { return (isZero(tokens[ResolutionX]) && isZero(tokens[ResolutionY])); } static inline bool isFixedPitch( char **tokens ) { return (tokens[Spacing][0] == 'm' || tokens[Spacing][0] == 'c' || tokens[Spacing][0] == 'M' || tokens[Spacing][0] == 'C'); } // XLFD fields enum FontFieldNames { Foundry, Family, Weight, Slant, Width, AddStyle, PixelSize, PointSize, ResolutionX, ResolutionY, Spacing, AverageWidth, CharsetRegistry, CharsetEncoding, NFontFields }; #ifndef QT_NO_XFTFREETYPE XftPattern *findXftFont(const QChar &, bool *, double *scale) const; XftPattern *bestXftPattern(const QString &, const QString &, const QChar &, double *scale) const; #endif // QT_NO_XFTFREETYPE QCString findFont(QFont::Script, bool *, double *) const; QCString bestFamilyMember(QFont::Script, const QString &, const QString &, const QString &, int *, double *) const; QCString bestMatch(const char *, int *, QFont::Script, double *) const; int fontMatchScore(const char *, QCString &, float *, int *, bool *, bool *, QFont::Script, double *) const; void initFontInfo(QFont::Script, double scale); void load(QFont::Script = QFont::NoScript, bool = TRUE); bool loadUnicode(QFont::Script, const QChar &); void computeLineWidth(); int textWidth( const QString &str, int pos, int len, TextRun *cache ); void textExtents( const QString &str, int pos, int len, QCharStruct *overall ); void drawText( Display *dpy, int screen, Qt::HANDLE hd, Qt::HANDLE rendhd, GC gc, const QColor &pen, Qt::BGMode, const QColor &bgcolor, int x, int y, const TextRun *cache, int pdWidth ); bool inFont( const QChar &ch ); QFontX11Data x11data; static QFont::Script defaultScript; int x11Screen; #endif // Q_WS_X11 QPaintDevice *paintdevice; #ifdef Q_WS_WIN void load(); void initFontInfo(); HFONT create( bool *stockFont, HDC hdc = 0, bool compatMode = FALSE ); QFontStruct *fin; void buildCache( HDC hdc, const QString &str, int pos, int len, TextRun *cache ); void drawText( HDC hdc, int x, int y, TextRun *cache ); #endif // Q_WS_WIN #ifdef Q_WS_QWS void load(); QFontStruct *fin; int textWidth( const QString &str, int pos, int len, TextRun *cache ); void drawText( QGfx *gfx, int x, int y, const TextRun *cache ); #endif #if defined( Q_WS_MAC ) void macSetFont(QPaintDevice *); - void drawText(int x, int y, QString s, int len, QPaintDevice *dev, const QRegion *rgn); + void drawText(int x, int y, const QString &s, int from, int len, QPaintDevice *dev, const QRegion *rgn, int dir); void computeLineWidth(); void load(); QFontStruct *fin; #endif }; inline QFontPrivate::QFontPrivate() : QShared(), exactMatch(FALSE), lineWidth(1) { #if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) fin = 0; #endif // Q_WS_WIN || Q_WS_QWS #if defined(Q_WS_X11) x11Screen = QPaintDevice::x11AppScreen(); #endif // Q_WS_X11 paintdevice = 0; } inline QFontPrivate::QFontPrivate(const QFontPrivate &fp) : QShared(), request(fp.request), actual(fp.actual), exactMatch(fp.exactMatch), lineWidth(1) { Q_ASSERT(!fp.paintdevice); #if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) fin = 0; #endif // Q_WS_WIN || Q_WS_QWS #if defined(Q_WS_X11) x11Screen = fp.x11Screen; #endif // Q_WS_X11 paintdevice = 0; } inline QFontPrivate::QFontPrivate( const QFontPrivate &fp, QPaintDevice *pd ) : QShared(), request(fp.request), actual(fp.actual), exactMatch(fp.exactMatch), lineWidth(1) { #if defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_MAC) fin = 0; #endif // Q_WS_WIN || Q_WS_QWS #if defined(Q_WS_X11) x11Screen = pd->x11Screen(); #endif // Q_WS_X11 paintdevice = pd; } #ifndef Q_WS_QWS inline QFontPrivate::~QFontPrivate() { #if defined(Q_WS_WIN) if( fin ) fin->deref(); #endif #if defined(Q_WS_MAC) if( fin && fin->deref() ) delete fin; #endif } #endif #endif // QFONTDATA_P_H diff --git a/qmake/include/private/qgfxdriverinterface_p.h b/qmake/include/private/qgfxdriverinterface_p.h index 1782ed4..e8259ac 100644 --- a/qmake/include/private/qgfxdriverinterface_p.h +++ b/qmake/include/private/qgfxdriverinterface_p.h @@ -1,56 +1,68 @@ /**************************************************************************** ** $Id$ ** ** Definition of Qt/Embedded Graphics Driver Interface ** ** Created : 20020211 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Qt/Embedded may use this file in accordance with the ** Qt Embedded Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QGFXDRIVERINTERFACE_H -#define QGFXDRIVERINTERFACE_H +#ifndef QGFXDRIVERINTERFACE_P_H +#define QGFXDRIVERINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #ifndef QT_NO_COMPONENT // {449EC6C6-DF3E-43E3-9E57-354A3D05AB34} #ifndef IID_QGfxDriver #define IID_QGfxDriver QUuid( 0x449ec6c6, 0xdf3e, 0x43e3, 0x9e, 0x57, 0x35, 0x4a, 0x3d, 0x05, 0xab, 0x34) #endif class QScreen; struct Q_EXPORT QGfxDriverInterface : public QFeatureListInterface { virtual QScreen* create( const QString& driver, int displayId ) = 0; }; #endif // QT_NO_COMPONENT -#endif // QGFXDRIVERINTERFACE_H +#endif // QGFXDRIVERINTERFACE_P_H diff --git a/qmake/include/private/qgpluginmanager_p.h b/qmake/include/private/qgpluginmanager_p.h index e0c0e78..2e4e9c5 100644 --- a/qmake/include/private/qgpluginmanager_p.h +++ b/qmake/include/private/qgpluginmanager_p.h @@ -1,107 +1,107 @@ /********************************************************************** ** $Id$ ** ** Definition of QGPluginManager class ** -** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QGPLUGINMANAGER_H -#define QGPLUGINMANAGER_H +#ifndef QGPLUGINMANAGER_P_H +#define QGPLUGINMANAGER_P_H #ifndef QT_H #include "qdict.h" #include "qlibrary.h" #include "quuid.h" #include "qstringlist.h" #include "qcom_p.h" #endif // QT_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_NO_COMPONENT #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QLibrary>; // MOC_SKIP_END #endif class Q_EXPORT QGPluginManager { public: QGPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ); ~QGPluginManager(); void addLibraryPath( const QString& path ); const QLibrary* library( const QString& feature ) const; QStringList featureList() const; bool autoUnload() const; void setAutoUnload( bool ); protected: bool enabled() const; bool addLibrary( QLibrary* plugin ); QRESULT queryUnknownInterface(const QString& feature, QUnknownInterface** iface) const; QUuid interfaceId; QDict<QLibrary> plugDict; // Dict to match feature with library QDict<QLibrary> libDict; // Dict to match library file with library QStringList libList; uint casesens : 1; uint autounload : 1; }; inline void QGPluginManager::setAutoUnload( bool unload ) { autounload = unload; } inline bool QGPluginManager::autoUnload() const { return autounload; } #endif -#endif //QGPLUGINMANAGER_H +#endif //QGPLUGINMANAGER_P_H diff --git a/qmake/include/private/qimageformatinterface_p.h b/qmake/include/private/qimageformatinterface_p.h index 5f7601c..fd4c256 100644 --- a/qmake/include/private/qimageformatinterface_p.h +++ b/qmake/include/private/qimageformatinterface_p.h @@ -1,75 +1,75 @@ /**************************************************************************** ** $Id$ ** -** Definition of ??? +** ... ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QIMAGEFORMATINTERFACE_H -#define QIMAGEFORMATINTERFACE_H +#ifndef QIMAGEFORMATINTERFACE_P_H +#define QIMAGEFORMATINTERFACE_P_H #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of internal files. This header file may change from version to version // without notice, or even be removed. // // We mean it. // // #ifndef QT_NO_COMPONENT // {04903F05-54B1-4726-A849-FB5CB097CA87} #ifndef IID_QImageFormat #define IID_QImageFormat QUuid( 0x04903f05, 0x54b1, 0x4726, 0xa8, 0x49, 0xfb, 0x5c, 0xb0, 0x97, 0xca, 0x87 ) #endif class QImage; struct Q_EXPORT QImageFormatInterface : public QFeatureListInterface { virtual QRESULT loadImage( const QString &format, const QString &filename, QImage * ) = 0; virtual QRESULT saveImage( const QString &format, const QString &filename, const QImage & ) = 0; virtual QRESULT installIOHandler( const QString & ) = 0; }; #endif // QT_NO_COMPONENT -#endif // QIMAGEFORMATINTERFACE_H +#endif // QIMAGEFORMATINTERFACE_P_H diff --git a/qmake/include/private/qinputcontext_p.h b/qmake/include/private/qinputcontext_p.h index 9ac0d2b..4d94147 100644 --- a/qmake/include/private/qinputcontext_p.h +++ b/qmake/include/private/qinputcontext_p.h @@ -1,121 +1,124 @@ /**************************************************************************** ** $Id$ ** ** Definition of ??? ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QINPUTCONTEXT_P_H #define QINPUTCONTEXT_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of internal files. This header file may change from version to version // without notice, or even be removed. // // We mean it. // // #include <qglobal.h> class QKeyEvent; class QWidget; class QFont; class QString; #ifdef Q_WS_X11 #include "qarray.h" #include "qwindowdefs.h" #include "qt_x11.h" #endif #ifdef Q_WS_WIN #include <qt_windows.h> #endif #ifdef Q_WS_QWS class QWSIMEvent; #endif class QInputContext { public: #ifdef Q_WS_X11 QInputContext(QWidget *); // should be a toplevel widget ~QInputContext(); void setFocus(); void setComposePosition(int, int); void setComposeArea(int, int, int, int); void reset(); int lookupString(XKeyEvent *, QCString &, KeySym *, Status *) const; void setXFontSet(const QFont &); void *ic; - QString text, lastcompose; + QString text; QWidget *focusWidget; bool composing; QFont font; XFontSet fontset; QMemArray<bool> selectedChars; #endif // Q_WS_X11 #ifdef Q_WS_QWS static void translateIMEvent( QWSIMEvent *, QWidget * ); static void reset(); private: static QWidget* focusWidget; static QString* composition; #endif //Q_WS_QWS #ifdef Q_WS_WIN static void init(); static void shutdown(); static void TranslateMessage( const MSG *msg); static LRESULT DefWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); static void setFont( const QWidget *w, const QFont & ); static void setFocusHint( int x, int y, int w, int h, const QWidget *widget ); static bool startComposition(); static bool endComposition( QWidget *fw = 0 ); static bool composition( LPARAM lparam ); + + static void accept( QWidget *fw = 0 ); + static void enable( bool ); #endif }; #endif // QINPUTCONTEXT_P_H diff --git a/qmake/include/private/qkbddriverinterface_p.h b/qmake/include/private/qkbddriverinterface_p.h index efc7ded..fe13487 100644 --- a/qmake/include/private/qkbddriverinterface_p.h +++ b/qmake/include/private/qkbddriverinterface_p.h @@ -1,56 +1,68 @@ /**************************************************************************** ** $Id$ ** ** Definition of Qt/Embedded Keyboard Driver Interface ** ** Created : 20020218 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Qt/Embedded may use this file in accordance with the ** Qt Embedded Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QKBDDRIVERINTERFACE_H -#define QKBDDRIVERINTERFACE_H +#ifndef QKBDDRIVERINTERFACE_P_H +#define QKBDDRIVERINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #ifndef QT_NO_COMPONENT // {C7C838EA-FC3E-4905-92AD-F479E81F1D02} #ifndef IID_QKbdDriver #define IID_QKbdDriver QUuid( 0xc7c838ea, 0xfc3e, 0x4905, 0x92, 0xad, 0xf4, 0x79, 0xe8, 0x1f, 0x1d, 0x02) #endif class QWSKeyboardHandler; struct Q_EXPORT QKbdDriverInterface : public QFeatureListInterface { virtual QWSKeyboardHandler* create( const QString& driver, const QString& device ) = 0; }; #endif // QT_NO_COMPONENT -#endif // QKBDDRIVERINTERFACE_H +#endif // QKBDDRIVERINTERFACE_P_H diff --git a/qmake/include/private/qlibrary_p.h b/qmake/include/private/qlibrary_p.h index c4dd565..1624ca5 100644 --- a/qmake/include/private/qlibrary_p.h +++ b/qmake/include/private/qlibrary_p.h @@ -1,84 +1,81 @@ /**************************************************************************** ** $Id$ ** ** Definition of an internal QLibrary class ** -** Created : 2000-01-01 +** Created : 000101 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QLIBRARY_P_H #define QLIBRARY_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of the QLibrary class. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #include "qlibrary.h" #ifndef QT_NO_LIBRARY #ifndef QT_H -#if defined(Q_CC_GNU) -#warning "avoid including header file \"qwindowdefs.h\" in directory 'tools'" -#endif #include "qwindowdefs.h" #endif // QT_H class QLibraryPrivate { public: QLibraryPrivate( QLibrary *lib ); #ifdef Q_WS_WIN HINSTANCE pHnd; #else void *pHnd; #endif bool loadLibrary(); bool freeLibrary(); void *resolveSymbol( const char * ); private: QLibrary *library; }; #endif // QT_NO_LIBRARY #endif // QLIBRARY_P_H diff --git a/qmake/include/private/qlock_p.h b/qmake/include/private/qlock_p.h new file mode 100644 index 0000000..5c261aa --- a/dev/null +++ b/qmake/include/private/qlock_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QLock class. This manages interprocess locking +** +** Created : 20000406 +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Qt/Embedded may use this file in accordance with the +** Qt Embedded Commercial License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QLOCK_P_H +#define QLOCK_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include <qstring.h> +#endif // QT_H + +class QLockData; + +class QLock +{ +public: + QLock( const QString &filename, char id, bool create = FALSE ); + ~QLock(); + + enum Type { Read, Write }; + + bool isValid() const; + void lock( Type type ); + void unlock(); + bool locked() const; + +private: + Type type; + QLockData *data; +}; + + +// Nice class for ensuring the lock is released. +// Just create one on the stack and the lock is automatically released +// when QLockHolder is destructed. +class QLockHolder +{ +public: + QLockHolder( QLock *l, QLock::Type type ) : qlock(l) { + qlock->lock( type ); + } + ~QLockHolder() { if ( locked() ) qlock->unlock(); } + + void lock( QLock::Type type ) { qlock->lock( type ); } + void unlock() { qlock->unlock(); } + bool locked() const { return qlock->locked(); } + +private: + QLock *qlock; +}; + +#endif + diff --git a/qmake/include/private/qmousedriverinterface_p.h b/qmake/include/private/qmousedriverinterface_p.h index fd76308..42a2e3e 100644 --- a/qmake/include/private/qmousedriverinterface_p.h +++ b/qmake/include/private/qmousedriverinterface_p.h @@ -1,56 +1,68 @@ /**************************************************************************** ** $Id$ ** ** Definition of Qt/Embedded Mouse Driver Interface ** ** Created : 20020220 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Qt/Embedded may use this file in accordance with the ** Qt Embedded Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QMOUSEDRIVERINTERFACE_H -#define QMOUSEDRIVERINTERFACE_H +#ifndef QMOUSEDRIVERINTERFACE_P_H +#define QMOUSEDRIVERINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #ifndef QT_NO_COMPONENT // {4367CF5A-F7CE-407B-8BB6-DF19AEDA2EBB} #ifndef IID_QMouseDriver #define IID_QMouseDriver QUuid( 0x4367cf5a, 0xf7ce, 0x407b, 0x8b, 0xb6, 0xdf, 0x19, 0xae, 0xda, 0x2e, 0xbb) #endif class QWSMouseHandler; struct Q_EXPORT QMouseDriverInterface : public QFeatureListInterface { virtual QWSMouseHandler* create( const QString& driver, const QString &device ) = 0; }; #endif // QT_NO_COMPONENT -#endif // QMOUSEDRIVERINTERFACE_H +#endif // QMOUSEDRIVERINTERFACE_P_H diff --git a/qmake/include/private/qmutexpool_p.h b/qmake/include/private/qmutexpool_p.h index 3d9fef7..fb84157 100644 --- a/qmake/include/private/qmutexpool_p.h +++ b/qmake/include/private/qmutexpool_p.h @@ -1,39 +1,75 @@ -#ifndef QMUTEXPOOL_H -#define QMUTEXPOOL_H +/**************************************************************************** +** $Id$ +** +** ... +** +** Copyright (C) 2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QMUTEXPOOL_P_H +#define QMUTEXPOOL_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of QSettings. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // #ifdef QT_THREAD_SUPPORT #include "qmutex.h" #include "qmemarray.h" class QMutexPool { public: QMutexPool( bool recursive = FALSE, int size = 17 ); ~QMutexPool(); QMutex *get( void *address ); private: QMutex mutex; - QMemArray<QMutex*> mutexes; + QMutex **mutexes; + int count; bool recurs; }; extern QMutexPool *qt_global_mutexpool; #endif // QT_THREAD_SUPPORT -#endif // QMUTEXPOOL_H +#endif // QMUTEXPOOL_P_H diff --git a/qmake/include/private/qpluginmanager_p.h b/qmake/include/private/qpluginmanager_p.h index 4b64ba0..a8da10e 100644 --- a/qmake/include/private/qpluginmanager_p.h +++ b/qmake/include/private/qpluginmanager_p.h @@ -1,73 +1,73 @@ /**************************************************************************** ** $Id$ ** ** Definition of QPluginManager class ** -** Created : 2000-01-01 +** Created : 000101 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QPLUGINMANAGER_H -#define QPLUGINMANAGER_H - -#ifndef QT_H -#include "qgpluginmanager_p.h" -#endif // QT_H +#ifndef QPLUGINMANAGER_P_H +#define QPLUGINMANAGER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // +#ifndef QT_H +#include "qgpluginmanager_p.h" +#endif // QT_H + #ifndef QT_NO_COMPONENT template<class Type> class QPluginManager : public QGPluginManager { public: QPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ) : QGPluginManager( id, paths, suffix, cs ) {} QRESULT queryInterface(const QString& feature, Type** iface) const { return queryUnknownInterface( feature, (QUnknownInterface**)iface ); } }; #endif //QT_NO_COMPONENT -#endif //QPLUGINMANAGER_H +#endif //QPLUGINMANAGER_P_H diff --git a/qmake/include/private/qpsprinter_p.h b/qmake/include/private/qpsprinter_p.h index 27a4968..692cb44 100644 --- a/qmake/include/private/qpsprinter_p.h +++ b/qmake/include/private/qpsprinter_p.h @@ -1,89 +1,89 @@ /********************************************************************** ** $Id$ ** ** Definition of internal QPSPrinter class. ** QPSPrinter implements PostScript (tm) output via QPrinter. ** ** Created : 940927 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QPSPRINTER_P_H #define QPSPRINTER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qpsprinter.cpp and qprinter_x11.cpp. // This header file may change from version to version without notice, // or even be removed. // // We mean it. // // #ifndef QT_H #include "qprinter.h" #include "qtextstream.h" #endif // QT_H #ifndef QT_NO_PRINTER -struct QPSPrinterPrivate; +class QPSPrinterPrivate; class Q_EXPORT QPSPrinter : public QPaintDevice { private: // QPrinter uses these QPSPrinter( QPrinter *, int ); ~QPSPrinter(); bool cmd ( int, QPainter *, QPDevCmdParam * ); enum { NewPage = 100, AbortPrinting }; friend class QPrinter; private: // not used by QPrinter QPSPrinterPrivate *d; // Disabled copy constructor and operator= QPSPrinter( const QPSPrinter & ); QPSPrinter &operator=( const QPSPrinter & ); }; #endif // QT_NO_PRINTER #endif // QPSPRINTER_P_H diff --git a/qmake/include/private/qrichtext_p.h b/qmake/include/private/qrichtext_p.h index 8e29804..9ed87cf 100644 --- a/qmake/include/private/qrichtext_p.h +++ b/qmake/include/private/qrichtext_p.h @@ -1,2133 +1,2156 @@ /**************************************************************************** ** $Id$ ** ** Definition of internal rich text classes ** ** Created : 990124 ** ** Copyright (C) 1999-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QRICHTEXT_P_H #define QRICHTEXT_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qstring.h" #include "qptrlist.h" #include "qrect.h" #include "qfontmetrics.h" #include "qintdict.h" #include "qmap.h" #include "qstringlist.h" #include "qfont.h" #include "qcolor.h" #include "qsize.h" #include "qvaluelist.h" #include "qvaluestack.h" #include "qobject.h" #include "qdict.h" #include "qpixmap.h" #include "qstylesheet.h" #include "qptrvector.h" #include "qpainter.h" #include "qlayout.h" #include "qobject.h" #include "private/qcomplextext_p.h" #include "qapplication.h" #endif // QT_H #ifndef QT_NO_RICHTEXT class QTextDocument; class QTextString; class QTextPreProcessor; class QTextFormat; class QTextCursor; class QTextParagraph; class QTextFormatter; class QTextIndent; class QTextFormatCollection; class QStyleSheetItem; #ifndef QT_NO_TEXTCUSTOMITEM class QTextCustomItem; #endif class QTextFlow; struct QBidiContext; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextStringChar { friend class QTextString; public: // this is never called, initialize variables in QTextString::insert()!!! QTextStringChar() : lineStart( 0 ), type( Regular ), startOfRun( 0 ) {d.format=0;} ~QTextStringChar(); QChar c; enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; uint lineStart : 1; uint rightToLeft : 1; uint hasCursor : 1; uint canBreak : 1; Type type : 2; uint startOfRun : 1; int x; int height() const; int ascent() const; int descent() const; bool isCustom() const { return (type & Custom) != 0; } QTextFormat *format() const; #ifndef QT_NO_TEXTCUSTOMITEM QTextCustomItem *customItem() const; #endif void setFormat( QTextFormat *f ); #ifndef QT_NO_TEXTCUSTOMITEM void setCustomItem( QTextCustomItem *i ); #endif struct CustomData { QTextFormat *format; #ifndef QT_NO_TEXTCUSTOMITEM QTextCustomItem *custom; #endif QString anchorName; QString anchorHref; }; #ifndef QT_NO_TEXTCUSTOMITEM void loseCustomItem(); #endif union { QTextFormat* format; CustomData* custom; } d; bool isAnchor() const { return ( type & Anchor) != 0; } bool isLink() const { return isAnchor() && !!d.custom->anchorHref; } QString anchorName() const; QString anchorHref() const; void setAnchor( const QString& name, const QString& href ); private: QTextStringChar &operator=( const QTextStringChar & ) { //abort(); return *this; } + QTextStringChar( const QTextStringChar & ) { + } friend class QComplexText; friend class QTextParagraph; }; #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<QTextStringChar>; // MOC_SKIP_END #endif class Q_EXPORT QTextString { public: QTextString(); QTextString( const QTextString &s ); virtual ~QTextString(); - static QString toString( const QMemArray<QTextStringChar> &data ); - QString toString() const; + static QString toString( const QMemArray<QTextStringChar> &data, bool fixspaces = TRUE ); + QString toString( bool fixspaces = TRUE ) const; QTextStringChar &at( int i ) const; #if defined(Q_STRICT_INLINING_RULES) // This is for the IRIX MIPSpro o32 ABI - it fails, claiming the // implementation to be a redefinition. inline int length() const; #else int length() const; #endif int width( int idx ) const; void insert( int index, const QString &s, QTextFormat *f ); void insert( int index, const QChar *unicode, int len, QTextFormat *f ); void insert( int index, QTextStringChar *c, bool doAddRefFormat = FALSE ); void truncate( int index ); void remove( int index, int len ); void clear(); void setFormat( int index, QTextFormat *f, bool useCollection ); void setBidi( bool b ) { bidi = b; } bool isBidi() const; bool isRightToLeft() const; QChar::Direction direction() const; void setDirection( QChar::Direction d ) { dir = d; bidiDirty = TRUE; } QMemArray<QTextStringChar> subString( int start = 0, int len = 0xFFFFFF ) const; QMemArray<QTextStringChar> rawData() const { return data.copy(); } void operator=( const QString &s ) { clear(); insert( 0, s, 0 ); } void operator+=( const QString &s ) { insert( length(), s, 0 ); } void prepend( const QString &s ) { insert( 0, s, 0 ); } private: void checkBidi() const; QMemArray<QTextStringChar> data; uint bidiDirty : 1; uint bidi : 1; // true when the paragraph has right to left characters uint rightToLeft : 1; uint dir : 5; }; inline bool QTextString::isBidi() const { if ( bidiDirty ) checkBidi(); return bidi; } inline bool QTextString::isRightToLeft() const { if ( bidiDirty ) checkBidi(); return rightToLeft; } inline QChar::Direction QTextString::direction() const { return (QChar::Direction) dir; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<int>; Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<QTextParagraph*>; Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<bool>; // MOC_SKIP_END #endif class Q_EXPORT QTextCursor { public: QTextCursor( QTextDocument *d = 0 ); QTextCursor( const QTextCursor &c ); QTextCursor &operator=( const QTextCursor &c ); virtual ~QTextCursor() {} bool operator==( const QTextCursor &c ) const; bool operator!=( const QTextCursor &c ) const { return !(*this == c); } #if defined(Q_STRICT_INLINING_RULES) // This is for the IRIX MIPSpro o32 ABI - it fails, claiming the // implementation to be a redefinition. inline QTextParagraph *paragraph() const; #else QTextParagraph *paragraph() const; #endif void setParagraph( QTextParagraph*p ) { gotoPosition(p, 0 ); } QTextDocument *document() const; int index() const; void setIndex( int index ) { gotoPosition(paragraph(), index ); } void gotoPosition( QTextParagraph* p, int index = 0); void gotoLeft(); void gotoRight(); void gotoNextLetter(); void gotoPreviousLetter(); void gotoUp(); void gotoDown(); void gotoLineEnd(); void gotoLineStart(); void gotoHome(); void gotoEnd(); void gotoPageUp( int visibleHeight ); void gotoPageDown( int visibleHeight ); - void gotoNextWord(); - void gotoPreviousWord(); + void gotoNextWord( bool onlySpace = FALSE ); + void gotoPreviousWord( bool onlySpace = FALSE ); void gotoWordLeft(); void gotoWordRight(); void insert( const QString &s, bool checkNewLine, QMemArray<QTextStringChar> *formatting = 0 ); void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE ); bool remove(); void indent(); bool atParagStart(); bool atParagEnd(); int x() const; // x in current paragraph int y() const; // y in current paragraph int globalX() const; int globalY() const; QTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); } int offsetX() const { return ox; } // inner document offset int offsetY() const { return oy; } // inner document offset int totalOffsetX() const; // total document offset int totalOffsetY() const; // total document offset bool place( const QPoint &pos, QTextParagraph *s ) { return place( pos, s, FALSE ); } bool place( const QPoint &pos, QTextParagraph *s, bool link ); void restoreState(); int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast void oneUp() { if ( !indices.isEmpty() ) pop(); } void setValid( bool b ) { valid = b; } bool isValid() const { return valid; } private: enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down }; void push(); void pop(); - void processNesting( Operation op ); + bool processNesting( Operation op ); void invalidateNested(); void gotoIntoNested( const QPoint &globalPos ); QTextParagraph *para; int idx, tmpIndex; int ox, oy; QValueStack<int> indices; QValueStack<QTextParagraph*> paras; QValueStack<int> xOffsets; QValueStack<int> yOffsets; uint valid : 1; }; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextCommand { public: enum Commands { Invalid, Insert, Delete, Format, Style }; QTextCommand( QTextDocument *d ) : doc( d ), cursor( d ) {} virtual ~QTextCommand(); virtual Commands type() const; virtual QTextCursor *execute( QTextCursor *c ) = 0; virtual QTextCursor *unexecute( QTextCursor *c ) = 0; protected: QTextDocument *doc; QTextCursor cursor; }; #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCommand>; // MOC_SKIP_END #endif class Q_EXPORT QTextCommandHistory { public: QTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); } virtual ~QTextCommandHistory(); void clear() { history.clear(); current = -1; } void addCommand( QTextCommand *cmd ); QTextCursor *undo( QTextCursor *c ); QTextCursor *redo( QTextCursor *c ); bool isUndoAvailable(); bool isRedoAvailable(); void setUndoDepth( int d ) { steps = d; } int undoDepth() const { return steps; } int historySize() const { return history.count(); } int currentPosition() const { return current; } private: QPtrList<QTextCommand> history; int current, steps; }; inline QTextCommandHistory::~QTextCommandHistory() { clear(); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifndef QT_NO_TEXTCUSTOMITEM class Q_EXPORT QTextCustomItem { public: QTextCustomItem( QTextDocument *p ) : xpos(0), ypos(-1), width(-1), height(0), parent( p ) {} virtual ~QTextCustomItem(); virtual void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) = 0; virtual void adjustToPainter( QPainter* ); enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight }; virtual Placement placement() const; bool placeInline() { return placement() == PlaceInline; } virtual bool ownLine() const; virtual void resize( int nwidth ); virtual void invalidate(); virtual int ascent() const { return height; } virtual bool isNested() const; virtual int minimumWidth() const; virtual QString richText() const; int xpos; // used for floating items int ypos; // used for floating items int width; int height; QRect geometry() const { return QRect( xpos, ypos, width, height ); } virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint & ); virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); void setParagraph( QTextParagraph *p ) { parag = p; } QTextParagraph *paragraph() const { return parag; } QTextDocument *parent; QTextParagraph *parag; virtual void pageBreak( int y, QTextFlow* flow ); }; #endif #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QString, QString>; // MOC_SKIP_END #endif #ifndef QT_NO_TEXTCUSTOMITEM class Q_EXPORT QTextImage : public QTextCustomItem { public: QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, QMimeSourceFactory &factory ); virtual ~QTextImage(); Placement placement() const { return place; } void adjustToPainter( QPainter* ); int minimumWidth() const { return width; } QString richText() const; void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); private: QRegion* reg; QPixmap pm; Placement place; int tmpwidth, tmpheight; QMap<QString, QString> attributes; QString imgId; }; #endif #ifndef QT_NO_TEXTCUSTOMITEM class Q_EXPORT QTextHorizontalLine : public QTextCustomItem { public: QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, QMimeSourceFactory &factory ); virtual ~QTextHorizontalLine(); void adjustToPainter( QPainter* ); void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); QString richText() const; bool ownLine() const { return TRUE; } private: int tmpheight; QColor color; bool shade; }; #endif #ifndef QT_NO_TEXTCUSTOMITEM #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCustomItem>; // MOC_SKIP_END #endif #endif class Q_EXPORT QTextFlow { friend class QTextDocument; #ifndef QT_NO_TEXTCUSTOMITEM friend class QTextTableCell; #endif public: QTextFlow(); virtual ~QTextFlow(); virtual void setWidth( int width ); int width() const; virtual void setPageSize( int ps ); int pageSize() const { return pagesize; } virtual int adjustLMargin( int yp, int h, int margin, int space ); virtual int adjustRMargin( int yp, int h, int margin, int space ); #ifndef QT_NO_TEXTCUSTOMITEM virtual void registerFloatingItem( QTextCustomItem* item ); virtual void unregisterFloatingItem( QTextCustomItem* item ); #endif virtual QRect boundingRect() const; virtual void drawFloatingItems(QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift. virtual bool isEmpty(); void clear(); private: int w; int pagesize; #ifndef QT_NO_TEXTCUSTOMITEM QPtrList<QTextCustomItem> leftItems; QPtrList<QTextCustomItem> rightItems; #endif }; inline int QTextFlow::width() const { return w; } #ifndef QT_NO_TEXTCUSTOMITEM class QTextTable; class Q_EXPORT QTextTableCell : public QLayoutItem { friend class QTextTable; public: QTextTableCell( QTextTable* table, int row, int column, const QMap<QString, QString> &attr, const QStyleSheetItem* style, const QTextFormat& fmt, const QString& context, QMimeSourceFactory &factory, QStyleSheet *sheet, const QString& doc ); virtual ~QTextTableCell(); QSize sizeHint() const ; QSize minimumSize() const ; QSize maximumSize() const ; QSizePolicy::ExpandData expanding() const; bool isEmpty() const; void setGeometry( const QRect& ) ; QRect geometry() const; bool hasHeightForWidth() const; int heightForWidth( int ) const; void adjustToPainter( QPainter* ); int row() const { return row_; } int column() const { return col_; } int rowspan() const { return rowspan_; } int colspan() const { return colspan_; } int stretch() const { return stretch_; } QTextDocument* richText() const { return richtext; } QTextTable* table() const { return parent; } void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); QBrush *backGround() const { return background; } virtual void invalidate(); int verticalAlignmentOffset() const; int horizontalAlignmentOffset() const; private: QRect geom; QTextTable* parent; QTextDocument* richtext; int row_; int col_; int rowspan_; int colspan_; int stretch_; int maxw; int minw; bool hasFixedWidth; QBrush *background; int cached_width; int cached_sizehint; QMap<QString, QString> attributes; int align; }; #endif #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextTableCell>; Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QTextCursor*, int>; // MOC_SKIP_END #endif #ifndef QT_NO_TEXTCUSTOMITEM class Q_EXPORT QTextTable: public QTextCustomItem { friend class QTextTableCell; public: QTextTable( QTextDocument *p, const QMap<QString, QString> &attr ); virtual ~QTextTable(); void adjustToPainter( QPainter *p ); void pageBreak( int y, QTextFlow* flow ); void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); bool noErase() const { return TRUE; } bool ownLine() const { return TRUE; } Placement placement() const { return place; } bool isNested() const { return TRUE; } void resize( int nwidth ); virtual void invalidate(); virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint &pos ); virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); QString richText() const; int minimumWidth() const; QPtrList<QTextTableCell> tableCells() const { return cells; } bool isStretching() const { return stretch; } private: void format( int w ); void addCell( QTextTableCell* cell ); private: QGridLayout* layout; QPtrList<QTextTableCell> cells; int cachewidth; int fixwidth; int cellpadding; int cellspacing; int border; int outerborder; int stretch; int innerborder; int us_cp, us_ib, us_b, us_ob, us_cs; QMap<QString, QString> attributes; QMap<QTextCursor*, int> currCell; Placement place; void adjustCells( int y , int shift ); int pageBreakFor; }; #endif // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifndef QT_NO_TEXTCUSTOMITEM class QTextTableCell; class QTextParagraph; #endif struct Q_EXPORT QTextDocumentSelection { QTextCursor startCursor, endCursor; bool swapped; + Q_DUMMY_COMPARISON_OPERATOR(QTextDocumentSelection) }; #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QColor>; Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, bool>; Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextDocumentSelection>; Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextDocument>; // MOC_SKIP_END #endif class Q_EXPORT QTextDocument : public QObject { Q_OBJECT #ifndef QT_NO_TEXTCUSTOMITEM friend class QTextTableCell; #endif friend class QTextCursor; friend class QTextEdit; friend class QTextParagraph; public: enum SelectionIds { Standard = 0, IMSelectionText = 31998, IMCompositionText = 31999, // this must be higher! Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to // remove multiple lines with removeSelectedText() }; QTextDocument( QTextDocument *p ); QTextDocument( QTextDocument *d, QTextFormatCollection *f ); virtual ~QTextDocument(); QTextDocument *parent() const { return par; } QTextParagraph *parentParagraph() const { return parentPar; } void setText( const QString &text, const QString &context ); QMap<QString, QString> attributes() const { return attribs; } void setAttributes( const QMap<QString, QString> &attr ) { attribs = attr; } QString text() const; QString text( int parag ) const; QString originalText() const; int x() const; int y() const; int width() const; int widthUsed() const; int visibleWidth() const; int height() const; void setWidth( int w ); int minimumWidth() const; bool setMinimumWidth( int needed, int used = -1, QTextParagraph *parag = 0 ); void setY( int y ); int leftMargin() const; void setLeftMargin( int lm ); int rightMargin() const; void setRightMargin( int rm ); QTextParagraph *firstParagraph() const; QTextParagraph *lastParagraph() const; void setFirstParagraph( QTextParagraph *p ); void setLastParagraph( QTextParagraph *p ); void invalidate(); void setPreProcessor( QTextPreProcessor *sh ); QTextPreProcessor *preProcessor() const; void setFormatter( QTextFormatter *f ); QTextFormatter *formatter() const; void setIndent( QTextIndent *i ); QTextIndent *indent() const; QColor selectionColor( int id ) const; bool invertSelectionText( int id ) const; void setSelectionColor( int id, const QColor &c ); void setInvertSelectionText( int id, bool b ); bool hasSelection( int id, bool visible = FALSE ) const; void setSelectionStart( int id, const QTextCursor &cursor ); bool setSelectionEnd( int id, const QTextCursor &cursor ); void selectAll( int id ); bool removeSelection( int id ); void selectionStart( int id, int ¶gId, int &index ); QTextCursor selectionStartCursor( int id ); QTextCursor selectionEndCursor( int id ); void selectionEnd( int id, int ¶gId, int &index ); void setFormat( int id, QTextFormat *f, int flags ); int numSelections() const { return nSelections; } void addSelection( int id ); QString selectedText( int id, bool asRichText = FALSE ) const; void removeSelectedText( int id, QTextCursor *cursor ); void indentSelection( int id ); QTextParagraph *paragAt( int i ) const; void addCommand( QTextCommand *cmd ); QTextCursor *undo( QTextCursor *c = 0 ); QTextCursor *redo( QTextCursor *c = 0 ); QTextCommandHistory *commands() const { return commandHistory; } QTextFormatCollection *formatCollection() const; bool find( QTextCursor &cursor, const QString &expr, bool cs, bool wo, bool forward); void setTextFormat( Qt::TextFormat f ); Qt::TextFormat textFormat() const; bool inSelection( int selId, const QPoint &pos ) const; QStyleSheet *styleSheet() const { return sheet_; } #ifndef QT_NO_MIME QMimeSourceFactory *mimeSourceFactory() const { return factory_; } #endif QString context() const { return contxt; } void setStyleSheet( QStyleSheet *s ); void setDefaultFormat( const QFont &font, const QColor &color ); #ifndef QT_NO_MIME void setMimeSourceFactory( QMimeSourceFactory *f ) { if ( f ) factory_ = f; } #endif void setContext( const QString &c ) { if ( !c.isEmpty() ) contxt = c; } void setUnderlineLinks( bool b ); bool underlineLinks() const { return underlLinks; } void setPaper( QBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; } QBrush *paper() const { return backBrush; } void doLayout( QPainter *p, int w ); void draw( QPainter *p, const QRect& rect, const QColorGroup &cg, const QBrush *paper = 0 ); + void eraseParagraphEmptyArea( QTextParagraph *parag, QPainter *p, const QColorGroup &cg ); + bool useDoubleBuffer( QTextParagraph *parag, QPainter *p ); + void drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, QPixmap *&doubleBuffer, const QColorGroup &cg, bool drawCursor, QTextCursor *cursor, bool resetChanged = TRUE ); QTextParagraph *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, bool onlyChanged = FALSE, bool drawCursor = FALSE, QTextCursor *cursor = 0, bool resetChanged = TRUE ); #ifndef QT_NO_TEXTCUSTOMITEM void registerCustomItem( QTextCustomItem *i, QTextParagraph *p ); void unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ); #endif void setFlow( QTextFlow *f ); void takeFlow(); QTextFlow *flow() const { return flow_; } bool isPageBreakEnabled() const { return pages; } void setPageBreakEnabled( bool b ) { pages = b; } void setUseFormatCollection( bool b ) { useFC = b; } bool useFormatCollection() const { return useFC; } #ifndef QT_NO_TEXTCUSTOMITEM QTextTableCell *tableCell() const { return tc; } void setTableCell( QTextTableCell *c ) { tc = c; } #endif void setPlainText( const QString &text ); void setRichText( const QString &text, const QString &context ); QString richText() const; QString plainText() const; bool focusNextPrevChild( bool next ); int alignment() const; void setAlignment( int a ); int *tabArray() const; int tabStopWidth() const; void setTabArray( int *a ); void setTabStops( int tw ); void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); } int undoDepth() const { return commandHistory->undoDepth(); } int length() const; void clear( bool createEmptyParag = FALSE ); virtual QTextParagraph *createParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); void insertChild( QObject *o ) { QObject::insertChild( o ); } void removeChild( QObject *o ) { QObject::removeChild( o ); } void insertChild( QTextDocument *d ) { childList.append( d ); } void removeChild( QTextDocument *d ) { childList.removeRef( d ); } QPtrList<QTextDocument> children() const { return childList; } bool hasFocusParagraph() const; QString focusHref() const; QString focusName() const; void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } signals: void minimumWidthChanged( int ); private: void init(); QPixmap *bufferPixmap( const QSize &s ); // HTML parser bool hasPrefix(const QChar* doc, int length, int pos, QChar c); bool hasPrefix(const QChar* doc, int length, int pos, const QString& s); #ifndef QT_NO_TEXTCUSTOMITEM QTextCustomItem* parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, const QChar* doc, int length, int& pos, QTextParagraph *curpar ); #endif bool eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp = FALSE ); bool eat(const QChar* doc, int length, int& pos, QChar c); QString parseOpenTag(const QChar* doc, int length, int& pos, QMap<QString, QString> &attr, bool& emptyTag); QString parseCloseTag( const QChar* doc, int length, int& pos ); QChar parseHTMLSpecialChar(const QChar* doc, int length, int& pos); QString parseWord(const QChar* doc, int length, int& pos, bool lower = TRUE); QChar parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ); void setRichTextInternal( const QString &text, QTextCursor* cursor = 0 ); void setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ); private: struct Q_EXPORT Focus { QTextParagraph *parag; int start, len; QString href; QString name; }; int cx, cy, cw, vw; QTextParagraph *fParag, *lParag; QTextPreProcessor *pProcessor; QMap<int, QColor> selectionColors; QMap<int, QTextDocumentSelection> selections; QMap<int, bool> selectionText; QTextCommandHistory *commandHistory; QTextFormatter *pFormatter; QTextIndent *indenter; QTextFormatCollection *fCollection; Qt::TextFormat txtFormat; uint preferRichText : 1; uint pages : 1; uint useFC : 1; uint withoutDoubleBuffer : 1; uint underlLinks : 1; uint nextDoubleBuffered : 1; uint oTextValid : 1; uint mightHaveCustomItems : 1; int align; int nSelections; QTextFlow *flow_; QTextDocument *par; QTextParagraph *parentPar; #ifndef QT_NO_TEXTCUSTOMITEM QTextTableCell *tc; #endif QBrush *backBrush; QPixmap *buf_pixmap; Focus focusIndicator; int minw; int wused; int leftmargin; int rightmargin; QTextParagraph *minwParag, *curParag; QStyleSheet* sheet_; #ifndef QT_NO_MIME QMimeSourceFactory* factory_; #endif QString contxt; QMap<QString, QString> attribs; int *tArray; int tStopWidth; int uDepth; QString oText; QPtrList<QTextDocument> childList; QColor linkColor; double scaleFontsFactor; short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm; #if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator= QTextDocument( const QTextDocument & ); QTextDocument &operator=( const QTextDocument & ); #endif }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextDeleteCommand : public QTextCommand { public: QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, const QByteArray& oldStyle ); QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ); virtual ~QTextDeleteCommand(); Commands type() const { return Delete; } QTextCursor *execute( QTextCursor *c ); QTextCursor *unexecute( QTextCursor *c ); protected: int id, index; QTextParagraph *parag; QMemArray<QTextStringChar> text; QByteArray styleInformation; }; class Q_EXPORT QTextInsertCommand : public QTextDeleteCommand { public: QTextInsertCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, const QByteArray& oldStyleInfo ) : QTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {} QTextInsertCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) : QTextDeleteCommand( p, idx, str ) {} virtual ~QTextInsertCommand() {} Commands type() const { return Insert; } QTextCursor *execute( QTextCursor *c ) { return QTextDeleteCommand::unexecute( c ); } QTextCursor *unexecute( QTextCursor *c ) { return QTextDeleteCommand::execute( c ); } }; class Q_EXPORT QTextFormatCommand : public QTextCommand { public: QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ); virtual ~QTextFormatCommand(); Commands type() const { return Format; } QTextCursor *execute( QTextCursor *c ); QTextCursor *unexecute( QTextCursor *c ); protected: int startId, startIndex, endId, endIndex; QTextFormat *format; QMemArray<QTextStringChar> oldFormats; int flags; }; class Q_EXPORT QTextStyleCommand : public QTextCommand { public: QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ); virtual ~QTextStyleCommand() {} Commands type() const { return Style; } QTextCursor *execute( QTextCursor *c ); QTextCursor *unexecute( QTextCursor *c ); static QByteArray readStyleInformation( QTextDocument* d, int fParag, int lParag ); static void writeStyleInformation( QTextDocument* d, int fParag, const QByteArray& style ); private: int firstParag, lastParag; QByteArray before; QByteArray after; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ struct Q_EXPORT QTextParagraphSelection { int start, end; + Q_DUMMY_COMPARISON_OPERATOR(QTextParagraphSelection) }; struct Q_EXPORT QTextLineStart { QTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) #ifndef QT_NO_COMPLEXTEXT , bidicontext( 0 ) #endif { } QTextLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ), w( 0 ) #ifndef QT_NO_COMPLEXTEXT , bidicontext( 0 ) #endif { } #ifndef QT_NO_COMPLEXTEXT QTextLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0), status( s ), bidicontext( c ) { if ( bidicontext ) bidicontext->ref(); } #endif virtual ~QTextLineStart() { #ifndef QT_NO_COMPLEXTEXT if ( bidicontext && bidicontext->deref() ) delete bidicontext; #endif } #ifndef QT_NO_COMPLEXTEXT void setContext( QBidiContext *c ) { if ( c == bidicontext ) return; if ( bidicontext && bidicontext->deref() ) delete bidicontext; bidicontext = c; if ( bidicontext ) bidicontext->ref(); } QBidiContext *context() const { return bidicontext; } #endif public: ushort y, baseLine, h; #ifndef QT_NO_COMPLEXTEXT QBidiStatus status; #endif int w; private: #ifndef QT_NO_COMPLEXTEXT QBidiContext *bidicontext; #endif }; #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextParagraphSelection>; Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextLineStart*>; // MOC_SKIP_END #endif class Q_EXPORT QTextParagraphData { public: QTextParagraphData() {} virtual ~QTextParagraphData(); virtual void join( QTextParagraphData * ); }; -class Q_EXPORT QTextParagraphPseudoDocument -{ -public: - QTextParagraphPseudoDocument(); - ~QTextParagraphPseudoDocument(); - QRect docRect; - QTextFormatter *pFormatter; - QTextCommandHistory *commandHistory; - int minw; - int wused; -}; +class QTextParagraphPseudoDocument; + +class QSyntaxHighlighter; -//nase class Q_EXPORT QTextParagraph { friend class QTextDocument; friend class QTextCursor; + friend class QSyntaxHighlighter; public: QTextParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); virtual ~QTextParagraph(); QTextString *string() const; QTextStringChar *at( int i ) const; // maybe remove later int leftGap() const; int length() const; // maybe remove later void setListStyle( QStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; } QStyleSheetItem::ListStyle listStyle() const { return lstyle; } void setListItem( bool li ); bool isListItem() const { return litem; } void setListValue( int v ) { list_val = v; } int listValue() const { return list_val > 0 ? list_val : -1; } void setListDepth( int depth ); int listDepth() const { return ldepth; } // void setFormat( QTextFormat *fm ); // QTextFormat *paragFormat() const; +#if defined(Q_STRICT_INLINING_RULES) + // This is for the IRIX MIPSpro o32 ABI - it fails, claiming the + // implementation to be a redefinition. + inline QTextDocument *document() const; +#else QTextDocument *document() const; +#endif QTextParagraphPseudoDocument *pseudoDocument() const; QRect rect() const; void setHeight( int h ) { r.setHeight( h ); } void show(); void hide(); bool isVisible() const { return visible; } QTextParagraph *prev() const; QTextParagraph *next() const; void setPrev( QTextParagraph *s ); void setNext( QTextParagraph *s ); void insert( int index, const QString &s ); void insert( int index, const QChar *unicode, int len ); void append( const QString &s, bool reallyAtEnd = FALSE ); void truncate( int index ); void remove( int index, int len ); void join( QTextParagraph *s ); void invalidate( int chr ); void move( int &dy ); void format( int start = -1, bool doMove = TRUE ); bool isValid() const; bool hasChanged() const; void setChanged( bool b, bool recursive = FALSE ); int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; QTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; int lines() const; QTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; int lineY( int l ) const; int lineBaseLine( int l ) const; int lineHeight( int l ) const; void lineInfo( int l, int &y, int &h, int &bl ) const; void setSelection( int id, int start, int end ); void removeSelection( int id ); int selectionStart( int id ) const; int selectionEnd( int id ) const; bool hasSelection( int id ) const; bool hasAnySelection() const; bool fullSelected( int id ) const; void setEndState( int s ); int endState() const; void setParagId( int i ); int paragId() const; bool firstPreProcess() const; void setFirstPreProcess( bool b ); void indent( int *oldIndent = 0, int *newIndent = 0 ); void setExtraData( QTextParagraphData *data ); QTextParagraphData *extraData() const; QMap<int, QTextLineStart*> &lineStartList(); void setFormat( int index, int len, QTextFormat *f, bool useCollection = TRUE, int flags = -1 ); void setAlignment( int a ); int alignment() const; virtual void paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor = 0, bool drawSelections = FALSE, int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); virtual int topMargin() const; virtual int bottomMargin() const; virtual int leftMargin() const; virtual int firstLineMargin() const; virtual int rightMargin() const; virtual int lineSpacing() const; #ifndef QT_NO_TEXTCUSTOMITEM void registerFloatingItem( QTextCustomItem *i ); void unregisterFloatingItem( QTextCustomItem *i ); #endif void setFullWidth( bool b ) { fullWidth = b; } bool isFullWidth() const { return fullWidth; } #ifndef QT_NO_TEXTCUSTOMITEM QTextTableCell *tableCell() const; #endif QBrush *background() const; int documentWidth() const; int documentVisibleWidth() const; int documentX() const; int documentY() const; QTextFormatCollection *formatCollection() const; QTextFormatter *formatter() const; virtual int nextTab( int i, int x ); int *tabArray() const; void setTabArray( int *a ); void setTabStops( int tw ); void adjustToPainter( QPainter *p ); void setNewLinesAllowed( bool b ); bool isNewLinesAllowed() const; QString richText() const; void addCommand( QTextCommand *cmd ); QTextCursor *undo( QTextCursor *c = 0 ); QTextCursor *redo( QTextCursor *c = 0 ); QTextCommandHistory *commands() const; virtual void copyParagData( QTextParagraph *parag ); void setBreakable( bool b ) { breakable = b; } bool isBreakable() const { return breakable; } void setBackgroundColor( const QColor &c ); QColor *backgroundColor() const { return bgcol; } void clearBackgroundColor(); void setMovedDown( bool b ) { movedDown = b; } bool wasMovedDown() const { return movedDown; } void setDirection( QChar::Direction d ); QChar::Direction direction() const; void setPaintDevice( QPaintDevice *pd ) { paintdevice = pd; } void readStyleInformation( QDataStream& stream ); void writeStyleInformation( QDataStream& stream ) const; protected: virtual void setColorForSelection( QColor &c, QPainter &p, const QColorGroup& cg, int selection ); virtual void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ); virtual void drawString( QPainter &painter, const QString &str, int start, int len, int xstart, int y, int baseLine, int w, int h, int selection, QTextStringChar *formatChar, const QColorGroup& cg, bool rightToLeft ); private: QMap<int, QTextParagraphSelection> &selections() const; #ifndef QT_NO_TEXTCUSTOMITEM QPtrList<QTextCustomItem> &floatingItems() const; #endif QBrush backgroundBrush( const QColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( QColorGroup::Base ); } void invalidateStyleCache(); QMap<int, QTextLineStart*> lineStarts; int invalid; QRect r; QTextParagraph *p, *n; void *docOrPseudo; uint changed : 1; uint firstFormat : 1; uint firstPProcess : 1; uint needPreProcess : 1; uint fullWidth : 1; uint lastInFrame : 1; uint visible : 1; uint breakable : 1; uint movedDown : 1; uint mightHaveCustomItems : 1; uint hasdoc : 1; uint litem : 1; // whether the paragraph is a list item uint rtext : 1; // whether the paragraph needs rich text margin int align : 4; int state, id; QTextString *str; QMap<int, QTextParagraphSelection> *mSelections; #ifndef QT_NO_TEXTCUSTOMITEM QPtrList<QTextCustomItem> *mFloatingItems; #endif QStyleSheetItem::ListStyle lstyle; short utm, ubm, ulm, urm, uflm, ulinespacing; int *tArray; short tabStopWidth; QTextParagraphData *eData; short list_val; QColor *bgcol; ushort ldepth; QPaintDevice *paintdevice; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextFormatter { public: QTextFormatter(); virtual ~QTextFormatter(); virtual int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ) = 0; virtual int formatVertically( QTextDocument* doc, QTextParagraph* parag ); bool isWrapEnabled( QTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} int wrapAtColumn() const { return wrapColumn;} virtual void setWrapEnabled( bool b ); virtual void setWrapAtColumn( int c ); virtual void setAllowBreakInWords( bool b ) { biw = b; } bool allowBreakInWords() const { return biw; } int minimumWidth() const { return thisminw; } int widthUsed() const { return thiswused; } static bool isBreakable( QTextString *string, int pos ); protected: virtual QTextLineStart *formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, QTextStringChar *last, int align = Qt::AlignAuto, int space = 0 ); #ifndef QT_NO_COMPLEXTEXT virtual QTextLineStart *bidiReorderLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, QTextStringChar *last, int align, int space ); #endif void insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ); int thisminw; int thiswused; private: bool wrapEnabled; int wrapColumn; bool biw; #ifdef HAVE_THAI_BREAKS static QCString *thaiCache; static QTextString *cachedString; static ThBreakIterator *thaiIt; #endif }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextFormatterBreakInWords : public QTextFormatter { public: QTextFormatterBreakInWords(); virtual ~QTextFormatterBreakInWords() {} int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextFormatterBreakWords : public QTextFormatter { public: QTextFormatterBreakWords(); virtual ~QTextFormatterBreakWords() {} int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextIndent { public: QTextIndent(); virtual ~QTextIndent() {} virtual void indent( QTextDocument *doc, QTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextPreProcessor { public: enum Ids { Standard = 0 }; QTextPreProcessor(); virtual ~QTextPreProcessor() {} virtual void process( QTextDocument *doc, QTextParagraph *, int, bool = TRUE ) = 0; virtual QTextFormat *format( int id ) = 0; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ class Q_EXPORT QTextFormat { friend class QTextFormatCollection; friend class QTextDocument; public: enum Flags { NoFlags, Bold = 1, Italic = 2, Underline = 4, Family = 8, Size = 16, Color = 32, Misspelled = 64, VAlign = 128, StrikeOut= 256, Font = Bold | Italic | Underline | Family | Size | StrikeOut, Format = Font | Color | Misspelled | VAlign }; enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript }; QTextFormat(); virtual ~QTextFormat(); QTextFormat( const QStyleSheetItem *s ); QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent = 0 ); QTextFormat( const QTextFormat &fm ); QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const; QTextFormat& operator=( const QTextFormat &fm ); QColor color() const; QFont font() const; bool isMisspelled() const; VerticalAlignment vAlign() const; int minLeftBearing() const; int minRightBearing() const; int width( const QChar &c ) const; int width( const QString &str, int pos ) const; int height() const; int ascent() const; int descent() const; int leading() const; bool useLinkColor() const; void setBold( bool b ); void setItalic( bool b ); void setUnderline( bool b ); void setStrikeOut( bool b ); void setFamily( const QString &f ); void setPointSize( int s ); void setFont( const QFont &f ); void setColor( const QColor &c ); void setMisspelled( bool b ); void setVAlign( VerticalAlignment a ); bool operator==( const QTextFormat &f ) const; QTextFormatCollection *parent() const; const QString &key() const; static QString getKey( const QFont &f, const QColor &c, bool misspelled, VerticalAlignment vAlign ); void addRef(); void removeRef(); QString makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const; QString makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const; static void setPainter( QPainter *p ); static QPainter* painter(); bool fontSizesInPixels() { return usePixelSizes; } protected: virtual void generateKey(); private: void update(); static void applyFont( const QFont &f ); private: QFont fn; QColor col; QFontMetrics fm; uint missp : 1; uint linkColor : 1; uint usePixelSizes : 1; int leftBearing, rightBearing; VerticalAlignment ha; uchar widths[ 256 ]; int hei, asc, dsc; QTextFormatCollection *collection; int ref; QString k; int logicalFontSize; int stdSize; static QPainter *pntr; static QFontMetrics *pntr_fm; static int pntr_asc; static int pntr_hei; static int pntr_ldg; static int pntr_dsc; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QTextFormat>; // MOC_SKIP_END #endif class Q_EXPORT QTextFormatCollection { friend class QTextDocument; friend class QTextFormat; public: QTextFormatCollection(); virtual ~QTextFormatCollection(); void setDefaultFormat( QTextFormat *f ); QTextFormat *defaultFormat() const; virtual QTextFormat *format( QTextFormat *f ); virtual QTextFormat *format( QTextFormat *of, QTextFormat *nf, int flags ); virtual QTextFormat *format( const QFont &f, const QColor &c ); virtual void remove( QTextFormat *f ); virtual QTextFormat *createFormat( const QTextFormat &f ) { return new QTextFormat( f ); } virtual QTextFormat *createFormat( const QFont &f, const QColor &c ) { return new QTextFormat( f, c, this ); } void updateDefaultFormat( const QFont &font, const QColor &c, QStyleSheet *sheet ); - QDict<QTextFormat> dict() const { return cKey; } QPaintDevice *paintDevice() const { return paintdevice; } void setPaintDevice( QPaintDevice * ); private: void updateKeys(); private: QTextFormat *defFormat, *lastFormat, *cachedFormat; QDict<QTextFormat> cKey; QTextFormat *cres; QFont cfont; QColor ccol; QString kof, knf; int cflags; QPaintDevice *paintdevice; }; +class Q_EXPORT QTextParagraphPseudoDocument +{ +public: + QTextParagraphPseudoDocument(); + ~QTextParagraphPseudoDocument(); + QRect docRect; + QTextFormatter *pFormatter; + QTextCommandHistory *commandHistory; + int minw; + int wused; + QTextFormatCollection collection; +}; + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline int QTextString::length() const { return data.size(); } inline int QTextParagraph::length() const { return str->length(); } inline QRect QTextParagraph::rect() const { return r; } inline QTextParagraph *QTextCursor::paragraph() const { return para; } inline int QTextCursor::index() const { return idx; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline int QTextDocument::x() const { return cx; } inline int QTextDocument::y() const { return cy; } inline int QTextDocument::width() const { return QMAX( cw, flow_->width() ); } inline int QTextDocument::visibleWidth() const { return vw; } inline QTextParagraph *QTextDocument::firstParagraph() const { return fParag; } inline QTextParagraph *QTextDocument::lastParagraph() const { return lParag; } inline void QTextDocument::setFirstParagraph( QTextParagraph *p ) { fParag = p; } inline void QTextDocument::setLastParagraph( QTextParagraph *p ) { lParag = p; } inline void QTextDocument::setWidth( int w ) { cw = QMAX( w, minw ); flow_->setWidth( cw ); vw = w; } inline int QTextDocument::minimumWidth() const { return minw; } inline void QTextDocument::setY( int y ) { cy = y; } inline int QTextDocument::leftMargin() const { return leftmargin; } inline void QTextDocument::setLeftMargin( int lm ) { leftmargin = lm; } inline int QTextDocument::rightMargin() const { return rightmargin; } inline void QTextDocument::setRightMargin( int rm ) { rightmargin = rm; } inline QTextPreProcessor *QTextDocument::preProcessor() const { return pProcessor; } inline void QTextDocument::setPreProcessor( QTextPreProcessor * sh ) { pProcessor = sh; } inline void QTextDocument::setFormatter( QTextFormatter *f ) { delete pFormatter; pFormatter = f; } inline QTextFormatter *QTextDocument::formatter() const { return pFormatter; } inline void QTextDocument::setIndent( QTextIndent *i ) { indenter = i; } inline QTextIndent *QTextDocument::indent() const { return indenter; } inline QColor QTextDocument::selectionColor( int id ) const { return selectionColors[ id ]; } inline bool QTextDocument::invertSelectionText( int id ) const { return selectionText[ id ]; } inline void QTextDocument::setSelectionColor( int id, const QColor &c ) { selectionColors[ id ] = c; } inline void QTextDocument::setInvertSelectionText( int id, bool b ) { selectionText[ id ] = b; } inline QTextFormatCollection *QTextDocument::formatCollection() const { return fCollection; } inline int QTextDocument::alignment() const { return align; } inline void QTextDocument::setAlignment( int a ) { align = a; } inline int *QTextDocument::tabArray() const { return tArray; } inline int QTextDocument::tabStopWidth() const { return tStopWidth; } inline void QTextDocument::setTabArray( int *a ) { tArray = a; } inline void QTextDocument::setTabStops( int tw ) { tStopWidth = tw; } inline QString QTextDocument::originalText() const { if ( oTextValid ) return oText; return text(); } inline void QTextDocument::setFlow( QTextFlow *f ) { if ( flow_ ) delete flow_; flow_ = f; } inline void QTextDocument::takeFlow() { flow_ = 0; } +inline bool QTextDocument::useDoubleBuffer( QTextParagraph *parag, QPainter *p ) +{ + return ( !parag->document()->parent() || parag->document()->nextDoubleBuffered ) && + ( !p || !p->device() || p->device()->devType() != QInternal::Printer ); +} + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline QColor QTextFormat::color() const { return col; } inline QFont QTextFormat::font() const { return fn; } inline bool QTextFormat::isMisspelled() const { return missp; } inline QTextFormat::VerticalAlignment QTextFormat::vAlign() const { return ha; } inline bool QTextFormat::operator==( const QTextFormat &f ) const { return k == f.k; } inline QTextFormatCollection *QTextFormat::parent() const { return collection; } inline void QTextFormat::addRef() { ref++; } inline void QTextFormat::removeRef() { ref--; if ( !collection ) return; if ( this == collection->defFormat ) return; if ( ref == 0 ) collection->remove( this ); } inline const QString &QTextFormat::key() const { return k; } inline bool QTextFormat::useLinkColor() const { return linkColor; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline QTextStringChar &QTextString::at( int i ) const { return data[ i ]; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline QTextStringChar *QTextParagraph::at( int i ) const { return &str->at( i ); } inline bool QTextParagraph::isValid() const { return invalid == -1; } inline bool QTextParagraph::hasChanged() const { return changed; } inline void QTextParagraph::setBackgroundColor( const QColor & c ) { delete bgcol; bgcol = new QColor( c ); setChanged( TRUE ); } inline void QTextParagraph::clearBackgroundColor() { delete bgcol; bgcol = 0; setChanged( TRUE ); } inline void QTextParagraph::append( const QString &s, bool reallyAtEnd ) { if ( reallyAtEnd ) insert( str->length(), s ); else insert( QMAX( str->length() - 1, 0 ), s ); } inline QTextParagraph *QTextParagraph::prev() const { return p; } inline QTextParagraph *QTextParagraph::next() const { return n; } inline bool QTextParagraph::hasAnySelection() const { return mSelections ? !selections().isEmpty() : FALSE; } inline void QTextParagraph::setEndState( int s ) { if ( s == state ) return; state = s; } inline int QTextParagraph::endState() const { return state; } inline void QTextParagraph::setParagId( int i ) { id = i; } inline int QTextParagraph::paragId() const { if ( id == -1 ) qWarning( "invalid parag id!!!!!!!! (%p)", (void*)this ); return id; } inline bool QTextParagraph::firstPreProcess() const { return firstPProcess; } inline void QTextParagraph::setFirstPreProcess( bool b ) { firstPProcess = b; } inline QMap<int, QTextLineStart*> &QTextParagraph::lineStartList() { return lineStarts; } inline QTextString *QTextParagraph::string() const { return str; } inline QTextDocument *QTextParagraph::document() const { if ( hasdoc ) return (QTextDocument*) docOrPseudo; return 0; } inline QTextParagraphPseudoDocument *QTextParagraph::pseudoDocument() const { if ( hasdoc ) return 0; return (QTextParagraphPseudoDocument*) docOrPseudo; } #ifndef QT_NO_TEXTCUSTOMITEM inline QTextTableCell *QTextParagraph::tableCell() const { return hasdoc ? document()->tableCell () : 0; } #endif inline QTextCommandHistory *QTextParagraph::commands() const { return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; } inline int QTextParagraph::alignment() const { return align; } #ifndef QT_NO_TEXTCUSTOMITEM inline void QTextParagraph::registerFloatingItem( QTextCustomItem *i ) { floatingItems().append( i ); } inline void QTextParagraph::unregisterFloatingItem( QTextCustomItem *i ) { floatingItems().removeRef( i ); } #endif inline QBrush *QTextParagraph::background() const { #ifndef QT_NO_TEXTCUSTOMITEM return tableCell() ? tableCell()->backGround() : 0; #else return 0; #endif } inline int QTextParagraph::documentWidth() const { return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); } inline int QTextParagraph::documentVisibleWidth() const { return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); } inline int QTextParagraph::documentX() const { return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); } inline int QTextParagraph::documentY() const { return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); } inline void QTextParagraph::setExtraData( QTextParagraphData *data ) { eData = data; } inline QTextParagraphData *QTextParagraph::extraData() const { return eData; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline void QTextFormatCollection::setDefaultFormat( QTextFormat *f ) { defFormat = f; } inline QTextFormat *QTextFormatCollection::defaultFormat() const { return defFormat; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inline QTextFormat *QTextStringChar::format() const { return (type == Regular) ? d.format : d.custom->format; } #ifndef QT_NO_TEXTCUSTOMITEM inline QTextCustomItem *QTextStringChar::customItem() const { return isCustom() ? d.custom->custom : 0; } #endif inline int QTextStringChar::height() const { #ifndef QT_NO_TEXTCUSTOMITEM return !isCustom() ? format()->height() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->height : 0 ); #else return format()->height(); #endif } inline int QTextStringChar::ascent() const { #ifndef QT_NO_TEXTCUSTOMITEM return !isCustom() ? format()->ascent() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->ascent() : 0 ); #else return format()->ascent(); #endif } inline int QTextStringChar::descent() const { #ifndef QT_NO_TEXTCUSTOMITEM return !isCustom() ? format()->descent() : 0; #else return format()->descent(); #endif } #endif //QT_NO_RICHTEXT #endif diff --git a/qmake/include/private/qsettings_p.h b/qmake/include/private/qsettings_p.h index 18d118b..095291c 100644 --- a/qmake/include/private/qsettings_p.h +++ b/qmake/include/private/qsettings_p.h @@ -1,133 +1,133 @@ /**************************************************************************** ** $Id$ ** ** Definition of QSettings related classes ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Windows may use this file in accordance with the Qt Commercial ** License Agreement provided with the Software. ** ** This file is not available for use under any other license without ** express written permission from the copyright holder. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QSETTINGS_P_H #define QSETTINGS_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of QSettings. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qstringlist.h" #include "qmap.h" #include "qvaluestack.h" #endif // QT_H class QSettingsSysPrivate; // QSettingsGroup is a map of key/value pairs class QSettingsGroup : public QMap<QString,QString> { public: QSettingsGroup(); bool modified; }; // QSettingsHeading is a map of heading/group pairs class QSettingsHeading : public QMap<QString,QSettingsGroup> { public: QSettingsHeading::Iterator git; void read(const QString &); void parseLine(QTextStream &); }; class QSettingsPrivate { public: QSettingsPrivate( QSettings::Format format ); ~QSettingsPrivate(); QSettingsGroup readGroup(); void removeGroup(const QString &); void writeGroup(const QString &, const QString &); QDateTime modificationTime(); QStringList searchPaths; QMap<QString,QSettingsHeading> headings; QString group; QString heading; /*### static data brings threading trouble static QString *defProduct; static QString *defDomain; */ QValueStack<QString> groupStack; QString groupPrefix; bool groupDirty :1; bool modified :1; bool globalScope :1; -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) // system dependent implementations to use the // system specific setting database (ie. registry on Windows) QSettingsSysPrivate *sysd; void sysInit(); void sysClear(); #if !defined(Q_NO_BOOL_TYPE) bool sysWriteEntry( const QString &, bool ); #endif bool sysWriteEntry( const QString &, double ); bool sysWriteEntry( const QString &, int ); bool sysWriteEntry( const QString &, const QString & ); bool sysWriteEntry( const QString &, const QStringList & ); bool sysWriteEntry( const QString &, const QStringList &, const QChar& sep ); QStringList sysEntryList(const QString &) const; QStringList sysSubkeyList(const QString &) const; QStringList sysReadListEntry( const QString &, bool * = 0 ) const; QStringList sysReadListEntry( const QString &, const QChar& sep, bool * = 0 ) const; QString sysReadEntry( const QString &, const QString &def = QString::null, bool * = 0 ) const; int sysReadNumEntry( const QString &, int def = 0, bool * = 0 ) const; double sysReadDoubleEntry( const QString &, double def = 0, bool * = 0 ) const; bool sysReadBoolEntry( const QString &, bool def = 0, bool * = 0 ) const; bool sysRemoveEntry( const QString & ); bool sysSync(); void sysInsertSearchPath( QSettings::System, const QString & ); void sysRemoveSearchPath( QSettings::System, const QString & ); #endif }; #endif // QSETTINGS_P_H diff --git a/qmake/include/private/qsharedmemory_p.h b/qmake/include/private/qsharedmemory_p.h index 4a8339d..927de89 100644 --- a/qmake/include/private/qsharedmemory_p.h +++ b/qmake/include/private/qsharedmemory_p.h @@ -1,84 +1,87 @@ /**************************************************************************** ** $Id$ ** ** Includes system files for shared memory ** ** Created : 020124 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Qt/Embedded may use this file in accordance with the ** Qt Embedded Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ +#ifndef QSHAREDMEMORY_P_H +#define QSHAREDMEMORY_P_H + // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qapplication_qws.cpp and qgfxvnc_qws.cpp. This header file may // change from version to version without notice, or even be removed. // +// We mean it. +// // - -#if !defined(QT_QSHM_H) -#define QT_QSHM_H #include <qstring.h> #if !defined (QT_QWS_NO_SHM) #include <sys/types.h> #include <sys/ipc.h> class QSharedMemory { public: QSharedMemory(){}; QSharedMemory(int, QString, char c = 'Q'); ~QSharedMemory(){}; bool create(); void destroy(); bool attach(); void detach(); void setPermissions(mode_t mode); int size(); void * base() { return shmBase; }; private: void *shmBase; int shmSize; QString shmFile; char character; #if defined(QT_POSIX_QSHM) int shmFD; #else int shmId; key_t key; int idInitted; #endif }; #endif + #endif diff --git a/qmake/include/private/qsqldriverinterface_p.h b/qmake/include/private/qsqldriverinterface_p.h index 8957b86..8a39ddf 100644 --- a/qmake/include/private/qsqldriverinterface_p.h +++ b/qmake/include/private/qsqldriverinterface_p.h @@ -1,69 +1,82 @@ /**************************************************************************** +** $Id$ ** ** Definition of QSqlDriverInterface class ** ** Created : 2000-11-03 ** -** Copyright (C) 2000 Trolltech AS. All rights reserved. +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the sql module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QSQLDRIVERINTERFACE_H #define QSQLDRIVERINTERFACE_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) #define QM_EXPORT_SQL #else #define QM_EXPORT_SQL Q_EXPORT #endif #ifndef QT_NO_SQL #ifndef QT_NO_COMPONENT // {EDDD5AD5-DF3C-400c-A711-163B72FE5F61} #ifndef IID_QSqlDriverFactory #define IID_QSqlDriverFactory QUuid(0xeddd5ad5, 0xdf3c, 0x400c, 0xa7, 0x11, 0x16, 0x3b, 0x72, 0xfe, 0x5f, 0x61) #endif class QSqlDriver; struct QM_EXPORT_SQL QSqlDriverFactoryInterface : public QFeatureListInterface { virtual QSqlDriver* create( const QString& name ) = 0; }; #endif //QT_NO_COMPONENT #endif // QT_NO_SQL -#endif // QSQLDRIVERINTERFACE_H +#endif // QSQLDRIVERINTERFACE_P_H diff --git a/qmake/include/private/qsqlextension_p.h b/qmake/include/private/qsqlextension_p.h index 597b266..3445b47 100644 --- a/qmake/include/private/qsqlextension_p.h +++ b/qmake/include/private/qsqlextension_p.h @@ -1,101 +1,128 @@ /**************************************************************************** ** ** Definition of the QSqlExtension class ** ** Created : 2002-06-03 ** ** Copyright (C) 2002 Trolltech AS. All rights reserved. ** ** This file is part of the sql module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QSQLEXTENSION_P_H #define QSQLEXTENSION_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of other Qt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qmap.h" +#include "qvaluevector.h" #include "qstring.h" #include "qvariant.h" +#include "qsql.h" #endif // QT_H #ifndef QT_NO_SQL #if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) #define QM_EXPORT_SQL +#define QM_TEMPLATE_EXTERN_SQL #else #define QM_EXPORT_SQL Q_EXPORT +#define QM_TEMPLATE_EXTERN_SQL Q_TEMPLATE_EXTERN #endif +struct Param { + Param( const QVariant& v = QVariant(), QSql::ParameterType t = QSql::In ): value( v ), typ( t ) {} + QVariant value; + QSql::ParameterType typ; + Q_DUMMY_COMPARISON_OPERATOR(Param) +}; + +struct Holder { + Holder( const QString& hldr = QString::null, int pos = -1 ): holderName( hldr ), holderPos( pos ) {} + bool operator==( const Holder& h ) const { return h.holderPos == holderPos && h.holderName == holderName; } + bool operator!=( const Holder& h ) const { return h.holderPos != holderPos || h.holderName != holderName; } + QString holderName; + int holderPos; +}; + #if defined(Q_TEMPLATEDLL) -Q_TEMPLATE_EXTERN template class QM_EXPORT_SQL QMap<QString,QVariant>; -Q_TEMPLATE_EXTERN template class QM_EXPORT_SQL QMap<int,QString>; +QM_TEMPLATE_EXTERN_SQL template class QM_EXPORT_SQL QMap<QString,Param>; +QM_TEMPLATE_EXTERN_SQL template class QM_EXPORT_SQL QMap<int,QString>; +QM_TEMPLATE_EXTERN_SQL template class QM_EXPORT_SQL QValueVector<Holder>; #endif class QM_EXPORT_SQL QSqlExtension { public: QSqlExtension(); virtual ~QSqlExtension(); virtual bool prepare( const QString& query ); virtual bool exec(); - virtual void bindValue( const QString& holder, const QVariant& value ); - virtual void bindValue( int pos, const QVariant& value ); - virtual void addBindValue( const QVariant& value ); + virtual void bindValue( const QString& holder, const QVariant& value, QSql::ParameterType = QSql::In ); + virtual void bindValue( int pos, const QVariant& value, QSql::ParameterType = QSql::In ); + virtual void addBindValue( const QVariant& value, QSql::ParameterType = QSql::In ); + virtual QVariant parameterValue( const QString& holder ); + virtual QVariant parameterValue( int pos ); void clearValues(); void clearIndex(); enum BindMethod { BindByPosition, BindByName }; BindMethod bindMethod(); BindMethod bindm; int bindCount; QMap<int, QString> index; - QMap<QString, QVariant> values; + typedef QMap<QString, Param> ValueMap; + ValueMap values; + + // convenience container for QSqlQuery + // to map holders <-> positions + typedef QValueVector<Holder> HolderVector; + HolderVector holders; }; class QM_EXPORT_SQL QSqlDriverExtension { public: QSqlDriverExtension(); virtual ~QSqlDriverExtension(); virtual bool isOpen() const = 0; }; - #endif #endif diff --git a/qmake/include/private/qstyleinterface_p.h b/qmake/include/private/qstyleinterface_p.h index 4aaedc7..24a43ad 100644 --- a/qmake/include/private/qstyleinterface_p.h +++ b/qmake/include/private/qstyleinterface_p.h @@ -1,61 +1,73 @@ /**************************************************************************** ** $Id$ ** ** ... ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the widgets module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QSTYLEINTERFACE_H -#define QSTYLEINTERFACE_H +#ifndef QSTYLEINTERFACE_P_H +#define QSTYLEINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #ifndef QT_NO_STYLE #ifndef QT_NO_COMPONENT class QStyle; // {FC1B6EBE-053C-49c1-A483-C377739AB9A5} #ifndef IID_QStyleFactory #define IID_QStyleFactory QUuid(0xfc1b6ebe, 0x53c, 0x49c1, 0xa4, 0x83, 0xc3, 0x77, 0x73, 0x9a, 0xb9, 0xa5) #endif struct Q_EXPORT QStyleFactoryInterface : public QFeatureListInterface { virtual QStyle* create( const QString& style ) = 0; }; #endif //QT_NO_COMPONENT #endif //QT_NO_STYLE -#endif //QSTYLEINTERFACE_H +#endif //QSTYLEINTERFACE_P_H diff --git a/qmake/include/private/qsvgdevice_p.h b/qmake/include/private/qsvgdevice_p.h index c1cc389..3407705 100644 --- a/qmake/include/private/qsvgdevice_p.h +++ b/qmake/include/private/qsvgdevice_p.h @@ -1,134 +1,134 @@ /**************************************************************************** ** $Id$ ** ** Definition of the QSvgDevice class ** -** Created : 20001024 +** Created : 001024 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the xml module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** *****************************************************************************/ -#ifndef QSVGDEVICE_H -#define QSVGDEVICE_H +#ifndef QSVGDEVICE_P_H +#define QSVGDEVICE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of the QPicture class. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qpaintdevice.h" #include "qrect.h" #include "qdom.h" #endif // QT_H #if !defined(QT_MODULE_XML) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_XML ) #define QM_EXPORT_SVG #else #define QM_EXPORT_SVG Q_EXPORT #endif #ifndef QT_NO_SVG class QPainter; class QDomNode; class QDomNamedNodeMap; struct QSvgDeviceState; class QSvgDevicePrivate; class QM_EXPORT_SVG QSvgDevice : public QPaintDevice { public: QSvgDevice(); ~QSvgDevice(); bool play( QPainter *p ); QString toString() const; bool load( QIODevice *dev ); bool save( QIODevice *dev ); bool save( const QString &fileName ); QRect boundingRect() const; void setBoundingRect( const QRect &r ); protected: virtual bool cmd ( int, QPainter*, QPDevCmdParam* ); virtual int metric( int ) const; private: // reading bool play( const QDomNode &node ); void saveAttributes(); void restoreAttributes(); QColor parseColor( const QString &col ); double parseLen( const QString &str, bool *ok=0, bool horiz=TRUE ) const; int lenToInt( const QDomNamedNodeMap &map, const QString &attr, int def=0 ) const; void setStyleProperty( const QString &prop, const QString &val, QPen *pen, QFont *font, int *talign ); void setStyle( const QString &s ); void setTransform( const QString &tr ); void drawPath( const QString &data ); // writing void applyStyle( QDomElement *e, int c ) const; void applyTransform( QDomElement *e ) const; // reading QRect brect; // bounding rectangle QDomDocument doc; // document tree QDomNode current; QPoint curPt; QSvgDeviceState *curr; QPainter *pt; // used by play() et al // writing bool dirtyTransform, dirtyStyle; QSvgDevicePrivate *d; }; inline QRect QSvgDevice::boundingRect() const { return brect; } #endif // QT_NO_SVG -#endif // QSVGDEVICE_H +#endif // QSVGDEVICE_P_H diff --git a/qmake/include/private/qtextcodecinterface_p.h b/qmake/include/private/qtextcodecinterface_p.h index d2a2cb9..76e77f7 100644 --- a/qmake/include/private/qtextcodecinterface_p.h +++ b/qmake/include/private/qtextcodecinterface_p.h @@ -1,79 +1,77 @@ /**************************************************************************** ** $Id$ ** ** Definition of QTextCodecFactoryInterface interface ** ** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QTEXTCODECINTERFACE_P_H #define QTEXTCODECINTERFACE_P_H - // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qpsprinter.cpp and qprinter_x11.cpp. // This header file may change from version to version without notice, // or even be removed. // // We mean it. // // - #ifndef QT_H #include <private/qcom_p.h> #endif // QT_H #ifndef QT_NO_TEXTCODEC #ifndef QT_NO_COMPONENT class QTextCodec; // {F55BFA60-F695-11D4-823E-009027DC0F37} #ifndef IID_QTextCodecFactory #define IID_QTextCodecFactory QUuid( 0xf55bfa60, 0xf695, 0x11d4, 0x82, 0x3e, 0x00, 0x90, 0x27, 0xdc, 0x0f, 0x37) #endif struct Q_EXPORT QTextCodecFactoryInterface : public QFeatureListInterface { virtual QTextCodec *createForMib( int mib ) = 0; virtual QTextCodec *createForName( const QString &name ) = 0; }; #endif // QT_NO_COMPONENT #endif // QT_NO_TEXTCODEC #endif // QTEXTCODECINTERFACE_P_H diff --git a/qmake/include/private/qtitlebar_p.h b/qmake/include/private/qtitlebar_p.h index dabb6bf..091845f 100644 --- a/qmake/include/private/qtitlebar_p.h +++ b/qmake/include/private/qtitlebar_p.h @@ -1,136 +1,136 @@ /**************************************************************************** ** $Id$ ** ** Definition of some Qt private functions. ** -** Created : 2000-01-01 +** Created : 000101 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the widgets module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QTITLEBAR_P_H #define QTITLEBAR_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of qworkspace.cpp and qdockwindow.cpp. This header file may change // from version to version without notice, or even be removed. // // We mean it. // // #ifndef QT_H #include "qbutton.h" #include "qlabel.h" #endif // QT_H #if !defined(QT_NO_TITLEBAR) class QToolTip; class QTitleBarPrivate; class QPixmap; class Q_EXPORT QTitleBar : public QWidget { Q_OBJECT Q_PROPERTY( bool autoRaise READ autoRaise WRITE setAutoRaise ) Q_PROPERTY( bool movable READ isMovable WRITE setMovable ) public: QTitleBar (QWidget* w, QWidget* parent, const char* name=0); ~QTitleBar(); bool isActive() const; bool usesActiveColor() const; virtual QString visibleText() const; bool isMovable() const; void setMovable(bool); bool autoRaise() const; void setAutoRaise(bool); QWidget *window() const; QSize sizeHint() const; #ifdef QT_NO_WIDGET_TOPEXTRA // We provide one, since titlebar is useless otherwise. QString caption() const; #endif public slots: void setActive( bool ); void setCaption( const QString& title ); void setIcon( const QPixmap& icon ); signals: void doActivate(); void doNormal(); void doClose(); void doMaximize(); void doMinimize(); void doShade(); void showOperationMenu(); void popupOperationMenu( const QPoint& ); void doubleClicked(); protected: bool event( QEvent *); void resizeEvent( QResizeEvent *); void contextMenuEvent( QContextMenuEvent * ); void mousePressEvent( QMouseEvent * ); void mouseDoubleClickEvent( QMouseEvent * ); void mouseReleaseEvent( QMouseEvent * ); void mouseMoveEvent( QMouseEvent * ); void enterEvent( QEvent *e ); void leaveEvent( QEvent *e ); void paintEvent( QPaintEvent *p ); virtual void cutText(); private: void readColors(); QTitleBarPrivate *d; #if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator= QTitleBar( const QTitleBar & ); QTitleBar &operator=( const QTitleBar & ); #endif }; #endif #endif //QTITLEBAR_P_H diff --git a/qmake/include/private/qucom_p.h b/qmake/include/private/qucom_p.h index d2ff48e..6b6ad40 100644 --- a/qmake/include/private/qucom_p.h +++ b/qmake/include/private/qucom_p.h @@ -1,499 +1,463 @@ /**************************************************************************** ** $Id$ ** ** Definition of the QUcom interfaces ** ** Created : 990101 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QUCOM_H -#define QUCOM_H - -#ifndef QT_H -#include <qstring.h> -#include "quuid.h" -#endif // QT_H +#ifndef QUCOM_P_H +#define QUCOM_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // +#ifndef QT_H +#include <qstring.h> +#include "quuid.h" +#endif // QT_H + #ifdef check #undef check #endif struct QUObject; struct QUInterfaceDescription; struct QUnknownInterface; struct QDispatchInterface; struct Q_EXPORT QUBuffer { virtual long read( char *data, ulong maxlen ) = 0; virtual long write( const char *data, ulong len ) = 0; }; // A type for a QUObject struct Q_EXPORT QUType { virtual const QUuid *uuid() const = 0; virtual const char *desc() const = 0; virtual bool canConvertFrom( QUObject *, QUType * ) = 0; // virtual private, only called by canConvertFrom virtual bool canConvertTo( QUObject *, QUType * ) = 0; virtual bool convertFrom( QUObject *, QUType * ) = 0; // virtual private, only called by convertFrom virtual bool convertTo( QUObject *, QUType * ) = 0; virtual void clear( QUObject * ) = 0; virtual int serializeTo( QUObject *, QUBuffer * ) = 0; virtual int serializeFrom( QUObject *, QUBuffer * ) = 0; static bool isEqual( const QUType *t1, const QUType *t2 ); static bool check( QUObject* o, QUType* t ); }; // {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} extern Q_EXPORT const QUuid TID_QUType_Null; struct Q_EXPORT QUType_Null : public QUType { const QUuid *uuid() const; const char *desc() const; bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ); int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_Null static_QUType_Null; // The magic QUObject struct Q_EXPORT QUObject { public: // scary MSVC bug makes this necessary QUObject() : type( &static_QUType_Null ) {} ~QUObject() { type->clear( this ); } QUType *type; // the unavoidable union union { bool b; char c; short s; int i; long l; unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul; float f; double d; char byte[16]; struct { char* data; unsigned long size; } bytearray; void* ptr; struct { void *ptr; bool owner; } voidstar; struct { char *ptr; bool owner; } charstar; struct { char *ptr; bool owner; } utf8; struct { char *ptr; bool owner; } local8bit; QUnknownInterface* iface; QDispatchInterface* idisp; } payload; }; // A parameter description describes one method parameters. A // parameter has a name, a type and a flag describing whether it's an // in parameter, an out parameter, or both ways struct Q_EXPORT QUParameter { const char* name; QUType *type; const void* typeExtra; //Usually 0, UEnum* for QUType_enum, const char* for QUType_ptr, int* for QUType_varptr enum { In = 1, Out = 2, InOut = In | Out }; int inOut; }; // A method description describes one method. A method has a name and // an array of parameters. struct Q_EXPORT QUMethod { const char* name; int count; const QUParameter* parameters; }; // A Property description. Not used yet in the example. struct Q_EXPORT QUProperty { const char* name; QUType* type; const void* typeExtra; //type dependend. Usually 0, but UEnum for QUTypeenum or const char* for QUTypeptr int set; // -1 undefined int get; // -1 undefined int designable; // -1 FALSE, -2 TRUE, else method int stored; // -1 FALSE, -2 TRUE, else method }; // An interface description describes one interface, that is all its // methods and properties. struct Q_EXPORT QUInterfaceDescription { int methodCount; const QUMethod* methods; int propertyCount; const QUProperty* properties; }; // A component description describe one component, that is its name, // vendor, release, info, its component uuid and all its interface // uuids. struct Q_EXPORT QUComponentDescription { const char* name; const char* vendor; const char* release; const char* info; QUuid cid; int count; const QUuid* interfaces; }; // A component server description describe one component server, that // is its name, vendor, release, info and the descriptions of all // components it can instantiate. struct Q_EXPORT QUComponentServerDescription { const char* name; const char* vendor; const char* release; const char* info; int count; const QUComponentDescription* components; }; struct Q_EXPORT QUEnumItem // - a name/value pair { const char *key; int value; }; struct Q_EXPORT QUEnum { const char *name; // - enumerator name unsigned int count; // - number of values const QUEnumItem *items; // - the name/value pairs bool set; // whether enum has to be treated as a set }; inline bool QUType::isEqual( const QUType *t1, const QUType *t2 ) { return t1 == t2 || t1->uuid() == t2->uuid() || *(t1->uuid()) == *(t2->uuid()); } inline bool QUType::check( QUObject* o, QUType* t ) { return isEqual( o->type, t ) || t->convertFrom( o, o->type ); } // {7EE17B08-5419-47e2-9776-8EEA112DCAEC} extern Q_EXPORT const QUuid TID_QUType_enum; struct Q_EXPORT QUType_enum : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, int ); int &get( QUObject * o ) { return o->payload.i; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_enum static_QUType_enum; // {8AC26448-5AB4-49eb-968C-8F30AB13D732} extern Q_EXPORT const QUuid TID_QUType_ptr; struct Q_EXPORT QUType_ptr : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, const void* ); void* &get( QUObject * o ) { return o->payload.ptr; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_ptr static_QUType_ptr; // {97A2594D-6496-4402-A11E-55AEF2D4D25C} extern Q_EXPORT const QUuid TID_QUType_iface; struct Q_EXPORT QUType_iface : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, QUnknownInterface* ); QUnknownInterface* &get( QUObject *o ){ return o->payload.iface; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_iface static_QUType_iface; // {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} extern Q_EXPORT const QUuid TID_QUType_idisp; struct Q_EXPORT QUType_idisp : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, QDispatchInterface* ); QDispatchInterface* &get( QUObject *o ){ return o->payload.idisp; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_idisp static_QUType_idisp; // {CA42115D-13D0-456c-82B5-FC10187F313E} extern Q_EXPORT const QUuid TID_QUType_bool; struct Q_EXPORT QUType_bool : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, bool ); bool &get( QUObject *o ) { return o->payload.b; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_bool static_QUType_bool; // {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} extern Q_EXPORT const QUuid TID_QUType_int; struct Q_EXPORT QUType_int : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, int ); int &get( QUObject *o ) { return o->payload.i; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_int static_QUType_int; -// {5938712A-C496-11D5-8CB2-00C0F03BC0F3} -extern Q_EXPORT const QUuid TID_QUType_uint; -struct Q_EXPORT QUType_uint : public QUType -{ - const QUuid *uuid() const; - const char *desc() const; - - void set( QUObject *, uint ); - uint &get( QUObject *o ) { return o->payload.ui; } - bool canConvertFrom( QUObject *, QUType * ); - bool canConvertTo( QUObject *, QUType * ); - bool convertFrom( QUObject *, QUType * ); - bool convertTo( QUObject *, QUType * ); - void clear( QUObject * ) {} - int serializeTo( QUObject *, QUBuffer * ); - int serializeFrom( QUObject *, QUBuffer * ); -}; -extern Q_EXPORT QUType_uint static_QUType_uint; // {2D0974E5-0BA6-4ec2-8837-C198972CB48C} extern Q_EXPORT const QUuid TID_QUType_double; struct Q_EXPORT QUType_double : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, double ); double &get( QUObject *o ) { return o->payload.d; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_double static_QUType_double; -// {544C5175-6993-4486-B04D-CEC4D21BF4B9 } -extern Q_EXPORT const QUuid TID_QUType_float; -struct Q_EXPORT QUType_float : public QUType -{ - const QUuid *uuid() const; - const char *desc() const; - - void set( QUObject *, float ); - float &get( QUObject *o ) { return o->payload.f; } - bool canConvertFrom( QUObject *, QUType * ); - bool canConvertTo( QUObject *, QUType * ); - bool convertFrom( QUObject *, QUType * ); - bool convertTo( QUObject *, QUType * ); - void clear( QUObject * ) {} - int serializeTo( QUObject *, QUBuffer * ); - int serializeFrom( QUObject *, QUBuffer * ); -}; -extern Q_EXPORT QUType_float static_QUType_float; // {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} extern Q_EXPORT const QUuid TID_QUType_charstar; struct Q_EXPORT QUType_charstar : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, const char*, bool take = FALSE ); char* get( QUObject *o ){ return o->payload.charstar.ptr; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ); int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_charstar static_QUType_charstar; // {44C2A547-01E7-4e56-8559-35AF9D2F42B7} extern const QUuid TID_QUType_QString; struct Q_EXPORT QUType_QString : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, const QString & ); QString &get( QUObject * o ) { return *(QString*)o->payload.ptr; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ); int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_QString static_QUType_QString; -#endif // QUCOM_H +#endif // QUCOM_P_H diff --git a/qmake/include/private/qucomextra_p.h b/qmake/include/private/qucomextra_p.h index 3de6104..fe39692 100644 --- a/qmake/include/private/qucomextra_p.h +++ b/qmake/include/private/qucomextra_p.h @@ -1,93 +1,105 @@ /**************************************************************************** ** $Id$ ** ** Definition of extra QUcom classes ** ** Created : 990101 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the kernel module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QUCOMEXTRA_H -#define QUCOMEXTRA_H +#ifndef QUCOMEXTRA_P_H +#define QUCOMEXTRA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include <private/qucom_p.h> #endif // QT_H class QVariant; #ifndef QT_NO_VARIANT // 6dc75d58-a1d9-4417-b591-d45c63a3a4ea extern const QUuid TID_QUType_QVariant; struct Q_EXPORT QUType_QVariant : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, const QVariant & ); QVariant &get( QUObject * o ); bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ); int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_QVariant static_QUType_QVariant; #endif //QT_NO_VARIANT // {0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 } extern Q_EXPORT const QUuid TID_QUType_varptr; struct Q_EXPORT QUType_varptr : public QUType { const QUuid *uuid() const; const char *desc() const; void set( QUObject *, const void* ); void* &get( QUObject * o ) { return o->payload.ptr; } bool canConvertFrom( QUObject *, QUType * ); bool canConvertTo( QUObject *, QUType * ); bool convertFrom( QUObject *, QUType * ); bool convertTo( QUObject *, QUType * ); void clear( QUObject * ) {} int serializeTo( QUObject *, QUBuffer * ); int serializeFrom( QUObject *, QUBuffer * ); }; extern Q_EXPORT QUType_varptr static_QUType_varptr; -#endif // QUCOMEXTRA_H +#endif // QUCOMEXTRA_P_H diff --git a/qmake/include/private/qwidgetinterface_p.h b/qmake/include/private/qwidgetinterface_p.h index 5b5776b..78e9aad 100644 --- a/qmake/include/private/qwidgetinterface_p.h +++ b/qmake/include/private/qwidgetinterface_p.h @@ -1,111 +1,140 @@ - /********************************************************************** -** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +/**************************************************************************** +** $Id$ ** -** This file is part of Qt Designer. +** ... +** +** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QWIDGETINTERFACE_H -#define QWIDGETINTERFACE_H - - -#ifndef QT_H -#include <private/qcom_p.h> -#include <qiconset.h> -#endif // QT_H - -#ifndef QT_NO_WIDGETPLUGIN +#ifndef QWIDGETINTERFACE_P_H +#define QWIDGETINTERFACE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of a number of Qt sources files. This header file may change from // version to version without notice, or even be removed. // // We mean it. // // +#ifndef QT_H +#include <private/qcom_p.h> +#include <qiconset.h> +#endif // QT_H + +#ifndef QT_NO_WIDGETPLUGIN + class QWidget; // {55184143-f18f-42c0-a8eb-71c01516019a} #ifndef IID_QWidgetFactory #define IID_QWidgetFactory QUuid( 0x55184143, 0xf18f, 0x42c0, 0xa8, 0xeb, 0x71, 0xc0, 0x15, 0x16, 0x1, 0x9a ) #endif /*! To add custom widgets to the Qt Designer, implement that interface in your custom widget plugin. You also have to implement the function featureList() (\sa QFeatureListInterface) and return there all widgets (names of it) which this interface provides. */ struct QWidgetFactoryInterface : public QFeatureListInterface { public: /*! In the implementation create and return the widget \a widget here, use \a parent and \a name when creating the widget */ virtual QWidget* create( const QString &widget, QWidget* parent = 0, const char* name = 0 ) = 0; /*! In the implementation return the name of the group of the widget \a widget */ virtual QString group( const QString &widget ) const = 0; /*! In the implementation return the iconset, which should be used in the Qt Designer menubar and toolbar to represent the widget \a widget */ virtual QIconSet iconSet( const QString &widget ) const = 0; /*! In the implementation return the include file which is needed for the widget \a widget in the generated code which uic generates. */ virtual QString includeFile( const QString &widget ) const = 0; /*! In the implementation return the text which should be displayed as tooltip for the widget \a widget */ virtual QString toolTip( const QString &widget ) const = 0; /*! In the implementation return the text which should be used for what's this help for the widget \a widget. */ virtual QString whatsThis( const QString &widget ) const = 0; /*! In the implementation return TRUE here, of the \a widget should be able to contain other widget in the Qt Designer, else FALSE. */ virtual bool isContainer( const QString &widget ) const = 0; }; -#if CONTAINER_CUSTOM_WIDGETS +#ifdef QT_CONTAINER_CUSTOM_WIDGETS // {15976628-e3c3-47f4-b525-d124a3caf30e} #ifndef IID_QWidgetContainer #define IID_QWidgetContainer QUuid( 0x15976628, 0xe3c3, 0x47f4, 0xb5, 0x25, 0xd1, 0x24, 0xa3, 0xca, 0xf3, 0x0e ) #endif struct QWidgetContainerInterfacePrivate : public QUnknownInterface { public: - virtual QWidget *containerOfWidget( QWidget *widget ) const = 0; - virtual QWidgetList containersOf( QWidget *widget ) const = 0; - virtual bool isPassiveInteractor( QWidget *widget ) const = 0; + virtual QWidget *containerOfWidget( const QString &f, QWidget *container ) const = 0; + virtual bool isPassiveInteractor( const QString &f, QWidget *container ) const = 0; + + virtual bool supportsPages( const QString &f ) const = 0; + + virtual QWidget *addPage( const QString &f, QWidget *container, + const QString &name, int index ) const = 0; + virtual void insertPage( const QString &f, QWidget *container, + const QString &name, int index, QWidget *page ) const = 0; + virtual void removePage( const QString &f, QWidget *container, int index ) const = 0; + virtual void movePage( const QString &f, QWidget *container, int fromIndex, int toIndex ) const = 0; + virtual int count( const QString &key, QWidget *container ) const = 0; + virtual int currentIndex( const QString &key, QWidget *container ) const = 0; + virtual QString pageLabel( const QString &key, QWidget *container, int index ) const = 0; + virtual QWidget *page( const QString &key, QWidget *container, int index ) const = 0; + virtual void renamePage( const QString &key, QWidget *container, + int index, const QString &newName ) const = 0; + virtual QWidgetList pages( const QString &f, QWidget *container ) const = 0; }; #endif #endif // QT_NO_WIDGETPLUGIN -#endif // QWIDGETINTERFACE_H +#endif // QWIDGETINTERFACE_P_H diff --git a/qmake/include/private/qwidgetresizehandler_p.h b/qmake/include/private/qwidgetresizehandler_p.h index ca229db..9297832 100644 --- a/qmake/include/private/qwidgetresizehandler_p.h +++ b/qmake/include/private/qwidgetresizehandler_p.h @@ -1,113 +1,125 @@ /**************************************************************************** ** $Id$ ** ** Definition of the QWidgetResizeHandler class ** ** Created : 001010 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the workspace module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef QWIDGETRESIZEHANDLER_H -#define QWIDGETRESIZEHANDLER_H +#ifndef QWIDGETRESIZEHANDLER_P_H +#define QWIDGETRESIZEHANDLER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// #ifndef QT_H #include "qobject.h" #endif // QT_H #ifndef QT_NO_RESIZEHANDLER class QMouseEvent; class QKeyEvent; class Q_EXPORT QWidgetResizeHandler : public QObject { Q_OBJECT public: QWidgetResizeHandler( QWidget *parent, QWidget *cw = 0, const char *name = 0 ); void setActive( bool b ) { active = b; if ( !active ) setMouseCursor( Nowhere ); } bool isActive() const { return active; } void setMovingEnabled( bool b ) { moving = b; } bool isMovingEnabled() const { return moving; } bool isButtonDown() const { return buttonDown; } void setExtraHeight( int h ) { extrahei = h; } void setSizeProtection( bool b ) { sizeprotect = b; } void doResize(); void doMove(); signals: void activate(); protected: bool eventFilter( QObject *o, QEvent *e ); void mouseMoveEvent( QMouseEvent *e ); void keyPressEvent( QKeyEvent *e ); private: enum MousePosition { Nowhere, TopLeft, BottomRight, BottomLeft, TopRight, Top, Bottom, Left, Right, Center }; QWidget *widget; QWidget *childWidget; QPoint moveOffset; QPoint invertedMoveOffset; MousePosition mode; int extrahei; int range; uint buttonDown :1; uint moveResizeMode :1; uint active :1; uint sizeprotect :1; uint moving :1; void setMouseCursor( MousePosition m ); bool isMove() const { return moveResizeMode && mode == Center; } bool isResize() const { return moveResizeMode && !isMove(); } private: // Disabled copy constructor and operator= #if defined(Q_DISABLE_COPY) QWidgetResizeHandler( const QWidgetResizeHandler & ); QWidgetResizeHandler& operator=( const QWidgetResizeHandler & ); #endif }; #endif //QT_NO_RESIZEHANDLER #endif diff --git a/qmake/include/qasciidict.h b/qmake/include/qasciidict.h index 8f344cd..ecd9c9f 100644 --- a/qmake/include/qasciidict.h +++ b/qmake/include/qasciidict.h @@ -1,118 +1,122 @@ /**************************************************************************** ** $Id$ ** ** Definition of QAsciiDict template class ** ** Created : 920821 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QASCIIDICT_H #define QASCIIDICT_H #ifndef QT_H #include "qgdict.h" #endif // QT_H template<class type> class QAsciiDict #ifdef Q_QDOC : public QPtrCollection #else : public QGDict #endif { public: QAsciiDict(int size=17, bool caseSensitive=TRUE, bool copyKeys=TRUE ) : QGDict(size,AsciiKey,caseSensitive,copyKeys) {} QAsciiDict( const QAsciiDict<type> &d ) : QGDict(d) {} ~QAsciiDict() { clear(); } QAsciiDict<type> &operator=(const QAsciiDict<type> &d) { return (QAsciiDict<type>&)QGDict::operator=(d); } uint count() const { return QGDict::count(); } uint size() const { return QGDict::size(); } bool isEmpty() const { return QGDict::count() == 0; } void insert( const char *k, const type *d ) { QGDict::look_ascii(k,(Item)d,1); } void replace( const char *k, const type *d ) { QGDict::look_ascii(k,(Item)d,2); } bool remove( const char *k ) { return QGDict::remove_ascii(k); } type *take( const char *k ) { return (type *)QGDict::take_ascii(k); } type *find( const char *k ) const { return (type *)((QGDict*)this)->QGDict::look_ascii(k,0,0); } type *operator[]( const char *k ) const { return (type *)((QGDict*)this)->QGDict::look_ascii(k,0,0); } void clear() { QGDict::clear(); } void resize( uint n ) { QGDict::resize(n); } void statistics() const { QGDict::statistics(); } #ifdef Q_QDOC protected: virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; #endif private: void deleteItem( Item d ); }; #if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) template<> inline void QAsciiDict<void>::deleteItem( QPtrCollection::Item ) { } #endif template<class type> inline void QAsciiDict<type>::deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete (type *)d; } template<class type> class QAsciiDictIterator : public QGDictIterator { public: QAsciiDictIterator(const QAsciiDict<type> &d) : QGDictIterator((QGDict &)d) {} ~QAsciiDictIterator() {} uint count() const { return dict->count(); } bool isEmpty() const { return dict->count() == 0; } type *toFirst() { return (type *)QGDictIterator::toFirst(); } operator type *() const { return (type *)QGDictIterator::get(); } type *current() const { return (type *)QGDictIterator::get(); } const char *currentKey() const { return QGDictIterator::getKeyAscii(); } type *operator()() { return (type *)QGDictIterator::operator()(); } type *operator++() { return (type *)QGDictIterator::operator++(); } type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j);} }; +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QASCIIDICT +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QASCIIDICT_H diff --git a/qmake/include/qcstring.h b/qmake/include/qcstring.h index 004bb3b..6b7352a 100644 --- a/qmake/include/qcstring.h +++ b/qmake/include/qcstring.h @@ -1,391 +1,398 @@ /**************************************************************************** ** $Id$ ** ** Definition of the extended char array operations, ** and QByteArray and QCString classes ** ** Created : 920609 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QCSTRING_H #define QCSTRING_H #ifndef QT_H #include "qmemarray.h" #endif // QT_H #include <string.h> /***************************************************************************** Safe and portable C string functions; extensions to standard string.h *****************************************************************************/ Q_EXPORT void *qmemmove( void *dst, const void *src, uint len ); Q_EXPORT char *qstrdup( const char * ); Q_EXPORT inline uint qstrlen( const char *str ) { return str ? (uint)strlen(str) : 0; } Q_EXPORT inline char *qstrcpy( char *dst, const char *src ) { return src ? strcpy(dst, src) : 0; } Q_EXPORT char *qstrncpy( char *dst, const char *src, uint len ); Q_EXPORT inline int qstrcmp( const char *str1, const char *str2 ) { return ( str1 && str2 ) ? strcmp( str1, str2 ) : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); } Q_EXPORT inline int qstrncmp( const char *str1, const char *str2, uint len ) { return ( str1 && str2 ) ? strncmp( str1, str2, len ) : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); } Q_EXPORT int qstricmp( const char *, const char * ); Q_EXPORT int qstrnicmp( const char *, const char *, uint len ); #ifndef QT_CLEAN_NAMESPACE Q_EXPORT inline uint cstrlen( const char *str ) { return (uint)strlen(str); } Q_EXPORT inline char *cstrcpy( char *dst, const char *src ) { return strcpy(dst,src); } Q_EXPORT inline int cstrcmp( const char *str1, const char *str2 ) { return strcmp(str1,str2); } Q_EXPORT inline int cstrncmp( const char *str1, const char *str2, uint len ) { return strncmp(str1,str2,len); } #endif // qChecksum: Internet checksum Q_EXPORT Q_UINT16 qChecksum( const char *s, uint len ); /***************************************************************************** QByteArray class *****************************************************************************/ +#ifndef QT_QWINEXPORT #if defined(Q_TEMPLATEDLL) Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<char>; #endif +#endif /* QT_QWINEXPORT */ #if defined(Q_QDOC) /* We want qdoc to document QByteArray as a real class that inherits QMemArray<char> and that is inherited by QBitArray. */ class QByteArray : public QMemArray<char> { public: QByteArray(); QByteArray( int size ); }; #else typedef QMemArray<char> QByteArray; #endif #ifndef QT_NO_COMPRESS Q_EXPORT QByteArray qCompress( const uchar* data, int nbytes ); Q_EXPORT QByteArray qUncompress( const uchar* data, int nbytes ); Q_EXPORT inline QByteArray qCompress( const QByteArray& data) { return qCompress( (const uchar*)data.data(), data.size() ); } Q_EXPORT inline QByteArray qUncompress( const QByteArray& data ) { return qUncompress( (const uchar*)data.data(), data.size() ); } #endif /***************************************************************************** QByteArray stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM Q_EXPORT QDataStream &operator<<( QDataStream &, const QByteArray & ); Q_EXPORT QDataStream &operator>>( QDataStream &, QByteArray & ); #endif /***************************************************************************** QCString class *****************************************************************************/ class QRegExp; class Q_EXPORT QCString : public QByteArray // C string class { public: QCString() {} // make null string QCString( int size ); // allocate size incl. \0 QCString( const QCString &s ) : QByteArray( s ) {} QCString( const char *str ); // deep copy QCString( const char *str, uint maxlen ); // deep copy, max length ~QCString(); QCString &operator=( const QCString &s );// shallow copy QCString &operator=( const char *str ); // deep copy bool isNull() const; bool isEmpty() const; uint length() const; bool resize( uint newlen ); bool truncate( uint pos ); bool fill( char c, int len = -1 ); QCString copy() const; QCString &sprintf( const char *format, ... ); int find( char c, int index=0, bool cs=TRUE ) const; int find( const char *str, int index=0, bool cs=TRUE ) const; #ifndef QT_NO_REGEXP int find( const QRegExp &, int index=0 ) const; #endif int findRev( char c, int index=-1, bool cs=TRUE) const; int findRev( const char *str, int index=-1, bool cs=TRUE) const; #ifndef QT_NO_REGEXP_CAPTURE int findRev( const QRegExp &, int index=-1 ) const; #endif int contains( char c, bool cs=TRUE ) const; int contains( const char *str, bool cs=TRUE ) const; #ifndef QT_NO_REGEXP int contains( const QRegExp & ) const; #endif QCString left( uint len ) const; QCString right( uint len ) const; QCString mid( uint index, uint len=0xffffffff) const; QCString leftJustify( uint width, char fill=' ', bool trunc=FALSE)const; QCString rightJustify( uint width, char fill=' ',bool trunc=FALSE)const; QCString lower() const; QCString upper() const; QCString stripWhiteSpace() const; QCString simplifyWhiteSpace() const; QCString &insert( uint index, const char * ); QCString &insert( uint index, char ); QCString &append( const char * ); QCString &prepend( const char * ); QCString &remove( uint index, uint len ); QCString &replace( uint index, uint len, const char * ); #ifndef QT_NO_REGEXP QCString &replace( const QRegExp &, const char * ); #endif QCString &replace( char c, const char *after ); QCString &replace( const char *, const char * ); QCString &replace( char, char ); short toShort( bool *ok=0 ) const; ushort toUShort( bool *ok=0 ) const; int toInt( bool *ok=0 ) const; uint toUInt( bool *ok=0 ) const; long toLong( bool *ok=0 ) const; ulong toULong( bool *ok=0 ) const; float toFloat( bool *ok=0 ) const; double toDouble( bool *ok=0 ) const; QCString &setStr( const char *s ); QCString &setNum( short ); QCString &setNum( ushort ); QCString &setNum( int ); QCString &setNum( uint ); QCString &setNum( long ); QCString &setNum( ulong ); QCString &setNum( float, char f='g', int prec=6 ); QCString &setNum( double, char f='g', int prec=6 ); bool setExpand( uint index, char c ); operator const char *() const; QCString &operator+=( const char *str ); QCString &operator+=( char c ); +private: + int find( const char *str, int index, bool cs, uint l ) const; }; /***************************************************************************** QCString stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM Q_EXPORT QDataStream &operator<<( QDataStream &, const QCString & ); Q_EXPORT QDataStream &operator>>( QDataStream &, QCString & ); #endif /***************************************************************************** QCString inline functions *****************************************************************************/ inline QCString &QCString::operator=( const QCString &s ) { return (QCString&)assign( s ); } inline QCString &QCString::operator=( const char *str ) { return (QCString&)duplicate( str, qstrlen(str)+1 ); } inline bool QCString::isNull() const { return data() == 0; } inline bool QCString::isEmpty() const { return data() == 0 || *data() == '\0'; } inline uint QCString::length() const { return qstrlen( data() ); } inline bool QCString::truncate( uint pos ) { return resize(pos+1); } inline QCString QCString::copy() const { return QCString( data() ); } inline QCString &QCString::prepend( const char *s ) { return insert(0,s); } inline QCString &QCString::append( const char *s ) { return operator+=(s); } inline QCString &QCString::setNum( short n ) { return setNum((long)n); } inline QCString &QCString::setNum( ushort n ) { return setNum((ulong)n); } inline QCString &QCString::setNum( int n ) { return setNum((long)n); } inline QCString &QCString::setNum( uint n ) { return setNum((ulong)n); } inline QCString &QCString::setNum( float n, char f, int prec ) { return setNum((double)n,f,prec); } inline QCString::operator const char *() const { return (const char *)data(); } /***************************************************************************** QCString non-member operators *****************************************************************************/ Q_EXPORT inline bool operator==( const QCString &s1, const QCString &s2 ) { return qstrcmp( s1.data(), s2.data() ) == 0; } Q_EXPORT inline bool operator==( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) == 0; } Q_EXPORT inline bool operator==( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) == 0; } Q_EXPORT inline bool operator!=( const QCString &s1, const QCString &s2 ) { return qstrcmp( s1.data(), s2.data() ) != 0; } Q_EXPORT inline bool operator!=( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) != 0; } Q_EXPORT inline bool operator!=( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) != 0; } Q_EXPORT inline bool operator<( const QCString &s1, const QCString& s2 ) { return qstrcmp( s1.data(), s2.data() ) < 0; } Q_EXPORT inline bool operator<( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) < 0; } Q_EXPORT inline bool operator<( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) < 0; } Q_EXPORT inline bool operator<=( const QCString &s1, const QCString &s2 ) { return qstrcmp( s1.data(), s2.data() ) <= 0; } Q_EXPORT inline bool operator<=( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) <= 0; } Q_EXPORT inline bool operator<=( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) <= 0; } Q_EXPORT inline bool operator>( const QCString &s1, const QCString &s2 ) { return qstrcmp( s1.data(), s2.data() ) > 0; } Q_EXPORT inline bool operator>( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) > 0; } Q_EXPORT inline bool operator>( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) > 0; } Q_EXPORT inline bool operator>=( const QCString &s1, const QCString& s2 ) { return qstrcmp( s1.data(), s2.data() ) >= 0; } Q_EXPORT inline bool operator>=( const QCString &s1, const char *s2 ) { return qstrcmp( s1.data(), s2 ) >= 0; } Q_EXPORT inline bool operator>=( const char *s1, const QCString &s2 ) { return qstrcmp( s1, s2.data() ) >= 0; } Q_EXPORT inline const QCString operator+( const QCString &s1, const QCString &s2 ) { QCString tmp( s1.data() ); tmp += s2; return tmp; } Q_EXPORT inline const QCString operator+( const QCString &s1, const char *s2 ) { QCString tmp( s1.data() ); tmp += s2; return tmp; } Q_EXPORT inline const QCString operator+( const char *s1, const QCString &s2 ) { QCString tmp( s1 ); tmp += s2; return tmp; } Q_EXPORT inline const QCString operator+( const QCString &s1, char c2 ) { QCString tmp( s1.data() ); tmp += c2; return tmp; } Q_EXPORT inline const QCString operator+( char c1, const QCString &s2 ) { QCString tmp; tmp += c1; tmp += s2; return tmp; } +#ifdef QT_QWINEXPORT +#include <qwinexport.h> +#endif /* QT_QWINEXPORT */ #endif // QCSTRING_H diff --git a/qmake/include/qdict.h b/qmake/include/qdict.h index 04ae7bf..d8943ad 100644 --- a/qmake/include/qdict.h +++ b/qmake/include/qdict.h @@ -1,118 +1,122 @@ /**************************************************************************** ** $Id$ ** ** Definition of QDict template class ** ** Created : 920821 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QDICT_H #define QDICT_H #ifndef QT_H #include "qgdict.h" #endif // QT_H template<class type> class QDict #ifdef Q_QDOC : public QPtrCollection #else : public QGDict #endif { public: QDict( int size = 17, bool caseSensitive = TRUE ) : QGDict( size, StringKey, caseSensitive, FALSE ) { } QDict( const QDict<type> &d ) : QGDict( d ) { } ~QDict() { clear(); } QDict<type> &operator=(const QDict<type> &d) { return (QDict<type>&)QGDict::operator=(d); } uint count() const { return QGDict::count(); } uint size() const { return QGDict::size(); } bool isEmpty() const { return QGDict::count() == 0; } void insert( const QString &k, const type *d ) { QGDict::look_string(k,(Item)d,1); } void replace( const QString &k, const type *d ) { QGDict::look_string(k,(Item)d,2); } bool remove( const QString &k ) { return QGDict::remove_string(k); } type *take( const QString &k ) { return (type *)QGDict::take_string(k); } type *find( const QString &k ) const { return (type *)((QGDict*)this)->QGDict::look_string(k,0,0); } type *operator[]( const QString &k ) const { return (type *)((QGDict*)this)->QGDict::look_string(k,0,0); } void clear() { QGDict::clear(); } void resize( uint n ) { QGDict::resize(n); } void statistics() const { QGDict::statistics(); } #ifdef Q_QDOC protected: virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; #endif private: void deleteItem( Item d ); }; #if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) template<> inline void QDict<void>::deleteItem( Item ) { } #endif template<class type> inline void QDict<type>::deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete (type *)d; } template<class type> class QDictIterator : public QGDictIterator { public: QDictIterator(const QDict<type> &d) : QGDictIterator((QGDict &)d) { } ~QDictIterator() {} uint count() const { return dict->count(); } bool isEmpty() const { return dict->count() == 0; } type *toFirst() { return (type *)QGDictIterator::toFirst(); } operator type *() const { return (type *)QGDictIterator::get(); } type *operator*() { return (type *)QGDictIterator::get(); } type *current() const { return (type *)QGDictIterator::get(); } QString currentKey() const{ return QGDictIterator::getKeyString(); } type *operator()() { return (type *)QGDictIterator::operator()(); } type *operator++() { return (type *)QGDictIterator::operator++(); } type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j); } }; +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QDICT +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QDICT_H diff --git a/qmake/include/qdir.h b/qmake/include/qdir.h index 6e9f1ab..4b08b79 100644 --- a/qmake/include/qdir.h +++ b/qmake/include/qdir.h @@ -1,241 +1,242 @@ /**************************************************************************** ** $Id$ ** ** Definition of QDir class ** ** Created : 950427 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QDIR_H #define QDIR_H #ifndef QT_H #include "qglobal.h" #include "qstrlist.h" #include "qfileinfo.h" #endif // QT_H #ifndef QT_NO_DIR typedef QPtrList<QFileInfo> QFileInfoList; typedef QPtrListIterator<QFileInfo> QFileInfoListIterator; class QStringList; class Q_EXPORT QDir { public: enum FilterSpec { Dirs = 0x001, Files = 0x002, Drives = 0x004, NoSymLinks = 0x008, All = 0x007, TypeMask = 0x00F, Readable = 0x010, Writable = 0x020, Executable = 0x040, RWEMask = 0x070, Modified = 0x080, Hidden = 0x100, System = 0x200, AccessMask = 0x3F0, DefaultFilter = -1 }; enum SortSpec { Name = 0x00, Time = 0x01, Size = 0x02, Unsorted = 0x03, SortByMask = 0x03, DirsFirst = 0x04, Reversed = 0x08, IgnoreCase = 0x10, DefaultSort = -1 }; QDir(); QDir( const QString &path, const QString &nameFilter = QString::null, int sortSpec = Name | IgnoreCase, int filterSpec = All ); QDir( const QDir & ); virtual ~QDir(); QDir &operator=( const QDir & ); QDir &operator=( const QString &path ); virtual void setPath( const QString &path ); virtual QString path() const; virtual QString absPath() const; virtual QString canonicalPath() const; virtual QString dirName() const; virtual QString filePath( const QString &fileName, bool acceptAbsPath = TRUE ) const; virtual QString absFilePath( const QString &fileName, bool acceptAbsPath = TRUE ) const; static QString convertSeparators( const QString &pathName ); virtual bool cd( const QString &dirName, bool acceptAbsPath = TRUE ); virtual bool cdUp(); QString nameFilter() const; virtual void setNameFilter( const QString &nameFilter ); FilterSpec filter() const; virtual void setFilter( int filterSpec ); SortSpec sorting() const; virtual void setSorting( int sortSpec ); bool matchAllDirs() const; virtual void setMatchAllDirs( bool ); uint count() const; QString operator[]( int ) const; virtual QStrList encodedEntryList( int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; virtual QStrList encodedEntryList( const QString &nameFilter, int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; virtual QStringList entryList( int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; virtual QStringList entryList( const QString &nameFilter, int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; virtual const QFileInfoList *entryInfoList( int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; virtual const QFileInfoList *entryInfoList( const QString &nameFilter, int filterSpec = DefaultFilter, int sortSpec = DefaultSort ) const; static const QFileInfoList *drives(); virtual bool mkdir( const QString &dirName, bool acceptAbsPath = TRUE ) const; virtual bool rmdir( const QString &dirName, bool acceptAbsPath = TRUE ) const; virtual bool isReadable() const; virtual bool exists() const; virtual bool isRoot() const; virtual bool isRelative() const; virtual void convertToAbs(); virtual bool operator==( const QDir & ) const; virtual bool operator!=( const QDir & ) const; virtual bool remove( const QString &fileName, bool acceptAbsPath = TRUE ); virtual bool rename( const QString &name, const QString &newName, bool acceptAbsPaths = TRUE ); virtual bool exists( const QString &name, bool acceptAbsPath = TRUE ); static char separator(); static bool setCurrent( const QString &path ); static QDir current(); static QDir home(); static QDir root(); static QString currentDirPath(); static QString homeDirPath(); static QString rootDirPath(); static bool match( const QStringList &filters, const QString &fileName ); static bool match( const QString &filter, const QString &fileName ); static QString cleanDirPath( const QString &dirPath ); static bool isRelativePath( const QString &path ); + void refresh() const; private: #ifdef Q_OS_MAC typedef struct FSSpec FSSpec; static FSSpec *make_spec(const QString &); #endif void init(); virtual bool readDirEntries( const QString &nameFilter, int FilterSpec, int SortSpec ); static void slashify ( QString &); QString dPath; QStringList *fList; QFileInfoList *fiList; QString nameFilt; FilterSpec filtS; SortSpec sortS; uint dirty : 1; uint allDirs : 1; }; inline QString QDir::path() const { return dPath; } inline QString QDir::nameFilter() const { return nameFilt; } inline QDir::FilterSpec QDir::filter() const { return filtS; } inline QDir::SortSpec QDir::sorting() const { return sortS; } inline bool QDir::matchAllDirs() const { return allDirs; } inline bool QDir::operator!=( const QDir &d ) const { return !(*this == d); } struct QDirSortItem { QString filename_cache; QFileInfo* item; }; #endif // QT_NO_DIR #endif // QDIR_H diff --git a/qmake/include/qfeatures.h b/qmake/include/qfeatures.h index 57502f9..270a6de 100644 --- a/qmake/include/qfeatures.h +++ b/qmake/include/qfeatures.h @@ -1,461 +1,461 @@ // All feature and their dependencies // // This list is generated from $QTDIR/src/tools/qfeatures.txt // // Asynchronous I/O //#define QT_NO_ASYNC_IO // Bezier curves //#define QT_NO_BEZIER // Buttons //#define QT_NO_BUTTON // Named colors //#define QT_NO_COLORNAMES // Cursors //#define QT_NO_CURSOR // QDataStream //#define QT_NO_DATASTREAM // QDate/QTime/QDateTime toString() and fromString() //#define QT_NO_DATESTRING // Dialogs //#define QT_NO_DIALOG // QDirectPainter //#define QT_NO_DIRECTPAINTER // Special widget effects (fading, scrolling) //#define QT_NO_EFFECTS // Freetype font engine //#define QT_NO_FREETYPE // Dither QImage to 1-bit image //#define QT_NO_IMAGE_DITHER_TO_1 // QImage::createHeuristicMask() //#define QT_NO_IMAGE_HEURISTIC_MASK // QImage mirroring //#define QT_NO_IMAGE_MIRROR // Smooth QImage scaling //#define QT_NO_IMAGE_SMOOTHSCALE // TrueColor QImage //#define QT_NO_IMAGE_TRUECOLOR // Automatic widget layout //#define QT_NO_LAYOUT // Networking //#define QT_NO_NETWORK // Palettes //#define QT_NO_PALETTE // Alpha-blended cursor //#define QT_NO_QWS_ALPHA_CURSOR // 1-bit monochrome //#define QT_NO_QWS_DEPTH_1 // 15 or 16-bit color //#define QT_NO_QWS_DEPTH_16 // 24-bit color //#define QT_NO_QWS_DEPTH_24 // 32-bit color //#define QT_NO_QWS_DEPTH_32 -// 4-bit greyscale +// 4-bit grayscale //#define QT_NO_QWS_DEPTH_4 // 8-bit color //#define QT_NO_QWS_DEPTH_8 // 8-bit grayscale //#define QT_NO_QWS_DEPTH_8GRAYSCALE // Favour code size over graphics speed //#define QT_NO_QWS_GFX_SPEED // Console keyboard //#define QT_NO_QWS_KEYBOARD // Linux framebuffer //#define QT_NO_QWS_LINUXFB // Mach64 acceleration //#define QT_NO_QWS_MACH64 // Window Manager //#define QT_NO_QWS_MANAGER // Matrox MGA acceleration //#define QT_NO_QWS_MATROX // Autodetecting mouse driver //#define QT_NO_QWS_MOUSE_AUTO // Non-autodetecting mouse driver //#define QT_NO_QWS_MOUSE_MANUAL // Qt/Embedded window system properties. //#define QT_NO_QWS_PROPERTIES // Repeater display //#define QT_NO_QWS_REPEATER // Saving of fonts //#define QT_NO_QWS_SAVEFONTS // Shadow frame buffer //#define QT_NO_QWS_SHADOWFB // Virtual frame buffer //#define QT_NO_QWS_VFB // 4-bit VGA //#define QT_NO_QWS_VGA_16 // Voodoo3 acceleration //#define QT_NO_QWS_VOODOO3 // Range-control widgets //#define QT_NO_RANGECONTROL // Regular expression capture //#define QT_NO_REGEXP // QSignalMapper //#define QT_NO_SIGNALMAPPER // Playing sounds //#define QT_NO_SOUND // Standard template library compatiblity //#define QT_NO_STL // QStringList //#define QT_NO_STRINGLIST // Character set conversions //#define QT_NO_TEXTCODEC // QTextStream //#define QT_NO_TEXTSTREAM // Unicode property tables //#define QT_NO_UNICODETABLES // Input validators //#define QT_NO_VALIDATOR // QVariant //#define QT_NO_VARIANT // Wheel-mouse events //#define QT_NO_WHEELEVENT // QWMatrix //#define QT_NO_WMATRIX // Non-Unicode text conversions #if !defined(QT_NO_CODECS) && (defined(QT_NO_TEXTCODEC)) #define QT_NO_CODECS #endif // QCop IPC #if !defined(QT_NO_COP) && (defined(QT_NO_DATASTREAM)) #define QT_NO_COP #endif // QFontDatabase #if !defined(QT_NO_FONTDATABASE) && (defined(QT_NO_STRINGLIST)) #define QT_NO_FONTDATABASE #endif // Image formats #if !defined(QT_NO_IMAGEIO) && (defined(QT_NO_REGEXP)) #define QT_NO_IMAGEIO #endif // 16-bit QImage #if !defined(QT_NO_IMAGE_16_BIT) && (defined(QT_NO_IMAGE_TRUECOLOR)) #define QT_NO_IMAGE_16_BIT #endif // Image file text strings #if !defined(QT_NO_IMAGE_TEXT) && (defined(QT_NO_STRINGLIST)) #define QT_NO_IMAGE_TEXT #endif // Shared library wrapper #if !defined(QT_NO_LIBRARY) && (defined(QT_NO_REGEXP)) #define QT_NO_LIBRARY #endif // Pixmap transformations #if !defined(QT_NO_PIXMAP_TRANSFORMATION) && (defined(QT_NO_WMATRIX)) #define QT_NO_PIXMAP_TRANSFORMATION #endif // Convert UUID to/from string #if !defined(QT_NO_QUUID_STRING) && (defined(QT_NO_STRINGLIST)) #define QT_NO_QUUID_STRING #endif // The "BeOS" style #if !defined(QT_NO_QWS_BEOS_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) #define QT_NO_QWS_BEOS_WM_STYLE #endif // Visible cursor #if !defined(QT_NO_QWS_CURSOR) && (defined(QT_NO_CURSOR)) #define QT_NO_QWS_CURSOR #endif // 32-bit color, BGR order #if !defined(QT_NO_QWS_DEPTH_32_BGR) && (defined(QT_NO_QWS_DEPTH_32)) #define QT_NO_QWS_DEPTH_32_BGR #endif // The "Hydro" style #if !defined(QT_NO_QWS_HYDRO_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) #define QT_NO_QWS_HYDRO_WM_STYLE #endif // The "KDE2" style #if !defined(QT_NO_QWS_KDE2_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) #define QT_NO_QWS_KDE2_WM_STYLE #endif // The "KDE" style #if !defined(QT_NO_QWS_KDE_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) #define QT_NO_QWS_KDE_WM_STYLE #endif // Multi-process architecture #if !defined(QT_NO_QWS_MULTIPROCESS) && (defined(QT_NO_NETWORK)) #define QT_NO_QWS_MULTIPROCESS #endif // Transformed frame buffer #if !defined(QT_NO_QWS_TRANSFORMED) && (defined(QT_NO_QWS_LINUXFB)) #define QT_NO_QWS_TRANSFORMED #endif // Remote frame buffer (VNC) #if !defined(QT_NO_QWS_VNC) && (defined(QT_NO_NETWORK)) #define QT_NO_QWS_VNC #endif // The "Windows" style #if !defined(QT_NO_QWS_WINDOWS_WM_STYLE) && (defined(QT_NO_QWS_MANAGER)) #define QT_NO_QWS_WINDOWS_WM_STYLE #endif // Regular expression anchors #if !defined(QT_NO_REGEXP_ANCHOR_ALT) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_ANCHOR_ALT #endif // Regular expression back-reference #if !defined(QT_NO_REGEXP_BACKREF) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_BACKREF #endif // Regular expression character-class #if !defined(QT_NO_REGEXP_CCLASS) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_CCLASS #endif // Regular expression escape #if !defined(QT_NO_REGEXP_ESCAPE) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_ESCAPE #endif // Regular expression interval #if !defined(QT_NO_REGEXP_INTERVAL) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_INTERVAL #endif // Regular expression lookahead #if !defined(QT_NO_REGEXP_LOOKAHEAD) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_LOOKAHEAD #endif // Regular expression optimization #if !defined(QT_NO_REGEXP_OPTIM) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_OPTIM #endif // Regular expression wildcard #if !defined(QT_NO_REGEXP_WILDCARD) && (defined(QT_NO_REGEXP)) #define QT_NO_REGEXP_WILDCARD #endif // Semi-modal dialogs #if !defined(QT_NO_SEMIMODAL) && (defined(QT_NO_DIALOG)) #define QT_NO_SEMIMODAL #endif // Session management #if !defined(QT_NO_SESSIONMANAGER) && (defined(QT_NO_STRINGLIST)) #define QT_NO_SESSIONMANAGER #endif // QString::sprintf() #if !defined(QT_NO_SPRINTF) && (defined(QT_NO_REGEXP)) #define QT_NO_SPRINTF #endif // Scaling and rotation #if !defined(QT_NO_TRANSFORMATIONS) && (defined(QT_NO_WMATRIX)) #define QT_NO_TRANSFORMATIONS #endif // Translations via QObject::tr() #if !defined(QT_NO_TRANSLATION) && (defined(QT_NO_DATASTREAM)) #define QT_NO_TRANSLATION #endif // Window icon and caption #if !defined(QT_NO_WIDGET_TOPEXTRA) && (defined(QT_NO_IMAGE_HEURISTIC_MASK)) #define QT_NO_WIDGET_TOPEXTRA #endif // Keyboard accelerators and shortcuts #if !defined(QT_NO_ACCEL) && (defined(QT_NO_SPRINTF)) #define QT_NO_ACCEL #endif // Asynchronous image I/O #if !defined(QT_NO_ASYNC_IMAGE_IO) && (defined(QT_NO_IMAGEIO)) #define QT_NO_ASYNC_IMAGE_IO #endif // BDF font files #if !defined(QT_NO_BDF) && (defined(QT_NO_TEXTSTREAM) || defined(QT_NO_STRINGLIST)) #define QT_NO_BDF #endif // QDir #if !defined(QT_NO_DIR) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_REGEXP)) #define QT_NO_DIR #endif // JPEG image I/O #if !defined(QT_NO_IMAGEIO_JPEG) && (defined(QT_NO_IMAGEIO)) #define QT_NO_IMAGEIO_JPEG #endif // MNG image I/O #if !defined(QT_NO_IMAGEIO_MNG) && (defined(QT_NO_IMAGEIO)) #define QT_NO_IMAGEIO_MNG #endif // PNG image I/O #if !defined(QT_NO_IMAGEIO_PNG) && (defined(QT_NO_IMAGEIO)) #define QT_NO_IMAGEIO_PNG #endif // PPM image I/O #if !defined(QT_NO_IMAGEIO_PPM) && (defined(QT_NO_IMAGEIO)) #define QT_NO_IMAGEIO_PPM #endif // XBM image I/O #if !defined(QT_NO_IMAGEIO_XBM) && (defined(QT_NO_IMAGEIO)) #define QT_NO_IMAGEIO_XBM #endif // Image transformations #if !defined(QT_NO_IMAGE_TRANSFORMATION) && (defined(QT_NO_PIXMAP_TRANSFORMATION)) #define QT_NO_IMAGE_TRANSFORMATION #endif // External process invocation. #if !defined(QT_NO_PROCESS) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_REGEXP)) #define QT_NO_PROCESS #endif // Regular expression capture #if !defined(QT_NO_REGEXP_CAPTURE) && (defined(QT_NO_REGEXP) || defined(QT_NO_STRINGLIST)) #define QT_NO_REGEXP_CAPTURE #endif // Template classes in QVariant #if !defined(QT_NO_TEMPLATE_VARIANT) && (defined(QT_NO_VARIANT) || defined(QT_NO_STRINGLIST)) #define QT_NO_TEMPLATE_VARIANT #endif // Month and day names in dates #if !defined(QT_NO_TEXTDATE) && (defined(QT_NO_STRINGLIST) || defined(QT_NO_DATESTRING)) #define QT_NO_TEXTDATE #endif // Drawing utility functions #if !defined(QT_NO_DRAWUTIL) && (defined(QT_NO_SPRINTF) || defined(QT_NO_PALETTE)) #define QT_NO_DRAWUTIL #endif // BMP image I/O #if !defined(QT_NO_IMAGEIO_BMP) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_DATASTREAM)) #define QT_NO_IMAGEIO_BMP #endif // QPicture #if !defined(QT_NO_PICTURE) && (defined(QT_NO_DATASTREAM) || defined(QT_NO_IMAGEIO)) #define QT_NO_PICTURE #endif // Translations via QObject::trUtf8() #if !defined(QT_NO_TRANSLATION_UTF8) && (defined(QT_NO_TRANSLATION) || defined(QT_NO_TEXTCODEC)) #define QT_NO_TRANSLATION_UTF8 #endif // URL parser #if !defined(QT_NO_URL) && (defined(QT_NO_DIR)) #define QT_NO_URL #endif // Animated images #if !defined(QT_NO_MOVIE) && (defined(QT_NO_ASYNC_IO) || defined(QT_NO_ASYNC_IMAGE_IO)) #define QT_NO_MOVIE #endif // Persistent application settings #if !defined(QT_NO_SETTINGS) && (defined(QT_NO_DIR) || defined(QT_NO_TEXTSTREAM)) #define QT_NO_SETTINGS #endif // QStyle #if !defined(QT_NO_STYLE) && (defined(QT_NO_DRAWUTIL)) #define QT_NO_STYLE #endif // DNS #if !defined(QT_NO_DNS) && (defined(QT_NO_NETWORK) || defined(QT_NO_STRINGLIST) || defined(QT_NO_TEXTSTREAM) || defined(QT_NO_SPRINTF)) #define QT_NO_DNS #endif // Framed widgets #if !defined(QT_NO_FRAME) && (defined(QT_NO_STYLE)) #define QT_NO_FRAME #endif // QIconSet #if !defined(QT_NO_ICONSET) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_IMAGE_SMOOTHSCALE) || defined(QT_NO_PALETTE) || defined(QT_NO_IMAGE_HEURISTIC_MASK)) #define QT_NO_ICONSET #endif // XPM image I/O #if !defined(QT_NO_IMAGEIO_XPM) && (defined(QT_NO_IMAGEIO) || defined(QT_NO_SPRINTF) || defined(QT_NO_TEXTSTREAM)) diff --git a/qmake/include/qgarray.h b/qmake/include/qgarray.h index 12edea6..40720a6 100644 --- a/qmake/include/qgarray.h +++ b/qmake/include/qgarray.h @@ -1,121 +1,130 @@ /**************************************************************************** ** $Id$ ** ** Definition of QGArray class ** ** Created : 930906 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QGARRAY_H #define QGARRAY_H #ifndef QT_H #include "qshared.h" #endif // QT_H class Q_EXPORT QGArray // generic array { friend class QBuffer; public: //### DO NOT USE THIS. IT IS PUBLIC BUT DO NOT USE IT IN NEW CODE. struct array_data : public QShared { // shared array - array_data() { data=0; len=0; } + array_data():data(0),len(0) +#ifdef QT_QGARRAY_SPEED_OPTIM + ,maxl(0) +#endif + {} char *data; // actual array data uint len; +#ifdef QT_QGARRAY_SPEED_OPTIM + uint maxl; +#endif }; QGArray(); + enum Optimization { MemOptim, SpeedOptim }; protected: QGArray( int, int ); // dummy; does not alloc QGArray( int size ); // allocate 'size' bytes QGArray( const QGArray &a ); // shallow copy virtual ~QGArray(); QGArray &operator=( const QGArray &a ) { return assign( a ); } virtual void detach() { duplicate(*this); } // ### Qt 4.0: maybe provide two versions of data(), at(), etc. char *data() const { return shd->data; } uint nrefs() const { return shd->count; } uint size() const { return shd->len; } bool isEqual( const QGArray &a ) const; + bool resize( uint newsize, Optimization optim ); bool resize( uint newsize ); bool fill( const char *d, int len, uint sz ); QGArray &assign( const QGArray &a ); QGArray &assign( const char *d, uint len ); QGArray &duplicate( const QGArray &a ); QGArray &duplicate( const char *d, uint len ); void store( const char *d, uint len ); array_data *sharedBlock() const { return shd; } void setSharedBlock( array_data *p ) { shd=(array_data*)p; } QGArray &setRawData( const char *d, uint len ); void resetRawData( const char *d, uint len ); int find( const char *d, uint index, uint sz ) const; int contains( const char *d, uint sz ) const; void sort( uint sz ); int bsearch( const char *d, uint sz ) const; char *at( uint index ) const; bool setExpand( uint index, const char *d, uint sz ); protected: virtual array_data *newData(); virtual void deleteData( array_data *p ); private: static void msg_index( uint ); array_data *shd; }; inline char *QGArray::at( uint index ) const { #if defined(QT_CHECK_RANGE) if ( index >= size() ) { msg_index( index ); index = 0; } #endif return &shd->data[index]; } #endif // QGARRAY_H diff --git a/qmake/include/qglobal.h b/qmake/include/qglobal.h index 13cff64..d212bff 100644 --- a/qmake/include/qglobal.h +++ b/qmake/include/qglobal.h @@ -1,1006 +1,1065 @@ /**************************************************************************** ** $Id$ ** ** Global type declarations and definitions ** ** Created : 920529 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QGLOBAL_H #define QGLOBAL_H -#define QT_VERSION_STR "3.1.0-b2" +#define QT_VERSION_STR "3.1.2" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x030100 +#define QT_VERSION 0x030102 /* The operating system, must be one of: (Q_OS_x) MACX - Mac OS X MAC9 - Mac OS 9 MSDOS - MS-DOS and Windows OS2 - OS/2 OS2EMX - XFree86 on OS/2 (not PM) WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) CYGWIN - Cygwin SOLARIS - Sun Solaris HPUX - HP-UX ULTRIX - DEC Ultrix LINUX - Linux FREEBSD - FreeBSD NETBSD - NetBSD OPENBSD - OpenBSD BSDI - BSD/OS IRIX - SGI Irix OSF - HP Tru64 UNIX SCO - SCO OpenServer 5 UNIXWARE - UnixWare 7, Open UNIX 8 AIX - AIX HURD - GNU Hurd DGUX - DG/UX RELIANT - Reliant UNIX DYNIX - DYNIX/ptx QNX - QNX QNX6 - QNX RTP 6.1 LYNX - LynxOS BSD4 - Any BSD 4.4 system UNIX - Any UNIX BSD/SYSV system */ #if defined(__APPLE__) && defined(__GNUC__) # define Q_OS_MACX #elif defined(__MACOSX__) # define Q_OS_MACX #elif defined(macintosh) # define Q_OS_MAC9 #elif defined(__CYGWIN__) # define Q_OS_CYGWIN #elif defined(MSDOS) || defined(_MSDOS) # define Q_OS_MSDOS #elif defined(__OS2__) # if defined(__EMX__) # define Q_OS_OS2EMX # else # define Q_OS_OS2 # endif #elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) # define Q_OS_WIN32 # define Q_OS_WIN64 #elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) # define Q_OS_WIN32 #elif defined(__MWERKS__) && defined(__INTEL__) # define Q_OS_WIN32 #elif defined(__sun) || defined(sun) # define Q_OS_SOLARIS #elif defined(hpux) || defined(__hpux) # define Q_OS_HPUX #elif defined(__ultrix) || defined(ultrix) # define Q_OS_ULTRIX #elif defined(sinix) # define Q_OS_RELIANT #elif defined(__linux__) || defined(__linux) # define Q_OS_LINUX #elif defined(__FreeBSD__) # define Q_OS_FREEBSD # define Q_OS_BSD4 #elif defined(__NetBSD__) # define Q_OS_NETBSD # define Q_OS_BSD4 #elif defined(__OpenBSD__) # define Q_OS_OPENBSD # define Q_OS_BSD4 #elif defined(__bsdi__) # define Q_OS_BSDI # define Q_OS_BSD4 #elif defined(__sgi) # define Q_OS_IRIX #elif defined(__osf__) # define Q_OS_OSF #elif defined(_AIX) # define Q_OS_AIX #elif defined(__Lynx__) # define Q_OS_LYNX #elif defined(__GNU_HURD__) # define Q_OS_HURD #elif defined(__DGUX__) # define Q_OS_DGUX #elif defined(__QNXNTO__) # define Q_OS_QNX6 #elif defined(__QNX__) # define Q_OS_QNX #elif defined(_SEQUENT_) # define Q_OS_DYNIX -#elif defined(_SCO_DS) /* SCO OpenServer 5 */ +#elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */ # define Q_OS_SCO -#elif defined(__UNIXWARE__) /* UnixWare 7 + GCC, Open UNIX 8 + GCC */ +#elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */ # define Q_OS_UNIXWARE # define Q_OS_UNIXWARE7 -#elif defined(__USLC__) /* UnixWare 7 + UDK, Open UNIX 8 + OUDK */ +#elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */ # define Q_OS_UNIXWARE # define Q_OS_UNIXWARE7 #else # error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" #endif #if defined(Q_OS_MAC9) || defined(Q_OS_MACX) # define Q_OS_MAC #endif #if defined(Q_OS_MAC9) || defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) # undef Q_OS_UNIX #elif !defined(Q_OS_UNIX) # define Q_OS_UNIX #endif /* The compiler, must be one of: (Q_CC_x) SYM - Symantec C++ for both PC and Macintosh MPW - MPW C++ MWERKS - Metrowerks CodeWarrior MSVC - Microsoft Visual C/C++ BOR - Borland/Turbo C++ WAT - Watcom C++ GNU - GNU C++ COMEAU - Comeau C++ EDG - Edison Design Group C++ OC - CenterLine C++ SUN - Sun WorkShop, Forte Developer, or Sun ONE Studio C++ MIPS - MIPSpro C++ DEC - DEC C++ HP - HPUX C++ HPACC - HPUX ANSI C++ USLC - SCO OUDK, UDK, and UnixWare 2.X C++ CDS - Reliant C++ KAI - KAI C++ INTEL - Intel C++ HIGHC - MetaWare High C/C++ PGI - Portland Group C++ GHS - Green Hills Optimizing C++ Compilers Should be sorted most to least authoritative. */ /* Symantec C++ is now Digital Mars */ #if defined(__DMC__) || defined(__SC__) # define Q_CC_SYM /* "explicit" semantics implemented in 8.1e but keyword recognized since 7.5 */ # if defined(__SC__) && __SC__ < 0x750 # define Q_NO_EXPLICIT_KEYWORD # endif # define Q_NO_USING_KEYWORD # if !defined(_CPPUNWIND) # define Q_NO_EXCEPTIONS # endif #elif defined(applec) # define Q_CC_MPW # define Q_NO_BOOL_TYPE # define Q_NO_EXPLICIT_KEYWORD # define Q_NO_USING_KEYWORD #elif defined(__MWERKS__) # define Q_CC_MWERKS /* "explicit" recognized since 4.0d1 */ # define QMAC_PASCAL pascal # define Q_NO_USING_KEYWORD /* ### check "using" status */ #elif defined(_MSC_VER) # define Q_CC_MSVC /* proper support of bool for _MSC_VER >= 1100 */ # define Q_CANNOT_DELETE_CONSTANT # define Q_INLINE_TEMPLATES inline /* Visual C++.Net issues for _MSC_VER >= 1300 */ # if _MSC_VER >= 1300 # define Q_CC_MSVC_NET +# if _MSC_VER < 1310 # define Q_TYPENAME # endif +# endif # define Q_NO_USING_KEYWORD /* ### check "using" status */ #elif defined(__BORLANDC__) || defined(__TURBOC__) # define Q_CC_BOR # if __BORLANDC__ < 0x502 # define Q_NO_BOOL_TYPE # define Q_NO_EXPLICIT_KEYWORD # endif # define Q_NO_USING_KEYWORD /* ### check "using" status */ #elif defined(__WATCOMC__) # define Q_CC_WAT # if defined(Q_OS_QNX4) /* compiler flags */ # define Q_TYPENAME # define Q_NO_BOOL_TYPE # define Q_CANNOT_DELETE_CONSTANT # define mutable /* ??? */ # define Q_BROKEN_TEMPLATE_SPECIALIZATION /* no template classes in QVariant */ # define QT_NO_TEMPLATE_VARIANT /* Wcc does not fill in functions needed by valuelists, maps, and valuestacks implicitly */ # define Q_FULL_TEMPLATE_INSTANTIATION /* can we just compare the structures? */ # define Q_FULL_TEMPLATE_INSTANTIATION_MEMCMP /* these are not useful to our customers */ # define QT_QWS_NO_SHM # define QT_NO_QWS_MULTIPROCESS # define QT_NO_SQL # define QT_NO_QWS_CURSOR # endif #elif defined(__GNUC__) # define Q_CC_GNU # define Q_C_CALLBACKS # if __GNUC__ == 2 && __GNUC_MINOR__ <= 7 # define Q_FULL_TEMPLATE_INSTANTIATION # endif /* GCC 2.95 knows "using" but does not support it correctly */ # if __GNUC__ == 2 && __GNUC_MINOR__ <= 95 # define Q_NO_USING_KEYWORD # endif +/* GCC 3.1 and GCC 3.2 wrongly define _SB_CTYPE_MACROS on HP-UX */ +# if defined(Q_OS_HPUX) && __GNUC__ == 3 && __GNUC_MINOR__ >= 1 +# define Q_WRONG_SB_CTYPE_MACROS +# endif # if (defined(__arm__) || defined(__ARMEL__)) && !defined(QT_MOC_CPP) # define Q_PACKED __attribute__ ((packed)) # endif # if !defined(__EXCEPTIONS) # define Q_NO_EXCEPTIONS # endif /* IBM compiler versions are a bit messy. There are actually two products: the C product, and the C++ product. The C++ compiler is always packaged with the latest version of the C compiler. Version numbers do not always match. This little table (I'm not sure it's accurate) should be helpful: C++ product C product C Set 3.1 C Compiler 3.0 ... ... C++ Compiler 3.6.6 C Compiler 4.3 ... ... Visual Age C++ 4.0 ... ... ... Visual Age C++ 5.0 C Compiler 5.0 Now: __xlC__ is the version of the C compiler in hexadecimal notation is only an approximation of the C++ compiler version __IBMCPP__ is the version of the C++ compiler in decimal notation but it is not defined on older compilers like C Set 3.1 */ #elif defined(__xlC__) # define Q_CC_XLC # define Q_FULL_TEMPLATE_INSTANTIATION # if __xlC__ < 0x400 # define Q_NO_BOOL_TYPE # define Q_NO_EXPLICIT_KEYWORD # define Q_NO_USING_KEYWORD # define Q_TYPENAME # define Q_INLINE_TEMPLATES inline # define Q_BROKEN_TEMPLATE_SPECIALIZATION # define Q_CANNOT_DELETE_CONSTANT # endif /* Older versions of DEC C++ do not define __EDG__ or __EDG - observed on DEC C++ V5.5-004. New versions do define __EDG__ - observed on Compaq C++ V6.3-002. This compiler is different enough from other EDG compilers to handle it separately anyway. */ #elif defined(__DECCXX) # define Q_CC_DEC /* Compaq C++ V6 compilers are EDG-based but I'm not sure about older DEC C++ V5 compilers. */ # if defined(__EDG__) # define Q_CC_EDG # endif /* Compaq have disabled EDG's _BOOL macro and use _BOOL_EXISTS instead - observed on Compaq C++ V6.3-002. In any case versions prior to Compaq C++ V6.0-005 do not have bool. */ # if !defined(_BOOL_EXISTS) # define Q_NO_BOOL_TYPE # endif /* Spurious (?) error messages observed on Compaq C++ V6.5-014. */ # define Q_NO_USING_KEYWORD /* Apply to all versions prior to Compaq C++ V6.0-000 - observed on DEC C++ V5.5-004. */ # if __DECCXX_VER < 60060000 # define Q_TYPENAME # define Q_BROKEN_TEMPLATE_SPECIALIZATION # define Q_CANNOT_DELETE_CONSTANT # endif /* avoid undefined symbol problems with out-of-line template members */ # define Q_INLINE_TEMPLATES inline /* Compilers with EDG front end are similar. To detect them we test: __EDG documented by SGI, observed on MIPSpro 7.3.1.1 and KAI C++ 4.0b __EDG__ documented in EDG online docs, observed on Compaq C++ V6.3-002 */ #elif defined(__EDG) || defined(__EDG__) # define Q_CC_EDG /* From the EDG documentation (does not seem to apply to Compaq C++): _BOOL Defined in C++ mode when bool is a keyword. The name of this predefined macro is specified by a configuration flag. _BOOL is the default. __BOOL_DEFINED Defined in Microsoft C++ mode when bool is a keyword. */ # if !defined(_BOOL) && !defined(__BOOL_DEFINED) # define Q_NO_BOOL_TYPE # endif /* The Portland Group compiler is based on EDG and does define __EDG__ */ # if defined(__COMO__) # define Q_CC_COMEAU # define Q_C_CALLBACKS /* Using the `using' keyword avoids KAI C++ warnings */ # elif defined(__KCC) # define Q_CC_KAI # if !defined(_EXCEPTIONS) # define Q_NO_EXCEPTIONS # endif /* Using the `using' keyword avoids Intel C++ warnings */ # elif defined(__INTEL_COMPILER) # define Q_CC_INTEL # if !defined(__EXCEPTIONS) # define Q_NO_EXCEPTIONS # endif /* The Portland Group compiler is based on EDG and does define __EDG__ */ # elif defined(__PGI) # define Q_CC_PGI # if !defined(__EXCEPTIONS) # define Q_NO_EXCEPTIONS # endif /* Never tested! */ # elif defined(__ghs) # define Q_CC_GHS /* The UnixWare 7 UDK compiler is based on EDG and does define __EDG__ */ # elif defined(__USLC__) && defined(__SCO_VERSION__) # define Q_CC_USLC +/* The latest UDK 7.1.1b does not need this, but previous versions do */ +# if !defined(__SCO_VERSION__) || (__SCO_VERSION__ < 302200010) +# define Q_INLINE_TEMPLATES inline +# endif # define Q_NO_USING_KEYWORD /* ### check "using" status */ /* Never tested! */ # elif defined(CENTERLINE_CLPP) || defined(OBJECTCENTER) # define Q_CC_OC # define Q_NO_USING_KEYWORD -/* CDS++ is not documented to define __EDG__ or __EDG in the Reliant - documentation but we suppose it does, in any case it does follow - conventions like _BOOL */ +/* CDS++ defines __EDG__ although this is not documented in the Reliant + documentation. It also follows conventions like _BOOL and this documented */ # elif defined(sinix) # define Q_CC_CDS # define Q_NO_USING_KEYWORD # if defined(__cplusplus) && (__cplusplus < 2) /* Cfront C++ mode */ # define Q_NO_EXCEPTIONS # endif /* The MIPSpro compiler in o32 mode is based on EDG but disables features such as template specialization nevertheless */ # elif defined(__sgi) # define Q_CC_MIPS # if defined(_MIPS_SIM) && (_MIPS_SIM == _ABIO32) /* o32 ABI */ # define Q_TYPENAME # define Q_BROKEN_TEMPLATE_SPECIALIZATION # define Q_STRICT_INLINING_RULES +# define Q_NO_EXPLICIT_KEYWORD +# define Q_INLINE_TEMPLATES inline # elif defined(_COMPILER_VERSION) && (_COMPILER_VERSION < 730) /* 7.2 */ # define Q_TYPENAME # define Q_BROKEN_TEMPLATE_SPECIALIZATION # endif # define Q_NO_USING_KEYWORD /* ### check "using" status */ # endif /* The older UnixWare 2.X compiler? */ -#elif defined(__USLC__) && !defined(__SCO_VERSION__) +#elif defined(__USLC__) # define Q_CC_USLC +# define Q_TYPENAME # define Q_NO_BOOL_TYPE # define Q_NO_EXPLICIT_KEYWORD # define Q_NO_USING_KEYWORD +# define Q_INLINE_TEMPLATES inline /* Never tested! */ #elif defined(__HIGHC__) # define Q_CC_HIGHC #elif defined(__SUNPRO_CC) # define Q_CC_SUN /* 5.0 compiler or better 'bool' is enabled by default but can be disabled using -features=nobool in which case _BOOL is not defined this is the default in 4.2 compatibility mode triggered by -compat=4 */ # if __SUNPRO_CC >= 0x500 # if !defined(_BOOL) # define Q_NO_BOOL_TYPE # endif # if defined(__SUNPRO_CC_COMPAT) && (__SUNPRO_CC_COMPAT <= 4) # define Q_NO_USING_KEYWORD # endif # define Q_C_CALLBACKS /* 4.2 compiler or older */ # else # define Q_NO_BOOL_TYPE # define Q_NO_EXPLICIT_KEYWORD # define Q_NO_USING_KEYWORD # endif +/* CDS++ does not seem to define __EDG__ or __EDG according to Reliant + documentation but nevertheless uses EDG conventions like _BOOL */ +#elif defined(sinix) +# define Q_CC_EDG +# define Q_CC_CDS +# if !defined(_BOOL) +# define Q_NO_BOOL_TYPE +# endif +# define Q_BROKEN_TEMPLATE_SPECIALIZATION + #elif defined(Q_OS_HPUX) /* __HP_aCC was not defined in first aCC releases */ # if defined(__HP_aCC) || __cplusplus >= 199707L # define Q_CC_HPACC # else # define Q_CC_HP # define Q_NO_BOOL_TYPE # define Q_FULL_TEMPLATE_INSTANTIATION # define Q_BROKEN_TEMPLATE_SPECIALIZATION # define Q_NO_EXPLICIT_KEYWORD # endif # define Q_NO_USING_KEYWORD /* ### check "using" status */ #else # error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com" #endif #ifndef Q_PACKED # define Q_PACKED #endif /* The window system, must be one of: (Q_WS_x) MACX - Mac OS X MAC9 - Mac OS 9 QWS - Qt/Embedded WIN32 - Windows X11 - X Window System PM - unsupported WIN16 - unsupported */ #if defined(Q_OS_MAC9) # define Q_WS_MAC9 #elif defined(Q_OS_MSDOS) # define Q_WS_WIN16 # error "Qt requires Win32 and does not work with Windows 3.x" #elif defined(_WIN32_X11_) # define Q_WS_X11 #elif defined(Q_OS_WIN32) # define Q_WS_WIN32 # if defined(Q_OS_WIN64) # define Q_WS_WIN64 # endif #elif defined(Q_OS_OS2) # define Q_WS_PM # error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" #elif defined(Q_OS_UNIX) # if defined(QWS) # define Q_WS_QWS +# define QT_NO_QWS_IM # elif defined(Q_OS_MACX) # define Q_WS_MACX # else # define Q_WS_X11 # endif #endif #if defined(Q_OS_MAC) && !defined(QMAC_PASCAL) # define QMAC_PASCAL #endif #if defined(Q_WS_WIN16) || defined(Q_WS_WIN32) # define Q_WS_WIN #endif #if (defined(Q_WS_MAC9) || defined(Q_WS_MACX)) && !defined(Q_WS_QWS) && !defined(Q_WS_X11) # define Q_WS_MAC #endif /* Some classes do not permit copies to be made of an object. These classes contains a private copy constructor and operator= to disable copying (the compiler gives an error message). Undefine Q_DISABLE_COPY to turn off this checking. */ #define Q_DISABLE_COPY #if defined(__cplusplus) // // Useful type definitions for Qt // #if defined(Q_NO_BOOL_TYPE) #if defined(Q_CC_HP) // bool is an unsupported reserved keyword in later versions #define bool int #else typedef int bool; #endif #endif typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned uint; typedef unsigned long ulong; typedef char *pchar; typedef uchar *puchar; typedef const char *pcchar; // // Constant bool values // #ifndef TRUE const bool FALSE = 0; const bool TRUE = !0; #endif #if defined(__WATCOMC__) # if defined(Q_OS_QNX4) const bool false = FALSE; const bool true = TRUE; # endif #endif // // Use the "explicit" keyword on platforms that support it. // #if !defined(Q_NO_EXPLICIT_KEYWORD) # define Q_EXPLICIT explicit #else # define Q_EXPLICIT #endif // // Workaround for static const members on MSVC++. // #if defined(Q_CC_MSVC) # define QT_STATIC_CONST static # define QT_STATIC_CONST_IMPL #else # define QT_STATIC_CONST static const # define QT_STATIC_CONST_IMPL const #endif // // Utility macros and inline functions // #define QMAX(a, b) ((b) < (a) ? (a) : (b)) #define QMIN(a, b) ((a) < (b) ? (a) : (b)) #define QABS(a) ((a) >= 0 ? (a) : -(a)) inline int qRound( double d ) { return d >= 0.0 ? int(d + 0.5) : int( d - ((int)d-1) + 0.5 ) + ((int)d-1); } // // Size-dependent types (architechture-dependent byte order) // #if !defined(QT_CLEAN_NAMESPACE) // source compatibility with Qt 1.x typedef signed char INT8; // 8 bit signed typedef unsigned char UINT8; // 8 bit unsigned typedef short INT16; // 16 bit signed typedef unsigned short UINT16; // 16 bit unsigned typedef int INT32; // 32 bit signed typedef unsigned int UINT32; // 32 bit unsigned #endif typedef signed char Q_INT8; // 8 bit signed typedef unsigned char Q_UINT8; // 8 bit unsigned typedef short Q_INT16; // 16 bit signed typedef unsigned short Q_UINT16; // 16 bit unsigned typedef int Q_INT32; // 32 bit signed typedef unsigned int Q_UINT32; // 32 bit unsigned #if defined(Q_OS_WIN64) // LLP64 64-bit model on Windows typedef __int64 Q_LONG; // word up to 64 bit signed typedef unsigned __int64 Q_ULONG; // word up to 64 bit unsigned #else // LP64 64-bit model on Linux typedef long Q_LONG; typedef unsigned long Q_ULONG; #endif #if !defined(QT_CLEAN_NAMESPACE) // mininum size of 64 bits is not guaranteed #define Q_INT64 Q_LONG #define Q_UINT64 Q_ULONG #endif #if defined(Q_OS_MACX) && !defined(QT_LARGEFILE_SUPPORT) # define QT_LARGEFILE_SUPPORT 64 #endif #if defined(QT_LARGEFILE_SUPPORT) typedef unsigned long long QtOffset; #else typedef Q_ULONG QtOffset; #endif // // Data stream functions is provided by many classes (defined in qdatastream.h) // class QDataStream; // // Feature subsetting // // Note that disabling some features will produce a libqt that is not // compatible with other libqt builds. Such modifications are only // supported on Qt/Embedded where reducing the library size is important // and where the application-suite is often a fixed set. // #if !defined(QT_MOC) #if defined(QCONFIG_LOCAL) #include <qconfig-local.h> #elif defined(QCONFIG_MINIMAL) #include <qconfig-minimal.h> #elif defined(QCONFIG_SMALL) #include <qconfig-small.h> #elif defined(QCONFIG_MEDIUM) #include <qconfig-medium.h> #elif defined(QCONFIG_LARGE) #include <qconfig-large.h> #else // everything... #include <qconfig.h> #endif #endif #ifndef QT_BUILD_KEY #define QT_BUILD_KEY "unspecified" #endif // prune to local config #include "qmodules.h" #ifndef QT_MODULE_ICONVIEW # define QT_NO_ICONVIEW #endif #ifndef QT_MODULE_WORKSPACE # define QT_NO_WORKSPACE #endif #ifndef QT_MODULE_NETWORK #define QT_NO_NETWORK #endif #ifndef QT_MODULE_CANVAS # define QT_NO_CANVAS #endif #ifndef QT_MODULE_TABLE #define QT_NO_TABLE #endif #ifndef QT_MODULE_XML # define QT_NO_XML #endif #ifndef QT_MODULE_OPENGL # define QT_NO_OPENGL #endif #if !defined(QT_MODULE_SQL) # define QT_NO_SQL #endif #if defined(Q_WS_MAC9) //No need for menu merging # ifndef QMAC_QMENUBAR_NO_MERGE # define QMAC_QMENUBAR_NO_MERGE # endif //Mac9 does not use quartz # ifndef QMAC_NO_QUARTZ # define QMAC_NO_QUARTZ # endif # ifndef QMAC_QMENUBAR_NO_EVENT # define QMAC_QMENUBAR_NO_EVENT # endif #endif #if defined(Q_WS_MACX) //for no nobody uses quartz, just putting in first level hooks # ifndef QMAC_NO_QUARTZ # define QMAC_NO_QUARTZ # endif # ifndef QMAC_QMENUBAR_NO_EVENT # define QMAC_QMENUBAR_NO_EVENT # endif #endif +#if !defined(Q_WS_QWS) && !defined(QT_NO_COP) +# define QT_NO_COP +#endif + #ifndef QT_H #include <qfeatures.h> #endif // QT_H // // Create Qt DLL if QT_DLL is defined (Windows only) +// or QT_SHARED is defined (Kylix only) // #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) # if defined(QT_NODLL) # undef QT_MAKEDLL # undef QT_DLL # elif defined(QT_MAKEDLL) /* create a Qt DLL library */ # if defined(QT_DLL) # undef QT_DLL # endif # define Q_EXPORT __declspec(dllexport) # define Q_TEMPLATEDLL # define Q_TEMPLATE_EXTERN # undef Q_DISABLE_COPY /* avoid unresolved externals */ # elif defined(QT_DLL) /* use a Qt DLL library */ # define Q_EXPORT __declspec(dllimport) # define Q_TEMPLATEDLL # ifndef Q_TEMPLATE_EXTERN -# if defined(Q_CC_MSVC) -# define Q_TEMPLATE_EXTERN /*extern*/ //### too many warnings, even though disabled +# if defined(Q_CC_MSVC_NET) +# define Q_TEMPLATE_EXTERN extern # else # define Q_TEMPLATE_EXTERN # endif # endif # undef Q_DISABLE_COPY /* avoid unresolved externals */ # endif +#elif defined(Q_OS_LINUX) && defined(Q_CC_BOR) +# if defined(QT_SHARED) /* create a Qt shared library */ +# define Q_EXPORT __declspec(dllexport) +# define Q_TEMPLATEDLL +# define Q_TEMPLATE_EXTERN +# undef Q_DISABLE_COPY /* avoid unresolved externals */ +# else +# define Q_TEMPLATEDLL +# define Q_TEMPLATE_EXTERN +# undef Q_DISABLE_COPY /* avoid unresolved externals */ +# endif #else # undef QT_MAKEDLL /* ignore these for other platforms */ # undef QT_DLL #endif #ifndef Q_EXPORT # define Q_EXPORT #endif // // Some platform specific stuff // #if defined(Q_WS_WIN) extern Q_EXPORT bool qt_winunicode; #endif // // System information // Q_EXPORT const char *qVersion(); Q_EXPORT bool qSysInfo( int *wordSize, bool *bigEndian ); -#if defined(Q_WS_WIN) +#if defined(Q_OS_MAC) +int qMacVersion(); +#elif defined(Q_WS_WIN) Q_EXPORT int qWinVersion(); #if defined(UNICODE) #define QT_WA( uni, ansi ) if ( qt_winunicode ) { uni } else { ansi } #define QT_WA_INLINE( uni, ansi ) ( qt_winunicode ? uni : ansi ) #else #define QT_WA( uni, ansi ) ansi #define QT_WA_INLINE( uni, ansi ) ansi #endif #endif #ifdef Q_OS_TEMP #ifdef QT_WA #undef QT_WA #undef QT_WA_INLINE #endif #define QT_WA( uni, ansi ) uni #define QT_WA_INLINE( uni, ansi ) ( uni ) #endif #ifndef Q_INLINE_TEMPLATES # define Q_INLINE_TEMPLATES #endif #ifndef Q_TYPENAME # define Q_TYPENAME typename #endif // // Use to avoid "unused parameter" warnings // #define Q_UNUSED(x) (void)x; // // Debugging and error handling // #if !defined(QT_NO_CHECK) # define QT_CHECK_STATE // check state of objects etc. # define QT_CHECK_RANGE // check range of indexes etc. # define QT_CHECK_NULL // check null pointers # define QT_CHECK_MATH // check math functions #endif #if !defined(QT_NO_DEBUG) && !defined(QT_DEBUG) # define QT_DEBUG // display debug messages # if !defined(QT_NO_COMPAT) // compatibility with Qt 2 # if !defined(NO_DEBUG) && !defined(DEBUG) # if !defined(Q_OS_MACX) // clash with MacOS X headers # define DEBUG # endif # endif # endif #endif Q_EXPORT void qDebug( const char *, ... ) // print debug message #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 1, 2))) #endif ; Q_EXPORT void qWarning( const char *, ... ) // print warning message #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 1, 2))) #endif ; Q_EXPORT void qFatal( const char *, ... ) // print fatal message and exit #if defined(Q_CC_GNU) __attribute__ ((format (printf, 1, 2))) #endif ; Q_EXPORT void qSystemWarning( const char *, int code = -1 ); #if !defined(QT_CLEAN_NAMESPACE) // compatibility with Qt 1 Q_EXPORT void debug( const char *, ... ) // print debug message #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 1, 2))) #endif ; Q_EXPORT void warning( const char *, ... ) // print warning message #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 1, 2))) #endif ; Q_EXPORT void fatal( const char *, ... ) // print fatal message and exit #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 1, 2))) #endif ; #endif // QT_CLEAN_NAMESPACE #if !defined(Q_ASSERT) # if defined(QT_CHECK_STATE) # if defined(QT_FATAL_ASSERT) # define Q_ASSERT(x) ((x) ? (void)0 : qFatal("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__)) # else # define Q_ASSERT(x) ((x) ? (void)0 : qWarning("ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__)) # endif # else # define Q_ASSERT(x) # endif #endif #if !defined(QT_NO_COMPAT) // compatibility with Qt 2 # if !defined(ASSERT) # if !defined(Q_OS_TEMP) # define ASSERT(x) Q_ASSERT(x) # endif # endif #endif // QT_NO_COMPAT Q_EXPORT bool qt_check_pointer( bool c, const char *, int ); #if defined(QT_CHECK_NULL) # define Q_CHECK_PTR(p) (qt_check_pointer((p)==0,__FILE__,__LINE__)) #else # define Q_CHECK_PTR(p) #endif #if !defined(QT_NO_COMPAT) // compatibility with Qt 2 # if !defined(CHECK_PTR) # define CHECK_PTR(x) Q_CHECK_PTR(x) # endif #endif // QT_NO_COMPAT enum QtMsgType { QtDebugMsg, QtWarningMsg, QtFatalMsg }; typedef void (*QtMsgHandler)(QtMsgType, const char *); Q_EXPORT QtMsgHandler qInstallMsgHandler( QtMsgHandler ); #if !defined(QT_NO_COMPAT) // compatibility with Qt 2 typedef QtMsgHandler msg_handler; #endif // QT_NO_COMPAT Q_EXPORT void qSuppressObsoleteWarnings( bool = TRUE ); Q_EXPORT void qObsolete( const char *obj, const char *oldfunc, const char *newfunc ); Q_EXPORT void qObsolete( const char *obj, const char *oldfunc ); Q_EXPORT void qObsolete( const char *message ); // // Install paths from configure // Q_EXPORT const char *qInstallPath(); Q_EXPORT const char *qInstallPathDocs(); Q_EXPORT const char *qInstallPathHeaders(); Q_EXPORT const char *qInstallPathLibs(); Q_EXPORT const char *qInstallPathBins(); Q_EXPORT const char *qInstallPathPlugins(); Q_EXPORT const char *qInstallPathData(); #endif // __cplusplus +// compilers which follow outdated template instantiation rules +// require a class to have a comparison operator to exist when +// a QValueList of this type is instantiated. It's not actually +// used in the list, though. Hence the dummy implementation. +// Just in case other code relies on it we better trigger a warning +// mandating a real implementation. +#ifdef Q_FULL_TEMPLATE_INSTANTIATION +# define Q_DUMMY_COMPARISON_OPERATOR(C) \ + bool operator==( const C& ) const { \ + qWarning( #C"::operator==( const "#C"& ) got called." ); \ + return FALSE; \ + } +#else +# define Q_DUMMY_COMPARISON_OPERATOR(C) +#endif + #endif // QGLOBAL_H // // Avoid some particularly useless warnings from some stupid compilers. // To get ALL C++ compiler warnings, define QT_CC_WARNINGS or comment out // the line "#define QT_NO_WARNINGS" // #if !defined(QT_CC_WARNINGS) # define QT_NO_WARNINGS #endif #if defined(QT_NO_WARNINGS) # if defined(Q_CC_MSVC) # pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data # pragma warning(disable: 4275) // non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' # pragma warning(disable: 4514) // unreferenced inline/local function has been removed # pragma warning(disable: 4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning) # pragma warning(disable: 4097) // typedef-name 'identifier1' used as synonym for class-name 'identifier2' # pragma warning(disable: 4706) // assignment within conditional expression # pragma warning(disable: 4786) // truncating debug info after 255 characters # pragma warning(disable: 4660) // template-class specialization 'identifier' is already instantiated # pragma warning(disable: 4355) // 'this' : used in base member initializer list # pragma warning(disable: 4231) // nonstandard extension used : 'extern' before template explicit instantiation +# pragma warning(disable: 4710) // function not inlined # elif defined(Q_CC_BOR) # pragma option -w-inl # pragma option -w-aus # pragma warn -inl # pragma warn -pia # pragma warn -ccc # pragma warn -rch # pragma warn -sig # elif defined(Q_CC_MWERKS) # pragma warn_possunwant off # endif #endif diff --git a/qmake/include/qintdict.h b/qmake/include/qintdict.h index b4cb223..0299879 100644 --- a/qmake/include/qintdict.h +++ b/qmake/include/qintdict.h @@ -1,114 +1,118 @@ /**************************************************************************** ** $Id$ ** ** Definition of QIntDict template class ** ** Created : 940624 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QINTDICT_H #define QINTDICT_H #ifndef QT_H #include "qgdict.h" #endif // QT_H template<class type> class QIntDict #ifdef Q_QDOC : public QPtrCollection #else : public QGDict #endif { public: QIntDict(int size=17) : QGDict(size,IntKey,0,0) {} QIntDict( const QIntDict<type> &d ) : QGDict(d) {} ~QIntDict() { clear(); } QIntDict<type> &operator=(const QIntDict<type> &d) { return (QIntDict<type>&)QGDict::operator=(d); } uint count() const { return QGDict::count(); } uint size() const { return QGDict::size(); } bool isEmpty() const { return QGDict::count() == 0; } void insert( long k, const type *d ) { QGDict::look_int(k,(Item)d,1); } void replace( long k, const type *d ) { QGDict::look_int(k,(Item)d,2); } bool remove( long k ) { return QGDict::remove_int(k); } type *take( long k ) { return (type*)QGDict::take_int(k); } type *find( long k ) const { return (type *)((QGDict*)this)->QGDict::look_int(k,0,0); } type *operator[]( long k ) const { return (type *)((QGDict*)this)->QGDict::look_int(k,0,0); } void clear() { QGDict::clear(); } void resize( uint n ) { QGDict::resize(n); } void statistics() const { QGDict::statistics(); } #ifdef Q_QDOC protected: virtual QDataStream& read( QDataStream &, QPtrCollection::Item & ); virtual QDataStream& write( QDataStream &, QPtrCollection::Item ) const; #endif private: void deleteItem( Item d ); }; #if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) template<> inline void QIntDict<void>::deleteItem( QPtrCollection::Item ) { } #endif template<class type> inline void QIntDict<type>::deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete (type*)d; } template<class type> class QIntDictIterator : public QGDictIterator { public: QIntDictIterator(const QIntDict<type> &d) :QGDictIterator((QGDict &)d) {} ~QIntDictIterator() {} uint count() const { return dict->count(); } bool isEmpty() const { return dict->count() == 0; } type *toFirst() { return (type *)QGDictIterator::toFirst(); } operator type *() const { return (type *)QGDictIterator::get(); } type *current() const { return (type *)QGDictIterator::get(); } long currentKey() const { return QGDictIterator::getKeyInt(); } type *operator()() { return (type *)QGDictIterator::operator()(); } type *operator++() { return (type *)QGDictIterator::operator++(); } type *operator+=(uint j) { return (type *)QGDictIterator::operator+=(j);} }; +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QINTDICT +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QINTDICT_H diff --git a/qmake/include/qmap.h b/qmake/include/qmap.h index 269bd6b..4bc0a2f 100644 --- a/qmake/include/qmap.h +++ b/qmake/include/qmap.h @@ -499,385 +499,389 @@ Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::ConstIterator QMapPrivate<Key, while ( x != 0 ) { // If as k <= key(x) go left if ( !( key(x) < k ) ) { y = x; x = x->left; } else { x = x->right; } } // Was k bigger/smaller then the biggest/smallest // element of the tree ? Return end() if ( y == header || k < key(y) ) return ConstIterator( header ); return ConstIterator( (NodePtr)y ); } template <class Key, class T> Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::Iterator QMapPrivate<Key,T>::insertSingle( const Key& k ) { // Search correct position in the tree QMapNodeBase* y = header; QMapNodeBase* x = header->parent; bool result = TRUE; while ( x != 0 ) { result = ( k < key(x) ); y = x; x = result ? x->left : x->right; } // Get iterator on the last not empty one Iterator j( (NodePtr)y ); if ( result ) { // Smaller then the leftmost one ? if ( j == begin() ) { return insert(x, y, k ); } else { // Perhaps daddy is the right one ? --j; } } // Really bigger ? if ( (j.node->key) < k ) return insert(x, y, k ); // We are going to replace a node return j; } template <class Key, class T> Q_INLINE_TEMPLATES Q_TYPENAME QMapPrivate<Key,T>::Iterator QMapPrivate<Key,T>::insert( QMapNodeBase* x, QMapNodeBase* y, const Key& k ) { NodePtr z = new Node( k ); if (y == header || x != 0 || k < key(y) ) { y->left = z; // also makes leftmost = z when y == header if ( y == header ) { header->parent = z; header->right = z; } else if ( y == header->left ) header->left = z; // maintain leftmost pointing to min node } else { y->right = z; if ( y == header->right ) header->right = z; // maintain rightmost pointing to max node } z->parent = y; z->left = 0; z->right = 0; rebalance( z, header->parent ); ++node_count; return Iterator(z); } #ifdef QT_CHECK_RANGE # if !defined( QT_NO_DEBUG ) && defined( QT_CHECK_MAP_RANGE ) # define QT_CHECK_INVALID_MAP_ELEMENT if ( empty() ) qWarning( "QMap: Warning invalid element" ) # define QT_CHECK_INVALID_MAP_ELEMENT_FATAL Q_ASSERT( !empty() ); # else # define QT_CHECK_INVALID_MAP_ELEMENT # define QT_CHECK_INVALID_MAP_ELEMENT_FATAL # endif #else # define QT_CHECK_INVALID_MAP_ELEMENT # define QT_CHECK_INVALID_MAP_ELEMENT_FATAL #endif template <class T> class QDeepCopy; template<class Key, class T> class QMap { public: /** * Typedefs */ typedef Key key_type; typedef T mapped_type; typedef QPair<const key_type, mapped_type> value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; #ifndef QT_NO_STL typedef ptrdiff_t difference_type; #else typedef int difference_type; #endif typedef size_t size_type; typedef QMapIterator<Key,T> iterator; typedef QMapConstIterator<Key,T> const_iterator; typedef QPair<iterator,bool> insert_pair; typedef QMapIterator< Key, T > Iterator; typedef QMapConstIterator< Key, T > ConstIterator; typedef T ValueType; typedef QMapPrivate< Key, T > Priv; /** * API */ QMap() { sh = new QMapPrivate< Key, T >; } QMap( const QMap<Key,T>& m ) { sh = m.sh; sh->ref(); } #ifndef QT_NO_STL # ifdef Q_CC_HPACC // HP-UX aCC does require typename in some place # undef Q_TYPENAME // but not accept them at others. # define Q_TYPENAME // also doesn't like re-defines ... # endif QMap( const Q_TYPENAME std::map<Key,T>& m ) { sh = new QMapPrivate<Key,T>; #if defined(Q_OS_WIN32) std::map<Key,T>::const_iterator it = m.begin(); #else QMapConstIterator<Key,T> it = m.begin(); #endif for ( ; it != m.end(); ++it ) { value_type p( (*it).first, (*it).second ); insert( p ); } } #endif ~QMap() { if ( sh->deref() ) delete sh; } QMap<Key,T>& operator= ( const QMap<Key,T>& m ); #ifndef QT_NO_STL QMap<Key,T>& operator= ( const Q_TYPENAME std::map<Key,T>& m ) { clear(); #if defined(Q_OS_WIN32) std::map<Key,T>::const_iterator it = m.begin(); #else QMapConstIterator<Key,T> it = m.begin(); #endif for ( ; it != m.end(); ++it ) { value_type p( (*it).first, (*it).second ); insert( p ); } return *this; } # ifdef Q_CC_HPACC // undo the HP-UX aCC hackery done above # undef Q_TYPENAME # define Q_TYPENAME typename # endif #endif iterator begin() { detach(); return sh->begin(); } iterator end() { detach(); return sh->end(); } const_iterator begin() const { return ((const Priv*)sh)->begin(); } const_iterator end() const { return ((const Priv*)sh)->end(); } iterator replace( const Key& k, const T& v ) { remove( k ); return insert( k, v ); } size_type size() const { return sh->node_count; } bool empty() const { return sh->node_count == 0; } QPair<iterator,bool> insert( const value_type& x ); void erase( iterator it ) { detach(); sh->remove( it ); } void erase( const key_type& k ); size_type count( const key_type& k ) const; T& operator[] ( const Key& k ); void clear(); iterator find ( const Key& k ) { detach(); return iterator( sh->find( k ).node ); } const_iterator find ( const Key& k ) const { return sh->find( k ); } const T& operator[] ( const Key& k ) const { QT_CHECK_INVALID_MAP_ELEMENT; return sh->find( k ).data(); } bool contains ( const Key& k ) const { return find( k ) != end(); } //{ return sh->find( k ) != ((const Priv*)sh)->end(); } size_type count() const { return sh->node_count; } QValueList<Key> keys() const { QValueList<Key> r; for (const_iterator i=begin(); i!=end(); ++i) r.append(i.key()); return r; } QValueList<T> values() const { QValueList<T> r; for (const_iterator i=begin(); i!=end(); ++i) r.append(*i); return r; } bool isEmpty() const { return sh->node_count == 0; } iterator insert( const Key& key, const T& value, bool overwrite = TRUE ); void remove( iterator it ) { detach(); sh->remove( it ); } void remove( const Key& k ); #if defined(Q_FULL_TEMPLATE_INSTANTIATION) bool operator==( const QMap<Key,T>& ) const { return FALSE; } #ifndef QT_NO_STL bool operator==( const Q_TYPENAME std::map<Key,T>& ) const { return FALSE; } #endif #endif protected: /** * Helpers */ void detach() { if ( sh->count > 1 ) detachInternal(); } Priv* sh; private: void detachInternal(); friend class QDeepCopy< QMap<Key,T> >; }; template<class Key, class T> Q_INLINE_TEMPLATES QMap<Key,T>& QMap<Key,T>::operator= ( const QMap<Key,T>& m ) { m.sh->ref(); if ( sh->deref() ) delete sh; sh = m.sh; return *this; } template<class Key, class T> Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::insert_pair QMap<Key,T>::insert( const Q_TYPENAME QMap<Key,T>::value_type& x ) { detach(); size_type n = size(); iterator it = sh->insertSingle( x.first ); bool inserted = FALSE; if ( n < size() ) { inserted = TRUE; it.data() = x.second; } return QPair<iterator,bool>( it, inserted ); } template<class Key, class T> Q_INLINE_TEMPLATES void QMap<Key,T>::erase( const Key& k ) { detach(); iterator it( sh->find( k ).node ); if ( it != end() ) sh->remove( it ); } template<class Key, class T> Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::size_type QMap<Key,T>::count( const Key& k ) const { const_iterator it( sh->find( k ).node ); if ( it != end() ) { size_type c = 0; while ( it != end() ) { ++it; ++c; } return c; } return 0; } template<class Key, class T> Q_INLINE_TEMPLATES T& QMap<Key,T>::operator[] ( const Key& k ) { detach(); QMapNode<Key,T>* p = sh->find( k ).node; if ( p != sh->end().node ) return p->data; return insert( k, T() ).data(); } template<class Key, class T> Q_INLINE_TEMPLATES void QMap<Key,T>::clear() { if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QMapPrivate<Key,T>; } } template<class Key, class T> Q_INLINE_TEMPLATES Q_TYPENAME QMap<Key,T>::iterator QMap<Key,T>::insert( const Key& key, const T& value, bool overwrite ) { detach(); size_type n = size(); iterator it = sh->insertSingle( key ); if ( overwrite || n < size() ) it.data() = value; return it; } template<class Key, class T> Q_INLINE_TEMPLATES void QMap<Key,T>::remove( const Key& k ) { detach(); iterator it( sh->find( k ).node ); if ( it != end() ) sh->remove( it ); } template<class Key, class T> Q_INLINE_TEMPLATES void QMap<Key,T>::detachInternal() { sh->deref(); sh = new QMapPrivate<Key,T>( sh ); } #ifndef QT_NO_DATASTREAM template<class Key, class T> Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QMap<Key,T>& m ) { m.clear(); Q_UINT32 c; s >> c; for( Q_UINT32 i = 0; i < c; ++i ) { Key k; T t; s >> k >> t; m.insert( k, t ); if ( s.atEnd() ) break; } return s; } template<class Key, class T> Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QMap<Key,T>& m ) { s << (Q_UINT32)m.size(); QMapConstIterator<Key,T> it = m.begin(); for( ; it != m.end(); ++it ) s << it.key() << it.data(); return s; } #endif +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QMAP +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QMAP_H diff --git a/qmake/include/qmemarray.h b/qmake/include/qmemarray.h index a5baf99..267670d 100644 --- a/qmake/include/qmemarray.h +++ b/qmake/include/qmemarray.h @@ -1,122 +1,129 @@ /**************************************************************************** ** $Id$ ** ** Definition of QMemArray template/macro class ** ** Created : 930906 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QMEMARRAY_H #define QMEMARRAY_H #ifndef QT_H #include "qgarray.h" #endif // QT_H template<class type> class QMemArray : public QGArray { public: typedef type* Iterator; typedef const type* ConstIterator; typedef type ValueType; protected: QMemArray( int, int ) : QGArray( 0, 0 ) {} public: QMemArray() {} QMemArray( int size ) : QGArray(size*sizeof(type)) {} QMemArray( const QMemArray<type> &a ) : QGArray(a) {} ~QMemArray() {} QMemArray<type> &operator=(const QMemArray<type> &a) { return (QMemArray<type>&)QGArray::assign(a); } type *data() const { return (type *)QGArray::data(); } uint nrefs() const { return QGArray::nrefs(); } uint size() const { return QGArray::size()/sizeof(type); } uint count() const { return size(); } bool isEmpty() const { return QGArray::size() == 0; } bool isNull() const { return QGArray::data() == 0; } bool resize( uint size ) { return QGArray::resize(size*sizeof(type)); } + bool resize( uint size, Optimization optim ) { return QGArray::resize(size*sizeof(type), optim); } bool truncate( uint pos ) { return QGArray::resize(pos*sizeof(type)); } bool fill( const type &d, int size = -1 ) { return QGArray::fill((char*)&d,size,sizeof(type) ); } void detach() { QGArray::detach(); } QMemArray<type> copy() const { QMemArray<type> tmp; return tmp.duplicate(*this); } QMemArray<type>& assign( const QMemArray<type>& a ) { return (QMemArray<type>&)QGArray::assign(a); } QMemArray<type>& assign( const type *a, uint n ) { return (QMemArray<type>&)QGArray::assign((char*)a,n*sizeof(type)); } QMemArray<type>& duplicate( const QMemArray<type>& a ) { return (QMemArray<type>&)QGArray::duplicate(a); } QMemArray<type>& duplicate( const type *a, uint n ) { return (QMemArray<type>&)QGArray::duplicate((char*)a,n*sizeof(type)); } QMemArray<type>& setRawData( const type *a, uint n ) { return (QMemArray<type>&)QGArray::setRawData((char*)a, n*sizeof(type)); } void resetRawData( const type *a, uint n ) { QGArray::resetRawData((char*)a,n*sizeof(type)); } int find( const type &d, uint i=0 ) const { return QGArray::find((char*)&d,i,sizeof(type)); } int contains( const type &d ) const { return QGArray::contains((char*)&d,sizeof(type)); } void sort() { QGArray::sort(sizeof(type)); } int bsearch( const type &d ) const { return QGArray::bsearch((const char*)&d,sizeof(type)); } // ### Qt 4.0: maybe provide uint overload as work-around for MSVC bug type& operator[]( int i ) const { return (type &)(*(type *)QGArray::at(i*sizeof(type))); } type& at( uint i ) const { return (type &)(*(type *)QGArray::at(i*sizeof(type))); } operator const type*() const { return (const type *)QGArray::data(); } bool operator==( const QMemArray<type> &a ) const { return isEqual(a); } bool operator!=( const QMemArray<type> &a ) const { return !isEqual(a); } Iterator begin() { return data(); } Iterator end() { return data() + size(); } ConstIterator begin() const { return data(); } ConstIterator end() const { return data() + size(); } }; +#ifndef QT_QWINEXPORT #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<int>; Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<bool>; // MOC_SKIP_END #endif +#endif /* QT_QWINEXPORT */ #ifndef QT_NO_COMPAT #define QArray QMemArray #endif +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QMEMARRAY +#include <qwinexport.h> +#endif /* QT_QWINEXPORT */ #endif // QARRAY_H diff --git a/qmake/include/qptrlist.h b/qmake/include/qptrlist.h index 53fb605..17b5ee9 100644 --- a/qmake/include/qptrlist.h +++ b/qmake/include/qptrlist.h @@ -1,160 +1,162 @@ /**************************************************************************** ** $Id$ ** ** Definition of QPtrList template/macro class ** -** Created : -** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QPTRLIST_H #define QPTRLIST_H #ifndef QT_H #include "qglist.h" #endif // QT_H template<class type> class QPtrList #ifdef Q_QDOC : public QPtrCollection #else : public QGList #endif { public: QPtrList() {} QPtrList( const QPtrList<type> &l ) : QGList(l) {} ~QPtrList() { clear(); } QPtrList<type> &operator=(const QPtrList<type> &l) { return (QPtrList<type>&)QGList::operator=(l); } bool operator==( const QPtrList<type> &list ) const { return QGList::operator==( list ); } bool operator!=( const QPtrList<type> &list ) const { return !QGList::operator==( list ); } uint count() const { return QGList::count(); } bool isEmpty() const { return QGList::count() == 0; } bool insert( uint i, const type *d){ return QGList::insertAt(i,(QPtrCollection::Item)d); } void inSort( const type *d ) { QGList::inSort((QPtrCollection::Item)d); } void prepend( const type *d ) { QGList::insertAt(0,(QPtrCollection::Item)d); } void append( const type *d ) { QGList::append((QPtrCollection::Item)d); } bool remove( uint i ) { return QGList::removeAt(i); } bool remove() { return QGList::remove((QPtrCollection::Item)0); } bool remove( const type *d ) { return QGList::remove((QPtrCollection::Item)d); } bool removeRef( const type *d ) { return QGList::removeRef((QPtrCollection::Item)d); } void removeNode( QLNode *n ) { QGList::removeNode(n); } bool removeFirst() { return QGList::removeFirst(); } bool removeLast() { return QGList::removeLast(); } type *take( uint i ) { return (type *)QGList::takeAt(i); } type *take() { return (type *)QGList::take(); } type *takeNode( QLNode *n ) { return (type *)QGList::takeNode(n); } void clear() { QGList::clear(); } void sort() { QGList::sort(); } int find( const type *d ) { return QGList::find((QPtrCollection::Item)d); } int findNext( const type *d ) { return QGList::find((QPtrCollection::Item)d,FALSE); } int findRef( const type *d ) { return QGList::findRef((QPtrCollection::Item)d); } int findNextRef( const type *d ){ return QGList::findRef((QPtrCollection::Item)d,FALSE);} uint contains( const type *d ) const { return QGList::contains((QPtrCollection::Item)d); } uint containsRef( const type *d ) const { return QGList::containsRef((QPtrCollection::Item)d); } bool replace( uint i, const type *d ) { return QGList::replaceAt( i, (QPtrCollection::Item)d ); } type *at( uint i ) { return (type *)QGList::at(i); } int at() const { return QGList::at(); } type *current() const { return (type *)QGList::get(); } QLNode *currentNode() const { return QGList::currentNode(); } type *getFirst() const { return (type *)QGList::cfirst(); } type *getLast() const { return (type *)QGList::clast(); } type *first() { return (type *)QGList::first(); } type *last() { return (type *)QGList::last(); } type *next() { return (type *)QGList::next(); } type *prev() { return (type *)QGList::prev(); } void toVector( QGVector *vec )const{ QGList::toVector(vec); } #ifdef Q_QDOC protected: virtual int compareItems( QPtrCollection::Item, QPtrCollection::Item ); virtual QDataStream& read( QDataStream&, QPtrCollection::Item& ); virtual QDataStream& write( QDataStream&, QPtrCollection::Item ) const; #endif private: void deleteItem( Item d ); }; #if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) template<> inline void QPtrList<void>::deleteItem( QPtrCollection::Item ) { } #endif template<class type> inline void QPtrList<type>::deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete (type *)d; } template<class type> class QPtrListIterator : public QGListIterator { public: QPtrListIterator(const QPtrList<type> &l) :QGListIterator((QGList &)l) {} ~QPtrListIterator() {} uint count() const { return list->count(); } bool isEmpty() const { return list->count() == 0; } bool atFirst() const { return QGListIterator::atFirst(); } bool atLast() const { return QGListIterator::atLast(); } type *toFirst() { return (type *)QGListIterator::toFirst(); } type *toLast() { return (type *)QGListIterator::toLast(); } operator type *() const { return (type *)QGListIterator::get(); } type *operator*() { return (type *)QGListIterator::get(); } // No good, since QPtrList<char> (ie. QStrList fails... // // MSVC++ gives warning // Sunpro C++ 4.1 gives error // type *operator->() { return (type *)QGListIterator::get(); } type *current() const { return (type *)QGListIterator::get(); } type *operator()() { return (type *)QGListIterator::operator()();} type *operator++() { return (type *)QGListIterator::operator++(); } type *operator+=(uint j) { return (type *)QGListIterator::operator+=(j);} type *operator--() { return (type *)QGListIterator::operator--(); } type *operator-=(uint j) { return (type *)QGListIterator::operator-=(j);} QPtrListIterator<type>& operator=(const QPtrListIterator<type>&it) { QGListIterator::operator=(it); return *this; } }; #ifndef QT_NO_COMPAT #define QList QPtrList #define QListIterator QPtrListIterator #endif +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QPTRLIST +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QPTRLIST_H diff --git a/qmake/include/qptrvector.h b/qmake/include/qptrvector.h index f6d9623..49b40b7 100644 --- a/qmake/include/qptrvector.h +++ b/qmake/include/qptrvector.h @@ -1,113 +1,117 @@ /**************************************************************************** ** $Id$ ** ** Definition of QPtrVector pointer based template class ** ** Created : 930907 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QPTRVECTOR_H #define QPTRVECTOR_H #ifndef QT_H #include "qgvector.h" #endif // QT_H template<class type> class QPtrVector #ifdef Q_QDOC : public QPtrCollection #else : public QGVector #endif { public: QPtrVector() { } QPtrVector( uint size ) : QGVector(size) { } QPtrVector( const QPtrVector<type> &v ) : QGVector( v ) { } ~QPtrVector() { clear(); } QPtrVector<type> &operator=(const QPtrVector<type> &v) { return (QPtrVector<type>&)QGVector::operator=(v); } bool operator==( const QPtrVector<type> &v ) const { return QGVector::operator==(v); } type **data() const { return (type **)QGVector::data(); } uint size() const { return QGVector::size(); } uint count() const { return QGVector::count(); } bool isEmpty() const { return QGVector::count() == 0; } bool isNull() const { return QGVector::size() == 0; } bool resize( uint size ) { return QGVector::resize(size); } bool insert( uint i, const type *d){ return QGVector::insert(i,(Item)d); } bool remove( uint i ) { return QGVector::remove(i); } type *take( uint i ) { return (type *)QGVector::take(i); } void clear() { QGVector::clear(); } bool fill( const type *d, int size=-1 ) { return QGVector::fill((Item)d,size);} void sort() { QGVector::sort(); } int bsearch( const type *d ) const{ return QGVector::bsearch((Item)d); } int findRef( const type *d, uint i=0 ) const { return QGVector::findRef((Item)d,i);} int find( const type *d, uint i= 0 ) const { return QGVector::find((Item)d,i); } uint containsRef( const type *d ) const { return QGVector::containsRef((Item)d); } uint contains( const type *d ) const { return QGVector::contains((Item)d); } type *operator[]( int i ) const { return (type *)QGVector::at(i); } type *at( uint i ) const { return (type *)QGVector::at(i); } void toList( QGList *list ) const { QGVector::toList(list); } #ifdef Q_QDOC protected: virtual int compareItems( QPtrCollection::Item d1, QPtrCollection::Item d2 ); virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &d ); virtual QDataStream& write( QDataStream &s, QPtrCollection::Item d ) const; #endif private: void deleteItem( Item d ); }; #if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) template<> inline void QPtrVector<void>::deleteItem( QPtrCollection::Item ) { } #endif template<class type> inline void QPtrVector<type>::deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete (type *)d; } #ifndef QT_NO_COMPAT #define QVector QPtrVector #endif +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QPTRVECTOR +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QVECTOR_H diff --git a/qmake/include/qregexp.h b/qmake/include/qregexp.h index 7bb777a..90f54bd 100644 --- a/qmake/include/qregexp.h +++ b/qmake/include/qregexp.h @@ -1,115 +1,115 @@ /**************************************************************************** ** $Id$ ** ** Definition of QRegExp class ** ** Created : 950126 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QREGEXP_H #define QREGEXP_H #ifndef QT_H #include "qstringlist.h" #endif // QT_H #ifndef QT_NO_REGEXP class QRegExpEngine; struct QRegExpPrivate; class Q_EXPORT QRegExp { public: enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; QRegExp(); QRegExp( const QString& pattern, bool caseSensitive = TRUE, bool wildcard = FALSE ); QRegExp( const QRegExp& rx ); ~QRegExp(); QRegExp& operator=( const QRegExp& rx ); bool operator==( const QRegExp& rx ) const; bool operator!=( const QRegExp& rx ) const { return !operator==( rx ); } bool isEmpty() const; bool isValid() const; QString pattern() const; void setPattern( const QString& pattern ); bool caseSensitive() const; void setCaseSensitive( bool sensitive ); #ifndef QT_NO_REGEXP_WILDCARD bool wildcard() const; void setWildcard( bool wildcard ); #endif bool minimal() const; void setMinimal( bool minimal ); bool exactMatch( const QString& str ) const; #ifndef QT_NO_COMPAT int match( const QString& str, int index = 0, int *len = 0, bool indexIsStart = TRUE ) const; #endif -#if defined(qdoc) +#if defined(Q_QDOC) int search( const QString& str, int offset = 0, CaretMode caretMode = CaretAtZero ) const; int searchRev( const QString& str, int offset = -1, CaretMode caretMode = CaretAtZero ) const; #else // ### Qt 4.0: reduce these four to two functions int search( const QString& str, int offset = 0 ) const; int search( const QString& str, int offset, CaretMode caretMode ) const; int searchRev( const QString& str, int offset = -1 ) const; int searchRev( const QString& str, int offset, CaretMode caretMode ) const; #endif int matchedLength() const; #ifndef QT_NO_REGEXP_CAPTURE int numCaptures() const; QStringList capturedTexts(); QString cap( int nth = 0 ); int pos( int nth = 0 ); QString errorString(); #endif static QString escape( const QString& str ); private: void compile( bool caseSensitive ); static int caretIndex( int offset, CaretMode caretMode ); QRegExpEngine *eng; QRegExpPrivate *priv; }; #endif // QT_NO_REGEXP #endif // QREGEXP_H diff --git a/qmake/include/qstring.h b/qmake/include/qstring.h index 2a87a5a..c1d6740 100644 --- a/qmake/include/qstring.h +++ b/qmake/include/qstring.h @@ -1,950 +1,991 @@ /**************************************************************************** ** $Id$ ** -** Definition of the QString class, and related Unicode -** functions. +** Definition of the QString class, and related Unicode functions. ** ** Created : 920609 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QSTRING_H #define QSTRING_H #ifndef QT_H #include "qcstring.h" #endif // QT_H +#ifndef QT_NO_STL +#include <string> +#if defined(Q_WRONG_SB_CTYPE_MACROS) && defined(_SB_CTYPE_MACROS) +#undef _SB_CTYPE_MACROS +#endif +#endif + /***************************************************************************** QString class *****************************************************************************/ class QRegExp; class QString; class QCharRef; template <class T> class QDeepCopy; class Q_EXPORT QChar { public: QChar(); QChar( char c ); QChar( uchar c ); QChar( uchar c, uchar r ); QChar( const QChar& c ); QChar( ushort rc ); QChar( short rc ); QChar( uint rc ); QChar( int rc ); QT_STATIC_CONST QChar null; // 0000 QT_STATIC_CONST QChar replacement; // FFFD QT_STATIC_CONST QChar byteOrderMark; // FEFF QT_STATIC_CONST QChar byteOrderSwapped; // FFFE QT_STATIC_CONST QChar nbsp; // 00A0 // Unicode information enum Category { NoCategory, Mark_NonSpacing, // Mn Mark_SpacingCombining, // Mc Mark_Enclosing, // Me Number_DecimalDigit, // Nd Number_Letter, // Nl Number_Other, // No Separator_Space, // Zs Separator_Line, // Zl Separator_Paragraph, // Zp Other_Control, // Cc Other_Format, // Cf Other_Surrogate, // Cs Other_PrivateUse, // Co Other_NotAssigned, // Cn Letter_Uppercase, // Lu Letter_Lowercase, // Ll Letter_Titlecase, // Lt Letter_Modifier, // Lm Letter_Other, // Lo Punctuation_Connector, // Pc Punctuation_Dash, // Pd Punctuation_Dask = Punctuation_Dash, // oops Punctuation_Open, // Ps Punctuation_Close, // Pe Punctuation_InitialQuote, // Pi Punctuation_FinalQuote, // Pf Punctuation_Other, // Po Symbol_Math, // Sm Symbol_Currency, // Sc Symbol_Modifier, // Sk Symbol_Other // So }; enum Direction { DirL, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON, DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN }; enum Decomposition { Single, Canonical, Font, NoBreak, Initial, Medial, Final, Isolated, Circle, Super, Sub, Vertical, Wide, Narrow, Small, Square, Compat, Fraction }; enum Joining { OtherJoining, Dual, Right, Center }; enum CombiningClass { Combining_BelowLeftAttached = 200, Combining_BelowAttached = 202, Combining_BelowRightAttached = 204, Combining_LeftAttached = 208, Combining_RightAttached = 210, Combining_AboveLeftAttached = 212, Combining_AboveAttached = 214, Combining_AboveRightAttached = 216, Combining_BelowLeft = 218, Combining_Below = 220, Combining_BelowRight = 222, Combining_Left = 224, Combining_Right = 226, Combining_AboveLeft = 228, Combining_Above = 230, Combining_AboveRight = 232, Combining_DoubleBelow = 233, Combining_DoubleAbove = 234, Combining_IotaSubscript = 240 }; // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO int digitValue() const; QChar lower() const; QChar upper() const; Category category() const; Direction direction() const; Joining joining() const; bool mirrored() const; QChar mirroredChar() const; const QString &decomposition() const; // ### return just QString in 4.0 Decomposition decompositionTag() const; unsigned char combiningClass() const; char latin1() const { return ucs > 0xff ? 0 : (char) ucs; } ushort unicode() const { return ucs; } ushort &unicode() { return ucs; } #ifndef QT_NO_CAST_ASCII // like all ifdef'd code this is undocumented operator char() const { return latin1(); } #endif bool isNull() const { return unicode()==0; } bool isPrint() const; bool isPunct() const; bool isSpace() const; bool isMark() const; bool isLetter() const; bool isNumber() const; bool isLetterOrNumber() const; bool isDigit() const; bool isSymbol() const; uchar cell() const { return ((uchar) ucs & 0xff); } uchar row() const { return ((uchar) (ucs>>8)&0xff); } void setCell( uchar cell ) { ucs = (ucs & 0xff00) + cell; } void setRow( uchar row ) { ucs = (((ushort) row)<<8) + (ucs&0xff); } static bool networkOrdered() { int wordSize; bool bigEndian = FALSE; qSysInfo( &wordSize, &bigEndian ); return bigEndian; } friend inline bool operator==( char ch, QChar c ); friend inline bool operator==( QChar c, char ch ); friend inline bool operator==( QChar c1, QChar c2 ); friend inline bool operator!=( QChar c1, QChar c2 ); friend inline bool operator!=( char ch, QChar c ); friend inline bool operator!=( QChar c, char ch ); friend inline bool operator<=( QChar c, char ch ); friend inline bool operator<=( char ch, QChar c ); friend inline bool operator<=( QChar c1, QChar c2 ); private: ushort ucs; #if defined(QT_QSTRING_UCS_4) ushort grp; #endif } Q_PACKED; inline QChar::QChar() : ucs( 0 ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( char c ) : ucs( (uchar)c ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( uchar c ) : ucs( c ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( uchar c, uchar r ) : ucs( (r << 8) | c ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( const QChar& c ) : ucs( c.ucs ) #ifdef QT_QSTRING_UCS_4 , grp( c.grp ) #endif { } inline QChar::QChar( ushort rc ) : ucs( rc ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( short rc ) : ucs( (ushort) rc ) #ifdef QT_QSTRING_UCS_4 , grp( 0 ) #endif { } inline QChar::QChar( uint rc ) : ucs( (ushort ) (rc & 0xffff) ) #ifdef QT_QSTRING_UCS_4 , grp( (ushort) ((rc >> 16) & 0xffff) ) #endif { } inline QChar::QChar( int rc ) : ucs( (ushort) (rc & 0xffff) ) #ifdef QT_QSTRING_UCS_4 , grp( (ushort) ((rc >> 16) & 0xffff) ) #endif { } inline bool operator==( char ch, QChar c ) { return ((uchar) ch) == c.ucs; } inline bool operator==( QChar c, char ch ) { return ((uchar) ch) == c.ucs; } inline bool operator==( QChar c1, QChar c2 ) { return c1.ucs == c2.ucs; } inline bool operator!=( QChar c1, QChar c2 ) { return c1.ucs != c2.ucs; } inline bool operator!=( char ch, QChar c ) { return ((uchar)ch) != c.ucs; } inline bool operator!=( QChar c, char ch ) { return ((uchar) ch) != c.ucs; } inline bool operator<=( QChar c, char ch ) { return c.ucs <= ((uchar) ch); } inline bool operator<=( char ch, QChar c ) { return ((uchar) ch) <= c.ucs; } inline bool operator<=( QChar c1, QChar c2 ) { return c1.ucs <= c2.ucs; } inline bool operator>=( QChar c, char ch ) { return ch <= c; } inline bool operator>=( char ch, QChar c ) { return c <= ch; } inline bool operator>=( QChar c1, QChar c2 ) { return c2 <= c1; } inline bool operator<( QChar c, char ch ) { return !(ch<=c); } inline bool operator<( char ch, QChar c ) { return !(c<=ch); } inline bool operator<( QChar c1, QChar c2 ) { return !(c2<=c1); } inline bool operator>( QChar c, char ch ) { return !(ch>=c); } inline bool operator>( char ch, QChar c ) { return !(c>=ch); } inline bool operator>( QChar c1, QChar c2 ) { return !(c2>=c1); } // internal struct Q_EXPORT QStringData : public QShared { QStringData() : - QShared(), unicode(0), ascii(0), len(0), simpletext(1), maxl(0), dirty(0) { ref(); } + QShared(), unicode(0), ascii(0), len(0), issimpletext(TRUE), maxl(0), islatin1(FALSE) { ref(); } QStringData(QChar *u, uint l, uint m) : - QShared(), unicode(u), ascii(0), len(l), simpletext(1), maxl(m), dirty(1) { } + QShared(), unicode(u), ascii(0), len(l), issimpletext(FALSE), maxl(m), islatin1(FALSE) { } ~QStringData() { if ( unicode ) delete[] ((char*)unicode); if ( ascii ) delete[] ascii; } void deleteSelf(); QChar *unicode; char *ascii; void setDirty() { if ( ascii ) { delete [] ascii; ascii = 0; } - dirty = 1; + issimpletext = FALSE; } #ifdef Q_OS_MAC9 uint len; #else uint len : 30; #endif - uint simpletext : 1; + uint issimpletext : 1; #ifdef Q_OS_MAC9 uint maxl; #else uint maxl : 30; #endif - uint dirty : 1; + uint islatin1 : 1; private: #if defined(Q_DISABLE_COPY) QStringData( const QStringData& ); QStringData& operator=( const QStringData& ); #endif }; class Q_EXPORT QString { public: QString(); // make null string QString( QChar ); // one-char string QString( const QString & ); // impl-shared copy QString( const QByteArray& ); // deep copy QString( const QChar* unicode, uint length ); // deep copy #ifndef QT_NO_CAST_ASCII QString( const char *str ); // deep copy #endif +#ifndef QT_NO_STL + QString( const std::string& ); // deep copy +#endif ~QString(); QString &operator=( const QString & ); // impl-shared copy -#ifndef QT_NO_CAST_ASCII QString &operator=( const char * ); // deep copy +#ifndef QT_NO_STL + QString &operator=( const std::string& ); // deep copy #endif QString &operator=( const QCString& ); // deep copy QString &operator=( QChar c ); QString &operator=( char c ); QT_STATIC_CONST QString null; bool isNull() const; bool isEmpty() const; uint length() const; void truncate( uint pos ); QString & fill( QChar c, int len = -1 ); QString copy() const; QString arg( long a, int fieldwidth=0, int base=10 ) const; QString arg( ulong a, int fieldwidth=0, int base=10 ) const; QString arg( int a, int fieldwidth=0, int base=10 ) const; QString arg( uint a, int fieldwidth=0, int base=10 ) const; QString arg( short a, int fieldwidth=0, int base=10 ) const; QString arg( ushort a, int fieldwidth=0, int base=10 ) const; QString arg( char a, int fieldwidth=0 ) const; QString arg( QChar a, int fieldwidth=0 ) const; QString arg( const QString& a, int fieldwidth=0 ) const; QString arg( double a, int fieldwidth=0, char fmt='g', int prec=-1 ) const; #ifndef QT_NO_SPRINTF QString &sprintf( const char* format, ... ) #if defined(Q_CC_GNU) && !defined(__INSURE__) __attribute__ ((format (printf, 2, 3))) #endif ; #endif int find( QChar c, int index=0, bool cs=TRUE ) const; int find( char c, int index=0, bool cs=TRUE ) const; int find( const QString &str, int index=0, bool cs=TRUE ) const; #ifndef QT_NO_REGEXP int find( const QRegExp &, int index=0 ) const; #endif #ifndef QT_NO_CAST_ASCII int find( const char* str, int index=0 ) const; #endif int findRev( QChar c, int index=-1, bool cs=TRUE) const; int findRev( char c, int index=-1, bool cs=TRUE) const; int findRev( const QString &str, int index=-1, bool cs=TRUE) const; #ifndef QT_NO_REGEXP int findRev( const QRegExp &, int index=-1 ) const; #endif #ifndef QT_NO_CAST_ASCII int findRev( const char* str, int index=-1 ) const; #endif int contains( QChar c, bool cs=TRUE ) const; int contains( char c, bool cs=TRUE ) const { return contains(QChar(c), cs); } #ifndef QT_NO_CAST_ASCII int contains( const char* str, bool cs=TRUE ) const; #endif int contains( const QString &str, bool cs=TRUE ) const; #ifndef QT_NO_REGEXP int contains( const QRegExp & ) const; #endif enum SectionFlags { SectionDefault = 0x00, SectionSkipEmpty = 0x01, SectionIncludeLeadingSep = 0x02, SectionIncludeTrailingSep = 0x04, SectionCaseInsensitiveSeps = 0x08 }; QString section( QChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; QString section( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; #ifndef QT_NO_CAST_ASCII QString section( const char *in_sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; #endif QString section( const QString &in_sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const; #ifndef QT_NO_REGEXP QString section( const QRegExp ®, int start, int end = 0xffffffff, int flags = SectionDefault ) const; #endif QString left( uint len ) const; QString right( uint len ) const; QString mid( uint index, uint len=0xffffffff) const; QString leftJustify( uint width, QChar fill=' ', bool trunc=FALSE)const; QString rightJustify( uint width, QChar fill=' ',bool trunc=FALSE)const; QString lower() const; QString upper() const; QString stripWhiteSpace() const; QString simplifyWhiteSpace() const; QString &insert( uint index, const QString & ); QString &insert( uint index, const QChar*, uint len ); QString &insert( uint index, QChar ); QString &insert( uint index, char c ) { return insert(index,QChar(c)); } QString &append( char ); QString &append( QChar ); QString &append( const QString & ); #ifndef QT_NO_CAST_ASCII QString &append( const QByteArray & ); QString &append( const char * ); #endif +#ifndef QT_NO_STL + QString &append( const std::string& ); +#endif QString &prepend( char ); QString &prepend( QChar ); QString &prepend( const QString & ); #ifndef QT_NO_CAST_ASCII QString &prepend( const QByteArray & ); QString &prepend( const char * ); #endif +#ifndef QT_NO_STL + QString &prepend( const std::string& ); +#endif QString &remove( uint index, uint len ); QString &remove( QChar c ); QString &remove( char c ) { return remove( QChar(c) ); } QString &remove( const QString & ); #ifndef QT_NO_REGEXP QString &remove( const QRegExp & ); #endif #ifndef QT_NO_CAST_ASCII QString &remove( const char * ); #endif QString &replace( uint index, uint len, const QString & ); QString &replace( uint index, uint len, const QChar*, uint clen ); QString &replace( uint index, uint len, QChar ); QString &replace( uint index, uint len, char c ) { return replace( index, len, QChar(c) ); } QString &replace( QChar c, const QString & ); QString &replace( char c, const QString & after ) { return replace( QChar(c), after ); } QString &replace( const QString &, const QString & ); #ifndef QT_NO_REGEXP_CAPTURE QString &replace( const QRegExp &, const QString & ); #endif QString &replace( QChar, QChar ); short toShort( bool *ok=0, int base=10 ) const; ushort toUShort( bool *ok=0, int base=10 ) const; int toInt( bool *ok=0, int base=10 ) const; uint toUInt( bool *ok=0, int base=10 ) const; long toLong( bool *ok=0, int base=10 ) const; ulong toULong( bool *ok=0, int base=10 ) const; float toFloat( bool *ok=0 ) const; double toDouble( bool *ok=0 ) const; QString &setNum( short, int base=10 ); QString &setNum( ushort, int base=10 ); QString &setNum( int, int base=10 ); QString &setNum( uint, int base=10 ); QString &setNum( long, int base=10 ); QString &setNum( ulong, int base=10 ); QString &setNum( float, char f='g', int prec=6 ); QString &setNum( double, char f='g', int prec=6 ); static QString number( long, int base=10 ); static QString number( ulong, int base=10); static QString number( int, int base=10 ); static QString number( uint, int base=10); static QString number( double, char f='g', int prec=6 ); void setExpand( uint index, QChar c ); QString &operator+=( const QString &str ); #ifndef QT_NO_CAST_ASCII QString &operator+=( const QByteArray &str ); QString &operator+=( const char *str ); #endif +#ifndef QT_NO_STL + QString &operator+=( const std::string& ); +#endif QString &operator+=( QChar c ); QString &operator+=( char c ); QChar at( uint i ) const { return i < d->len ? d->unicode[i] : QChar::null; } QChar operator[]( int i ) const { return at((uint)i); } QCharRef at( uint i ); QCharRef operator[]( int i ); QChar constref(uint i) const { return at(i); } QChar& ref(uint i) { // Optimized for easy-inlining by simple compilers. if ( d->count != 1 || i >= d->len ) subat( i ); d->setDirty(); return d->unicode[i]; } const QChar* unicode() const { return d->unicode; } - const char* ascii() const { return latin1(); } + const char* ascii() const; + static QString fromAscii(const char*, int len=-1); const char* latin1() const; static QString fromLatin1(const char*, int len=-1); QCString utf8() const; static QString fromUtf8(const char*, int len=-1); QCString local8Bit() const; static QString fromLocal8Bit(const char*, int len=-1); bool operator!() const; #ifndef QT_NO_ASCII_CAST - operator const char *() const { return latin1(); } + operator const char *() const { return ascii(); } +#endif +#ifndef QT_NO_STL + operator std::string() const { return ascii() ? ascii() : ""; } #endif + static QString fromUcs2( const unsigned short *ucs2 ); const unsigned short *ucs2() const; QString &setUnicode( const QChar* unicode, uint len ); QString &setUnicodeCodes( const ushort* unicode_as_ushorts, uint len ); + QString &setAscii( const char*, int len=-1 ); QString &setLatin1( const char*, int len=-1 ); int compare( const QString& s ) const; static int compare( const QString& s1, const QString& s2 ) { return s1.compare( s2 ); } int localeAwareCompare( const QString& s ) const; static int localeAwareCompare( const QString& s1, const QString& s2 ) { return s1.localeAwareCompare( s2 ); } #ifndef QT_NO_DATASTREAM friend Q_EXPORT QDataStream &operator>>( QDataStream &, QString & ); #endif void compose(); #ifndef QT_NO_COMPAT - const char* data() const { return latin1(); } + const char* data() const { return ascii(); } #endif bool startsWith( const QString& ) const; bool endsWith( const QString& ) const; void setLength( uint newLength ); - bool simpleText() const { if ( d->dirty ) checkSimpleText(); return (bool)d->simpletext; } + bool simpleText() const { if ( !d->issimpletext ) checkSimpleText(); return (bool)d->issimpletext; } bool isRightToLeft() const; private: QString( int size, bool /* dummy */ ); // allocate size incl. \0 void deref(); void real_detach(); void subat( uint ); bool findArg(int& pos, int& len) const; void checkSimpleText() const; - static QChar* asciiToUnicode( const char*, uint * len, uint maxlen=(uint)-1 ); - static QChar* asciiToUnicode( const QByteArray&, uint * len ); - static char* unicodeToAscii( const QChar*, uint len ); + static QChar* latin1ToUnicode( const char*, uint * len, uint maxlen=(uint)-1 ); + static QChar* latin1ToUnicode( const QByteArray&, uint * len ); + static char* unicodeToLatin1( const QChar*, uint len ); QStringData *d; static QStringData* shared_null; static QStringData* makeSharedNull(); friend class QConstString; friend class QTextStream; QString( QStringData* dd, bool /* dummy */ ) : d(dd) { } // needed for QDeepCopy void detach(); friend class QDeepCopy<QString>; }; class Q_EXPORT QCharRef { friend class QString; QString& s; uint p; QCharRef(QString* str, uint pos) : s(*str), p(pos) { } public: // most QChar operations repeated here... // all this is not documented: We just say "like QChar" and let it be. #ifndef Q_QDOC ushort unicode() const { return s.constref(p).unicode(); } char latin1() const { return s.constref(p).latin1(); } // An operator= for each QChar cast constructor... QCharRef operator=(char c ) { s.ref(p)=c; return *this; } QCharRef operator=(uchar c ) { s.ref(p)=c; return *this; } QCharRef operator=(QChar c ) { s.ref(p)=c; return *this; } QCharRef operator=(const QCharRef& c ) { s.ref(p)=c.unicode(); return *this; } QCharRef operator=(ushort rc ) { s.ref(p)=rc; return *this; } QCharRef operator=(short rc ) { s.ref(p)=rc; return *this; } QCharRef operator=(uint rc ) { s.ref(p)=rc; return *this; } QCharRef operator=(int rc ) { s.ref(p)=rc; return *this; } operator QChar () const { return s.constref(p); } // each function... bool isNull() const { return unicode()==0; } bool isPrint() const { return s.constref(p).isPrint(); } bool isPunct() const { return s.constref(p).isPunct(); } bool isSpace() const { return s.constref(p).isSpace(); } bool isMark() const { return s.constref(p).isMark(); } bool isLetter() const { return s.constref(p).isLetter(); } bool isNumber() const { return s.constref(p).isNumber(); } bool isLetterOrNumber() { return s.constref(p).isLetterOrNumber(); } bool isDigit() const { return s.constref(p).isDigit(); } int digitValue() const { return s.constref(p).digitValue(); } QChar lower() const { return s.constref(p).lower(); } QChar upper() const { return s.constref(p).upper(); } QChar::Category category() const { return s.constref(p).category(); } QChar::Direction direction() const { return s.constref(p).direction(); } QChar::Joining joining() const { return s.constref(p).joining(); } bool mirrored() const { return s.constref(p).mirrored(); } QChar mirroredChar() const { return s.constref(p).mirroredChar(); } const QString &decomposition() const { return s.constref(p).decomposition(); } QChar::Decomposition decompositionTag() const { return s.constref(p).decompositionTag(); } unsigned char combiningClass() const { return s.constref(p).combiningClass(); } // Not the non-const ones of these. uchar cell() const { return s.constref(p).cell(); } uchar row() const { return s.constref(p).row(); } #endif }; inline QCharRef QString::at( uint i ) { return QCharRef(this,i); } inline QCharRef QString::operator[]( int i ) { return at((uint)i); } class Q_EXPORT QConstString : private QString { public: QConstString( const QChar* unicode, uint length ); ~QConstString(); const QString& string() const { return *this; } }; /***************************************************************************** QString stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM Q_EXPORT QDataStream &operator<<( QDataStream &, const QString & ); Q_EXPORT QDataStream &operator>>( QDataStream &, QString & ); #endif /***************************************************************************** QString inline functions *****************************************************************************/ // These two move code into makeSharedNull() and deletesData() // to improve cache-coherence (and reduce code bloat), while // keeping the common cases fast. // // No safe way to pre-init shared_null on ALL compilers/linkers. inline QString::QString() : d(shared_null ? shared_null : makeSharedNull()) { d->ref(); } // inline QString::~QString() { if ( d->deref() ) { if ( d != shared_null ) d->deleteSelf(); } } // needed for QDeepCopy inline void QString::detach() { real_detach(); } inline QString QString::section( QChar sep, int start, int end, int flags ) const { return section(QString(sep), start, end, flags); } inline QString QString::section( char sep, int start, int end, int flags ) const { return section(QChar(sep), start, end, flags); } #ifndef QT_NO_CAST_ASCII inline QString QString::section( const char *in_sep, int start, int end, int flags ) const { return section(QString(in_sep), start, end, flags); } #endif inline QString &QString::operator=( QChar c ) { *this = QString(c); return *this; } inline QString &QString::operator=( char c ) { *this = QString(QChar(c)); return *this; } inline bool QString::isNull() const { return unicode() == 0; } inline bool QString::operator!() const { return isNull(); } inline uint QString::length() const { return d->len; } inline bool QString::isEmpty() const { return length() == 0; } inline QString QString::copy() const { return QString( *this ); } inline QString &QString::prepend( const QString & s ) { return insert(0,s); } inline QString &QString::prepend( QChar c ) { return insert(0,c); } inline QString &QString::prepend( char c ) { return insert(0,c); } #ifndef QT_NO_CAST_ASCII inline QString &QString::prepend( const QByteArray & s ) -{ return insert(0,s.data()); } +{ return insert(0,QString(s)); } +#endif + +#ifndef QT_NO_STL +inline QString &QString::prepend( const std::string& s ) +{ return insert(0, s); } +#endif + +#ifndef QT_NO_CAST_ASCII +inline QString &QString::operator+=( const QByteArray &s ) +{ return operator+=(QString(s)); } #endif inline QString &QString::append( const QString & s ) { return operator+=(s); } #ifndef QT_NO_CAST_ASCII inline QString &QString::append( const QByteArray &s ) -{ return operator+=(s.data()); } +{ return operator+=(s); } inline QString &QString::append( const char * s ) { return operator+=(s); } #endif inline QString &QString::append( QChar c ) { return operator+=(c); } inline QString &QString::append( char c ) { return operator+=(c); } -#ifndef QT_NO_CAST_ASCII -inline QString &QString::operator+=( const QByteArray &s ) -{ return operator+=(s.data()); } +#ifndef QT_NO_STL +inline QString &QString::operator+=( const std::string& s ) +{ return operator+=(s.c_str()); } +inline QString &QString::append( const std::string& s ) +{ return operator+=(s); } #endif inline QString &QString::setNum( short n, int base ) { return setNum((long)n, base); } inline QString &QString::setNum( ushort n, int base ) { return setNum((ulong)n, base); } inline QString &QString::setNum( int n, int base ) { return setNum((long)n, base); } inline QString &QString::setNum( uint n, int base ) { return setNum((ulong)n, base); } inline QString &QString::setNum( float n, char f, int prec ) { return setNum((double)n,f,prec); } inline QString QString::arg(int a, int fieldwidth, int base) const { return arg((long)a, fieldwidth, base); } inline QString QString::arg(uint a, int fieldwidth, int base) const { return arg((ulong)a, fieldwidth, base); } inline QString QString::arg(short a, int fieldwidth, int base) const { return arg((long)a, fieldwidth, base); } inline QString QString::arg(ushort a, int fieldwidth, int base) const { return arg((ulong)a, fieldwidth, base); } inline int QString::find( char c, int index, bool cs ) const { return find(QChar(c), index, cs); } inline int QString::findRev( char c, int index, bool cs) const { return findRev( QChar(c), index, cs ); } #ifndef QT_NO_CAST_ASCII inline int QString::find( const char* str, int index ) const -{ return find(QString::fromLatin1(str), index); } +{ return find(QString::fromAscii(str), index); } inline int QString::findRev( const char* str, int index ) const -{ return findRev(QString::fromLatin1(str), index); } +{ return findRev(QString::fromAscii(str), index); } #endif /***************************************************************************** QString non-member operators *****************************************************************************/ Q_EXPORT bool operator!=( const QString &s1, const QString &s2 ); Q_EXPORT bool operator<( const QString &s1, const QString &s2 ); Q_EXPORT bool operator<=( const QString &s1, const QString &s2 ); Q_EXPORT bool operator==( const QString &s1, const QString &s2 ); Q_EXPORT bool operator>( const QString &s1, const QString &s2 ); Q_EXPORT bool operator>=( const QString &s1, const QString &s2 ); #ifndef QT_NO_CAST_ASCII Q_EXPORT bool operator!=( const QString &s1, const char *s2 ); Q_EXPORT bool operator<( const QString &s1, const char *s2 ); Q_EXPORT bool operator<=( const QString &s1, const char *s2 ); Q_EXPORT bool operator==( const QString &s1, const char *s2 ); Q_EXPORT bool operator>( const QString &s1, const char *s2 ); Q_EXPORT bool operator>=( const QString &s1, const char *s2 ); Q_EXPORT bool operator!=( const char *s1, const QString &s2 ); Q_EXPORT bool operator<( const char *s1, const QString &s2 ); Q_EXPORT bool operator<=( const char *s1, const QString &s2 ); Q_EXPORT bool operator==( const char *s1, const QString &s2 ); //Q_EXPORT bool operator>( const char *s1, const QString &s2 ); // MSVC++ Q_EXPORT bool operator>=( const char *s1, const QString &s2 ); #endif Q_EXPORT inline const QString operator+( const QString &s1, const QString &s2 ) { QString tmp( s1 ); tmp += s2; return tmp; } #ifndef QT_NO_CAST_ASCII Q_EXPORT inline const QString operator+( const QString &s1, const char *s2 ) { QString tmp( s1 ); - tmp += QString::fromLatin1(s2); + tmp += QString::fromAscii(s2); return tmp; } Q_EXPORT inline const QString operator+( const char *s1, const QString &s2 ) { - QString tmp = QString::fromLatin1( s1 ); + QString tmp = QString::fromAscii( s1 ); tmp += s2; return tmp; } #endif Q_EXPORT inline const QString operator+( const QString &s1, QChar c2 ) { QString tmp( s1 ); tmp += c2; return tmp; } Q_EXPORT inline const QString operator+( const QString &s1, char c2 ) { QString tmp( s1 ); tmp += c2; return tmp; } Q_EXPORT inline const QString operator+( QChar c1, const QString &s2 ) { QString tmp; tmp += c1; tmp += s2; return tmp; } Q_EXPORT inline const QString operator+( char c1, const QString &s2 ) { QString tmp; tmp += c1; tmp += s2; return tmp; } #if defined(Q_OS_WIN32) extern Q_EXPORT QString qt_winQString(void*); extern Q_EXPORT const void* qt_winTchar(const QString& str, bool addnul); extern Q_EXPORT void* qt_winTchar_new(const QString& str); extern Q_EXPORT QCString qt_winQString2MB( const QString& s, int len=-1 ); extern Q_EXPORT QString qt_winMB2QString( const char* mb, int len=-1 ); #endif +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QSTRING +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QSTRING_H diff --git a/qmake/include/qstrlist.h b/qmake/include/qstrlist.h index 86de328..b9dd753 100644 --- a/qmake/include/qstrlist.h +++ b/qmake/include/qstrlist.h @@ -1,112 +1,114 @@ /**************************************************************************** ** $Id$ ** ** Definition of QStrList, QStrIList and QStrListIterator classes ** ** Created : 920730 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QSTRLIST_H #define QSTRLIST_H #ifndef QT_H #include "qstring.h" #include "qptrlist.h" #include "qdatastream.h" #endif // QT_H +#ifndef QT_QWINEXPORT #if defined(Q_TEMPLATEDLL) Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<char>; Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrListIterator<char>; #endif +#endif /* QT_QWINEXPORT */ #if defined(Q_QDOC) class QStrListIterator : public QPtrListIterator<char> { }; #else typedef QPtrListIterator<char> QStrListIterator; #endif class Q_EXPORT QStrList : public QPtrList<char> { public: QStrList( bool deepCopies=TRUE ) { dc = deepCopies; del_item = deepCopies; } QStrList( const QStrList & ); ~QStrList() { clear(); } QStrList& operator=( const QStrList & ); private: QPtrCollection::Item newItem( QPtrCollection::Item d ) { return dc ? qstrdup( (const char*)d ) : d; } void deleteItem( QPtrCollection::Item d ) { if ( del_item ) delete[] (char*)d; } int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 ) { return qstrcmp((const char*)s1, (const char*)s2); } #ifndef QT_NO_DATASTREAM QDataStream &read( QDataStream &s, QPtrCollection::Item &d ) { s >> (char *&)d; return s; } QDataStream &write( QDataStream &s, QPtrCollection::Item d ) const { return s << (const char *)d; } #endif bool dc; }; class Q_EXPORT QStrIList : public QStrList // case insensitive string list { public: QStrIList( bool deepCopies=TRUE ) : QStrList( deepCopies ) {} ~QStrIList() { clear(); } private: int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 ) { return qstricmp((const char*)s1, (const char*)s2); } }; inline QStrList & QStrList::operator=( const QStrList &strList ) { clear(); dc = strList.dc; del_item = dc; QPtrList<char>::operator=( strList ); return *this; } inline QStrList::QStrList( const QStrList &strList ) : QPtrList<char>( strList ) { dc = FALSE; operator=( strList ); } #endif // QSTRLIST_H diff --git a/qmake/include/qtextcodec.h b/qmake/include/qtextcodec.h index 149b5cb..995e434 100644 --- a/qmake/include/qtextcodec.h +++ b/qmake/include/qtextcodec.h @@ -1,114 +1,128 @@ /**************************************************************************** ** $Id$ ** ** Definition of QTextCodec class ** ** Created : 981015 ** ** Copyright (C) 1998-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QTEXTCODEC_H #define QTEXTCODEC_H #ifndef QT_H #include "qstring.h" #endif // QT_H #ifndef QT_NO_TEXTCODEC class QTextCodec; class QIODevice; class QFont; class Q_EXPORT QTextEncoder { public: virtual ~QTextEncoder(); virtual QCString fromUnicode(const QString& uc, int& lenInOut) = 0; }; class Q_EXPORT QTextDecoder { public: virtual ~QTextDecoder(); virtual QString toUnicode(const char* chars, int len) = 0; }; class Q_EXPORT QTextCodec { public: virtual ~QTextCodec(); #ifndef QT_NO_CODECS static QTextCodec* loadCharmap(QIODevice*); static QTextCodec* loadCharmapFile(QString filename); #endif //QT_NO_CODECS static QTextCodec* codecForMib(int mib); static QTextCodec* codecForName(const char* hint, int accuracy=0); static QTextCodec* codecForContent(const char* chars, int len); static QTextCodec* codecForIndex(int i); static QTextCodec* codecForLocale(); static void setCodecForLocale(QTextCodec *c); + static QTextCodec* codecForTr(); + static void setCodecForTr(QTextCodec *c); + static QTextCodec* codecForCStrings(); + static void setCodecForCStrings(QTextCodec *c); + static void deleteAllCodecs(); static const char* locale(); virtual const char* name() const = 0; virtual const char* mimeName() const; virtual int mibEnum() const = 0; virtual QTextDecoder* makeDecoder() const; virtual QTextEncoder* makeEncoder() const; virtual QString toUnicode(const char* chars, int len) const; virtual QCString fromUnicode(const QString& uc, int& lenInOut) const; QCString fromUnicode(const QString& uc) const; QString toUnicode(const QByteArray&, int len) const; QString toUnicode(const QByteArray&) const; QString toUnicode(const QCString&, int len) const; QString toUnicode(const QCString&) const; QString toUnicode(const char* chars) const; virtual bool canEncode( QChar ) const; virtual bool canEncode( const QString& ) const; virtual int heuristicContentMatch(const char* chars, int len) const = 0; virtual int heuristicNameMatch(const char* hint) const; virtual QByteArray fromUnicode(const QString& uc, int from, int len) const; virtual unsigned short characterFromUnicode(const QString &str, int pos) const; protected: QTextCodec(); static int simpleHeuristicNameMatch(const char* name, const char* hint); +private: + static QTextCodec *cftr; + static QTextCodec *cfcs; friend class QFont; }; + +inline QTextCodec* QTextCodec::codecForTr() { return cftr; } +inline void QTextCodec::setCodecForTr(QTextCodec *c) { cftr = c; } +inline QTextCodec* QTextCodec::codecForCStrings() { return cfcs; } +inline void QTextCodec::setCodecForCStrings(QTextCodec *c) { cfcs = c; } + #endif // QT_NO_TEXTCODEC #endif // QTEXTCODEC_H diff --git a/qmake/include/qtl.h b/qmake/include/qtl.h index 346cecc..25631fd 100644 --- a/qmake/include/qtl.h +++ b/qmake/include/qtl.h @@ -1,321 +1,322 @@ /**************************************************************************** ** $Id$ ** ** Definition of Qt template library classes ** ** Created : 990128 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QTL_H #define QTL_H #ifndef QT_H #include "qglobal.h" #include "qtextstream.h" #include "qstring.h" #endif // QT_H #ifndef QT_NO_TEXTSTREAM template <class T> class QTextOStreamIterator { protected: QTextOStream& stream; QString separator; public: QTextOStreamIterator( QTextOStream& s) : stream( s ) {} QTextOStreamIterator( QTextOStream& s, const QString& sep ) : stream( s ), separator( sep ) {} QTextOStreamIterator<T>& operator= ( const T& x ) { stream << x; if ( !separator.isEmpty() ) stream << separator; return *this; } QTextOStreamIterator<T>& operator*() { return *this; } QTextOStreamIterator<T>& operator++() { return *this; } QTextOStreamIterator<T>& operator++(int) { return *this; } }; #endif //QT_NO_TEXTSTREAM template <class InputIterator, class OutputIterator> inline OutputIterator qCopy( InputIterator _begin, InputIterator _end, OutputIterator _dest ) { while( _begin != _end ) *_dest++ = *_begin++; return _dest; } template <class BiIterator, class BiOutputIterator> inline BiOutputIterator qCopyBackward( BiIterator _begin, BiIterator _end, BiOutputIterator _dest ) { while ( _begin != _end ) *--_dest = *--_end; return _dest; } template <class InputIterator1, class InputIterator2> inline bool qEqual( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 ) { + // ### compare using !(*first1 == *first2) in Qt 4.0 for ( ; first1 != last1; ++first1, ++first2 ) if ( *first1 != *first2 ) return FALSE; return TRUE; } template <class ForwardIterator, class T> inline void qFill( ForwardIterator first, ForwardIterator last, const T& val ) { for ( ; first != last; ++first ) *first = val; } #if 0 template <class BiIterator, class OutputIterator> inline OutputIterator qReverseCopy( BiIterator _begin, BiIterator _end, OutputIterator _dest ) { while ( _begin != _end ) { --_end; *_dest = *_end; ++_dest; } return _dest; } #endif template <class InputIterator, class T> inline InputIterator qFind( InputIterator first, InputIterator last, const T& val ) { while ( first != last && *first != val ) ++first; return first; } template <class InputIterator, class T, class Size> inline void qCount( InputIterator first, InputIterator last, const T& value, Size& n ) { for ( ; first != last; ++first ) if ( *first == value ) ++n; } template <class T> inline void qSwap( T& _value1, T& _value2 ) { T tmp = _value1; _value1 = _value2; _value2 = tmp; } template <class InputIterator> Q_INLINE_TEMPLATES void qBubbleSort( InputIterator b, InputIterator e ) { // Goto last element; InputIterator last = e; --last; // only one element or no elements ? if ( last == b ) return; // So we have at least two elements in here while( b != last ) { bool swapped = FALSE; InputIterator swap_pos = b; InputIterator x = e; InputIterator y = x; y--; do { --x; --y; if ( *x < *y ) { swapped = TRUE; qSwap( *x, *y ); swap_pos = y; } } while( y != b ); if ( !swapped ) return; b = swap_pos; b++; } } template <class Container> inline void qBubbleSort( Container &c ) { qBubbleSort( c.begin(), c.end() ); } template <class Value> Q_INLINE_TEMPLATES void qHeapSortPushDown( Value* heap, int first, int last ) { int r = first; while ( r <= last / 2 ) { if ( last == 2 * r ) { // node r has only one child if ( heap[2 * r] < heap[r] ) qSwap( heap[r], heap[2 * r] ); r = last; } else { // node r has two children if ( heap[2 * r] < heap[r] && !(heap[2 * r + 1] < heap[2 * r]) ) { // swap with left child qSwap( heap[r], heap[2 * r] ); r *= 2; } else if ( heap[2 * r + 1] < heap[r] && heap[2 * r + 1] < heap[2 * r] ) { // swap with right child qSwap( heap[r], heap[2 * r + 1] ); r = 2 * r + 1; } else { r = last; } } } } template <class InputIterator, class Value> Q_INLINE_TEMPLATES void qHeapSortHelper( InputIterator b, InputIterator e, Value, uint n ) { // Create the heap InputIterator insert = b; Value* realheap = new Value[n]; // Wow, what a fake. But I want the heap to be indexed as 1...n Value* heap = realheap - 1; int size = 0; for( ; insert != e; ++insert ) { heap[++size] = *insert; int i = size; while( i > 1 && heap[i] < heap[i / 2] ) { qSwap( heap[i], heap[i / 2] ); i /= 2; } } // Now do the sorting for( uint i = n; i > 0; i-- ) { *b++ = heap[1]; if ( i > 1 ) { heap[1] = heap[i]; qHeapSortPushDown( heap, 1, (int)i - 1 ); } } delete[] realheap; } template <class InputIterator> Q_INLINE_TEMPLATES void qHeapSort( InputIterator b, InputIterator e ) { // Empty ? if ( b == e ) return; // How many entries have to be sorted ? InputIterator it = b; uint n = 0; while ( it != e ) { ++n; ++it; } // The second last parameter is a hack to retrieve the value type // Do the real sorting here qHeapSortHelper( b, e, *b, n ); } template <class Container> Q_INLINE_TEMPLATES void qHeapSort( Container &c ) { if ( c.begin() == c.end() ) return; // The second last parameter is a hack to retrieve the value type // Do the real sorting here qHeapSortHelper( c.begin(), c.end(), *(c.begin()), (uint)c.count() ); } template <class Container> class QBackInsertIterator { public: Q_EXPLICIT QBackInsertIterator( Container &c ) : container( &c ) { } QBackInsertIterator<Container>& operator=( const Q_TYPENAME Container::value_type &value ) { container->push_back( value ); return *this; } QBackInsertIterator<Container>& operator*() { return *this; } QBackInsertIterator<Container>& operator++() { return *this; } QBackInsertIterator<Container>& operator++(int) { return *this; } protected: Container *container; }; template <class Container> inline QBackInsertIterator<Container> qBackInserter( Container &c ) { return QBackInsertIterator<Container>( c ); } #endif diff --git a/qmake/include/quuid.h b/qmake/include/quuid.h index 591d2f1..664c149 100644 --- a/qmake/include/quuid.h +++ b/qmake/include/quuid.h @@ -1,168 +1,168 @@ /**************************************************************************** ** $Id$ ** ** Definition of QUuid class ** ** Created: 010523 ** -** Copyright (C) 1992-2001 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QUUID_H #define QUUID_H #ifndef QT_H #include <qstring.h> #endif // QT_H #include <string.h> #if defined(Q_OS_WIN32) #ifndef GUID_DEFINED #define GUID_DEFINED typedef struct _GUID { ulong Data1; ushort Data2; ushort Data3; uchar Data4[ 8 ]; -} GUID; +} GUID, *REFGUID, *LPGUID; #endif #endif struct Q_EXPORT QUuid { QUuid() { memset( this, 0, sizeof(QUuid) ); } QUuid( uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8 ) { data1 = l; data2 = w1; data3 = w2; data4[0] = b1; data4[1] = b2; data4[2] = b3; data4[3] = b4; data4[4] = b5; data4[5] = b6; data4[6] = b7; data4[7] = b8; } QUuid( const QUuid &uuid ) { memcpy( this, &uuid, sizeof(QUuid) ); } #ifndef QT_NO_QUUID_STRING QUuid( const QString & ); QUuid( const char * ); QString toString() const; operator QString() const { return toString(); } #endif bool isNull() const; QUuid &operator=(const QUuid &orig ) { memcpy( this, &orig, sizeof(QUuid) ); return *this; } bool operator==(const QUuid &orig ) const { uint i; if ( data1 != orig.data1 || data2 != orig.data2 || data3 != orig.data3 ) return FALSE; for( i = 0; i < 8; i++ ) if ( data4[i] != orig.data4[i] ) return FALSE; return TRUE; } bool operator!=(const QUuid &orig ) const { return !( *this == orig ); } #if defined(Q_OS_WIN32) // On Windows we have a type GUID that is used by the platform API, so we // provide convenience operators to cast from and to this type. QUuid( const GUID &guid ) { memcpy( this, &guid, sizeof(GUID) ); } QUuid &operator=(const GUID &orig ) { memcpy( this, &orig, sizeof(QUuid) ); return *this; } operator GUID() const { GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } }; return guid; } bool operator==( const GUID &guid ) const { uint i; if ( data1 != guid.Data1 || data2 != guid.Data2 || data3 != guid.Data3 ) return FALSE; for( i = 0; i < 8; i++ ) if ( data4[i] != guid.Data4[i] ) return FALSE; return TRUE; } bool operator!=( const GUID &guid ) const { return !( *this == guid ); } #endif uint data1; ushort data2; ushort data3; uchar data4[ 8 ]; }; #ifndef QT_NO_DATASTREAM Q_EXPORT QDataStream &operator<<( QDataStream &, const QUuid & ); Q_EXPORT QDataStream &operator>>( QDataStream &, QUuid & ); #endif #endif //QUUID_H diff --git a/qmake/include/qvaluelist.h b/qmake/include/qvaluelist.h index 54f7aec..f5cd7bb 100644 --- a/qmake/include/qvaluelist.h +++ b/qmake/include/qvaluelist.h @@ -281,385 +281,389 @@ Q_INLINE_TEMPLATES QValueListPrivate<T>::~QValueListPrivate() { p = x; } delete node; } template <class T> Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::insert( Q_TYPENAME QValueListPrivate<T>::Iterator it, const T& x ) { NodePtr p = new Node( x ); p->next = it.node; p->prev = it.node->prev; it.node->prev->next = p; it.node->prev = p; nodes++; return p; } template <class T> Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::Iterator QValueListPrivate<T>::remove( Q_TYPENAME QValueListPrivate<T>::Iterator it ) { Q_ASSERT ( it.node != node ); NodePtr next = it.node->next; NodePtr prev = it.node->prev; prev->next = next; next->prev = prev; delete it.node; nodes--; return Iterator( next ); } template <class T> Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::find( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const { ConstIterator first( start ); ConstIterator last( node ); while( first != last) { if ( *first == x ) return first.node; ++first; } return last.node; } template <class T> Q_INLINE_TEMPLATES int QValueListPrivate<T>::findIndex( Q_TYPENAME QValueListPrivate<T>::NodePtr start, const T& x ) const { ConstIterator first( start ); ConstIterator last( node ); int pos = 0; while( first != last) { if ( *first == x ) return pos; ++first; ++pos; } return -1; } template <class T> Q_INLINE_TEMPLATES uint QValueListPrivate<T>::contains( const T& x ) const { uint result = 0; Iterator first = Iterator( node->next ); Iterator last = Iterator( node ); while( first != last) { if ( *first == x ) ++result; ++first; } return result; } template <class T> Q_INLINE_TEMPLATES uint QValueListPrivate<T>::remove( const T& x ) { uint result = 0; Iterator first = Iterator( node->next ); Iterator last = Iterator( node ); while( first != last) { if ( *first == x ) { first = remove( first ); ++result; } else ++first; } return result; } template <class T> Q_INLINE_TEMPLATES Q_TYPENAME QValueListPrivate<T>::NodePtr QValueListPrivate<T>::at( size_type i ) const { Q_ASSERT( i <= nodes ); NodePtr p = node->next; for( size_type x = 0; x < i; ++x ) p = p->next; return p; } template <class T> Q_INLINE_TEMPLATES void QValueListPrivate<T>::clear() { nodes = 0; NodePtr p = node->next; while( p != node ) { NodePtr next = p->next; delete p; p = next; } node->next = node->prev = node; } #ifdef QT_CHECK_RANGE # if !defined( QT_NO_DEBUG ) && defined( QT_CHECK_VALUELIST_RANGE ) # define QT_CHECK_INVALID_LIST_ELEMENT if ( empty() ) qWarning( "QValueList: Warning invalid element" ) # define QT_CHECK_INVALID_LIST_ELEMENT_FATAL Q_ASSERT( !empty() ); # else # define QT_CHECK_INVALID_LIST_ELEMENT # define QT_CHECK_INVALID_LIST_ELEMENT_FATAL # endif #else # define QT_CHECK_INVALID_LIST_ELEMENT # define QT_CHECK_INVALID_LIST_ELEMENT_FATAL #endif template <class T> class QDeepCopy; template <class T> class QValueList { public: /** * Typedefs */ typedef QValueListIterator<T> iterator; typedef QValueListConstIterator<T> const_iterator; typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef size_t size_type; #ifndef QT_NO_STL typedef ptrdiff_t difference_type; #else typedef int difference_type; #endif /** * API */ QValueList() { sh = new QValueListPrivate<T>; } QValueList( const QValueList<T>& l ) { sh = l.sh; sh->ref(); } #ifndef QT_NO_STL # ifdef Q_CC_HPACC // HP-UX aCC does require typename in some place # undef Q_TYPENAME // but not accept them at others. # define Q_TYPENAME // also doesn't like re-defines ... # endif QValueList( const Q_TYPENAME std::list<T>& l ) { sh = new QValueListPrivate<T>; qCopy( l.begin(), l.end(), std::back_inserter( *this ) ); } #endif ~QValueList() { sh->derefAndDelete(); } QValueList<T>& operator= ( const QValueList<T>& l ) { l.sh->ref(); sh->derefAndDelete(); sh = l.sh; return *this; } #ifndef QT_NO_STL QValueList<T>& operator= ( const Q_TYPENAME std::list<T>& l ) { detach(); qCopy( l.begin(), l.end(), std::back_inserter( *this ) ); return *this; } bool operator== ( const Q_TYPENAME std::list<T>& l ) const { if ( size() != l.size() ) return FALSE; const_iterator it2 = begin(); #if !defined(Q_CC_MIPS) typename #endif std::list<T>::const_iterator it = l.begin(); for ( ; it2 != end(); ++it2, ++it ) if ( !((*it2) == (*it)) ) return FALSE; return TRUE; } # ifdef Q_CC_HPACC // undo the HP-UX aCC hackery done above # undef Q_TYPENAME # define Q_TYPENAME typename # endif #endif bool operator== ( const QValueList<T>& l ) const; bool operator!= ( const QValueList<T>& l ) const { return !( *this == l ); } iterator begin() { detach(); return iterator( sh->node->next ); } const_iterator begin() const { return const_iterator( sh->node->next ); } iterator end() { detach(); return iterator( sh->node ); } const_iterator end() const { return const_iterator( sh->node ); } iterator insert( iterator it, const T& x ) { detach(); return sh->insert( it, x ); } uint remove( const T& x ) { detach(); return sh->remove( x ); } void clear(); QValueList<T>& operator<< ( const T& x ) { append( x ); return *this; } size_type size() const { return sh->nodes; } bool empty() const { return sh->nodes == 0; } void push_front( const T& x ) { detach(); sh->insert( begin(), x ); } void push_back( const T& x ) { detach(); sh->insert( end(), x ); } iterator erase( iterator pos ) { detach(); return sh->remove( pos ); } iterator erase( iterator first, iterator last ); reference front() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); } const_reference front() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *begin(); } reference back() { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); } const_reference back() const { QT_CHECK_INVALID_LIST_ELEMENT_FATAL; return *(--end()); } void pop_front() { QT_CHECK_INVALID_LIST_ELEMENT; erase( begin() ); } void pop_back() { QT_CHECK_INVALID_LIST_ELEMENT; iterator tmp = end(); erase( --tmp ); } void insert( iterator pos, size_type n, const T& x ); // Some compilers (incl. vc++) would instantiate this function even if // it is not used; this would constrain QValueList to classes that provide // an operator< /* void sort() { qHeapSort( *this ); } */ QValueList<T> operator+ ( const QValueList<T>& l ) const; QValueList<T>& operator+= ( const QValueList<T>& l ); iterator fromLast() { detach(); return iterator( sh->node->prev ); } const_iterator fromLast() const { return const_iterator( sh->node->prev ); } bool isEmpty() const { return ( sh->nodes == 0 ); } iterator append( const T& x ) { detach(); return sh->insert( end(), x ); } iterator prepend( const T& x ) { detach(); return sh->insert( begin(), x ); } iterator remove( iterator it ) { detach(); return sh->remove( it ); } T& first() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->next->data; } const T& first() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->next->data; } T& last() { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->node->prev->data; } const T& last() const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->node->prev->data; } T& operator[] ( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return sh->at(i)->data; } const T& operator[] ( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return sh->at(i)->data; } iterator at( size_type i ) { QT_CHECK_INVALID_LIST_ELEMENT; detach(); return iterator( sh->at(i) ); } const_iterator at( size_type i ) const { QT_CHECK_INVALID_LIST_ELEMENT; return const_iterator( sh->at(i) ); } iterator find ( const T& x ) { detach(); return iterator( sh->find( sh->node->next, x) ); } const_iterator find ( const T& x ) const { return const_iterator( sh->find( sh->node->next, x) ); } iterator find ( iterator it, const T& x ) { detach(); return iterator( sh->find( it.node, x ) ); } const_iterator find ( const_iterator it, const T& x ) const { return const_iterator( sh->find( it.node, x ) ); } int findIndex( const T& x ) const { return sh->findIndex( sh->node->next, x) ; } size_type contains( const T& x ) const { return sh->contains( x ); } size_type count() const { return sh->nodes; } QValueList<T>& operator+= ( const T& x ) { append( x ); return *this; } typedef QValueListIterator<T> Iterator; typedef QValueListConstIterator<T> ConstIterator; typedef T ValueType; protected: /** * Helpers */ void detach() { if ( sh->count > 1 ) detachInternal(); } /** * Variables */ QValueListPrivate<T>* sh; private: void detachInternal(); friend class QDeepCopy< QValueList<T> >; }; template <class T> Q_INLINE_TEMPLATES bool QValueList<T>::operator== ( const QValueList<T>& l ) const { if ( size() != l.size() ) return FALSE; const_iterator it2 = begin(); const_iterator it = l.begin(); for( ; it != l.end(); ++it, ++it2 ) if ( !( *it == *it2 ) ) return FALSE; return TRUE; } template <class T> Q_INLINE_TEMPLATES void QValueList<T>::clear() { if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QValueListPrivate<T>; } } template <class T> Q_INLINE_TEMPLATES Q_TYPENAME QValueList<T>::iterator QValueList<T>::erase( Q_TYPENAME QValueList<T>::iterator first, Q_TYPENAME QValueList<T>::iterator last ) { while ( first != last ) erase( first++ ); return last; } template <class T> Q_INLINE_TEMPLATES void QValueList<T>::insert( Q_TYPENAME QValueList<T>::iterator pos, size_type n, const T& x ) { for ( ; n > 0; --n ) insert( pos, x ); } template <class T> Q_INLINE_TEMPLATES QValueList<T> QValueList<T>::operator+ ( const QValueList<T>& l ) const { QValueList<T> l2( *this ); for( const_iterator it = l.begin(); it != l.end(); ++it ) l2.append( *it ); return l2; } template <class T> Q_INLINE_TEMPLATES QValueList<T>& QValueList<T>::operator+= ( const QValueList<T>& l ) { for( const_iterator it = l.begin(); it != l.end(); ++it ) append( *it ); return *this; } template <class T> Q_INLINE_TEMPLATES void QValueList<T>::detachInternal() { sh->deref(); sh = new QValueListPrivate<T>( *sh ); } #ifndef QT_NO_DATASTREAM template <class T> Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QValueList<T>& l ) { l.clear(); Q_UINT32 c; s >> c; for( Q_UINT32 i = 0; i < c; ++i ) { T t; s >> t; l.append( t ); if ( s.atEnd() ) break; } return s; } template <class T> Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QValueList<T>& l ) { s << (Q_UINT32)l.size(); QValueListConstIterator<T> it = l.begin(); for( ; it != l.end(); ++it ) s << *it; return s; } #endif // QT_NO_DATASTREAM +#ifdef QT_QWINEXPORT +#define Q_DEFINED_QVALUELIST +#include "qwinexport.h" +#endif /* QT_QWINEXPORT */ #endif // QVALUELIST_H diff --git a/qmake/include/qvaluestack.h b/qmake/include/qvaluestack.h index 7e9bc48..c3f966e 100644 --- a/qmake/include/qvaluestack.h +++ b/qmake/include/qvaluestack.h @@ -1,64 +1,64 @@ /**************************************************************************** ** $Id$ ** ** Definition of QValueStack class ** ** Created : 990925 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef QVALUESTACK_H #define QVALUESTACK_H #ifndef QT_H #include "qvaluelist.h" #endif // QT_H template<class T> class QValueStack : public QValueList<T> { public: QValueStack() {} ~QValueStack() {} void push( const T& d ) { append(d); } T pop() { T elem( this->last() ); if ( !this->isEmpty() ) - remove( this->fromLast() ); + this->remove( this->fromLast() ); return elem; } T& top() { return this->last(); } const T& top() const { return this->last(); } }; #endif diff --git a/qmake/main.cpp b/qmake/main.cpp index eed1697..cc2d08a 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -1,153 +1,158 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "project.h" #include "option.h" #include "makefile.h" #include <qnamespace.h> #include <qregexp.h> #include <qdir.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> // for Borland, main is defined to qMain which breaks qmake #undef main int main(int argc, char **argv) { /* parse command line */ if(!Option::parseCommandLine(argc, argv)) return 666; QDir sunworkshop42workaround = QDir::current(); QString oldpwd = sunworkshop42workaround.currentDirPath(); Option::output_dir = oldpwd; //for now this is the output dir +#ifdef Q_WS_WIN + if ( !(Option::output_dir.length() == 3 && Option::output_dir[0].isLetter() && Option::output_dir.endsWith(":/") ) ) +#endif + { if(Option::output_dir.right(1) != QString(QChar(QDir::separator()))) Option::output_dir += QDir::separator(); + } QMakeProject proj; int exit_val = 0; QStringList files; if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) files << "(*hack*)"; //we don't even use files, but we do the for() body once else files = Option::mkfile::project_files; for(QStringList::Iterator pfile = files.begin(); pfile != files.end(); pfile++) { if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { QString fn = (*pfile); //setup pwd properly debug_msg(1, "Resetting dir to: %s", oldpwd.latin1()); QDir::setCurrent(oldpwd); //reset the old pwd int di = fn.findRev(Option::dir_sep); if(di != -1) { debug_msg(1, "Changing dir to: %s", fn.left(di).latin1()); if(!QDir::setCurrent(fn.left(fn.findRev(Option::dir_sep)))) fprintf(stderr, "Cannot find directory: %s\n", fn.left(di).latin1()); fn = fn.right(fn.length() - di - 1); } /* read project.. */ if(!proj.read(fn, oldpwd)) { fprintf(stderr, "Error processing project file: %s\n", fn == "-" ? "(stdin)" : (*pfile).latin1()); exit_val = 2; continue; } if(Option::mkfile::do_preprocess) //no need to create makefile continue; /* let Option post-process */ if(!Option::postProcessProject(&proj)) { fprintf(stderr, "Error post-processing project file: %s", fn == "-" ? "(stdin)" : (*pfile).latin1()); exit_val = 8; continue; } } bool using_stdout = FALSE; MakefileGenerator *mkfile = MakefileGenerator::create(&proj); //figure out generator if(mkfile && (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)) { //open output if(!(Option::output.state() & IO_Open)) { if(Option::output.name() == "-") { Option::output.setName(""); Option::output_dir = QDir::currentDirPath(); Option::output.open(IO_WriteOnly | IO_Translate, stdout); using_stdout = TRUE; } else { if(Option::output.name().isEmpty() && Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE) Option::output.setName(proj.first("QMAKE_MAKEFILE")); if(!mkfile->openOutput(Option::output)) { fprintf(stderr, "Failure to open file: %s\n", Option::output.name().isEmpty() ? "(stdout)" : Option::output.name().latin1()); return 5; } } } } else { using_stdout = TRUE; //kind of.. } if(mkfile && !mkfile->write()) { if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) fprintf(stderr, "Unable to generate project file.\n"); else fprintf(stderr, "Unable to generate makefile for: %s\n", (*pfile).latin1()); if(!using_stdout) QFile::remove(Option::output.name()); exit_val = 6; } delete mkfile; mkfile = NULL; /* debugging */ if(Option::debug_level) { QMap<QString, QStringList> &vars = proj.variables(); for(QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it) { if(it.key().left(1) != "." && !it.data().isEmpty()) debug_msg(1, "%s === %s", it.key().latin1(), it.data().join(" :: ").latin1()); } } } return exit_val; } diff --git a/qmake/option.cpp b/qmake/option.cpp index 34b3ee2..8b7e5e8 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -1,449 +1,504 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "option.h" #include <qdir.h> #include <qregexp.h> #include <stdlib.h> #include <stdarg.h> //convenience QString Option::prf_ext; QString Option::prl_ext; QString Option::ui_ext; QStringList Option::h_ext; QString Option::moc_ext; QStringList Option::cpp_ext; QString Option::obj_ext; QString Option::lex_ext; QString Option::yacc_ext; QString Option::dir_sep; QString Option::moc_mod; QString Option::yacc_mod; QString Option::lex_mod; //mode Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING; //all modes int Option::warn_level = WarnLogic; int Option::debug_level = 0; QFile Option::output; QString Option::output_dir; QStringList Option::before_user_vars; QStringList Option::after_user_vars; QString Option::user_template; QString Option::user_template_prefix; #if defined(Q_OS_WIN32) Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE; #elif defined(Q_OS_MAC9) Option::TARG_MODE Option::target_mode = Option::TARG_MAC9_MODE; #elif defined(Q_OS_MACX) Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE; #elif defined(Q_OS_QNX6) Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE; #else Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE; #endif //QMAKE_GENERATE_PROJECT stuff bool Option::projfile::do_pwd = TRUE; -bool Option::projfile::do_recursive = FALSE; +bool Option::projfile::do_recursive = TRUE; QStringList Option::projfile::project_dirs; //QMAKE_GENERATE_MAKEFILE stuff QString Option::mkfile::qmakespec; int Option::mkfile::cachefile_depth = -1; bool Option::mkfile::do_deps = TRUE; bool Option::mkfile::do_mocs = TRUE; bool Option::mkfile::do_dep_heuristics = TRUE; bool Option::mkfile::do_preprocess = FALSE; bool Option::mkfile::do_cache = TRUE; QString Option::mkfile::cachefile; QStringList Option::mkfile::project_files; QString Option::mkfile::qmakespec_commandline; +static Option::QMAKE_MODE default_mode(QString progname) +{ + int s = progname.findRev(Option::dir_sep); + if(s != -1) + progname = progname.right(progname.length() - (s + 1)); + if(progname == "qmakegen") + return Option::QMAKE_GENERATE_PROJECT; + return Option::QMAKE_GENERATE_MAKEFILE; +} + +QString project_builtin_regx(); bool usage(const char *a0) { fprintf(stdout, "Usage: %s [mode] [options] [files]\n" "\n" " QMake has two modes, one mode for generating project files based on\n" "some heuristics, and the other for generating makefiles. Normally you\n" "shouldn't need to specify a mode, as makefile generation is the default\n" "mode for qmake, but you may use this to test qmake on an existing project\n" "\n" "Mode:\n" - "\t-project Put qmake into project file generation mode\n" + "\t-project Put qmake into project file generation mode%s\n" "\t In this mode qmake interprets files as files to\n" "\t be built,\n" - "\t defaults to *.cpp; *.l; *.y; *.ui\n" - "\t-makefile Put qmake into makefile generation mode (default)\n" + "\t defaults to %s\n" + "\t-makefile Put qmake into makefile generation mode%s\n" "\t In this mode qmake interprets files as project files to\n" "\t be processed, if skipped qmake will try to find a project\n" "\t file in your current working directory\n" "\n" "Warnings Options:\n" "\t-Wnone Turn off all warnings\n" "\t-Wall Turn on all warnings\n" "\t-Wparser Turn on parser warnings\n" "\t-Wlogic Turn on logic warnings\n" "\n" "Options:\n" "\t * You can place any variable assignment in options and it will be *\n" "\t * processed as if it was in [files]. These assignments will be parsed *\n" "\t * before [files]. *\n" "\t-o file Write output to file\n" "\t-unix Run in unix mode\n" "\t-win32 Run in win32 mode\n" "\t-macx Run in Mac OS X mode\n" "\t-d Increase debug level\n" "\t-t templ Overrides TEMPLATE as templ\n" "\t-tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n" "\t-help This help\n" "\t-v Version information\n" "\t-after All variable assignments after this will be\n" - "\t parsed after [files] [makefile mode only]\n" + "\t parsed after [files]\n" "\t-cache file Use file as cache [makefile mode only]\n" "\t-spec spec Use spec as QMAKESPEC [makefile mode only]\n" "\t-nocache Don't use a cache file [makefile mode only]\n" "\t-nodepend Don't generate dependencies [makefile mode only]\n" "\t-nomoc Don't generate moc targets [makefile mode only]\n" "\t-nopwd Don't look for files in pwd [ project mode only]\n" - "\t-r Recursive search [ project mode only]\n" - ,a0); + "\t-norecursive Don't do a recursive search [ project mode only]\n" + ,a0, + default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().latin1(), + default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""); return FALSE; } -static Option::QMAKE_MODE default_mode(QString progname) -{ - int s = progname.findRev(Option::dir_sep); - if(s != -1) - progname = progname.right(progname.length() - (s + 1)); - if(progname == "qmakegen") - return Option::QMAKE_GENERATE_PROJECT; - return Option::QMAKE_GENERATE_MAKEFILE; -} - bool -Option::parseCommandLine(int argc, char **argv) +Option::internalParseCommandLine(int argc, char **argv, int skip) { bool before = TRUE; - for(int x = 1; x < argc; x++) { + for(int x = skip; x < argc; x++) { if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */ QString opt = argv[x] + 1; //first param is a mode, or we default if(x == 1) { bool specified = TRUE; if(opt == "project") { Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT; } else if(opt == "prl") { Option::mkfile::do_deps = FALSE; Option::mkfile::do_mocs = FALSE; Option::qmake_mode = Option::QMAKE_GENERATE_PRL; } else if(opt == "makefile") { Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE; } else { specified = FALSE; - Option::qmake_mode = default_mode(argv[0]); } if(specified) continue; } //all modes if(opt == "o" || opt == "output") { Option::output.setName(argv[++x]); } else if(opt == "after") { before = FALSE; } else if(opt == "t" || opt == "template") { Option::user_template = argv[++x]; } else if(opt == "tp" || opt == "template_prefix") { Option::user_template_prefix = argv[++x]; } else if(opt == "mac9") { Option::target_mode = TARG_MAC9_MODE; } else if(opt == "macx") { Option::target_mode = TARG_MACX_MODE; } else if(opt == "unix") { Option::target_mode = TARG_UNIX_MODE; } else if(opt == "win32") { Option::target_mode = TARG_WIN_MODE; } else if(opt == "d") { Option::debug_level++; } else if(opt == "version" || opt == "v" || opt == "-version") { - fprintf(stderr, "Qmake version: %s\n", qmake_version()); + fprintf(stderr, "Qmake version: %s (Qt %s)\n", qmake_version(), QT_VERSION_STR); fprintf(stderr, "Qmake is free software from Trolltech AS.\n"); return FALSE; } else if(opt == "h" || opt == "help") { - return usage(argv[0]); + return FALSE; } else if(opt == "Wall") { Option::warn_level |= WarnAll; } else if(opt == "Wparser") { Option::warn_level |= WarnParser; } else if(opt == "Wlogic") { Option::warn_level |= WarnLogic; } else if(opt == "Wnone") { Option::warn_level = WarnNone; } else { if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { if(opt == "nodepend") { Option::mkfile::do_deps = FALSE; } else if(opt == "nomoc") { Option::mkfile::do_mocs = FALSE; } else if(opt == "nocache") { Option::mkfile::do_cache = FALSE; } else if(opt == "nodependheuristics") { Option::mkfile::do_dep_heuristics = FALSE; } else if(opt == "E") { Option::mkfile::do_preprocess = TRUE; } else if(opt == "cache") { Option::mkfile::cachefile = argv[++x]; } else if(opt == "platform" || opt == "spec") { Option::mkfile::qmakespec = argv[++x]; Option::mkfile::qmakespec_commandline = argv[x]; } else { fprintf(stderr, "***Unknown option -%s\n", opt.latin1()); return usage(argv[0]); } } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { if(opt == "nopwd") { Option::projfile::do_pwd = FALSE; } else if(opt == "r") { Option::projfile::do_recursive = TRUE; + } else if(opt == "norecursive") { + Option::projfile::do_recursive = FALSE; } else { fprintf(stderr, "***Unknown option -%s\n", opt.latin1()); - return usage(argv[0]); + return FALSE; } } } } else { - if(x == 1) - Option::qmake_mode = default_mode(argv[0]); - QString arg = argv[x]; if(arg.find('=') != -1) { if(before) Option::before_user_vars.append(arg); else Option::after_user_vars.append(arg); } else { QFileInfo fi(arg); if(!fi.convertToAbs()) //strange arg = fi.filePath(); if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) Option::mkfile::project_files.append(arg); else Option::projfile::project_dirs.append(arg); } } } + return TRUE; +} + + +bool +Option::parseCommandLine(int argc, char **argv) +{ + Option::moc_mod = "moc_"; + Option::lex_mod = "_lex"; + Option::yacc_mod = "_yacc"; + Option::prl_ext = ".prl"; + Option::prf_ext = ".prf"; + Option::ui_ext = ".ui"; + Option::h_ext << ".h" << ".hpp" << ".hh" << ".H" << ".hxx"; + Option::moc_ext = ".moc"; + Option::cpp_ext << ".cpp" << ".cc" << ".cxx" << ".C"; + Option::lex_ext = ".l"; + Option::yacc_ext = ".y"; + if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING) Option::qmake_mode = default_mode(argv[0]); + if(const char *envflags = getenv("QMAKEFLAGS")) { + int env_argc = 0, env_size = 0, currlen=0; + char quote = 0, **env_argv = NULL; + for(int i = 0; envflags[i]; i++) { + if(!quote && (envflags[i] == '\'' || envflags[i] == '"')) { + quote = envflags[i]; + } else if(envflags[i] == quote) { + quote = 0; + } else if(!quote && envflags[i] == ' ') { + if(currlen && env_argv && env_argv[env_argc]) { + env_argv[env_argc][currlen] = '\0'; + currlen = 0; + env_argc++; + } + } else { + if(!env_argv || env_argc > env_size) { + env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10)); + for(int i2 = env_argc; i2 < env_size; i2++) + env_argv[i2] = NULL; + } + if(!env_argv[env_argc]) { + currlen = 0; + env_argv[env_argc] = (char*)malloc(255); + } + if(currlen < 255) + env_argv[env_argc][currlen++] = envflags[i]; + } + } + if(env_argv[env_argc]) { + env_argv[env_argc][currlen] = '\0'; + currlen = 0; + env_argc++; + } + internalParseCommandLine(env_argc, env_argv); + for(int i2 = 0; i2 < env_size; i2++) { + if(env_argv[i2]) + free(env_argv[i2]); + } + free(env_argv); + } + if(!internalParseCommandLine(argc, argv, 1)) + return usage(argv[0]); //last chance for defaults if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty()) Option::mkfile::qmakespec = getenv("QMAKESPEC"); //try REALLY hard to do it for them, lazy.. if(Option::mkfile::project_files.isEmpty()) { - QString proj = QDir::currentDirPath(); - proj = proj.right(proj.length() - (proj.findRev('/') + 1)) + ".pro"; - if(QFile::exists(proj)) + QString pwd = QDir::currentDirPath(), + proj = pwd + "/" + pwd.right(pwd.length() - (pwd.findRev('/') + 1)) + ".pro"; + if(QFile::exists(proj)) { Option::mkfile::project_files.append(proj); - else + } else { //last try.. + QDir d(pwd, "*.pro"); + if(d.count() != 1) return usage(argv[0]); + Option::mkfile::project_files.append(pwd + "/" + d[0]); + } } } //defaults for globals - Option::moc_mod = "moc_"; - Option::lex_mod = "_lex"; - Option::yacc_mod = "_yacc"; - Option::prl_ext = ".prl"; - Option::prf_ext = ".prf"; - Option::ui_ext = ".ui"; - Option::h_ext << ".h" << ".hpp" << ".hh" << ".H" << ".hxx"; - Option::moc_ext = ".moc"; - Option::cpp_ext << ".cpp" << ".cc" << ".cxx" << ".C"; - Option::lex_ext = ".l"; - Option::yacc_ext = ".y"; if(Option::target_mode == Option::TARG_WIN_MODE) { Option::dir_sep = "\\"; Option::obj_ext = ".obj"; } else { if(Option::target_mode == Option::TARG_MAC9_MODE) Option::dir_sep = ":"; else Option::dir_sep = "/"; Option::obj_ext = ".o"; } return TRUE; } bool Option::postProcessProject(QMakeProject *project) { Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"]; if(cpp_ext.isEmpty()) cpp_ext << ".cpp"; //something must be there Option::h_ext = project->variables()["QMAKE_EXT_H"]; if(h_ext.isEmpty()) h_ext << ".h"; if(!project->isEmpty("QMAKE_EXT_PRL")) Option::prl_ext = project->first("QMAKE_EXT_PRL"); if(!project->isEmpty("QMAKE_EXT_PRF")) Option::prf_ext = project->first("QMAKE_EXT_PRF"); if(!project->isEmpty("QMAKE_EXT_UI")) Option::ui_ext = project->first("QMAKE_EXT_UI"); if(!project->isEmpty("QMAKE_EXT_MOC")) Option::moc_ext = project->first("QMAKE_EXT_MOC"); if(!project->isEmpty("QMAKE_EXT_LEX")) Option::lex_ext = project->first("QMAKE_EXT_LEX"); if(!project->isEmpty("QMAKE_EXT_YACC")) Option::yacc_ext = project->first("QMAKE_EXT_YACC"); if(!project->isEmpty("QMAKE_EXT_OBJ")) Option::obj_ext = project->first("QMAKE_EXT_OBJ"); if(!project->isEmpty("QMAKE_MOD_MOC")) Option::moc_mod = project->first("QMAKE_MOD_MOC"); if(!project->isEmpty("QMAKE_MOD_LEX")) Option::lex_mod = project->first("QMAKE_MOD_LEX"); if(!project->isEmpty("QMAKE_MOD_YACC")) Option::yacc_mod = project->first("QMAKE_MOD_YACC"); if(!project->isEmpty("QMAKE_DIR_SEP")) Option::dir_sep = project->first("QMAKE_DIR_SEP"); return TRUE; } void fixEnvVariables(QString &x) { int rep; QRegExp reg_var("\\$\\(.*\\)"); reg_var.setMinimal( TRUE ); while((rep = reg_var.search(x)) != -1) x.replace(rep, reg_var.matchedLength(), QString(getenv(x.mid(rep + 2, reg_var.matchedLength() - 3).latin1()))); } static QString fixPath(QString x) { #if 0 QFileInfo fi(x); if(fi.isDir()) { QDir dir(x); x = dir.canonicalPath(); } else { QString dir = fi.dir().canonicalPath(); if(!dir.isEmpty() && dir.right(1) != Option::dir_sep) dir += Option::dir_sep; x = dir + fi.fileName(); } #endif return QDir::cleanDirPath(x); } QString Option::fixPathToTargetOS(const QString& in, bool fix_env, bool canonical) { QString tmp(in); if(fix_env) fixEnvVariables(tmp); if(canonical) tmp = fixPath(tmp); QString rep; if(Option::target_mode == TARG_MAC9_MODE) - rep = "[/\\\\]"; + tmp = tmp.replace('/', Option::dir_sep).replace('\\', Option::dir_sep); else if(Option::target_mode == TARG_WIN_MODE) - rep = "[/]"; + tmp = tmp.replace('/', Option::dir_sep); else - rep = "[\\\\]"; - return tmp.replace(QRegExp(rep), Option::dir_sep); + tmp = tmp.replace('\\', Option::dir_sep); + return tmp; } QString Option::fixPathToLocalOS(const QString& in, bool fix_env, bool canonical) { QString tmp(in); if(fix_env) fixEnvVariables(tmp); if(canonical) tmp = fixPath(tmp); #if defined(Q_OS_WIN32) return tmp.replace('/', '\\'); #else return tmp.replace('\\', '/'); #endif } const char *qmake_version() { static char *ret = NULL; if(ret) return ret; ret = (char *)malloc(15); sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH); return ret; } void debug_msg(int level, const char *fmt, ...) { if(Option::debug_level < level) return; fprintf(stderr, "DEBUG %d: ", level); { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } fprintf(stderr, "\n"); } void warn_msg(QMakeWarn type, const char *fmt, ...) { if(!(Option::warn_level & type)) return; fprintf(stderr, "WARNING: "); { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } fprintf(stderr, "\n"); } diff --git a/qmake/option.h b/qmake/option.h index 9a5a85a..8bd348e 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -1,122 +1,125 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #ifndef __OPTION_H__ #define __OPTION_H__ #include "project.h" #include <qstring.h> #include <qstringlist.h> #include <qfile.h> #define QMAKE_VERSION_MAJOR 1 -#define QMAKE_VERSION_MINOR 4 +#define QMAKE_VERSION_MINOR 5 #define QMAKE_VERSION_PATCH 0 const char *qmake_version(); void fixEnvVariables(QString &x); void debug_msg(int level, const char *fmt, ...); enum QMakeWarn { WarnNone = 0x00, WarnParser = 0x01, WarnLogic = 0x02, WarnAll = 0xFF }; void warn_msg(QMakeWarn t, const char *fmt, ...); struct Option { //simply global convenience static QString prf_ext; static QString prl_ext; static QString ui_ext; static QStringList h_ext; static QStringList cpp_ext; static QString moc_ext; static QString obj_ext; static QString lex_ext; static QString yacc_ext; static QString moc_mod; static QString lex_mod; static QString yacc_mod; static QString dir_sep; //both of these must be called.. static bool parseCommandLine(int argc, char **argv); //parse cmdline static bool postProcessProject(QMakeProject *); //and convenience functions static QString fixPathToLocalOS(const QString& in, bool fix_env=TRUE, bool canonical=TRUE); static QString fixPathToTargetOS(const QString& in, bool fix_env=TRUE, bool canonical=TRUE); //global qmake mode, can only be in one mode per invocation! enum QMAKE_MODE { QMAKE_GENERATE_NOTHING, QMAKE_GENERATE_PROJECT, QMAKE_GENERATE_MAKEFILE, QMAKE_GENERATE_PRL }; static QMAKE_MODE qmake_mode; //all modes static QFile output; static QString output_dir; static int debug_level; static int warn_level; static QStringList before_user_vars, after_user_vars; enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE }; static TARG_MODE target_mode; static QString user_template, user_template_prefix; //QMAKE_GENERATE_PROJECT options struct projfile { static bool do_pwd; static bool do_recursive; static QStringList project_dirs; }; //QMAKE_GENERATE_MAKEFILE options struct mkfile { static QString qmakespec; static bool do_cache; static bool do_deps; static bool do_mocs; static bool do_dep_heuristics; static bool do_preprocess; static QString cachefile; static int cachefile_depth; static QStringList project_files; static QString qmakespec_commandline; }; + +private: + static bool internalParseCommandLine(int, char **, int=0); }; #endif /* __OPTION_H__ */ diff --git a/qmake/project.cpp b/qmake/project.cpp index 44eb503..834823d 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1,994 +1,1077 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "project.h" #include "option.h" #include <qfile.h> #include <qdir.h> #include <qregexp.h> #include <qtextstream.h> #include <qvaluestack.h> #ifdef Q_OS_UNIX # include <unistd.h> #endif #include <stdio.h> #include <stdlib.h> #ifdef Q_OS_WIN32 #define QT_POPEN _popen #else #define QT_POPEN popen #endif struct parser_info { QString file; int line_no; } parser; static void qmake_error_msg(const char *msg) { fprintf(stderr, "%s:%d: %s\n", parser.file.latin1(), parser.line_no, msg); } static QString varMap(const QString &x) { QString ret(x); - ret.replace(QRegExp("^TMAKE"), "QMAKE"); + if(ret.startsWith("TMAKE")) //tmake no more! + ret = "QMAKE" + ret.mid(5); if(ret == "INTERFACES") ret = "FORMS"; + if(ret == "QMAKE_POST_BUILD") + ret = "QMAKE_POST_LINK"; + if(ret == "TARGETDEPS") + ret = "POST_TARGETDEPS"; return ret; } static QStringList split_arg_list(const QString ¶ms) { QStringList args; int last = 0, parens = 0; QChar quote = 0; for(int x = 0; x < (int)params.length(); x++) { if(params[x] == ')') { parens--; } else if(params[x] == '(') { parens++; } else if(params[x] == quote) { quote = 0; } else if(params[x] == '\'' || params[x] == '"') { quote = params[x]; } else if(!parens && !quote && params[x] == ',') { args << params.mid(last, x - last); last = x+1; } } if(last != (int)params.length()) args << params.mid(last); return args; } static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE) { int last = 0; QStringList ret; QValueStack<QChar> quote; for(int x = 0; x < (int)vals.length(); x++) { if(!quote.isEmpty() && vals[x] == quote.top()) { quote.pop(); } else if(vals[x] == '\'' || vals[x] == '"') { quote.push(vals[x]); } else if(quote.isEmpty() && ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) { ret << vals.mid(last, x - last); last = x+1; } } if(last != (int)vals.length()) ret << vals.mid(last); return ret; } QMakeProject::QMakeProject() { } bool -QMakeProject::parse(QString t, QMap<QString, QStringList> &place) +QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) { QString s = t.simplifyWhiteSpace(); - s.replace(QRegExp("#.*$"), ""); /* bye comments */ + int hash_mark = s.find('#'); + if(hash_mark != -1) //good bye comments + s = s.left(hash_mark); if(s.isEmpty()) /* blank_line */ return TRUE; if(s.stripWhiteSpace().left(1) == "}") { debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), parser.line_no, scope_block); test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); scope_block--; s = s.mid(1).stripWhiteSpace(); if(s.isEmpty()) return TRUE; } if(!(scope_flag & (0x01 << scope_block))) { /* adjust scope for each block which appears on a single line */ for(int i = (s.contains('{')-s.contains('}')); i; i--) scope_flag &= ~(0x01 << (++scope_block)); debug_msg(1, "Project Parser: %s:%d : Ignored due to block being false.", parser.file.latin1(), parser.line_no); return TRUE; } QString scope, var, op; QStringList val; #define SKIP_WS(d) while(*d && (*d == ' ' || *d == '\t')) d++ const char *d = s.latin1(); SKIP_WS(d); bool scope_failed = FALSE, else_line = FALSE, or_op=FALSE; int parens = 0, scope_count=0; - while(*d && *d != '=') { - if((*d == '+' || *d == '-' || *d == '*' || *d == '~')) { + while(*d) { + if(!parens) { + if(*d == '=') + break; + if(*d == '+' || *d == '-' || *d == '*' || *d == '~') { if(*(d+1) == '=') { break; } else if(*(d+1) == ' ') { const char *k = d + 1; SKIP_WS(k); if(*k == '=') { QString msg; - qmake_error_msg(*d + "must be followed immediatly by ="); + qmake_error_msg(*d + "must be followed immediately by ="); return FALSE; } } } + } if ( *d == '(' ) ++parens; else if ( *d == ')' ) --parens; if(!parens && (*d == ':' || *d == '{' || *d == ')' || *d == '|')) { scope_count++; scope = var.stripWhiteSpace(); if ( *d == ')' ) scope += *d; /* need this */ var = ""; bool test = scope_failed; if(scope.lower() == "else") { if(scope_count != 1 || test_status == TestNone) { qmake_error_msg("Unexpected " + scope + " ('" + s + "')"); return FALSE; } else_line = TRUE; test = (test_status == TestSeek); debug_msg(1, "Project Parser: %s:%d : Else%s %s.", parser.file.latin1(), parser.line_no, scope == "else" ? "" : QString(" (" + scope + ")").latin1(), test ? "considered" : "excluded"); } else { QString comp_scope = scope; bool invert_test = (comp_scope.left(1) == "!"); if(invert_test) comp_scope = comp_scope.right(comp_scope.length()-1); int lparen = comp_scope.find('('); if(or_op || !scope_failed) { if(lparen != -1) { /* if there is an lparen in the scope, it IS a function */ int rparen = comp_scope.findRev(')'); if(rparen == -1) { QCString error; error.sprintf("Function missing right paren: %s ('%s')", comp_scope.latin1(), s.latin1()); qmake_error_msg(error); return FALSE; } QString func = comp_scope.left(lparen); test = doProjectTest(func, comp_scope.mid(lparen+1, rparen - lparen - 1), place); if ( *d == ')' && !*(d+1) ) { if(invert_test) test = !test; test_status = (test ? TestFound : TestSeek); return TRUE; /* assume we are done */ } } else { - test = isActiveConfig(comp_scope.stripWhiteSpace()); + test = isActiveConfig(comp_scope.stripWhiteSpace(), TRUE); } if(invert_test) test = !test; } } if(!test && !scope_failed) debug_msg(1, "Project Parser: %s:%d : Test (%s) failed.", parser.file.latin1(), parser.line_no, scope.latin1()); if(test == or_op) scope_failed = !test; or_op = (*d == '|'); if(*d == '{') { /* scoping block */ if(!scope_failed) scope_flag |= (0x01 << (++scope_block)); else scope_flag &= ~(0x01 << (++scope_block)); debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d).", parser.file.latin1(), parser.line_no, scope_block, !scope_failed); } } else { var += *d; } d++; } if(!scope_count || (scope_count == 1 && else_line)) test_status = TestNone; else if(!else_line || test_status != TestFound) test_status = (scope_failed ? TestSeek : TestFound); if(scope_failed) return TRUE; /* oh well */ if(!*d) { if(!var.isEmpty()) qmake_error_msg("Parse Error ('" + s + "')"); return var.isEmpty(); /* allow just a scope */ } SKIP_WS(d); for( ; *d && op.find('=') == -1; op += *(d++)); op.replace(QRegExp("\\s"), ""); SKIP_WS(d); QString vals(d); /* vals now contains the space separated list of values */ int rbraces = vals.contains('}'), lbraces = vals.contains('{'); if(scope_block && rbraces - lbraces == 1) { debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), parser.line_no, scope_block); test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); scope_block--; vals.truncate(vals.length()-1); } else if(rbraces != lbraces) { warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d", vals.latin1(), parser.file.latin1(), parser.line_no); } doVariableReplace(vals, place); var = var.stripWhiteSpace(); #undef SKIP_WS if(!var.isEmpty() && Option::mkfile::do_preprocess) { static QString last_file("*none*"); if(parser.file != last_file) { fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no); last_file = parser.file; } fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); } var = varMap(var); //backwards compatability /* vallist is the broken up list of values */ QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH")); if(!vallist.grep("=").isEmpty()) warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d", var.latin1(), parser.file.latin1(), parser.line_no); QStringList &varlist = place[var]; /* varlist is the list in the symbol table */ debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no, var.latin1(), op.latin1(), vallist.join(" :: ").latin1()); /* now do the operation */ if(op == "~=") { if(vallist.count() != 1) { qmake_error_msg("~= operator only accepts one right hand paramater ('" + s + "')"); return FALSE; } QString val(vallist.first()); if(val.length() < 4 || val.at(0) != 's') { qmake_error_msg("~= operator only can handle s/// function ('" + s + "')"); return FALSE; } QChar sep = val.at(1); QStringList func = QStringList::split(sep, val, TRUE); if(func.count() < 3 || func.count() > 4) { qmake_error_msg("~= operator only can handle s/// function ('" + s + "')"); return FALSE; } bool global = FALSE, case_sense = TRUE; if(func.count() == 4) { global = func[3].find('g') != -1; case_sense = func[3].find('i') == -1; } QRegExp regexp(func[1], case_sense); for(QStringList::Iterator varit = varlist.begin(); varit != varlist.end(); ++varit) { if((*varit).contains(regexp)) { (*varit) = (*varit).replace(regexp, func[2]); if(!global) break; } } } else { if(op == "=") { if(!varlist.isEmpty()) warn_msg(WarnParser, "Operator=(%s) clears variables previously set: %s:%d", var.latin1(), parser.file.latin1(), parser.line_no); varlist.clear(); } for(QStringList::Iterator valit = vallist.begin(); valit != vallist.end(); ++valit) { if((*valit).isEmpty()) continue; if((op == "*=" && !(*varlist.find((*valit)))) || op == "=" || op == "+=") varlist.append((*valit)); else if(op == "-=") varlist.remove((*valit)); } } if(var == "REQUIRES") /* special case to get communicated to backends! */ doProjectCheckReqs(vallist, place); return TRUE; } bool -QMakeProject::read(QString file, QMap<QString, QStringList> &place) +QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) { parser_info pi = parser; /* scope blocks start at true */ test_status = TestNone; scope_flag = 0x01; scope_block = 0; - file = Option::fixPathToLocalOS(file); - doVariableReplace(file, place); + QString filename = Option::fixPathToLocalOS(file); + doVariableReplace(filename, place); bool ret = FALSE, using_stdin = FALSE; QFile qfile; - if(!strcmp(file, "-")) { + if(!strcmp(filename, "-")) { qfile.setName(""); ret = qfile.open(IO_ReadOnly, stdin); using_stdin = TRUE; } else { - qfile.setName(file); + qfile.setName(filename); ret = qfile.open(IO_ReadOnly); } if ( ret ) { QTextStream t( &qfile ); QString s, line; - parser.file = file; + parser.file = filename; parser.line_no = 0; while ( !t.eof() ) { parser.line_no++; line = t.readLine().stripWhiteSpace(); int prelen = line.length(); - line.replace(QRegExp("#.*$"), ""); // bye comments + { + int hash_mark = line.find('#'); + if(hash_mark != -1) //bye comments + line = line.left(hash_mark); + } if(!line.isEmpty() && line.right(1) == "\\") { line.truncate(line.length() - 1); s += line + " "; } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) { if(s.isEmpty() && line.isEmpty()) continue; if(!line.isEmpty()) s += line; if(!s.isEmpty()) { if(!(ret = parse(s, place))) break; s = ""; } } } if(!using_stdin) qfile.close(); } parser = pi; return ret; } bool -QMakeProject::read(QString project, QString) +QMakeProject::read(const QString &project, const QString &, bool just_project) { + if(just_project) { //nothing more, nothing less + pfile = project; + if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") + pfile += ".pro"; + return read(pfile, vars); + } + if(cfile.isEmpty()) { // hack to get the Option stuff in there base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; base_vars["QMAKE_EXT_H"] = Option::h_ext; + if(!Option::user_template_prefix.isEmpty()) + base_vars["TEMPLATE_PREFIX"] = Option::user_template_prefix; /* parse the cache */ if(Option::mkfile::do_cache) { if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified QString dir = QDir::convertSeparators(Option::output_dir); while(!QFile::exists((Option::mkfile::cachefile = dir + QDir::separator() + ".qmake.cache"))) { dir = dir.left(dir.findRev(QDir::separator())); if(dir.isEmpty() || dir.find(QDir::separator()) == -1) { Option::mkfile::cachefile = ""; break; } if(Option::mkfile::cachefile_depth == -1) Option::mkfile::cachefile_depth = 1; else Option::mkfile::cachefile_depth++; } } if(!Option::mkfile::cachefile.isEmpty()) { read(Option::mkfile::cachefile, cache); if(Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); } } /* parse mkspec */ QStringList mkspec_roots; /* prefer $QTDIR if it is set */ - /* prefer QMAKESPECSDIR -cl */ - - if (getenv("QTDIR")) { + if (getenv("QTDIR")) mkspec_roots << getenv("QTDIR"); - } mkspec_roots << qInstallPathData(); - - if (Option::mkfile::qmakespec.isEmpty() && getenv("QMAKESPECSDIR")){ - QString mkspec = QString(getenv("QMAKESPECSDIR")) + QDir::separator() + - QDir::separator() + "default"; - if(QFile::exists(mkspec)) - Option::mkfile::qmakespec = mkspec; - } - if(Option::mkfile::qmakespec.isEmpty()) { for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + QDir::separator() + "default"; if(QFile::exists(mkspec)) { Option::mkfile::qmakespec = mkspec; break; } } - } - if(Option::mkfile::qmakespec.isEmpty()) { fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); return FALSE; } + } if(QDir::isRelativePath(Option::mkfile::qmakespec)) { bool found_mkspec = FALSE; for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + QDir::separator() + Option::mkfile::qmakespec; if(QFile::exists(mkspec)) { found_mkspec = TRUE; Option::mkfile::qmakespec = mkspec; break; } } if(!found_mkspec) { fprintf(stderr, "Could not find mkspecs for your QMAKESPEC after trying:\n\t%s\n", mkspec_roots.join("\n\t").latin1()); return FALSE; } } /* parse qmake configuration */ QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf"; debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1()); if(!read(spec, base_vars)) { fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.latin1()); return FALSE; } if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.latin1()); read(Option::mkfile::cachefile, base_vars); } /* commandline */ cfile = project; parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; for(QStringList::Iterator it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it) { if(!parse((*it), base_vars)) { fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); return FALSE; } parser.line_no++; } } /* parse project file */ debug_msg(1, "Project file: reading %s", project.latin1()); vars = base_vars; /* start with the base */ pfile = project; if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") pfile += ".pro"; if(!read(pfile, vars)) return FALSE; parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; for(QStringList::Iterator it = Option::after_user_vars.begin(); it != Option::after_user_vars.end(); ++it) { if(!parse((*it), vars)) { fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); return FALSE; } parser.line_no++; } /* now let the user override the template from an option.. */ if(!Option::user_template.isEmpty()) { debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1()); vars["TEMPLATE"].clear(); vars["TEMPLATE"].append(Option::user_template); } - if(vars["TEMPLATE"].isEmpty()) - vars["TEMPLATE"].append(QString("app")); - else - vars["TEMPLATE"].first().replace(QRegExp("\\.t$"), ""); - if(!Option::user_template_prefix.isEmpty()) - vars["TEMPLATE"].first().prepend(Option::user_template_prefix); + QStringList &templ = vars["TEMPLATE"]; + if(templ.isEmpty()) + templ.append(QString("app")); + else if(vars["TEMPLATE"].first().endsWith(".t")) + templ = QStringList(templ.first().left(templ.first().length() - 2)); + if ( !Option::user_template_prefix.isEmpty() ) { + templ.first().prepend(Option::user_template_prefix); + } if(vars["TARGET"].isEmpty()) { // ### why not simply use: // QFileInfo fi(pfile); // fi.baseName(); QString tmp = pfile; if(tmp.findRev('/') != -1) tmp = tmp.right( tmp.length() - tmp.findRev('/') - 1 ); if(tmp.findRev('.') != -1) tmp = tmp.left(tmp.findRev('.')); vars["TARGET"].append(tmp); } QString test_version = getenv("QTESTVERSION"); if (!test_version.isEmpty()) { QString s = vars["TARGET"].first(); if (s == "qt" || s == "qt-mt" || s == "qte" || s == "qte-mt") { QString &ver = vars["VERSION"].first(); // fprintf(stderr,"Current QT version number: " + ver + "\n"); if (ver != "" && ver != test_version) { ver = test_version; fprintf(stderr,"Changed QT version number to " + test_version + "!\n"); } } } return TRUE; } bool -QMakeProject::isActiveConfig(const QString &x) +QMakeProject::isActiveConfig(const QString &x, bool regex) { if(x.isEmpty()) return TRUE; - QRegExp re(x, FALSE, TRUE); - if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_UNIX_MODE) && - x == "unix") + if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || + Option::target_mode == Option::TARG_UNIX_MODE) && x == "unix") return TRUE; else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx") return TRUE; else if(Option::target_mode == Option::TARG_QNX6_MODE && x == "qnx6") return TRUE; else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9") return TRUE; else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) && x == "mac") return TRUE; else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32") return TRUE; + QRegExp re(x, FALSE, TRUE); QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() - (Option::mkfile::qmakespec.findRev(QDir::separator())+1)); - if(re.exactMatch(spec)) + if((regex && re.exactMatch(spec)) || (!regex && spec == x)) return TRUE; #ifdef Q_OS_UNIX else if(spec == "default") { static char *buffer = NULL; if(!buffer) buffer = (char *)malloc(1024); int l = readlink(Option::mkfile::qmakespec, buffer, 1024); if(l != -1) { buffer[l] = '\0'; QString r = buffer; if(r.findRev('/') != -1) r = r.mid(r.findRev('/') + 1); - if(re.exactMatch(r)) + if((regex && re.exactMatch(r)) || (!regex && r == x)) return TRUE; } } #endif QStringList &configs = vars["CONFIG"]; for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) { + if((regex && re.exactMatch((*it))) || (!regex && (*it) == x)) if(re.exactMatch((*it))) return TRUE; } return FALSE; } bool -QMakeProject::doProjectTest(QString func, const QString ¶ms, QMap<QString, QStringList> &place) +QMakeProject::doProjectTest(const QString& func, const QString ¶ms, QMap<QString, QStringList> &place) { QStringList args = split_arg_list(params); for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { QString tmp = (*arit).stripWhiteSpace(); if((tmp[0] == '\'' || tmp[0] == '"') && tmp.right(1) == tmp.left(1)) tmp = tmp.mid(1, tmp.length() - 2); } return doProjectTest(func.stripWhiteSpace(), args, place); } bool -QMakeProject::doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place) +QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, QStringList> &place) { for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space doVariableReplace((*arit), place); } debug_msg(1, "Running project test: %s( %s )", func.latin1(), args.join("::").latin1()); if(func == "requires") { return doProjectCheckReqs(args, place); + } else if(func == "equals") { + if(args.count() != 2) { + fprintf(stderr, "%s:%d: equals(variable, value) requires two arguments.\n", parser.file.latin1(), + parser.line_no); + return FALSE; + } + QString value = args[1]; + if((value.left(1) == "\"" || value.left(1) == "'") && value.right(1) == value.left(1)) + value = value.mid(1, value.length()-2); + return vars[args[0]].join(" ") == value; } else if(func == "exists") { if(args.count() != 1) { fprintf(stderr, "%s:%d: exists(file) requires one argument.\n", parser.file.latin1(), parser.line_no); return FALSE; } QString file = args.first(); file = Option::fixPathToLocalOS(file); doVariableReplace(file, place); if(QFile::exists(file)) return TRUE; //regular expression I guess QString dirstr = QDir::currentDirPath(); int slsh = file.findRev(Option::dir_sep); if(slsh != -1) { dirstr = file.left(slsh+1); file = file.right(file.length() - slsh - 1); } QDir dir(dirstr, file); return dir.count() != 0; } else if(func == "system") { if(args.count() != 1) { fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.latin1(), parser.line_no); return FALSE; } return system(args.first().latin1()) == 0; } else if(func == "contains") { if(args.count() != 2) { fprintf(stderr, "%s:%d: contains(var, val) requires two arguments.\n", parser.file.latin1(), parser.line_no); return FALSE; } QRegExp regx(args[1]); QStringList &l = place[args[0]]; for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if(regx.exactMatch((*it))) return TRUE; } return FALSE; } else if(func == "infile") { if(args.count() < 2 || args.count() > 3) { fprintf(stderr, "%s:%d: infile(file, var, val) requires at least 2 arguments.\n", parser.file.latin1(), parser.line_no); return FALSE; } QMakeProject proj; QString file = args[0]; doVariableReplace(file, place); fixEnvVariables(file); int di = file.findRev(Option::dir_sep); QDir sunworkshop42workaround = QDir::current(); QString oldpwd = sunworkshop42workaround.currentDirPath(); if(di != -1) { if(!QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) { fprintf(stderr, "Cannot find directory: %s\n", file.left(di).latin1()); return FALSE; } file = file.right(file.length() - di - 1); } parser_info pi = parser; bool ret = !proj.read(file, oldpwd); parser = pi; if(ret) { fprintf(stderr, "Error processing project file: %s\n", file.latin1()); QDir::setCurrent(oldpwd); return FALSE; } if(args.count() == 2) { ret = !proj.isEmpty(args[1]); } else { QRegExp regx(args[2]); QStringList &l = proj.values(args[1]); for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { if(regx.exactMatch((*it))) { ret = TRUE; break; } } } QDir::setCurrent(oldpwd); return ret; } else if(func == "count") { if(args.count() != 2) { fprintf(stderr, "%s:%d: count(var, count) requires two arguments.\n", parser.file.latin1(), parser.line_no); return FALSE; } return vars[args[0]].count() == args[1].toUInt(); } else if(func == "isEmpty") { if(args.count() != 1) { fprintf(stderr, "%s:%d: isEmpty(var) requires one argument.\n", parser.file.latin1(), parser.line_no); return FALSE; } return vars[args[0]].isEmpty(); } else if(func == "include" || func == "load") { if(args.count() != 1) { QString func_desc = "include(file)"; if(func == "load") func_desc = "load(feature)"; fprintf(stderr, "%s:%d: %s requires one argument.\n", parser.file.latin1(), parser.line_no, func_desc.latin1()); return FALSE; } QString file = args.first(); file = Option::fixPathToLocalOS(file); file.replace("\"", ""); doVariableReplace(file, place); if(func == "load") { if(!file.endsWith(Option::prf_ext)) file += Option::prf_ext; if(file.find(Option::dir_sep) == -1 || !QFile::exists(file)) { if(QFile::exists(Option::mkfile::qmakespec + QDir::separator() + file)) { file.prepend(Option::mkfile::qmakespec + QDir::separator()); } else { bool found = FALSE; QStringList feature_roots; if(getenv("QTDIR")) feature_roots << getenv("QTDIR"); #ifdef QT_INSTALL_PREFIX feature_roots << QT_INSTALL_PREFIX; #endif #ifdef QT_INSTALL_DATA feature_roots << QT_INSTALL_DATA; #endif for(QStringList::Iterator it = feature_roots.begin(); it != feature_roots.end(); ++it) { QString prf = (*it) + QDir::separator() + QString("mkspecs") + QDir::separator() + QString("features") + QDir::separator() + file; if(QFile::exists(prf)) { found = TRUE; file = prf; break; } } if(!found) { printf("Project LOAD(): Feature %s cannot be found.\n", args.first().latin1()); exit(3); } } } } debug_msg(1, "Project Parser: %s'ing file %s.", func.latin1(), file.latin1()); parser_info pi = parser; int sb = scope_block; int sf = scope_flag; TestStatus sc = test_status; bool r = read(file.latin1(), place); if(r) vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(file); + else + warn_msg(WarnParser, "%s:%d: Failure to include file %s.", + pi.file.latin1(), pi.line_no, file.latin1()); parser = pi; test_status = sc; scope_flag = sf; scope_block = sb; return r; } else if(func == "error" || func == "message") { if(args.count() != 1) { fprintf(stderr, "%s:%d: %s(message) requires one argument.\n", parser.file.latin1(), parser.line_no, func.latin1()); return FALSE; } QString msg = args.first(); + if((msg.startsWith("\"") || msg.startsWith("'")) && msg.endsWith(msg.left(1))) + msg = msg.mid(1, msg.length()-2); + msg.replace(QString("${QMAKE_FILE}"), parser.file.latin1()); + msg.replace(QString("${QMAKE_LINE_NUMBER}"), QString::number(parser.line_no)); + msg.replace(QString("${QMAKE_DATE}"), QDateTime::currentDateTime().toString()); doVariableReplace(msg, place); fixEnvVariables(msg); printf("Project %s: %s\n", func.upper().latin1(), msg.latin1()); if(func == "message") return TRUE; exit(2); } else { fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.latin1(), parser.line_no, func.latin1()); } return FALSE; } bool QMakeProject::doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place) { bool ret = FALSE; for(QStringList::ConstIterator it = deps.begin(); it != deps.end(); ++it) { QString chk = (*it); if(chk.isEmpty()) continue; bool invert_test = (chk.left(1) == "!"); if(invert_test) chk = chk.right(chk.length() - 1); bool test; int lparen = chk.find('('); if(lparen != -1) { /* if there is an lparen in the chk, it IS a function */ int rparen = chk.findRev(')'); if(rparen == -1) { QCString error; error.sprintf("Function (in REQUIRES) missing right paren: %s", chk.latin1()); qmake_error_msg(error); } else { QString func = chk.left(lparen); test = doProjectTest(func, chk.mid(lparen+1, rparen - lparen - 1), place); } } else { - test = isActiveConfig(chk); + test = isActiveConfig(chk, TRUE); } if(invert_test) { chk.prepend("!"); test = !test; } if(!test) { debug_msg(1, "Project Parser: %s:%d Failed test: REQUIRES = %s", parser.file.latin1(), parser.line_no, chk.latin1()); place["QMAKE_FAILED_REQUIREMENTS"].append(chk); ret = FALSE; } } return ret; } QString QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> &place) { - for(int x = 0, rep; x < 5; x++) { - QRegExp reg_var; - reg_var.setMinimal(TRUE); - if( x == 0 ) //function blocked out by {}'s - reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)\\}"); - else if( x == 1 ) //variables blocked out by {}'s - reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_\\.-]*)\\}"); - else if(x == 2) //environment - reg_var = QRegExp("\\$\\$\\(([a-zA-Z0-9_\\.-]*)\\)"); - else if(x == 3) //function - reg_var = QRegExp("\\$\\$([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)"); - else if(x == 4) //normal variable - reg_var = QRegExp("\\$\\$([a-zA-Z0-9_\\.-]*)"); - while((rep = reg_var.search(str)) != -1) { + for(int var_begin, var_last=0; (var_begin = str.find("$$", var_last)) != -1; var_last = var_begin) { + if(var_begin >= int( str.length() + 2 ) ) { + break; + } else if(var_begin != 0 && str[var_begin-1] == '\\') { + str.replace(var_begin-1, 1, ""); + var_begin += 1; + continue; + } + + int var_incr = var_begin + 2; + bool in_braces = FALSE, as_env = FALSE; + if(str[var_incr] == '{') { + in_braces = TRUE; + var_incr++; + while(var_incr < int( str.length() ) && + (str[var_incr] == ' ' || str[var_incr] == '\t' || str[var_incr] == '\n')) + var_incr++; + } + if(str[var_incr] == '(') { + as_env = TRUE; + var_incr++; + } + QString val, args; + while(var_incr < int( str.length() ) && + (str[var_incr].isLetter() || str[var_incr].isNumber() || str[var_incr] == '.' || str[var_incr] == '_')) + val += str[var_incr++]; + if(as_env) { + if(str[var_incr] != ')') { + var_incr++; + warn_msg(WarnParser, "%s:%d: Unterminated env-variable replacement '%s' (%s)", + parser.file.latin1(), parser.line_no, + str.mid(var_begin, QMAX(var_incr - var_begin, int(str.length()))).latin1(), str.latin1()); + var_begin += var_incr; + continue; + } + var_incr++; + } else if(str[var_incr] == '(') { //args + for(int parens = 0; var_incr < int( str.length() ); var_incr++) { + if(str[var_incr] == '(') { + parens++; + if(parens == 1) + continue; + } else if(str[var_incr] == ')') { + parens--; + if(!parens) { + var_incr++; + break; + } + } + args += str[var_incr]; + } + } + if(var_incr > int( str.length() ) || (in_braces && str[var_incr] != '}')) { + var_incr++; + warn_msg(WarnParser, "%s:%d: Unterminated variable replacement '%s' (%s)", + parser.file.latin1(), parser.line_no, + str.mid(var_begin, QMAX(var_incr - var_begin, int( str.length() ))).latin1(), str.latin1()); + var_begin += var_incr; + continue; + } else if(in_braces) { + var_incr++; + } + QString replacement; - if(x == 2) {//environment - replacement = getenv(reg_var.cap(1)); - } else if(x == 0 || x == 3) { //function - QStringList args = split_arg_list(reg_var.cap(2)); - for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { + if(as_env) { + replacement = getenv(val); + } else if(args.isEmpty()) { + if(val.left(1) == ".") + replacement = ""; + else if(val == "LITERAL_WHITESPACE") + replacement = "\t"; + else + replacement = place[varMap(val)].join(" "); + } else { + QStringList arg_list = split_arg_list(args); + for(QStringList::Iterator arit = arg_list.begin(); arit != arg_list.end(); ++arit) { (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space doVariableReplace((*arit), place); } - debug_msg(1, "Running function: %s( %s )", reg_var.cap(1).latin1(), args.join("::").latin1()); - if(reg_var.cap(1).lower() == "member") { - if(args.count() < 1 || args.count() > 2) { + debug_msg(1, "Running function: %s( %s )", val.latin1(), arg_list.join("::").latin1()); + if(val.lower() == "member") { + if(arg_list.count() < 1 || arg_list.count() > 2) { fprintf(stderr, "%s:%d: member(var, place) requires two arguments.\n", parser.file.latin1(), parser.line_no); } else { uint pos = 0; - if(args.count() == 2) - pos = args[1].toInt(); - const QStringList &var = place[varMap(args.first())]; + if(arg_list.count() == 2) + pos = arg_list[1].toInt(); + const QStringList &var = place[varMap(arg_list.first())]; if(var.count() >= pos) replacement = var[pos]; } - } else if(reg_var.cap(1).lower() == "list") { - if(args.count() != 1) { - fprintf(stderr, "%s:%d: list(vals) requires one" - "argument.\n", parser.file.latin1(), parser.line_no); - } else { + } else if(val.lower() == "list") { static int x = 0; replacement.sprintf(".QMAKE_INTERNAL_TMP_VAR_%d", x++); - (*((QMap<QString, QStringList>*)&place))[replacement] = split_value_list(args.first()); - } - } else if(reg_var.cap(1).lower() == "join") { - if(args.count() < 1 || args.count() > 4) { + QStringList &lst = (*((QMap<QString, QStringList>*)&place))[replacement]; + lst.clear(); + for(QStringList::ConstIterator arg_it = arg_list.begin(); + arg_it != arg_list.end(); ++arg_it) + lst += split_value_list((*arg_it)); + } else if(val.lower() == "join") { + if(arg_list.count() < 1 || arg_list.count() > 4) { fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four" "arguments.\n", parser.file.latin1(), parser.line_no); } else { QString glue, before, after; - if(args.count() >= 2) - glue = args[1].replace("\"", "" ); - if(args.count() >= 3) - before = args[2].replace("\"", "" ); - if(args.count() == 4) - after = args[3].replace("\"", "" ); - const QStringList &var = place[varMap(args.first())]; + if(arg_list.count() >= 2) + glue = arg_list[1].replace("\"", "" ); + if(arg_list.count() >= 3) + before = arg_list[2].replace("\"", "" ); + if(arg_list.count() == 4) + after = arg_list[3].replace("\"", "" ); + const QStringList &var = place[varMap(arg_list.first())]; if(!var.isEmpty()) replacement = before + var.join(glue) + after; } - } else if(reg_var.cap(1).lower() == "find") { - if(args.count() != 2) { + } else if(val.lower() == "find") { + if(arg_list.count() != 2) { fprintf(stderr, "%s:%d find(var, str) requires two arguments\n", parser.file.latin1(), parser.line_no); } else { - QRegExp regx(args[1]); - const QStringList &var = place[varMap(args.first())]; + QRegExp regx(arg_list[1]); + const QStringList &var = place[varMap(arg_list.first())]; for(QStringList::ConstIterator vit = var.begin(); vit != var.end(); ++vit) { if(regx.search(*vit) != -1) { if(!replacement.isEmpty()) replacement += " "; replacement += (*vit); } } } - } else if(reg_var.cap(1).lower() == "system") { - if(args.count() != 1) { + } else if(val.lower() == "system") { + if(arg_list.count() != 1) { fprintf(stderr, "%s:%d system(execut) requires one argument\n", parser.file.latin1(), parser.line_no); } else { char buff[256]; - FILE *proc = QT_POPEN(args.join(" ").latin1(), "r"); + FILE *proc = QT_POPEN(arg_list.join(" ").latin1(), "r"); while(proc && !feof(proc)) { int read_in = fread(buff, 1, 255, proc); if(!read_in) break; for(int i = 0; i < read_in; i++) { if(buff[i] == '\n' || buff[i] == '\t') buff[i] = ' '; } buff[read_in] = '\0'; replacement += buff; } } } else { fprintf(stderr, "%s:%d: Unknown replace function: %s\n", - parser.file.latin1(), parser.line_no, reg_var.cap(1).latin1()); - } - } else { //variable - if(reg_var.cap(1).left(1) == ".") - replacement = ""; - else if(reg_var.cap(1) == "LITERAL_WHITESPACE") - replacement = "\t"; - else - replacement = place[varMap(reg_var.cap(1))].join(" "); + parser.file.latin1(), parser.line_no, val.latin1()); } - debug_msg(2, "Project parser: %d (%s) :: %s -> %s", x, str.latin1(), - reg_var.capturedTexts().join("::").latin1(), replacement.latin1()); - str.replace(rep, reg_var.matchedLength(), replacement); } + //actually do replacement now.. + int mlen = var_incr - var_begin; + debug_msg(2, "Project Parser [var replace]: '%s' :: %s -> %s", str.latin1(), + str.mid(var_begin, mlen).latin1(), replacement.latin1()); + str.replace(var_begin, mlen, replacement); + var_begin += replacement.length(); } return str; } diff --git a/qmake/project.h b/qmake/project.h index 201e63c..ec19f0c 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -1,114 +1,114 @@ /**************************************************************************** ** $Id$ ** ** Definition of ________ class. ** ** Created : 970521 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the network module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition licenses may use this ** file in accordance with the Qt Commercial License Agreement provided ** with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef __QMAKE_H__ -#define __QMAKE_H__ +#ifndef __PROJECT_H__ +#define __PROJECT_H__ #include <qstringlist.h> #include <qstring.h> #include <qmap.h> class QMakeProject { enum TestStatus { TestNone, TestFound, TestSeek } test_status; int scope_block, scope_flag; QString pfile, cfile; QMap<QString, QStringList> vars, base_vars, cache; - bool parse(QString text, QMap<QString, QStringList> &place); - bool doProjectTest(QString func, const QString ¶ms, QMap<QString, QStringList> &place); - bool doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place); + bool parse(const QString &text, QMap<QString, QStringList> &place); + bool doProjectTest(const QString &func, const QString ¶ms, QMap<QString, QStringList> &place); + bool doProjectTest(const QString &func, QStringList args, QMap<QString, QStringList> &place); bool doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place); QString doVariableReplace(QString &str, const QMap<QString, QStringList> &place); public: QMakeProject(); - bool read(QString project, QString pwd); + bool read(const QString &project, const QString &pwd, bool just_project=FALSE); QString projectFile(); QString configFile(); bool isEmpty(const QString &v); QStringList &values(const QString &v); QString first(const QString &v); QMap<QString, QStringList> &variables(); - bool isActiveConfig(const QString &x); + bool isActiveConfig(const QString &x, bool regex=FALSE); protected: friend class MakefileGenerator; - bool read(QString file, QMap<QString, QStringList> &place); + bool read(const QString &file, QMap<QString, QStringList> &place); }; inline QString QMakeProject::projectFile() { #if defined(Q_CC_SUN) && (__SUNPRO_CC == 0x500) || defined(Q_CC_HP) // workaround for Sun WorkShop 5.0 bug fixed in Forte 6 if (pfile == "-") return QString("(stdin)"); else return pfile; #else return pfile == "-" ? QString("(stdin)") : pfile; #endif } inline QString QMakeProject::configFile() { return cfile; } inline bool QMakeProject::isEmpty(const QString &v) { return !vars.contains(v) || vars[v].isEmpty(); } inline QStringList &QMakeProject::values(const QString &v) { return vars[v]; } inline QString QMakeProject::first(const QString &v) { #if defined(Q_CC_SUN) && (__SUNPRO_CC == 0x500) || defined(Q_CC_HP) // workaround for Sun WorkShop 5.0 bug fixed in Forte 6 if (isEmpty(v)) return QString(""); else return vars[v].first(); #else return isEmpty(v) ? QString("") : vars[v].first(); #endif } inline QMap<QString, QStringList> &QMakeProject::variables() { return vars; } -#endif /* __QMAKE_H__ */ +#endif /* __PROJECT_H__ */ diff --git a/qmake/tools/qbitarray.cpp b/qmake/tools/qbitarray.cpp index 4f4e14b..1aaf963 100644 --- a/qmake/tools/qbitarray.cpp +++ b/qmake/tools/qbitarray.cpp @@ -1,584 +1,585 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QBitArray class ** ** Created : 940118 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qbitarray.h" #include "qdatastream.h" #define SHBLOCK ((bitarr_data*)(sharedBlock())) /*! \class QBitVal qbitarray.h \reentrant \brief The QBitVal class is an internal class, used with QBitArray. \ingroup collection The QBitVal is required by the indexing [] operator on bit arrays. It is not for use in any other context. */ /*! \fn QBitVal::QBitVal (QBitArray* a, uint i) Constructs a reference to element \a i in the QBitArray \a a. This is what QBitArray::operator[] constructs its return value with. */ /*! \fn QBitVal::operator int() Returns the value referenced by the QBitVal. */ /*! \fn QBitVal& QBitVal::operator= (const QBitVal& v) Sets the value referenced by the QBitVal to that referenced by QBitVal \a v. */ /*! \overload QBitVal& QBitVal::operator= (bool v) Sets the value referenced by the QBitVal to \a v. */ /*! \class QBitArray qbitarray.h \reentrant \brief The QBitArray class provides an array of bits. \ingroup collection \ingroup tools \ingroup shared Because QBitArray is a QMemArray, it uses explicit \link shclass.html sharing\endlink with a reference count. A QBitArray is a special byte array that can access individual bits and perform bit-operations (AND, OR, XOR and NOT) on entire arrays or bits. Bits can be manipulated by the setBit() and clearBit() functions, but it is also possible to use the indexing [] operator to test and set individual bits. The [] operator is a little slower than setBit() and clearBit() because some tricks are required to implement single-bit assignments. Example: \code QBitArray a(3); a.setBit( 0 ); a.clearBit( 1 ); a.setBit( 2 ); // a = [1 0 1] QBitArray b(3); b[0] = 1; b[1] = 1; b[2] = 0; // b = [1 1 0] QBitArray c; c = ~a & b; // c = [0 1 0] \endcode When a QBitArray is constructed the bits are uninitialized. Use fill() to set all the bits to 0 or 1. The array can be resized with resize() and copied with copy(). Bits can be set with setBit() and cleared with clearBit(). Bits can be toggled with toggleBit(). A bit's value can be obtained with testBit() and with at(). QBitArray supports the \& (AND), | (OR), ^ (XOR) and ~ (NOT) operators. */ /*! \class QBitArray::bitarr_data \brief The QBitArray::bitarr_data class is internal. \internal */ /*! Constructs an empty bit array. */ QBitArray::QBitArray() : QByteArray( 0, 0 ) { bitarr_data *x = new bitarr_data; Q_CHECK_PTR( x ); x->nbits = 0; setSharedBlock( x ); } /*! Constructs a bit array of \a size bits. The bits are uninitialized. \sa fill() */ QBitArray::QBitArray( uint size ) : QByteArray( 0, 0 ) { bitarr_data *x = new bitarr_data; Q_CHECK_PTR( x ); x->nbits = 0; setSharedBlock( x ); resize( size ); } /*! \fn QBitArray::QBitArray( const QBitArray &a ) Constructs a shallow copy of \a a. */ /*! \fn QBitArray &QBitArray::operator=( const QBitArray &a ) Assigns a shallow copy of \a a to this bit array and returns a reference to this array. */ /*! Pad last byte with 0-bits. */ void QBitArray::pad0() { uint sz = size(); if ( sz && sz%8 ) *(data()+sz/8) &= (1 << (sz%8)) - 1; } /*! \fn uint QBitArray::size() const Returns the bit array's size (number of bits). \sa resize() */ /*! Resizes the bit array to \a size bits and returns TRUE if the bit - array could be resized; otherwise returns FALSE. + array could be resized; otherwise returns FALSE. The array becomes + a null array if \a size == 0. If the array is expanded, the new bits are set to 0. \sa size() */ bool QBitArray::resize( uint size ) { uint s = this->size(); if ( !QByteArray::resize( (size+7)/8 ) ) return FALSE; // cannot resize SHBLOCK->nbits = size; if ( size != 0 ) { // not null array int ds = (int)(size+7)/8 - (int)(s+7)/8;// number of bytes difference if ( ds > 0 ) // expanding array memset( data() + (s+7)/8, 0, ds ); // reset new data } return TRUE; } /*! Fills the bit array with \a v (1's if \a v is TRUE, or 0's if \a v is FALSE). fill() resizes the bit array to \a size bits if \a size is nonnegative. Returns FALSE if a nonnegative \e size was specified and the bit array could not be resized; otherwise returns TRUE. \sa resize() */ bool QBitArray::fill( bool v, int size ) { if ( size >= 0 ) { // resize first if ( !resize( size ) ) return FALSE; // cannot resize } else { size = this->size(); } if ( size > 0 ) memset( data(), v ? 0xff : 0, (size + 7) / 8 ); if ( v ) pad0(); return TRUE; } /*! Detaches from shared bit array data and makes sure that this bit array is the only one referring to the data. If multiple bit arrays share common data, this bit array dereferences the data and gets a copy of the data. Nothing happens if there is only a single reference. \sa copy() */ void QBitArray::detach() { int nbits = SHBLOCK->nbits; this->duplicate( *this ); SHBLOCK->nbits = nbits; } /*! Returns a deep copy of the bit array. \sa detach() */ QBitArray QBitArray::copy() const { QBitArray tmp; tmp.duplicate( *this ); ((bitarr_data*)(tmp.sharedBlock()))->nbits = SHBLOCK->nbits; return tmp; } /*! Returns TRUE if the bit at position \a index is set, i.e. is 1; otherwise returns FALSE. \sa setBit(), clearBit() */ bool QBitArray::testBit( uint index ) const { #if defined(QT_CHECK_RANGE) if ( index >= size() ) { qWarning( "QBitArray::testBit: Index %d out of range", index ); return FALSE; } #endif return (*(data()+(index>>3)) & (1 << (index & 7))) != 0; } /*! \overload Sets the bit at position \a index to 1. \sa clearBit() toggleBit() */ void QBitArray::setBit( uint index ) { #if defined(QT_CHECK_RANGE) if ( index >= size() ) { qWarning( "QBitArray::setBit: Index %d out of range", index ); return; } #endif *(data()+(index>>3)) |= (1 << (index & 7)); } /*! \fn void QBitArray::setBit( uint index, bool value ) Sets the bit at position \a index to \a value. Equivalent to: \code if ( value ) setBit( index ); else clearBit( index ); \endcode \sa clearBit() toggleBit() */ /*! Clears the bit at position \a index, i.e. sets it to 0. \sa setBit(), toggleBit() */ void QBitArray::clearBit( uint index ) { #if defined(QT_CHECK_RANGE) if ( index >= size() ) { qWarning( "QBitArray::clearBit: Index %d out of range", index ); return; } #endif *(data()+(index>>3)) &= ~(1 << (index & 7)); } /*! Toggles the bit at position \a index. If the previous value was 0, the new value will be 1. If the previous value was 1, the new value will be 0. \sa setBit(), clearBit() */ bool QBitArray::toggleBit( uint index ) { #if defined(QT_CHECK_RANGE) if ( index >= size() ) { qWarning( "QBitArray::toggleBit: Index %d out of range", index ); return FALSE; } #endif register uchar *p = (uchar *)data() + (index>>3); uchar b = (1 << (index & 7)); // bit position uchar c = *p & b; // read bit *p ^= b; // toggle bit return c; } /*! \fn bool QBitArray::at( uint index ) const Returns the value (0 or 1) of the bit at position \a index. \sa operator[]() */ /*! \fn QBitVal QBitArray::operator[]( int index ) Implements the [] operator for bit arrays. The returned QBitVal is a context object. It makes it possible to get and set a single bit value by its \a index position. Example: \code QBitArray a( 3 ); a[0] = 0; a[1] = 1; a[2] = a[0] ^ a[1]; \endcode The functions testBit(), setBit() and clearBit() are faster. \sa at() */ /*! \overload bool QBitArray::operator[]( int index ) const Implements the [] operator for constant bit arrays. */ /*! Performs the AND operation between all bits in this bit array and \a a. Returns a reference to this bit array. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \code QBitArray a( 3 ), b( 2 ); a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] b[0] = 1; b[1] = 0; // b = [1 0] a &= b; // a = [1 0 0] \endcode \sa operator|=(), operator^=(), operator~() */ QBitArray &QBitArray::operator&=( const QBitArray &a ) { resize( QMAX(size(), a.size()) ); register uchar *a1 = (uchar *)data(); register uchar *a2 = (uchar *)a.data(); int n = QMIN( QByteArray::size(), a.QByteArray::size() ); int p = QMAX( QByteArray::size(), a.QByteArray::size() ) - n; while ( n-- > 0 ) *a1++ &= *a2++; while ( p-- > 0 ) *a1++ = 0; return *this; } /*! Performs the OR operation between all bits in this bit array and \a a. Returns a reference to this bit array. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \code QBitArray a( 3 ), b( 2 ); a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] b[0] = 1; b[1] = 0; // b = [1 0] a |= b; // a = [1 0 1] \endcode \sa operator&=(), operator^=(), operator~() */ QBitArray &QBitArray::operator|=( const QBitArray &a ) { resize( QMAX(size(), a.size()) ); register uchar *a1 = (uchar *)data(); register uchar *a2 = (uchar *)a.data(); int n = QMIN( QByteArray::size(), a.QByteArray::size() ); while ( n-- > 0 ) *a1++ |= *a2++; return *this; } /*! Performs the XOR operation between all bits in this bit array and \a a. Returns a reference to this bit array. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \code QBitArray a( 3 ), b( 2 ); a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] b[0] = 1; b[1] = 0; // b = [1 0] a ^= b; // a = [0 0 1] \endcode \sa operator&=(), operator|=(), operator~() */ QBitArray &QBitArray::operator^=( const QBitArray &a ) { resize( QMAX(size(), a.size()) ); register uchar *a1 = (uchar *)data(); register uchar *a2 = (uchar *)a.data(); int n = QMIN( QByteArray::size(), a.QByteArray::size() ); while ( n-- > 0 ) *a1++ ^= *a2++; return *this; } /*! Returns a bit array that contains the inverted bits of this bit array. Example: \code QBitArray a( 3 ), b; a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] b = ~a; // b = [0 1 0] \endcode */ QBitArray QBitArray::operator~() const { QBitArray a( size() ); register uchar *a1 = (uchar *)data(); register uchar *a2 = (uchar *)a.data(); int n = QByteArray::size(); while ( n-- ) *a2++ = ~*a1++; a.pad0(); return a; } /*! \relates QBitArray Returns the AND result between the bit arrays \a a1 and \a a2. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \sa QBitArray::operator&=() */ QBitArray operator&( const QBitArray &a1, const QBitArray &a2 ) { QBitArray tmp = a1.copy(); tmp &= a2; return tmp; } /*! \relates QBitArray Returns the OR result between the bit arrays \a a1 and \a a2. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \sa QBitArray::operator|=() */ QBitArray operator|( const QBitArray &a1, const QBitArray &a2 ) { QBitArray tmp = a1.copy(); tmp |= a2; return tmp; } /*! \relates QBitArray Returns the XOR result between the bit arrays \a a1 and \a a2. The result has the length of the longest of the two bit arrays, with any missing bits (i.e. if one array is shorter than the other), taken to be 0. \sa QBitArray::operator^() */ QBitArray operator^( const QBitArray &a1, const QBitArray &a2 ) { QBitArray tmp = a1.copy(); tmp ^= a2; return tmp; } /* \enum QGArray::array_data diff --git a/qmake/tools/qbuffer.cpp b/qmake/tools/qbuffer.cpp index b213dd9..0fc90e4 100644 --- a/qmake/tools/qbuffer.cpp +++ b/qmake/tools/qbuffer.cpp @@ -1,495 +1,495 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QBuffer class ** ** Created : 930812 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qbuffer.h" #include <stdlib.h> /*! \class QBuffer qbuffer.h \reentrant \brief The QBuffer class is an I/O device that operates on a QByteArray. \ingroup io \ingroup collection QBuffer is used to read and write to a memory buffer. It is normally used with a QTextStream or a QDataStream. QBuffer has an associated QByteArray which holds the buffer data. The size() of the buffer is automatically adjusted as data is written. The constructor \c QBuffer(QByteArray) creates a QBuffer using an existing byte array. The byte array can also be set with setBuffer(). Writing to the QBuffer will modify the original byte array because QByteArray is \link shclass.html explicitly shared.\endlink Use open() to open the buffer before use and to set the mode (read-only, write-only, etc.). close() closes the buffer. The buffer must be closed before reopening or calling setBuffer(). A common way to use QBuffer is through \l QDataStream or \l QTextStream, which have constructors that take a QBuffer parameter. For convenience, there are also QDataStream and QTextStream constructors that take a QByteArray parameter. These constructors create and open an internal QBuffer. Note that QTextStream can also operate on a QString (a Unicode string); a QBuffer cannot. You can also use QBuffer directly through the standard QIODevice functions readBlock(), writeBlock() readLine(), at(), getch(), putch() and ungetch(). \sa QFile, QDataStream, QTextStream, QByteArray, \link shclass.html Shared Classes\endlink */ /*! Constructs an empty buffer. */ QBuffer::QBuffer() { setFlags( IO_Direct ); a_inc = 16; // initial increment a_len = 0; ioIndex = 0; } /*! Constructs a buffer that operates on \a buf. If you open the buffer in write mode (\c IO_WriteOnly or \c IO_ReadWrite) and write something into the buffer, \a buf will be modified. Example: \code QCString str = "abc"; QBuffer b( str ); b.open( IO_WriteOnly ); b.at( 3 ); // position at the 4th character (the terminating \0) b.writeBlock( "def", 4 ); // write "def" including the terminating \0 b.close(); // Now, str == "abcdef" with a terminating \0 \endcode \sa setBuffer() */ QBuffer::QBuffer( QByteArray buf ) : a(buf) { setFlags( IO_Direct ); a_len = a.size(); a_inc = (a_len > 512) ? 512 : a_len; // initial increment if ( a_inc < 16 ) a_inc = 16; ioIndex = 0; } /*! Destroys the buffer. */ QBuffer::~QBuffer() { } /*! Replaces the buffer's contents with \a buf and returns TRUE. Does nothing (and returns FALSE) if isOpen() is TRUE. Note that if you open the buffer in write mode (\c IO_WriteOnly or IO_ReadWrite) and write something into the buffer, \a buf is also modified because QByteArray is an explicitly shared class. \sa buffer(), open(), close() */ bool QBuffer::setBuffer( QByteArray buf ) { if ( isOpen() ) { #if defined(QT_CHECK_STATE) qWarning( "QBuffer::setBuffer: Buffer is open" ); #endif return FALSE; } a = buf; a_len = a.size(); a_inc = (a_len > 512) ? 512 : a_len; // initial increment if ( a_inc < 16 ) a_inc = 16; ioIndex = 0; return TRUE; } /*! \fn QByteArray QBuffer::buffer() const Returns this buffer's byte array. \sa setBuffer() */ /*! \reimp Opens the buffer in mode \a m. Returns TRUE if successful; otherwise returns FALSE. The buffer must be opened before use. The mode parameter \a m must be a combination of the following flags. \list \i \c IO_ReadOnly opens the buffer in read-only mode. \i \c IO_WriteOnly opens the buffer in write-only mode. \i \c IO_ReadWrite opens the buffer in read/write mode. \i \c IO_Append sets the buffer index to the end of the buffer. \i \c IO_Truncate truncates the buffer. \endlist \sa close(), isOpen() */ bool QBuffer::open( int m ) { if ( isOpen() ) { // buffer already open #if defined(QT_CHECK_STATE) qWarning( "QBuffer::open: Buffer already open" ); #endif return FALSE; } setMode( m ); if ( m & IO_Truncate ) { // truncate buffer - a.resize( 0 ); - a_len = 0; + a.resize( 1 ); + a_len = 1; } if ( m & IO_Append ) { // append to end of buffer ioIndex = a.size(); } else { ioIndex = 0; } a_inc = 16; setState( IO_Open ); setStatus( 0 ); return TRUE; } /*! \reimp Closes an open buffer. \sa open() */ void QBuffer::close() { if ( isOpen() ) { setFlags( IO_Direct ); ioIndex = 0; a_inc = 16; } } /*! \reimp The flush function does nothing for a QBuffer. */ void QBuffer::flush() { return; } /*! \fn QIODevice::Offset QBuffer::at() const \reimp */ /*! \fn QIODevice::Offset QBuffer::size() const \reimp */ /*! \reimp */ bool QBuffer::at( Offset pos ) { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QBuffer::at: Buffer is not open" ); return FALSE; } #endif if ( pos > a_len ) { #if defined(QT_CHECK_RANGE) #if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) qWarning( "QBuffer::at: Index %llu out of range", pos ); #else qWarning( "QBuffer::at: Index %lu out of range", pos ); #endif #endif return FALSE; } ioIndex = pos; return TRUE; } /*! \reimp */ Q_LONG QBuffer::readBlock( char *p, Q_ULONG len ) { #if defined(QT_CHECK_STATE) if ( !p ) { qWarning( "QBuffer::readBlock: Null pointer error" ); return -1; } if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::readBlock: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QBuffer::readBlock: Read operation not permitted" ); return -1; } #endif if ( ioIndex + len > a.size() ) { // overflow if ( ioIndex >= a.size() ) { return 0; } else { len = a.size() - ioIndex; } } memcpy( p, a.data()+ioIndex, len ); ioIndex += len; return len; } /*! \overload Q_LONG QBuffer::writeBlock( const QByteArray& data ) This convenience function is the same as calling \c{writeBlock( data.data(), data.size() )} with \a data. */ /*! Writes \a len bytes from \a p into the buffer at the current index position, overwriting any characters there and extending the buffer if necessary. Returns the number of bytes actually written. Returns -1 if an error occurred. \sa readBlock() */ Q_LONG QBuffer::writeBlock( const char *p, Q_ULONG len ) { if ( len == 0 ) return 0; #if defined(QT_CHECK_NULL) if ( p == 0 ) { qWarning( "QBuffer::writeBlock: Null pointer error" ); return -1; } #endif #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::writeBlock: Buffer not open" ); return -1; } if ( !isWritable() ) { // writing not permitted qWarning( "QBuffer::writeBlock: Write operation not permitted" ); return -1; } #endif if ( ioIndex + len >= a_len ) { // overflow Q_ULONG new_len = a_len + a_inc*((ioIndex+len-a_len)/a_inc+1); if ( !a.resize( new_len ) ) { // could not resize #if defined(QT_CHECK_NULL) qWarning( "QBuffer::writeBlock: Memory allocation error" ); #endif setStatus( IO_ResourceError ); return -1; } a_inc *= 2; // double increment a_len = new_len; a.shd->len = ioIndex + len; } memcpy( a.data()+ioIndex, p, len ); ioIndex += len; if ( a.shd->len < ioIndex ) a.shd->len = ioIndex; // fake (not alloc'd) length return len; } /*! \reimp */ Q_LONG QBuffer::readLine( char *p, Q_ULONG maxlen ) { #if defined(QT_CHECK_NULL) if ( p == 0 ) { qWarning( "QBuffer::readLine: Null pointer error" ); return -1; } #endif #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::readLine: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QBuffer::readLine: Read operation not permitted" ); return -1; } #endif if ( maxlen == 0 ) return 0; Q_ULONG start = ioIndex; char *d = a.data() + ioIndex; maxlen--; // make room for 0-terminator if ( a.size() - ioIndex < maxlen ) maxlen = a.size() - ioIndex; while ( maxlen-- ) { if ( (*p++ = *d++) == '\n' ) break; } *p = '\0'; ioIndex = d - a.data(); return ioIndex - start; } /*! \reimp */ int QBuffer::getch() { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::getch: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QBuffer::getch: Read operation not permitted" ); return -1; } #endif if ( ioIndex+1 > a.size() ) { // overflow setStatus( IO_ReadError ); return -1; } return uchar(*(a.data()+ioIndex++)); } /*! \reimp Writes the character \a ch into the buffer at the current index position, overwriting any existing character and extending the buffer if necessary. Returns \a ch, or -1 if an error occurred. \sa getch(), ungetch() */ int QBuffer::putch( int ch ) { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::putch: Buffer not open" ); return -1; } if ( !isWritable() ) { // writing not permitted qWarning( "QBuffer::putch: Write operation not permitted" ); return -1; } #endif if ( ioIndex + 1 >= a_len ) { // overflow char buf[1]; buf[0] = (char)ch; if ( writeBlock(buf,1) != 1 ) return -1; // write error } else { *(a.data() + ioIndex++) = (char)ch; if ( a.shd->len < ioIndex ) a.shd->len = ioIndex; } return ch; } /*! \reimp */ int QBuffer::ungetch( int ch ) { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // buffer not open qWarning( "QBuffer::ungetch: Buffer not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QBuffer::ungetch: Read operation not permitted" ); return -1; } #endif if ( ch != -1 ) { if ( ioIndex ) ioIndex--; else ch = -1; } return ch; } diff --git a/qmake/tools/qcomlibrary.cpp b/qmake/tools/qcomlibrary.cpp index a7162fc..2a1b75a 100644 --- a/qmake/tools/qcomlibrary.cpp +++ b/qmake/tools/qcomlibrary.cpp @@ -1,538 +1,535 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QComLibrary class ** ** Copyright (C) 2001-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qcomlibrary_p.h" #ifndef QT_NO_COMPONENT #include <qapplication.h> #include <qsettings.h> #include <qfileinfo.h> #include <qdatetime.h> #include <qcleanuphandler.h> #include <errno.h> #ifdef QT_THREAD_SUPPORT # include "qmutexpool_p.h" #endif // QT_THREAD_SUPPORT #ifndef QT_DEBUG_COMPONENT # if defined(QT_DEBUG) # define QT_DEBUG_COMPONENT 1 # endif #endif QComLibrary::QComLibrary( const QString &filename ) : QLibrary( filename ), entry( 0 ), libiface( 0 ), qt_version( 0 ) { } QComLibrary::~QComLibrary() { if ( autoUnload() ) unload(); + if ( libiface ) + libiface->release(); + if ( entry ) + entry->release(); } bool QComLibrary::unload() { if ( libiface ) { libiface->cleanup(); if ( !libiface->canUnload() ) return FALSE; libiface->release(); libiface = 0; } int refs = entry ? entry->release() : 0; if ( refs ) return FALSE; entry = 0; return QLibrary::unload(); } static bool qt_verify( const QString& library, uint version, uint flags, const QCString &key, bool warn ) { uint our_flags = 1; #if defined(QT_THREAD_SUPPORT) our_flags |= 2; #endif if ( (flags & 1) == 0 ) { if ( warn ) qWarning( "Conflict in %s:\n" " Plugin cannot be queried successfully!", (const char*) QFile::encodeName(library) ); } else if ( ( version > QT_VERSION ) || ( ( QT_VERSION & 0xff0000 ) > ( version & 0xff0000 ) ) ) { if ( warn ) qWarning( "Conflict in %s:\n" " Plugin uses incompatible Qt library (%d.%d.%d)!", (const char*) QFile::encodeName(library), (version&0xff0000) >> 16, (version&0xff00) >> 8, version&0xff ); } else if ( (flags & 2) != (our_flags & 2) ) { if ( warn ) qWarning( "Conflict in %s:\n" " Plugin uses %s Qt library!", (const char*) QFile::encodeName(library), (flags & 2) ? "multi threaded" : "single threaded" ); } else if ( key != QT_BUILD_KEY ) { if ( warn ) qWarning( "Conflict in %s:\n" " Plugin uses incompatible Qt library!\n" " expected build key \"%s\", got \"%s\".", (const char*) QFile::encodeName(library), QT_BUILD_KEY, key.isEmpty() ? "<null>" : (const char *) key ); } else { return TRUE; } return FALSE; } struct qt_token_info { qt_token_info( const char *f, const ulong fc ) : fields( f ), field_count( fc ), results( fc ), lengths( fc ) { results.fill( 0 ); lengths.fill( 0 ); } const char *fields; const ulong field_count; QMemArray<const char *> results; QMemArray<ulong> lengths; }; /* return values: 1 parse ok 0 eos -1 parse error */ static int qt_tokenize( const char *s, ulong s_len, ulong *advance, const qt_token_info &token_info ) { ulong pos = 0, field = 0, fieldlen = 0; char current; int ret = -1; *advance = 0; for (;;) { current = s[ pos ]; // next char ++pos; ++fieldlen; ++*advance; if ( ! current || pos == s_len + 1 ) { // save result token_info.results[ (int)field ] = s; token_info.lengths[ (int)field ] = fieldlen - 1; // end of string ret = 0; break; } if ( current == token_info.fields[ field ] ) { // save result token_info.results[ (int)field ] = s; token_info.lengths[ (int)field ] = fieldlen - 1; // end of field fieldlen = 0; ++field; if ( field == token_info.field_count - 1 ) { // parse ok ret = 1; } if ( field == token_info.field_count ) { // done parsing break; } // reset string and its length s = s + pos; s_len -= pos; pos = 0; } } return ret; } /* returns TRUE if the string s was correctly parsed, FALSE otherwise. */ static bool qt_parse_pattern( const char *s, uint *version, uint *flags, QCString *key ) { bool ret = TRUE; qt_token_info pinfo("=\n", 2); int parse; ulong at = 0, advance, parselen = qstrlen( s ); do { parse = qt_tokenize( s + at, parselen, &advance, pinfo ); if ( parse == -1 ) { ret = FALSE; break; } at += advance; parselen -= advance; if ( qstrncmp( "version", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { // parse version string qt_token_info pinfo2("..-", 3); if ( qt_tokenize( pinfo.results[ 1 ], pinfo.lengths[ 1 ], &advance, pinfo2 ) != -1 ) { QCString m( pinfo2.results[ 0 ], pinfo2.lengths[ 0 ] + 1 ); QCString n( pinfo2.results[ 1 ], pinfo2.lengths[ 1 ] + 1 ); QCString p( pinfo2.results[ 2 ], pinfo2.lengths[ 2 ] + 1 ); *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt(); } else { ret = FALSE; break; } } else if ( qstrncmp( "flags", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { // parse flags string char ch; *flags = 0; ulong p = 0, c = 0, bit = 0; while ( p < pinfo.lengths[ 1 ] ) { ch = pinfo.results[ 1 ][ p ]; bit = pinfo.lengths[ 1 ] - p - 1; c = 1 << bit; if ( ch == '1' ) { *flags |= c; } else if ( ch != '0' ) { ret = FALSE; break; } ++p; } } else if ( qstrncmp( "buildkey", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ){ // save buildkey *key = QCString( pinfo.results[ 1 ], pinfo.lengths[ 1 ] + 1 ); } } while ( parse == 1 && parselen > 0 ); return ret; } #if defined(Q_OS_UNIX) #if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) # define USE_MMAP # include <sys/types.h> # include <sys/mman.h> #endif // Q_OS_FREEBSD || Q_OS_LINUX static long qt_find_pattern( const char *s, ulong s_len, const char *pattern, ulong p_len ) { /* this uses the same algorithm as QString::findRev... we search from the end of the file because on the supported systems, the read-only data/text segments are placed at the end of the file. HOWEVER, when building with debugging enabled, all the debug symbols are placed AFTER the data/text segments. what does this mean? when building in release mode, the search is fast because the data we are looking for is at the end of the file... when building in debug mode, the search is slower because we have to skip over all the debugging symbols first */ if ( ! s || ! pattern || p_len > s_len ) return -1; ulong i, hs = 0, hp = 0, delta = s_len - p_len; for (i = 0; i < p_len; ++i ) { hs += s[delta + i]; hp += pattern[i]; } i = delta; for (;;) { if ( hs == hp && qstrncmp( s + i, pattern, p_len ) == 0 ) return i; if ( i == 0 ) break; --i; hs -= s[i + p_len]; hs += s[i]; } return -1; } /* This opens the specified library, mmaps it into memory, and searches for the QT_UCM_VERIFICATION_DATA. The advantage of this approach is that we can get the verification data without have to actually load the library. This lets us detect mismatches more safely. Returns FALSE if version/flags/key information is not present, or if the information could not be read. Returns TRUE if version/flags/key information is present and succesfully read. */ static bool qt_unix_query( const QString &library, uint *version, uint *flags, QCString *key ) { QFile file( library ); if (! file.open( IO_ReadOnly ) ) { qWarning( "%s: %s", (const char*) QFile::encodeName(library), strerror( errno ) ); return FALSE; } QByteArray data; char *filedata = 0; ulong fdlen = 0; #ifdef USE_MMAP char *mapaddr = 0; size_t maplen = file.size(); mapaddr = (char *) mmap( mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0 ); if ( mapaddr != MAP_FAILED ) { // mmap succeeded filedata = mapaddr; fdlen = maplen; } else { // mmap failed qWarning( "mmap: %s", strerror( errno ) ); #endif // USE_MMAP // try reading the data into memory instead data = file.readAll(); filedata = data.data(); fdlen = data.size(); #ifdef USE_MMAP } #endif // USE_MMAP // verify that the pattern is present in the plugin const char *pattern = "pattern=QT_UCM_VERIFICATION_DATA"; const ulong plen = qstrlen( pattern ); long pos = qt_find_pattern( filedata, fdlen, pattern, plen ); bool ret = FALSE; if ( pos >= 0 ) { ret = qt_parse_pattern( filedata + pos, version, flags, key ); } #ifdef USE_MMAP if ( mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0 ) { qWarning( "munmap: %s", strerror( errno ) ); } #endif // USE_MMAP file.close(); return ret; } #endif // Q_OS_UNIX static QSettings *cache = 0; static QSingleCleanupHandler<QSettings> cleanup_cache; void QComLibrary::createInstanceInternal() { if ( library().isEmpty() ) return; QFileInfo fileinfo( library() ); QString lastModified = fileinfo.lastModified().toString(); QString regkey = QString("/Qt Plugins %1.%2/%3") .arg( ( QT_VERSION & 0xff0000 ) >> 16 ) .arg( ( QT_VERSION & 0xff00 ) >> 8 ) .arg( library() ); QStringList reg; uint flags = 0; QCString key; bool query_done = FALSE; bool warn_mismatch = TRUE; - if ( ! query_done ) { - #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cache ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &cache ) : 0 ); #endif // QT_THREAD_SUPPORT if ( ! cache ) { cache = new QSettings; cache->insertSearchPath( QSettings::Windows, "/Trolltech" ); cleanup_cache.set( &cache ); } reg = cache->readListEntry( regkey ); if ( reg.count() == 4 ) { // check timestamp if ( lastModified == reg[3] ) { qt_version = reg[0].toUInt(0, 16); flags = reg[1].toUInt(0, 16); key = reg[2].latin1(); query_done = TRUE; warn_mismatch = FALSE; } } - } #if defined(Q_OS_UNIX) if ( ! query_done ) { // get the query information directly from the plugin without loading if ( qt_unix_query( library(), &qt_version, &flags, &key ) ) { // info read succesfully from library query_done = TRUE; } } #else // !Q_OS_UNIX if ( ! query_done ) { // get the query information by loading the plugin if ( !isLoaded() ) { Q_ASSERT( entry == 0 ); if ( !load() ) return; } # ifdef Q_CC_BOR typedef const char * __stdcall (*UCMQueryVerificationDataProc)(); # else typedef const char * (*UCMQueryVerificationDataProc)(); # endif UCMQueryVerificationDataProc ucmQueryVerificationdataProc; ucmQueryVerificationdataProc = (UCMQueryVerificationDataProc) resolve( "qt_ucm_query_verification_data" ); if ( !ucmQueryVerificationdataProc || !qt_parse_pattern( ucmQueryVerificationdataProc(), &qt_version, &flags, &key ) ) { qt_version = flags = 0; key = "unknown"; } else { query_done = TRUE; } } #endif // Q_OS_UNIX QStringList queried; queried << QString::number( qt_version,16 ) << QString::number( flags, 16 ) << key << lastModified; if ( queried != reg ) { - -#ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cache ) ); -#endif // QT_THREAD_SUPPORT - cache->writeEntry( regkey, queried ); // delete the cache, which forces the settings to be written delete cache; cache = 0; } if ( ! query_done ) { if ( warn_mismatch ) { qWarning( "Conflict in %s:\n Plugin cannot be queried successfully!", (const char*) QFile::encodeName( library() ) ); } unload(); return; } if ( ! qt_verify( library(), qt_version, flags, key, warn_mismatch ) ) { unload(); return; } else if ( !isLoaded() ) { Q_ASSERT( entry == 0 ); if ( !load() ) return; } #ifdef Q_CC_BOR typedef QUnknownInterface* __stdcall (*UCMInstanceProc)(); #else typedef QUnknownInterface* (*UCMInstanceProc)(); #endif UCMInstanceProc ucmInstanceProc; ucmInstanceProc = (UCMInstanceProc) resolve( "ucm_instantiate" ); #if defined(QT_DEBUG_COMPONENT) if ( !ucmInstanceProc ) qWarning( "%s: Not a UCOM library.", (const char*) QFile::encodeName(library()) ); #endif entry = ucmInstanceProc ? ucmInstanceProc() : 0; if ( entry ) { if ( entry->queryInterface( IID_QLibrary, (QUnknownInterface**)&libiface ) == QS_OK ) { if ( libiface && !libiface->init() ) { libiface->release(); libiface = 0; unload(); return; } } } else { #if defined(QT_DEBUG_COMPONENT) qWarning( "%s: No exported component provided.", (const char*) QFile::encodeName(library()) ); #endif unload(); } } QRESULT QComLibrary::queryInterface( const QUuid& request, QUnknownInterface** iface ) { if ( !entry ) createInstanceInternal(); return entry ? entry->queryInterface( request, iface ) : QE_NOCOMPONENT; } uint QComLibrary::qtVersion() { if ( !entry ) createInstanceInternal(); return entry ? qt_version : 0; } #endif // QT_NO_COMPONENT diff --git a/qmake/tools/qconfig.cpp b/qmake/tools/qconfig.cpp index 433827c..5297a4e 100644 --- a/qmake/tools/qconfig.cpp +++ b/qmake/tools/qconfig.cpp @@ -1,17 +1,17 @@ /* Install paths from configure */ -static const char QT_INSTALL_PREFIX [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2"; -static const char QT_INSTALL_BINS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/bin"; -static const char QT_INSTALL_DOCS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/doc"; -static const char QT_INSTALL_HEADERS[256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/include"; -static const char QT_INSTALL_LIBS [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/lib"; -static const char QT_INSTALL_PLUGINS[256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2/plugins"; -static const char QT_INSTALL_DATA [256] = "/usr/src/coding/projects/userspace/qt-embedded-free-3.1.0-b2"; +static const char QT_INSTALL_PREFIX [256] = "/opt/qt-x11-free-3.1.2"; +static const char QT_INSTALL_BINS [256] = "/opt/qt-x11-free-3.1.2/bin"; +static const char QT_INSTALL_DOCS [256] = "/opt/qt-x11-free-3.1.2/doc"; +static const char QT_INSTALL_HEADERS[256] = "/opt/qt-x11-free-3.1.2/include"; +static const char QT_INSTALL_LIBS [256] = "/opt/qt-x11-free-3.1.2/lib"; +static const char QT_INSTALL_PLUGINS[256] = "/opt/qt-x11-free-3.1.2/plugins"; +static const char QT_INSTALL_DATA [256] = "/opt/qt-x11-free-3.1.2"; const char *qInstallPath() { return QT_INSTALL_PREFIX; } const char *qInstallPathDocs() { return QT_INSTALL_DOCS; } const char *qInstallPathHeaders() { return QT_INSTALL_HEADERS; } const char *qInstallPathLibs() { return QT_INSTALL_LIBS; } const char *qInstallPathBins() { return QT_INSTALL_BINS; } const char *qInstallPathPlugins() { return QT_INSTALL_PLUGINS; } const char *qInstallPathData() { return QT_INSTALL_DATA; } diff --git a/qmake/tools/qcriticalsection_p.cpp b/qmake/tools/qcriticalsection_p.cpp index 60fc8bd..c375730 100644 --- a/qmake/tools/qcriticalsection_p.cpp +++ b/qmake/tools/qcriticalsection_p.cpp @@ -1,75 +1,73 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QCriticalSection class ** -** Created : -** ** Copyright (C) 2001 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #if defined(QT_THREAD_SUPPORT) #include "qt_windows.h" #include <private/qcriticalsection_p.h> class QCriticalSectionPrivate { public: QCriticalSectionPrivate() {} CRITICAL_SECTION section; }; QCriticalSection::QCriticalSection() { d = new QCriticalSectionPrivate; InitializeCriticalSection( &d->section ); } QCriticalSection::~QCriticalSection() { DeleteCriticalSection( &d->section ); delete d; } void QCriticalSection::enter() { EnterCriticalSection( &d->section ); } void QCriticalSection::leave() { LeaveCriticalSection( &d->section ); } #endif diff --git a/qmake/tools/qcstring.cpp b/qmake/tools/qcstring.cpp index cf1b853..4651b97 100644 --- a/qmake/tools/qcstring.cpp +++ b/qmake/tools/qcstring.cpp @@ -1,2474 +1,2511 @@ /**************************************************************************** ** $Id$ ** ** Implementation of extended char array operations, and QByteArray and ** QCString classes ** ** Created : 920722 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qstring.h" #include "qregexp.h" #include "qdatastream.h" #ifdef QT_THREAD_SUPPORT # include <private/qmutexpool_p.h> #endif // QT_THREAD_SUPPORT #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <ctype.h> #include <limits.h> #ifndef QT_NO_COMPRESS #include "../3rdparty/zlib/zlib.h" #endif /***************************************************************************** Safe and portable C string functions; extensions to standard string.h *****************************************************************************/ /*! \relates QCString This function is normally part of the C library. Qt implements memmove() for platforms that do not provide it. memmove() copies \a len bytes from \a src into \a dst. The data is copied correctly even if \a src and \a dst overlap. */ void *qmemmove( void *dst, const void *src, uint len ) { register char *d; register char *s; if ( dst > src ) { d = (char *)dst + len - 1; s = (char *)src + len - 1; while ( len-- ) *d-- = *s--; } else if ( dst < src ) { d = (char *)dst; s = (char *)src; while ( len-- ) *d++ = *s++; } return dst; } /*! \relates QCString Returns a duplicate string. Allocates space for a copy of \a src, copies it, and returns a pointer to the copy. If \a src is 0, it immediately returns 0. The returned string must be deleted using \c delete[]. */ char *qstrdup( const char *src ) { if ( !src ) return 0; char *dst = new char[strlen(src)+1]; Q_CHECK_PTR( dst ); return strcpy( dst, src ); } /*! \fn char *qstrcpy( char *dst, const char *src ) \relates QCString A safe strcpy() function. Copies all characters up to and including the '\0' from \a src into \a dst and returns a pointer to \a dst. */ /*! \relates QCString A safe strncpy() function. Copies at most \a len bytes from \a src (stopping at \a len or the terminating '\0' whichever comes first) into \a dst and returns a pointer to \a dst. Guarantees that \a dst is '\0'-terminated. If \a src or \a dst is 0, returns 0 immediately. \sa qstrcpy() */ char *qstrncpy( char *dst, const char *src, uint len ) { if ( !src || !dst ) return 0; strncpy( dst, src, len ); if ( len > 0 ) dst[len-1] = '\0'; return dst; } /*! + \fn uint qstrlen( const char *str ); + + \relates QCString + + A safe strlen function. + + Returns the number of characters that precede the terminating '\0'. + or 0 if \a str is 0. +*/ + +/*! \fn int qstrcmp( const char *str1, const char *str2 ); \relates QCString A safe strcmp() function. Compares \a str1 and \a str2. Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. Special case I: Returns 0 if \a str1 and \a str2 are both 0. Special case II: Returns a random nonzero value if \a str1 is 0 or \a str2 is 0 (but not both). \sa qstrncmp() qstricmp() qstrnicmp() \link #asciinotion Note on character comparisons \endlink */ /*! \fn int qstrncmp( const char *str1, const char *str2, uint len ); \relates QCString A safe strncmp() function. Compares at most \a len bytes of \a str1 and \a str2. Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. Special case I: Returns 0 if \a str1 and \a str2 are both 0. Special case II: Returns a random nonzero value if \a str1 is 0 or \a str2 is 0 (but not both). \sa qstrcmp(), qstricmp(), qstrnicmp() \link #asciinotion Note on character comparisons \endlink */ /*! \relates QCString A safe stricmp() function. Compares \a str1 and \a str2 ignoring the case. Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. Special case I: Returns 0 if \a str1 and \a str2 are both 0. Special case II: Returns a random nonzero value if \a str1 is 0 or \a str2 is 0 (but not both). \sa qstrcmp(), qstrncmp(), qstrnicmp() \link #asciinotion Note on character comparisons \endlink */ int qstricmp( const char *str1, const char *str2 ) { register const uchar *s1 = (const uchar *)str1; register const uchar *s2 = (const uchar *)str2; int res; uchar c; if ( !s1 || !s2 ) return s1 ? 1 : ( s2 ? -1 : 0 ); for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ ) if ( !c ) // strings are equal break; return res; } /*! \relates QCString A safe strnicmp() function. Compares at most \a len bytes of \a str1 and \a str2 ignoring the case. Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. Special case I: Returns 0 if \a str1 and \a str2 are both 0. Special case II: Returns a random nonzero value if \a str1 is 0 or \a str2 is 0 (but not both). \sa qstrcmp(), qstrncmp() qstricmp() \link #asciinotion Note on character comparisons \endlink */ int qstrnicmp( const char *str1, const char *str2, uint len ) { register const uchar *s1 = (const uchar *)str1; register const uchar *s2 = (const uchar *)str2; int res; uchar c; if ( !s1 || !s2 ) return s1 ? 1 : ( s2 ? -1 : 0 ); for ( ; len--; s1++, s2++ ) { if ( (res = (c=tolower(*s1)) - tolower(*s2)) ) return res; if ( !c ) // strings are equal break; } return 0; } static Q_UINT16 crc_tbl[16]; static bool crc_tbl_init = FALSE; static void createCRC16Table() // build CRC16 lookup table { register uint i; register uint j; uint v0, v1, v2, v3; for ( i = 0; i < 16; i++ ) { v0 = i & 1; v1 = ( i >> 1 ) & 1; v2 = ( i >> 2 ) & 1; v3 = ( i >> 3 ) & 1; j = 0; #undef SET_BIT #define SET_BIT(x, b, v) (x) |= (v) << (b) SET_BIT( j, 0, v0 ); SET_BIT( j, 7, v0 ); SET_BIT( j, 12, v0 ); SET_BIT( j, 1, v1 ); SET_BIT( j, 8, v1 ); SET_BIT( j, 13, v1 ); SET_BIT( j, 2, v2 ); SET_BIT( j, 9, v2 ); SET_BIT( j, 14, v2 ); SET_BIT( j, 3, v3 ); SET_BIT( j, 10, v3 ); SET_BIT( j, 15, v3 ); crc_tbl[i] = j; } } /*! \relates QMemArray Returns the CRC-16 checksum of \a len bytes starting at \a data. The checksum is independent of the byte order (endianness). */ Q_UINT16 qChecksum( const char *data, uint len ) { if ( !crc_tbl_init ) { // create lookup table #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &crc_tbl_init ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &crc_tbl_init ) : 0 ); #endif // QT_THREAD_SUPPORT if ( !crc_tbl_init ) { createCRC16Table(); crc_tbl_init = TRUE; } } register Q_UINT16 crc = 0xffff; uchar c; uchar *p = (uchar *)data; while ( len-- ) { c = *p++; crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; c >>= 4; crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; } return ~crc & 0xffff; } -/*! \fn QByteArray qCompress( const QByteArray& data) +/*! + \fn QByteArray qCompress( const QByteArray& data ) + \relates QByteArray - \overload + + Compresses the array \a data and returns the compressed byte + array. + + \sa qUncompress() */ /*! \relates QByteArray + \overload + Compresses the array \a data which is \a nbytes long and returns the compressed byte array. - - \sa qUncompress() */ #ifndef QT_NO_COMPRESS QByteArray qCompress( const uchar* data, int nbytes ) { if ( nbytes == 0 ) { QByteArray tmp( 4 ); tmp.fill( 0 ); return tmp; } if ( !data ) { #if defined(QT_CHECK_RANGE) qWarning( "qCompress: data is NULL." ); #endif return QByteArray(); } ulong len = nbytes * 2; QByteArray bazip; int res; do { bazip.resize( len + 4 ); res = ::compress( (uchar*)bazip.data()+4, &len, (uchar*)data, nbytes ); switch ( res ) { case Z_OK: bazip.resize( len + 4 ); bazip[0] = ( nbytes & 0xff000000 ) >> 24; bazip[1] = ( nbytes & 0x00ff0000 ) >> 16; bazip[2] = ( nbytes & 0x0000ff00 ) >> 8; bazip[3] = ( nbytes & 0x000000ff ); break; case Z_MEM_ERROR: #if defined(QT_CHECK_RANGE) qWarning( "qCompress: Z_MEM_ERROR: Not enough memory." ); #endif bazip.resize( 0 ); break; case Z_BUF_ERROR: len *= 2; break; } } while ( res == Z_BUF_ERROR ); return bazip; } #endif -/*! \fn QByteArray qUncompress( const QByteArray& data ) +/*! + \fn QByteArray qUncompress( const QByteArray& data ) + \relates QByteArray - \overload + + Uncompresses the array \a data and returns the uncompressed byte + array. + + Returns an empty QByteArray if the input data was corrupt. + \omit + ADD THE FOLLOWING FOR Qt 4.0 + This function will uncompress data compressed with qCompress() + from this and any earlier Qt version, back to Qt 3.1 when this + feature was added. + \endomit + + \sa qCompress() */ /*! \relates QByteArray + \overload + Uncompresses the array \a data which is \a nbytes long and returns the uncompressed byte array. - - Returns an empty QByteArray if the input data was corrupt. - - \sa qCompress() */ #ifndef QT_NO_COMPRESS QByteArray qUncompress( const uchar* data, int nbytes ) { if ( !data ) { #if defined(QT_CHECK_RANGE) qWarning( "qUncompress: data is NULL." ); #endif return QByteArray(); } if ( nbytes <= 4 ) { #if defined(QT_CHECK_RANGE) if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) ) qWarning( "qUncompress: Input data is corrupted." ); #endif return QByteArray(); } ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3]; ulong len = QMAX( expectedSize, 1 ); QByteArray baunzip; int res; do { baunzip.resize( len ); res = ::uncompress( (uchar*)baunzip.data(), &len, (uchar*)data+4, nbytes-4 ); switch ( res ) { case Z_OK: if ( len != baunzip.size() ) baunzip.resize( len ); break; case Z_MEM_ERROR: #if defined(QT_CHECK_RANGE) qWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." ); #endif break; case Z_BUF_ERROR: len *= 2; break; case Z_DATA_ERROR: #if defined(QT_CHECK_RANGE) qWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." ); #endif break; } } while ( res == Z_BUF_ERROR ); if ( res != Z_OK ) baunzip = QByteArray(); return baunzip; } #endif /***************************************************************************** QByteArray documentation *****************************************************************************/ /*! \class QByteArray \reentrant \brief The QByteArray class provides an array of bytes. \ingroup collection \ingroup tools The QByteArray class provides an explicitly shared array of bytes. It is useful for manipulating memory areas with custom data. QByteArray is implemented as a QMemArray\<char\>. See the \l QMemArray documentation for further information. */ /*! \fn QByteArray::QByteArray() Constructs an empty QByteArray. */ /*! \fn QByteArray::QByteArray( int size ) Constructs a QByteArray of size \a size. */ /***************************************************************************** QByteArray stream functions *****************************************************************************/ /*! \relates QMemArray Writes byte array \a a to the stream \a s and returns a reference to the stream. \sa \link datastreamformat.html Format of the QDataStream operators \endlink */ #ifndef QT_NO_DATASTREAM QDataStream &operator<<( QDataStream &s, const QByteArray &a ) { return s.writeBytes( a.data(), a.size() ); } /*! \relates QMemArray Reads a byte array into \a a from the stream \a s and returns a reference to the stream. \sa \link datastreamformat.html Format of the QDataStream operators \endlink */ QDataStream &operator>>( QDataStream &s, QByteArray &a ) { Q_UINT32 len; s >> len; // read size of array if ( len == 0 || s.eof() ) { // end of file reached a.resize( 0 ); return s; } if ( !a.resize( (uint)len ) ) { // resize array #if defined(QT_CHECK_NULL) qWarning( "QDataStream: Not enough memory to read QByteArray" ); #endif len = 0; } if ( len > 0 ) // not null array s.readRawBytes( a.data(), (uint)len ); return s; } #endif //QT_NO_DATASTREAM /***************************************************************************** QCString member functions *****************************************************************************/ /*! \class QCString qcstring.h \reentrant \brief The QCString class provides an abstraction of the classic C zero-terminated char array (char *). \ingroup text \ingroup collection \ingroup tools \ingroup shared QCString inherits QByteArray, which is defined as QMemArray\<char\>. Since QCString is a QMemArray, it uses \link shclass.html explicit sharing\endlink with a reference count. QCString tries to behave like a more convenient \c{const char *}. The price of doing this is that some algorithms will perform badly. For example, append() is O(length()) since it scans for a null terminator. Although you might use QCString for text that is never exposed to the user, for most purposes, and especially for user-visible text, you should use QString. QString provides implicit sharing, Unicode and other internationalization support, and is well optimized. Note that for the QCString methods that take a \c{const char *} parameter the \c{const char *} must either be 0 (null) or not-null and '\0' (NUL byte) terminated; otherwise the results are undefined. A QCString that has not been assigned to anything is \e null, i.e. both the length and the data pointer is 0. A QCString that references the empty string ("", a single '\0' char) is \e empty. Both null and empty QCStrings are legal parameters to the methods. Assigning \c{const char *} 0 to QCString produces a null QCString. The length() function returns the length of the string; resize() resizes the string and truncate() truncates the string. A string can be filled with a character using fill(). Strings can be left or right padded with characters using leftJustify() and rightJustify(). Characters, strings and regular expressions can be searched for using find() and findRev(), and counted using contains(). Strings and characters can be inserted with insert() and appended with append(). A string can be prepended with prepend(). Characters can be removed from the string with remove() and replaced with replace(). Portions of a string can be extracted using left(), right() and mid(). Whitespace can be removed using stripWhiteSpace() and simplifyWhiteSpace(). Strings can be converted to uppercase or lowercase with upper() and lower() respectively. Strings that contain numbers can be converted to numbers with toShort(), toInt(), toLong(), toULong(), toFloat() and toDouble(). Numbers can be converted to strings with setNum(). Many operators are overloaded to work with QCStrings. QCString also supports some more obscure functions, e.g. sprintf(), setStr() and setExpand(). \target asciinotion \sidebar Note on Character Comparisons In QCString the notion of uppercase and lowercase and of which character is greater than or less than another character is locale dependent. This affects functions which support a case insensitive option or which compare or lowercase or uppercase their arguments. Case insensitive operations and comparisons will be accurate if both strings contain only ASCII characters. (If \c $LC_CTYPE is set, most Unix systems do "the right thing".) Functions that this affects include contains(), find(), findRev(), \l operator<(), \l operator<=(), \l operator>(), \l operator>=(), lower() and upper(). This issue does not apply to \l{QString}s since they represent characters using Unicode. \endsidebar Performance note: The QCString methods for QRegExp searching are implemented by converting the QCString to a QString and performing the search on that. This implies a deep copy of the QCString data. If you are going to perform many QRegExp searches on a large QCString, you will get better performance by converting the QCString to a QString yourself, and then searching in the QString. */ /*! \fn QCString::QCString() Constructs a null string. \sa isNull() */ /*! \fn QCString::QCString( const QCString &s ) Constructs a shallow copy \a s. \sa assign() */ /*! Constructs a string with room for \a size characters, including the '\0'-terminator. Makes a null string if \a size == 0. If \a size \> 0, then the first and last characters in the string are initialized to '\0'. All other characters are uninitialized. \sa resize(), isNull() */ QCString::QCString( int size ) : QByteArray( size ) { if ( size > 0 ) { *data() = '\0'; // set terminator *(data()+(size-1)) = '\0'; } } /*! Constructs a string that is a deep copy of \a str. If \a str is 0 a null string is created. \sa isNull() */ QCString::QCString( const char *str ) { duplicate( str, qstrlen(str) + 1 ); } /*! Constructs a string that is a deep copy of \a str. The copy will be at most \a maxsize bytes long including the '\0'-terminator. Example: \code QCString str( "helloworld", 6 ); // assigns "hello" to str \endcode If \a str contains a 0 byte within the first \a maxsize bytes, the resulting QCString will be terminated by this 0. If \a str is 0 a null string is created. \sa isNull() */ QCString::QCString( const char *str, uint maxsize ) { if ( str == 0 ) return; uint len; // index of first '\0' for ( len = 0; len < maxsize - 1; len++ ) { if ( str[len] == '\0' ) break; } QByteArray::resize( len + 1 ); memcpy( data(), str, len ); data()[len] = 0; } /*! \reimp */ QCString::~QCString() { } /*! \fn QCString &QCString::operator=( const QCString &s ) Assigns a shallow copy of \a s to this string and returns a reference to this string. */ /*! \overload QCString &QCString::operator=( const char *str ) Assigns a deep copy of \a str to this string and returns a reference to this string. If \a str is 0 a null string is created. \sa isNull() */ /*! \fn bool QCString::isNull() const Returns TRUE if the string is null, i.e. if data() == 0; otherwise returns FALSE. A null string is also an empty string. Example: \code QCString a; // a.data() == 0, a.size() == 0, a.length() == 0 QCString b == ""; // b.data() == "", b.size() == 1, b.length() == 0 a.isNull(); // TRUE because a.data() == 0 a.isEmpty(); // TRUE because a.length() == 0 b.isNull(); // FALSE because b.data() == "" b.isEmpty(); // TRUE because b.length() == 0 \endcode \sa isEmpty(), length(), size() */ /*! \fn bool QCString::isEmpty() const Returns TRUE if the string is empty, i.e. if length() == 0; otherwise returns FALSE. An empty string is not always a null string. See example in isNull(). \sa isNull(), length(), size() */ /*! \fn uint QCString::length() const Returns the length of the string, excluding the '\0'-terminator. Equivalent to calling \c strlen(data()). Null strings and empty strings have zero length. \sa size(), isNull(), isEmpty() */ /*! \fn bool QCString::truncate( uint pos ) Truncates the string at position \a pos. Equivalent to calling \c resize(pos+1). Example: \code QCString s = "truncate this string"; s.truncate( 5 ); // s == "trunc" \endcode \sa resize() */ /*! Extends or shrinks the string to \a len bytes, including the '\0'-terminator. A '\0'-terminator is set at position \c{len - 1} unless \c{len == 0}. Example: \code QCString s = "resize this string"; s.resize( 7 ); // s == "resize" \endcode \sa truncate() */ bool QCString::resize( uint len ) { detach(); uint wasNull = isNull(); if ( !QByteArray::resize(len) ) return FALSE; if ( len ) data()[len - 1] = '\0'; if ( len > 0 && wasNull ) data()[0] = '\0'; return TRUE; } /*! Implemented as a call to the native vsprintf() (see the manual for your C library). If the string is shorter than 256 characters, this sprintf() calls resize(256) to decrease the chance of memory corruption. The string is resized back to its actual length before sprintf() returns. Example: \code QCString s; s.sprintf( "%d - %s", 1, "first" ); // result < 256 chars QCString big( 25000 ); // very long string big.sprintf( "%d - %s", 2, longString ); // result < 25000 chars \endcode \warning All vsprintf() implementations will write past the end of the target string (*this) if the \a format specification and arguments happen to be longer than the target string, and some will also fail if the target string is longer than some arbitrary implementation limit. Giving user-supplied arguments to sprintf() is risky: Sooner or later someone will paste a huge line into your application. */ QCString &QCString::sprintf( const char *format, ... ) { detach(); va_list ap; va_start( ap, format ); if ( size() < 256 ) QByteArray::resize( 256 ); // make string big enough vsprintf( data(), format, ap ); resize( qstrlen(data()) + 1 ); // truncate va_end( ap ); return *this; } /*! Fills the string with \a len bytes of character \a c, followed by a '\0'-terminator. If \a len is negative, then the current string length is used. Returns FALSE is \a len is nonnegative and there is not enough memory to resize the string; otherwise returns TRUE. */ bool QCString::fill( char c, int len ) { detach(); if ( len < 0 ) len = length(); if ( !QByteArray::fill(c,len+1) ) return FALSE; *(data()+len) = '\0'; return TRUE; } /*! \fn QCString QCString::copy() const Returns a deep copy of this string. \sa detach() */ /*! Finds the first occurrence of the character \a c, starting at position \a index. The search is case sensitive if \a cs is TRUE, or case insensitive if \a cs is FALSE. Returns the position of \a c, or -1 if \a c could not be found. \sa \link #asciinotion Note on character comparisons \endlink */ int QCString::find( char c, int index, bool cs ) const { if ( (uint)index >= size() ) // index outside string return -1; register const char *d; if ( cs ) { // case sensitive d = strchr( data()+index, c ); } else { d = data()+index; c = tolower( (uchar) c ); while ( *d && tolower((uchar) *d) != c ) d++; if ( !*d && c ) // not found d = 0; } return d ? (int)(d - data()) : -1; } #define REHASH( a ) \ if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \ hashHaystack -= (a) << sl_minus_1; \ hashHaystack <<= 1 /*! \overload Finds the first occurrence of the string \a str, starting at position \a index. The search is case sensitive if \a cs is TRUE, or case insensitive if \a cs is FALSE. Returns the position of \a str, or -1 if \a str could not be found. \sa \link #asciinotion Note on character comparisons \endlink */ int QCString::find( const char *str, int index, bool cs ) const { + return find( str, index, cs, length() ); +} + +int QCString::find( const char *str, int index, bool cs, uint l ) const +{ if ( (uint)index >= size() ) return -1; if ( !str ) return -1; if ( !*str ) return index; - const uint l = length(); const uint sl = qstrlen( str ); if ( sl + index > l ) return -1; if ( sl == 1 ) return find( *str, index, cs ); /* See QString::find() for details. */ const char* needle = str; const char* haystack = data() + index; const char* end = data() + (l-sl); const uint sl_minus_1 = sl-1; uint hashNeedle = 0, hashHaystack = 0,i; if ( cs ) { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + needle[i] ); hashHaystack = ((hashHaystack<<1) + haystack[i] ); } hashHaystack -= *(haystack+sl_minus_1); while ( haystack <= end ) { hashHaystack += *(haystack+sl_minus_1); if ( hashHaystack == hashNeedle && *needle == *haystack && qstrncmp( needle, haystack, sl ) == 0 ) return haystack - data(); REHASH( *haystack ); ++haystack; } } else { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + tolower( needle[i] ) ); hashHaystack = ((hashHaystack<<1) + tolower( haystack[i] ) ); } hashHaystack -= tolower(*(haystack+sl_minus_1)); while ( haystack <= end ) { hashHaystack += tolower(*(haystack+sl_minus_1)); if ( hashHaystack == hashNeedle && qstrnicmp( needle, haystack, sl ) == 0 ) return haystack - data(); REHASH( tolower(*haystack) ); ++haystack; } } return -1; } /*! Finds the first occurrence of the character \a c, starting at position \a index and searching backwards. The search is case sensitive if \a cs is TRUE, or case insensitive if \a cs is FALSE. Returns the position of \a c, or -1 if \a c could not be found. \sa \link #asciinotion Note on character comparisons \endlink */ int QCString::findRev( char c, int index, bool cs ) const { register const char *b = data(); register const char *d; if ( index < 0 ) index = length(); if ( (uint)index >= size() ) return -1; d = b + index; if ( cs ) { while ( d >= b && *d != c ) d--; } else { c = tolower( (uchar) c ); while ( d >= b && tolower((uchar) *d) != c ) d--; } return d >= b ? (int)(d - b) : -1; } /*! \overload Finds the first occurrence of the string \a str, starting at position \a index and searching backwards. The search is case sensitive if \a cs is TRUE, or case insensitive if \a cs is FALSE. Returns the position of \a str, or -1 if \a str could not be found. \sa \link #asciinotion Note on character comparisons \endlink */ int QCString::findRev( const char *str, int index, bool cs ) const { /* See QString::find() for explanations. */ const uint sl = qstrlen( str ); const uint l = length(); int delta = l-sl; if ( index < 0 ) index = delta; if ( index < 0 || index > (int)l ) return -1; if ( index > delta ) index = delta; if ( sl == 1 ) return findRev( *str, index, cs ); const char* needle = str; const char* haystack = data() + index; const char* end = data(); const uint sl_minus_1 = sl-1; const char* n = needle+sl_minus_1; const char* h = haystack+sl_minus_1; uint hashNeedle = 0, hashHaystack = 0, i; if ( cs ) { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + *(n-i) ); hashHaystack = ((hashHaystack<<1) + *(h-i) ); } hashHaystack -= *haystack; while ( haystack >= end ) { hashHaystack += *haystack; if ( hashHaystack == hashNeedle && qstrncmp( needle, haystack, sl ) == 0 ) return haystack-data(); --haystack; REHASH( *(haystack+sl) ); } } else { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + tolower( *(n-i) ) ); hashHaystack = ((hashHaystack<<1) + tolower( *(h-i) ) ); } hashHaystack -= tolower(*haystack); while ( haystack >= end ) { hashHaystack += tolower(*haystack); if ( hashHaystack == hashNeedle && qstrnicmp( needle, haystack, sl ) == 0 ) return haystack-data(); --haystack; REHASH( tolower(*(haystack+sl)) ); } } return -1; } /*! Returns the number of times the character \a c occurs in the string. The match is case sensitive if \a cs is TRUE, or case insensitive if \a cs if FALSE. \sa \link #asciinotion Note on character comparisons \endlink */ int QCString::contains( char c, bool cs ) const { int count = 0; char *d = data(); if ( !d ) return 0; if ( cs ) { // case sensitive while ( *d ) if ( *d++ == c ) count++; } else { // case insensitive c = tolower( (uchar) c ); while ( *d ) { if ( tolower((uchar) *d) == c ) count++; d++; } } return count; } /*! \overload Returns the number of times \a str occurs in the string. The match is case sensitive if \a cs is TRUE, or case insensitive if \a cs if FALSE. This function counts overlapping substrings, for example, "banana" contains two occurrences of "ana". \sa findRev() \link #asciinotion Note on character comparisons \endlink */ int QCString::contains( const char *str, bool cs ) const { int count = 0; int i = -1; + uint l = length(); // use find for the faster hashing algorithm - while ( ( i = find ( str, i+1, cs ) ) != -1 ) + while ( ( i = find ( str, i+1, cs, l ) ) != -1 ) count++; return count; } /*! Returns a substring that contains the \a len leftmost characters of the string. The whole string is returned if \a len exceeds the length of the string. Example: \code QCString s = "Pineapple"; QCString t = s.left( 4 ); // t == "Pine" \endcode \sa right(), mid() */ - QCString QCString::left( uint len ) const { if ( isEmpty() ) { QCString empty; return empty; } else if ( len >= size() ) { QCString same( data() ); return same; } else { QCString s( len+1 ); strncpy( s.data(), data(), len ); *(s.data()+len) = '\0'; return s; } } /*! Returns a substring that contains the \a len rightmost characters of the string. The whole string is returned if \a len exceeds the length of the string. Example: \code QCString s = "Pineapple"; QCString t = s.right( 5 ); // t == "apple" \endcode \sa left(), mid() */ QCString QCString::right( uint len ) const { if ( isEmpty() ) { QCString empty; return empty; } else { uint l = length(); if ( len > l ) len = l; char *p = data() + (l - len); return QCString( p ); } } /*! Returns a substring that contains at most \a len characters from this string, starting at position \a index. Returns a null string if the string is empty or if \a index is out of range. Returns the whole string from \a index if \a index+len exceeds the length of the string. Example: \code QCString s = "Two pineapples"; QCString t = s.mid( 4, 3 ); // t == "pin" \endcode \sa left(), right() */ QCString QCString::mid( uint index, uint len ) const { uint slen = qstrlen( data() ); if ( isEmpty() || index >= slen ) { QCString empty; return empty; } else { if ( len > slen-index ) len = slen - index; register char *p = data()+index; QCString s( len+1 ); strncpy( s.data(), p, len ); *(s.data()+len) = '\0'; return s; } } /*! Returns a string of length \a width (plus one for the terminating '\0') that contains this string padded with the \a fill character. If the length of the string exceeds \a width and \a truncate is FALSE (the default), then the returned string is a copy of the string. If the length of the string exceeds \a width and \a truncate is TRUE, then the returned string is a left(\a width). Example: \code QCString s("apple"); QCString t = s.leftJustify(8, '.'); // t == "apple..." \endcode \sa rightJustify() */ QCString QCString::leftJustify( uint width, char fill, bool truncate ) const { QCString result; int len = qstrlen(data()); int padlen = width - len; if ( padlen > 0 ) { result.QByteArray::resize( len+padlen+1 ); memcpy( result.data(), data(), len ); memset( result.data()+len, fill, padlen ); result[len+padlen] = '\0'; } else { if ( truncate ) result = left( width ); else result = copy(); } return result; } /*! Returns a string of length \a width (plus one for the terminating '\0') that contains zero or more of the \a fill character followed by this string. If the length of the string exceeds \a width and \a truncate is FALSE (the default), then the returned string is a copy of the string. If the length of the string exceeds \a width and \a truncate is TRUE, then the returned string is a left(\a width). Example: \code QCString s("pie"); QCString t = s.rightJustify(8, '.'); // t == ".....pie" \endcode \sa leftJustify() */ QCString QCString::rightJustify( uint width, char fill, bool truncate ) const { QCString result; int len = qstrlen(data()); int padlen = width - len; if ( padlen > 0 ) { result.QByteArray::resize( len+padlen+1 ); memset( result.data(), fill, padlen ); memcpy( result.data()+padlen, data(), len ); result[len+padlen] = '\0'; } else { if ( truncate ) result = left( width ); else result = copy(); } return result; } /*! Returns a new string that is a copy of this string converted to lower case. Example: \code QCString s("Credit"); QCString t = s.lower(); // t == "credit" \endcode \sa upper() \link #asciinotion Note on character comparisons \endlink */ QCString QCString::lower() const { QCString s( data() ); register char *p = s.data(); if ( p ) { while ( *p ) { *p = tolower( (uchar) *p ); p++; } } return s; } /*! Returns a new string that is a copy of this string converted to upper case. Example: \code QCString s( "Debit" ); QCString t = s.upper(); // t == "DEBIT" \endcode \sa lower() \link #asciinotion Note on character comparisons \endlink */ QCString QCString::upper() const { QCString s( data() ); register char *p = s.data(); if ( p ) { while ( *p ) { *p = toupper(*p); p++; } } return s; } /*! Returns a new string that has white space removed from the start and the end. White space means the decimal ASCII codes 9, 10, 11, 12, 13 and 32. Example: \code QCString s = " space "; QCString t = s.stripWhiteSpace(); // t == "space" \endcode \sa simplifyWhiteSpace() */ QCString QCString::stripWhiteSpace() const { if ( isEmpty() ) // nothing to do return copy(); register char *s = data(); QCString result = s; int reslen = result.length(); if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) ) return result; // returns a copy s = result.data(); int start = 0; int end = reslen - 1; while ( isspace((uchar) s[start]) ) // skip white space from start start++; if ( s[start] == '\0' ) { // only white space result.resize( 1 ); return result; } while ( end && isspace((uchar) s[end]) ) // skip white space from end end--; end -= start - 1; memmove( result.data(), &s[start], end ); result.resize( end + 1 ); return result; } /*! Returns a new string that has white space removed from the start and the end, plus any sequence of internal white space replaced with a single space (ASCII 32). White space means the decimal ASCII codes 9, 10, 11, 12, 13 and 32. \code QCString s = " lots\t of\nwhite space "; QCString t = s.simplifyWhiteSpace(); // t == "lots of white space" \endcode \sa stripWhiteSpace() */ QCString QCString::simplifyWhiteSpace() const { if ( isEmpty() ) // nothing to do return copy(); QCString result( size() ); char *from = data(); char *to = result.data(); char *first = to; for ( ;; ) { while ( isspace((uchar) *from) ) from++; while ( *from && !isspace((uchar) *from) ) *to++ = *from++; if ( *from ) *to++ = 0x20; // ' ' else break; } if ( to > first && *(to-1) == 0x20 ) to--; *to = '\0'; result.resize( (int)(to - result.data()) + 1 ); return result; } /*! \overload Inserts string \a s into the string at position \a index. If \a index is beyond the end of the string, the string is padded with spaces (ASCII 32) to length \a index and then \a s is appended. \code QCString s = "I like fish"; s.insert( 2, "don't "); // s == "I don't like fish" s = "x"; // index 01234 s.insert( 3, "yz" ); // s == "x yz" \endcode */ QCString &QCString::insert( uint index, const char *s ) { int len = qstrlen(s); if ( len == 0 ) return *this; uint olen = length(); int nlen = olen + len; if ( index >= olen ) { // insert after end of string detach(); - if ( QByteArray::resize(nlen+index-olen+1) ) { + if ( QByteArray::resize(nlen+index-olen+1, QByteArray::SpeedOptim ) ) { memset( data()+olen, ' ', index-olen ); memcpy( data()+index, s, len+1 ); } - } else if ( QByteArray::resize(nlen+1) ) { // normal insert + } else { detach(); + if ( QByteArray::resize(nlen+1, QByteArray::SpeedOptim ) ) { // normal insert memmove( data()+index+len, data()+index, olen-index+1 ); memcpy( data()+index, s, len ); } + } return *this; } /*! Inserts character \a c into the string at position \a index and returns a reference to the string. If \a index is beyond the end of the string, the string is padded with spaces (ASCII 32) to length \a index and then \a c is appended. Example: \code QCString s = "Yes"; s.insert( 3, '!'); // s == "Yes!" \endcode \sa remove(), replace() */ QCString &QCString::insert( uint index, char c ) // insert char { char buf[2]; buf[0] = c; buf[1] = '\0'; return insert( index, buf ); } /*! \fn QCString &QCString::prepend( const char *s ) Prepend \a s to the string. Equivalent to insert(0, s). \sa insert() */ /*! Removes \a len characters from the string, starting at position \a index, and returns a reference to the string. If \a index is out of range, nothing happens. If \a index is valid, but \a index + \a len is larger than the length of the string, the string is truncated at position \a index. \code QCString s = "Montreal"; s.remove( 1, 4 ); // s == "Meal" \endcode \sa insert(), replace() */ QCString &QCString::remove( uint index, uint len ) { uint olen = length(); if ( index + len >= olen ) { // range problems if ( index < olen ) { // index ok detach(); resize( index+1 ); } } else if ( len != 0 ) { detach(); memmove( data()+index, data()+index+len, olen-index-len+1 ); - QByteArray::resize(olen-len+1); + QByteArray::resize(olen-len+1, QByteArray::SpeedOptim ); } return *this; } /*! Replaces \a len characters from the string, starting at position \a index, with \a str, and returns a reference to the string. If \a index is out of range, nothing is removed and \a str is appended at the end of the string. If \a index is valid, but \a index + \a len is larger than the length of the string, \a str replaces the rest of the string from position \a index. \code QCString s = "Say yes!"; s.replace( 4, 3, "NO" ); // s == "Say NO!" \endcode \sa insert(), remove() */ QCString &QCString::replace( uint index, uint len, const char *str ) { remove( index, len ); insert( index, str ); return *this; } /*! \overload Replaces every occurrence of the character \a c in the string with \a after. Returns a reference to the string. Example: \code QCString s = "a,b,c"; s.replace( ',', " or " ); // s == "a or b or c" \endcode */ QCString &QCString::replace( char c, const char *after ) { char str[2]; str[0] = c; str[1] = '\0'; return replace( str, after ); } /*! \overload Replaces every occurrence of the string \a before in the string with the string \a after. Returns a reference to the string. Example: \code QCString s = "Greek is Greek"; s.replace( "Greek", "English" ); // s == "English is English" \endcode */ + QCString &QCString::replace( const char *before, const char *after ) { if ( before == after || isNull() ) return *this; detach(); int index = 0; const int bl = before ? strlen( before ) : 0; const int al = after ? strlen( after ) : 0; char *d = data(); uint len = length(); if ( bl == al ) { if ( bl ) { - while( (index = find( before, index ) ) != -1 ) { + while( (index = find( before, index, TRUE, len ) ) != -1 ) { memcpy( d+index, after, al ); index += bl; } } } else if ( al < bl ) { uint to = 0; uint movestart = 0; uint num = 0; - while( (index = find( before, index ) ) != -1 ) { + while( (index = find( before, index, TRUE, len ) ) != -1 ) { if ( num ) { int msize = index - movestart; if ( msize > 0 ) { memmove( d + to, d + movestart, msize ); to += msize; } } else { to = index; } if ( al ) { memcpy( d + to, after, al ); to += al; } index += bl; movestart = index; num++; } if ( num ) { int msize = len - movestart; if ( msize > 0 ) memmove( d + to, d + movestart, msize ); resize( len - num*(bl-al) + 1 ); } } else { // the most complex case. We don't want to loose performance by doing repeated // copies and reallocs of the string. while( index != -1 ) { uint indices[4096]; uint pos = 0; while( pos < 4095 ) { - index = find(before, index); + index = find(before, index, TRUE, len); if ( index == -1 ) break; indices[pos++] = index; index += bl; // avoid infinite loop if ( !bl ) index++; } if ( !pos ) break; // we have a table of replacement positions, use them for fast replacing int adjust = pos*(al-bl); // index has to be adjusted in case we get back into the loop above. if ( index != -1 ) index += adjust; uint newlen = len + adjust; int moveend = len; if ( newlen > len ) { resize( newlen + 1 ); len = newlen; } d = data(); while( pos ) { pos--; int movestart = indices[pos] + bl; int insertstart = indices[pos] + pos*(al-bl); int moveto = insertstart + al; memmove( d + moveto, d + movestart, (moveend - movestart) ); if ( after ) memcpy( d + insertstart, after, al ); moveend = movestart - bl; } } } return *this; } /*! \overload Replaces every occurrence of \a c1 with the char \a c2. Returns a reference to the string. */ QCString &QCString::replace( char c1, char c2 ) { detach(); uint i = 0; char *d = data(); uint len = length(); while ( i < len ) { if ( d[i] == c1 ) d[i] = c2; i++; } return *this; } #ifndef QT_NO_REGEXP_CAPTURE /*! \overload Finds the first occurrence of the regular expression \a rx, starting at position \a index. Returns the position of the next match, or -1 if \a rx was not found. \warning If you want to apply this function repeatedly to the same string it is more efficient to convert the string to a QString and apply the function to that. */ int QCString::find( const QRegExp& rx, int index ) const { - QString d = QString::fromLatin1( data() ); + QString d = QString::fromAscii( data() ); return d.find( rx, index ); } /*! \overload Finds the first occurrence of the regular expression \a rx, starting at position \a index and searching backwards. Returns the position of the next match (backwards), or -1 if \a rx was not found. \warning If you want to apply this function repeatedly to the same string it is more efficient to convert the string to a QString and apply the function to that. */ int QCString::findRev( const QRegExp& rx, int index ) const { - QString d = QString::fromLatin1( data() ); + QString d = QString::fromAscii( data() ); return d.findRev( rx, index ); } /*! \overload Counts the number of overlapping occurrences of \a rx in the string. Example: \code QString s = "banana and panama"; QRegExp r = QRegExp( "a[nm]a", TRUE, FALSE ); s.contains( r ); // 4 matches \endcode \sa find(), findRev() \warning If you want to apply this function repeatedly to the same string it is more efficient to convert the string to a QString and apply the function to that. */ int QCString::contains( const QRegExp &rx ) const { - QString d = QString::fromLatin1( data() ); + QString d = QString::fromAscii( data() ); return d.contains( rx ); } /*! \overload Replaces every occurrence of \a rx in the string with \a str. Returns a reference to the string. Example: \code QString s = "banana"; s.replace( QRegExp("a.*a"), "" ); // becomes "b" s = "banana"; s.replace( QRegExp("^[bn]a"), "X" ); // becomes "Xnana" s = "banana"; s.replace( QRegExp("^[bn]a"), "" ); // becomes "nana" \endcode \warning If you want to apply this function repeatedly to the same string it is more efficient to convert the string to a QString and apply the function to that. */ QCString &QCString::replace( const QRegExp &rx, const char *str ) { - QString d = QString::fromLatin1( data() ); - QString r = QString::fromLatin1( str ); + QString d = QString::fromAscii( data() ); + QString r = QString::fromAscii( str ); d.replace( rx, r ); setStr( d.ascii() ); return *this; } #endif //QT_NO_REGEXP /*! Returns the string converted to a \c long value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ long QCString::toLong( bool *ok ) const { char *p = data(); long val=0; const long max_mult = 214748364; bool is_ok = FALSE; int neg = 0; if ( !p ) goto bye; while ( isspace((uchar) *p) ) // skip leading space p++; if ( *p == '-' ) { p++; neg = 1; } else if ( *p == '+' ) { p++; } if ( !isdigit((uchar) *p) ) goto bye; while ( isdigit((uchar) *p) ) { if ( val > max_mult || (val == max_mult && (*p-'0') > 7+neg) ) goto bye; val = 10*val + (*p++ - '0'); } if ( neg ) val = -val; while ( isspace((uchar) *p) ) // skip trailing space p++; if ( *p == '\0' ) is_ok = TRUE; bye: if ( ok ) *ok = is_ok; return is_ok ? val : 0; } /*! Returns the string converted to an \c{unsigned long} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ ulong QCString::toULong( bool *ok ) const { char *p = data(); ulong val=0; const ulong max_mult = 429496729; bool is_ok = FALSE; if ( !p ) goto bye; while ( isspace((uchar) *p) ) // skip leading space p++; if ( *p == '+' ) p++; if ( !isdigit((uchar) *p) ) goto bye; while ( isdigit((uchar) *p) ) { if ( val > max_mult || (val == max_mult && (*p-'0') > 5) ) goto bye; val = 10*val + (*p++ - '0'); } while ( isspace((uchar) *p) ) // skip trailing space p++; if ( *p == '\0' ) is_ok = TRUE; bye: if ( ok ) *ok = is_ok; return is_ok ? val : 0; } /*! Returns the string converted to a \c{short} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, is out of range, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ short QCString::toShort( bool *ok ) const { long v = toLong( ok ); if ( ok && *ok && (v < -32768 || v > 32767) ) *ok = FALSE; return (short)v; } /*! Returns the string converted to an \c{unsigned short} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, is out of range, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ ushort QCString::toUShort( bool *ok ) const { ulong v = toULong( ok ); if ( ok && *ok && (v > 65535) ) *ok = FALSE; return (ushort)v; } /*! Returns the string converted to a \c{int} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ int QCString::toInt( bool *ok ) const { return (int)toLong( ok ); } /*! Returns the string converted to an \c{unsigned int} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ uint QCString::toUInt( bool *ok ) const { return (uint)toULong( ok ); } /*! Returns the string converted to a \c{double} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ double QCString::toDouble( bool *ok ) const { char *end; double val = strtod( data() ? data() : "", &end ); if ( ok ) *ok = ( data() && *data() && ( end == 0 || *end == '\0' ) ); return val; } /*! Returns the string converted to a \c{float} value. If \a ok is not 0: \a *ok is set to FALSE if the string is not a number, or if it has trailing garbage; otherwise \a *ok is set to TRUE. */ float QCString::toFloat( bool *ok ) const { return (float)toDouble( ok ); } /*! Makes a deep copy of \a str. Returns a reference to the string. */ QCString &QCString::setStr( const char *str ) { detach(); if ( str ) // valid string store( str, qstrlen(str)+1 ); else // empty resize( 0 ); return *this; } /*! \overload Sets the string to the string representation of the number \a n and returns a reference to the string. */ QCString &QCString::setNum( long n ) { detach(); char buf[20]; register char *p = &buf[19]; bool neg; if ( n < 0 ) { neg = TRUE; n = -n; } else { neg = FALSE; } *p = '\0'; do { *--p = ((int)(n%10)) + '0'; n /= 10; } while ( n ); if ( neg ) *--p = '-'; store( p, qstrlen(p)+1 ); return *this; } /*! \overload Sets the string to the string representation of the number \a n and returns a reference to the string. */ QCString &QCString::setNum( ulong n ) { detach(); char buf[20]; register char *p = &buf[19]; *p = '\0'; do { *--p = ((int)(n%10)) + '0'; n /= 10; } while ( n ); store( p, qstrlen(p)+1 ); return *this; } /*! \overload QCString &QCString::setNum( int n ) Sets the string to the string representation of the number \a n and returns a reference to the string. */ /*! \overload QCString &QCString::setNum( uint n ) Sets the string to the string representation of the number \a n and returns a reference to the string. */ /*! \overload QCString &QCString::setNum( short n ) Sets the string to the string representation of the number \a n and returns a reference to the string. */ /*! \overload QCString &QCString::setNum( ushort n ) Sets the string to the string representation of the number \a n and returns a reference to the string. */ /*! Sets the string to the string representation of the number \a n and returns a reference to the string. The format of the string representation is specified by the format character \a f, and the precision (number of digits after the decimal point) is specified with \a prec. The valid formats for \a f are 'e', 'E', 'f', 'g' and 'G'. The formats are the same as for sprintf(); they are explained in \l QString::arg(). */ QCString &QCString::setNum( double n, char f, int prec ) { #if defined(QT_CHECK_RANGE) if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) qWarning( "QCString::setNum: Invalid format char '%c'", f ); #endif char format[20]; register char *fs = format; // generate format string *fs++ = '%'; // "%.<prec>l<f>" if ( prec > 99 ) prec = 99; *fs++ = '.'; if ( prec >= 10 ) { *fs++ = prec / 10 + '0'; *fs++ = prec % 10 + '0'; } else { *fs++ = prec + '0'; } *fs++ = 'l'; *fs++ = f; *fs = '\0'; return sprintf( format, n ); } /*! \overload QCString &QCString::setNum( float n, char f, int prec ) */ /*! Sets the character at position \a index to \a c and expands the string if necessary, padding with spaces. Returns FALSE if \a index was out of range and the string could not be expanded; otherwise returns TRUE. */ bool QCString::setExpand( uint index, char c ) { detach(); uint oldlen = length(); if ( index >= oldlen ) { if ( !QByteArray::resize( index+2 ) ) // no memory return FALSE; if ( index > oldlen ) memset( data() + oldlen, ' ', index - oldlen ); *(data() + index+1) = '\0'; // terminate padded string } *(data() + index) = c; return TRUE; } /*! \fn QCString::operator const char *() const Returns the string data. */ /*! \fn QCString& QCString::append( const char *str ) Appends string \a str to the string and returns a reference to the string. Equivalent to operator+=(). */ /*! Appends string \a str to the string and returns a reference to the string. */ QCString& QCString::operator+=( const char *str ) { if ( !str ) return *this; // nothing to append detach(); uint len1 = length(); uint len2 = qstrlen(str); - if ( !QByteArray::resize( len1 + len2 + 1 ) ) + if ( !QByteArray::resize( len1 + len2 + 1, QByteArray::SpeedOptim ) ) return *this; // no memory memcpy( data() + len1, str, len2 + 1 ); return *this; } /*! \overload Appends character \a c to the string and returns a reference to the string. */ QCString &QCString::operator+=( char c ) { detach(); uint len = length(); - if ( !QByteArray::resize( len + 2 ) ) + if ( !QByteArray::resize( len + 2, QByteArray::SpeedOptim ) ) return *this; // no memory *(data() + len) = c; *(data() + len+1) = '\0'; return *this; } /***************************************************************************** QCString stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM /*! \relates QCString Writes string \a str to the stream \a s. \sa \link datastreamformat.html Format of the QDataStream operators \endlink */ QDataStream &operator<<( QDataStream &s, const QCString &str ) { return s.writeBytes( str.data(), str.size() ); } /*! \relates QCString Reads a string into \a str from the stream \a s. \sa \link datastreamformat.html Format of the QDataStream operators \endlink */ QDataStream &operator>>( QDataStream &s, QCString &str ) { str.detach(); Q_UINT32 len; s >> len; // read size of string if ( len == 0 || s.eof() ) { // end of file reached str.resize( 0 ); return s; } if ( !str.QByteArray::resize( (uint)len )) {// resize string #if defined(QT_CHECK_NULL) qWarning( "QDataStream: Not enough memory to read QCString" ); #endif len = 0; } if ( len > 0 ) // not null array s.readRawBytes( str.data(), (uint)len ); return s; } #endif //QT_NO_DATASTREAM /***************************************************************************** Documentation for related functions *****************************************************************************/ /*! \fn bool operator==( const QCString &s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) == 0. */ /*! \overload bool operator==( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) == 0. */ /*! \overload bool operator==( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) == 0. */ /*! \fn bool operator!=( const QCString &s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) != 0. */ /*! \overload bool operator!=( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) != 0. */ /*! \overload bool operator!=( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) != 0. */ /*! \fn bool operator<( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \< 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \overload bool operator<( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \< 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \fn bool operator<=( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 is less than or equal to \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \<= 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \overload bool operator<=( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 is less than or equal to \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \<= 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \fn bool operator>( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \> 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \overload bool operator>( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \> 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \fn bool operator>=( const QCString &s1, const char *s2 ) \relates QCString Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \>= 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \overload bool operator>=( const char *s1, const QCString &s2 ) \relates QCString Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise returns FALSE. Equivalent to qstrcmp(\a s1, \a s2) \>= 0. \sa \link #asciinotion Note on character comparisons \endlink */ /*! \fn const QCString operator+( const QCString &s1, const QCString &s2 ) \relates QCString Returns a string which consists of the concatenation of \a s1 and \a s2. */ /*! \overload const QCString operator+( const QCString &s1, const char *s2 ) \relates QCString Returns a string which consists of the concatenation of \a s1 and \a s2. */ /*! \overload const QCString operator+( const char *s1, const QCString &s2 ) \relates QCString Returns a string which consists of the concatenation of \a s1 and \a s2. */ /*! \overload const QCString operator+( const QCString &s, char c ) \relates QCString Returns a string which consists of the concatenation of \a s and \a c. */ /*! \overload const QCString operator+( char c, const QCString &s ) \relates QCString Returns a string which consists of the concatenation of \a c and \a s. */ diff --git a/qmake/tools/qdatastream.cpp b/qmake/tools/qdatastream.cpp index 9c573c7..51a1448 100644 --- a/qmake/tools/qdatastream.cpp +++ b/qmake/tools/qdatastream.cpp @@ -369,656 +369,670 @@ void QDataStream::unsetDevice() Returns FALSE if the current position of the read/write head of the IO device is somewhere before the end position. \sa QIODevice::atEnd() */ /*! \fn int QDataStream::byteOrder() const Returns the current byte order setting -- either \c BigEndian or \c LittleEndian. \sa setByteOrder() */ /*! Sets the serialization byte order to \a bo. The \a bo parameter can be \c QDataStream::BigEndian or \c QDataStream::LittleEndian. The default setting is big endian. We recommend leaving this setting unless you have special requirements. \sa byteOrder() */ void QDataStream::setByteOrder( int bo ) { byteorder = bo; if ( systemBigEndian ) noswap = byteorder == BigEndian; else noswap = byteorder == LittleEndian; } /*! \fn bool QDataStream::isPrintableData() const Returns TRUE if the printable data flag has been set; otherwise returns FALSE. \sa setPrintableData() */ /*! \fn void QDataStream::setPrintableData( bool enable ) If \a enable is TRUE, data will be output in a human readable format. If \a enable is FALSE, data will be output in a binary format. If \a enable is TRUE, the write functions will generate output that consists of printable characters (7 bit ASCII). This output will typically be a lot larger than the default binary output, and consequently slower to write. We recommend only enabling printable data for debugging purposes. */ /*! \fn int QDataStream::version() const Returns the version number of the data serialization format. In Qt 3.1, this number is 5. \sa setVersion() */ /*! \fn void QDataStream::setVersion( int v ) Sets the version number of the data serialization format to \a v. You don't need to set a version if you are using the current version of Qt. In order to accommodate new functionality, the datastream serialization format of some Qt classes has changed in some versions of Qt. If you want to read data that was created by an earlier version of Qt, or write data that can be read by a program that was compiled with an earlier version of Qt, use this function to modify the serialization format of QDataStream. \table \header \i Qt Version \i QDataStream Version \row \i Qt 3.1 \i11 5 \row \i Qt 3.0 \i11 4 \row \i Qt 2.1.x and Qt 2.2.x \i11 3 \row \i Qt 2.0.x \i11 2 \row \i Qt 1.x \i11 1 \endtable \sa version() */ /***************************************************************************** QDataStream read functions *****************************************************************************/ static Q_INT32 read_int_ascii( QDataStream *s ) { register int n = 0; char buf[40]; for ( ;; ) { buf[n] = s->device()->getch(); if ( buf[n] == '\n' || n > 38 ) // $-terminator break; n++; } buf[n] = '\0'; return atol( buf ); } /*! \overload QDataStream &QDataStream::operator>>( Q_UINT8 &i ) Reads an unsigned byte from the stream into \a i, and returns a reference to the stream. */ /*! Reads a signed byte from the stream into \a i, and returns a reference to the stream. */ QDataStream &QDataStream::operator>>( Q_INT8 &i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data i = (Q_INT8)dev->getch(); if ( i == '\\' ) { // read octal code char buf[4]; dev->readBlock( buf, 3 ); i = (buf[2] & 0x07)+((buf[1] & 0x07) << 3)+((buf[0] & 0x07) << 6); } } else { // data or text i = (Q_INT8)dev->getch(); } return *this; } /*! \overload QDataStream &QDataStream::operator>>( Q_UINT16 &i ) Reads an unsigned 16-bit integer from the stream into \a i, and returns a reference to the stream. */ /*! \overload Reads a signed 16-bit integer from the stream into \a i, and returns a reference to the stream. */ QDataStream &QDataStream::operator>>( Q_INT16 &i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data i = (Q_INT16)read_int_ascii( this ); } else if ( noswap ) { // no conversion needed dev->readBlock( (char *)&i, sizeof(Q_INT16) ); } else { // swap bytes register uchar *p = (uchar *)(&i); char b[2]; dev->readBlock( b, 2 ); *p++ = b[1]; *p = b[0]; } return *this; } /*! \overload QDataStream &QDataStream::operator>>( Q_UINT32 &i ) Reads an unsigned 32-bit integer from the stream into \a i, and returns a reference to the stream. */ /*! \overload Reads a signed 32-bit integer from the stream into \a i, and returns a reference to the stream. */ QDataStream &QDataStream::operator>>( Q_INT32 &i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data i = read_int_ascii( this ); } else if ( noswap ) { // no conversion needed dev->readBlock( (char *)&i, sizeof(Q_INT32) ); } else { // swap bytes uchar *p = (uchar *)(&i); char b[4]; dev->readBlock( b, 4 ); *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; } return *this; } /*! \overload QDataStream &QDataStream::operator>>( Q_ULONG &i ) Reads an unsigned integer of the system's word length from the stream, into \a i, and returns a reference to the stream. */ /*! \overload Reads a signed integer of the system's word length from the stream into \a i, and returns a reference to the stream. */ QDataStream &QDataStream::operator>>( Q_LONG &i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data i = read_int_ascii( this ); } else if ( noswap ) { // no conversion needed dev->readBlock( (char *)&i, sizeof(Q_LONG) ); } else { // swap bytes register uchar *p = (uchar *)(&i); char b[sizeof(Q_LONG)]; dev->readBlock( b, sizeof(Q_LONG) ); for ( int j = sizeof(Q_LONG); j; ) *p++ = b[--j]; } return *this; } static double read_double_ascii( QDataStream *s ) { register int n = 0; char buf[80]; for ( ;; ) { buf[n] = s->device()->getch(); if ( buf[n] == '\n' || n > 78 ) // $-terminator break; n++; } buf[n] = '\0'; return atof( buf ); } /*! \overload Reads a 32-bit floating point number from the stream into \a f, using the standard IEEE754 format. Returns a reference to the stream. */ QDataStream &QDataStream::operator>>( float &f ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data f = (float)read_double_ascii( this ); } else if ( noswap ) { // no conversion needed dev->readBlock( (char *)&f, sizeof(float) ); } else { // swap bytes uchar *p = (uchar *)(&f); char b[4]; dev->readBlock( b, 4 ); *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; } return *this; } /*! \overload Reads a 64-bit floating point number from the stream into \a f, using the standard IEEE754 format. Returns a reference to the stream. */ QDataStream &QDataStream::operator>>( double &f ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data f = read_double_ascii( this ); } else if ( noswap ) { // no conversion needed dev->readBlock( (char *)&f, sizeof(double) ); } else { // swap bytes register uchar *p = (uchar *)(&f); char b[8]; dev->readBlock( b, 8 ); *p++ = b[7]; *p++ = b[6]; *p++ = b[5]; *p++ = b[4]; *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; } return *this; } /*! \overload Reads the '\0'-terminated string \a s from the stream and returns a reference to the stream. Space for the string is allocated using \c new -- the caller must destroy it with delete[]. */ QDataStream &QDataStream::operator>>( char *&s ) { uint len = 0; return readBytes( s, len ); } /*! Reads the buffer \a s from the stream and returns a reference to the stream. The buffer \a s is allocated using \c new. Destroy it with the \c delete[] operator. If the length is zero or \a s cannot be allocated, \a s is set to 0. The \a l parameter will be set to the length of the buffer. The serialization format is a Q_UINT32 length specifier first, then \a l bytes of data. Note that the data is \e not encoded. \sa readRawBytes(), writeBytes() */ QDataStream &QDataStream::readBytes( char *&s, uint &l ) { CHECK_STREAM_PRECOND Q_UINT32 len; *this >> len; // first read length spec l = (uint)len; if ( len == 0 || eof() ) { s = 0; return *this; } else { s = new char[len]; // create char array Q_CHECK_PTR( s ); if ( !s ) // no memory return *this; return readRawBytes( s, (uint)len ); } } /*! Reads \a len bytes from the stream into \a s and returns a reference to the stream. The buffer \a s must be preallocated. The data is \e not encoded. \sa readBytes(), QIODevice::readBlock(), writeRawBytes() */ QDataStream &QDataStream::readRawBytes( char *s, uint len ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data register Q_INT8 *p = (Q_INT8*)s; + if ( version() < 4 ) { + while ( len-- ) { + Q_INT32 tmp; + *this >> tmp; + *p++ = tmp; + } + } else { while ( len-- ) *this >> *p++; + } } else { // read data char array dev->readBlock( s, len ); } return *this; } /***************************************************************************** QDataStream write functions *****************************************************************************/ /*! \overload QDataStream &QDataStream::operator<<( Q_UINT8 i ) Writes an unsigned byte, \a i, to the stream and returns a reference to the stream. */ /*! Writes a signed byte, \a i, to the stream and returns a reference to the stream. */ QDataStream &QDataStream::operator<<( Q_INT8 i ) { CHECK_STREAM_PRECOND if ( printable && (i == '\\' || !isprint((uchar) i)) ) { char buf[6]; // write octal code buf[0] = '\\'; buf[1] = '0' + ((i >> 6) & 0x07); buf[2] = '0' + ((i >> 3) & 0x07); buf[3] = '0' + (i & 0x07); buf[4] = '\0'; dev->writeBlock( buf, 4 ); } else { dev->putch( i ); } return *this; } /*! \overload QDataStream &QDataStream::operator<<( Q_UINT16 i ) Writes an unsigned 16-bit integer, \a i, to the stream and returns a reference to the stream. */ /*! \overload Writes a signed 16-bit integer, \a i, to the stream and returns a reference to the stream. */ QDataStream &QDataStream::operator<<( Q_INT16 i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data char buf[16]; sprintf( buf, "%d\n", i ); dev->writeBlock( buf, strlen(buf) ); } else if ( noswap ) { // no conversion needed dev->writeBlock( (char *)&i, sizeof(Q_INT16) ); } else { // swap bytes register uchar *p = (uchar *)(&i); char b[2]; b[1] = *p++; b[0] = *p; dev->writeBlock( b, 2 ); } return *this; } /*! \overload Writes a signed 32-bit integer, \a i, to the stream and returns a reference to the stream. */ QDataStream &QDataStream::operator<<( Q_INT32 i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data char buf[16]; sprintf( buf, "%d\n", i ); dev->writeBlock( buf, strlen(buf) ); } else if ( noswap ) { // no conversion needed dev->writeBlock( (char *)&i, sizeof(Q_INT32) ); } else { // swap bytes register uchar *p = (uchar *)(&i); char b[4]; b[3] = *p++; b[2] = *p++; b[1] = *p++; b[0] = *p; dev->writeBlock( b, 4 ); } return *this; } /*! \overload QDataStream &QDataStream::operator<<( Q_ULONG i ) Writes an unsigned integer \a i, of the system's word length, to the stream and returns a reference to the stream. */ /*! \overload Writes a signed integer \a i, of the system's word length, to the stream and returns a reference to the stream. */ QDataStream &QDataStream::operator<<( Q_LONG i ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data char buf[20]; sprintf( buf, "%ld\n", i ); dev->writeBlock( buf, strlen(buf) ); } else if ( noswap ) { // no conversion needed dev->writeBlock( (char *)&i, sizeof(Q_LONG) ); } else { // swap bytes register uchar *p = (uchar *)(&i); char b[sizeof(Q_LONG)]; for ( int j = sizeof(Q_LONG); j; ) b[--j] = *p++; dev->writeBlock( b, sizeof(Q_LONG) ); } return *this; } /*! \overload QDataStream &QDataStream::operator<<( Q_UINT32 i ) Writes an unsigned integer, \a i, to the stream as a 32-bit unsigned integer (Q_UINT32). Returns a reference to the stream. */ /*! \overload Writes a 32-bit floating point number, \a f, to the stream using the standard IEEE754 format. Returns a reference to the stream. */ QDataStream &QDataStream::operator<<( float f ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data char buf[32]; sprintf( buf, "%g\n", (double)f ); dev->writeBlock( buf, strlen(buf) ); } else { float g = f; // fixes float-on-stack problem if ( noswap ) { // no conversion needed dev->writeBlock( (char *)&g, sizeof(float) ); } else { // swap bytes register uchar *p = (uchar *)(&g); char b[4]; b[3] = *p++; b[2] = *p++; b[1] = *p++; b[0] = *p; dev->writeBlock( b, 4 ); } } return *this; } /*! \overload Writes a 64-bit floating point number, \a f, to the stream using the standard IEEE754 format. Returns a reference to the stream. */ QDataStream &QDataStream::operator<<( double f ) { CHECK_STREAM_PRECOND if ( printable ) { // printable data char buf[32]; sprintf( buf, "%g\n", f ); dev->writeBlock( buf, strlen(buf) ); } else if ( noswap ) { // no conversion needed dev->writeBlock( (char *)&f, sizeof(double) ); } else { // swap bytes register uchar *p = (uchar *)(&f); char b[8]; b[7] = *p++; b[6] = *p++; b[5] = *p++; b[4] = *p++; b[3] = *p++; b[2] = *p++; b[1] = *p++; b[0] = *p; dev->writeBlock( b, 8 ); } return *this; } /*! \overload Writes the '\0'-terminated string \a s to the stream and returns a reference to the stream. The string is serialized using writeBytes(). */ QDataStream &QDataStream::operator<<( const char *s ) { if ( !s ) { *this << (Q_UINT32)0; return *this; } uint len = qstrlen( s ) + 1; // also write null terminator *this << (Q_UINT32)len; // write length specifier return writeRawBytes( s, len ); } /*! Writes the length specifier \a len and the buffer \a s to the stream and returns a reference to the stream. The \a len is serialized as a Q_UINT32, followed by \a len bytes from \a s. Note that the data is \e not encoded. \sa writeRawBytes(), readBytes() */ QDataStream &QDataStream::writeBytes(const char *s, uint len) { CHECK_STREAM_PRECOND *this << (Q_UINT32)len; // write length specifier if ( len ) writeRawBytes( s, len ); return *this; } /*! Writes \a len bytes from \a s to the stream and returns a reference to the stream. The data is \e not encoded. \sa writeBytes(), QIODevice::writeBlock(), readRawBytes() */ QDataStream &QDataStream::writeRawBytes( const char *s, uint len ) { CHECK_STREAM_PRECOND if ( printable ) { // write printable + if ( version() < 4 ) { + register char *p = (char *)s; + while ( len-- ) + *this << *p++; + } else { register Q_INT8 *p = (Q_INT8*)s; while ( len-- ) *this << *p++; + } } else { // write data char array dev->writeBlock( s, len ); } return *this; } #endif // QT_NO_DATASTREAM diff --git a/qmake/tools/qdatetime.cpp b/qmake/tools/qdatetime.cpp index 93e40a8..3137877 100644 --- a/qmake/tools/qdatetime.cpp +++ b/qmake/tools/qdatetime.cpp @@ -1,422 +1,421 @@ /**************************************************************************** ** $Id$ ** ** Implementation of date and time classes ** ** Created : 940124 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -// Get the system specific includes and defines #include "qplatformdefs.h" #include "qdatetime.h" #include "qdatastream.h" #include "qregexp.h" #include <stdio.h> #ifndef Q_OS_TEMP #include <time.h> #endif #if defined(Q_OS_WIN32) #include <windows.h> #endif static const uint FIRST_DAY = 2361222; // Julian day for 1752-09-14 static const int FIRST_YEAR = 1752; // ### wrong for many countries static const uint SECS_PER_DAY = 86400; static const uint MSECS_PER_DAY = 86400000; static const uint SECS_PER_HOUR = 3600; static const uint MSECS_PER_HOUR= 3600000; static const uint SECS_PER_MIN = 60; static const uint MSECS_PER_MIN = 60000; static const short monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static const char * const qt_shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #ifndef QT_NO_DATESTRING /***************************************************************************** Some static function used by QDate, QTime and QDateTime *****************************************************************************/ // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens static QString getFmtString( const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = FALSE ) { if ( f.isEmpty() ) return QString::null; QString buf = f; if ( dt ) { if ( f == "h" ) { if ( ( am_pm ) && ( dt->hour() > 12 ) ) buf = QString::number( dt->hour() - 12 ); else if ( ( am_pm ) && ( dt->hour() == 0 ) ) buf = "12"; else buf = QString::number( dt->hour() ); } else if ( f == "hh" ) { if ( ( am_pm ) && ( dt->hour() > 12 ) ) buf = QString::number( dt->hour() - 12 ).rightJustify( 2, '0', TRUE ); else if ( ( am_pm ) && ( dt->hour() == 0 ) ) buf = "12"; else buf = QString::number( dt->hour() ).rightJustify( 2, '0', TRUE ); } else if ( f == "m" ) { buf = QString::number( dt->minute() ); } else if ( f == "mm" ) { buf = QString::number( dt->minute() ).rightJustify( 2, '0', TRUE ); } else if ( f == "s" ) { buf = QString::number( dt->second() ); } else if ( f == "ss" ) { buf = QString::number( dt->second() ).rightJustify( 2, '0', TRUE ); } else if ( f == "z" ) { buf = QString::number( dt->msec() ); } else if ( f == "zzz" ) { buf = QString::number( dt->msec() ).rightJustify( 3, '0', TRUE ); } else if ( f == "ap" ) { buf = dt->hour() < 12 ? "am" : "pm"; } else if ( f == "AP" ) { buf = dt->hour() < 12 ? "AM" : "PM"; } } if ( dd ) { if ( f == "d" ) { buf = QString::number( dd->day() ); } else if ( f == "dd" ) { buf = QString::number( dd->day() ).rightJustify( 2, '0', TRUE ); } else if ( f == "M" ) { buf = QString::number( dd->month() ); } else if ( f == "MM" ) { buf = QString::number( dd->month() ).rightJustify( 2, '0', TRUE ); #ifndef QT_NO_TEXTDATE } else if ( f == "ddd" ) { buf = dd->shortDayName( dd->dayOfWeek() ); } else if ( f == "dddd" ) { buf = dd->longDayName( dd->dayOfWeek() ); } else if ( f == "MMM" ) { buf = dd->shortMonthName( dd->month() ); } else if ( f == "MMMM" ) { buf = dd->longMonthName( dd->month() ); #endif } else if ( f == "yy" ) { buf = QString::number( dd->year() ).right( 2 ); } else if ( f == "yyyy" ) { buf = QString::number( dd->year() ); } } return buf; } // Parses the format string and uses getFmtString to get the values for the tokens. Ret static QString fmtDateTime( const QString& f, const QTime* dt = 0, const QDate* dd = 0 ) { if ( f.isEmpty() ) { return QString::null; } bool ap = ( f.contains( "AP" ) || f.contains( "ap" ) ); QString buf; QString frm; QChar status = '0'; for ( int i = 0; i < (int)f.length(); ++i ) { if ( f[ i ] == status ) { if ( ( ap ) && ( ( f[ i ] == 'P' ) || ( f[ i ] == 'p' ) ) ) status = '0'; frm += f[ i ]; } else { buf += getFmtString( frm, dt, dd, ap ); frm = QString::null; if ( ( f[ i ] == 'h' ) || ( f[ i ] == 'm' ) || ( f[ i ] == 's' ) || ( f[ i ] == 'z' ) ) { status = f[ i ]; frm += f[ i ]; } else if ( ( f[ i ] == 'd' ) || ( f[ i ] == 'M' ) || ( f[ i ] == 'y' ) ) { status = f[ i ]; frm += f[ i ]; } else if ( ( ap ) && ( f[ i ] == 'A' ) ) { status = 'P'; frm += f[ i ]; } else if( ( ap ) && ( f[ i ] == 'a' ) ) { status = 'p'; frm += f[ i ]; } else { buf += f[ i ]; status = '0'; } } } buf += getFmtString( frm, dt, dd, ap ); return buf; } #endif // QT_NO_DATESTRING /***************************************************************************** QDate member functions *****************************************************************************/ /*! \class QDate qdatetime.h \reentrant \brief The QDate class provides date functions. \ingroup time \mainclass A QDate object contains a calendar date, i.e. year, month, and day numbers, in the modern Western (Gregorian) calendar. It can read the current date from the system clock. It provides functions for comparing dates and for manipulating dates, e.g. by adding a number of days or months or years. A QDate object is typically created either by giving the year, month and day numbers explicitly, or by using the static function currentDate(), which creates a QDate object containing the system clock's date. An explicit date can also be set using setYMD(). The fromString() function returns a QDate given a string and a date format which is used to interpret the date within the string. The year(), month(), and day() functions provide access to the year, month, and day numbers. Also, dayOfWeek() and dayOfYear() functions are provided. The same information is provided in textual format by the toString(), shortDayName(), longDayName(), shortMonthName() and longMonthName() functions. QDate provides a full set of operators to compare two QDate objects where smaller means earlier and larger means later. You can increment (or decrement) a date by a given number of days using addDays(). Similarly you can use addMonths() and addYears(). The daysTo() function returns the number of days between two dates. The daysInMonth() and daysInYear() functions return how many days there are in this date's month and year, respectively. The leapYear() function indicates whether this date is in a leap year. Note that QDate should not be used for date calculations for dates prior to the introduction of the Gregorian calendar. This calendar was adopted by England from the 14<sup><small>th</small></sup> September 1752 (hence this is the earliest valid QDate), and subsequently by most other Western countries, until 1923. The end of time is reached around the year 8000, by which time we expect Qt to be obsolete. \sa QTime QDateTime QDateEdit QDateTimeEdit */ /*! \enum Qt::DateFormat \value TextDate (default) Qt format \value ISODate ISO 8601 extended format (YYYY-MM-DD, or with time, YYYY-MM-DDTHH:MM:SS) \value LocalDate locale dependent format */ /*! \enum Qt::TimeSpec \value LocalTime Locale dependent time (Timezones and Daylight Savings Time) \value UTC Coordinated Universal Time, replaces Greenwich Time */ /*! \fn QDate::QDate() Constructs a null date. Null dates are invalid. \sa isNull(), isValid() */ /*! Constructs a date with year \a y, month \a m and day \a d. \a y must be in the range 1752..8000, \a m must be in the range 1..12, and \a d must be in the range 1..31. \warning If \a y is in the range 0..99, it is interpreted as 1900..1999. \sa isValid() */ QDate::QDate( int y, int m, int d ) { jd = 0; setYMD( y, m, d ); } /*! \fn bool QDate::isNull() const Returns TRUE if the date is null; otherwise returns FALSE. A null date is invalid. \sa isValid() */ /*! Returns TRUE if this date is valid; otherwise returns FALSE. \sa isNull() */ bool QDate::isValid() const { return jd >= FIRST_DAY; } /*! Returns the year (1752..8000) of this date. \sa month(), day() */ int QDate::year() const { int y, m, d; julianToGregorian( jd, y, m, d ); return y; } /*! Returns the month (January=1..December=12) of this date. \sa year(), day() */ int QDate::month() const { int y, m, d; julianToGregorian( jd, y, m, d ); return m; } /*! Returns the day of the month (1..31) of this date. \sa year(), month(), dayOfWeek() */ int QDate::day() const { int y, m, d; julianToGregorian( jd, y, m, d ); return d; } /*! Returns the weekday (Monday=1..Sunday=7) for this date. \sa day(), dayOfYear() */ int QDate::dayOfWeek() const { return ( jd % 7 ) + 1; } /*! Returns the day of the year (1..365) for this date. \sa day(), dayOfWeek() */ int QDate::dayOfYear() const { return jd - gregorianToJulian(year(), 1, 1) + 1; } /*! Returns the number of days in the month (28..31) for this date. \sa day(), daysInYear() */ int QDate::daysInMonth() const { int y, m, d; julianToGregorian( jd, y, m, d ); if ( m == 2 && leapYear(y) ) return 29; else return monthDays[m]; } /*! Returns the number of days in the year (365 or 366) for this date. \sa day(), daysInMonth() */ int QDate::daysInYear() const { int y, m, d; julianToGregorian( jd, y, m, d ); return leapYear( y ) ? 366 : 365; } /*! Returns the week number (1 to 53), and stores the year in \a *yearNumber unless \a yearNumber is null (the default). Returns 0 if the date is invalid. In accordance with ISO 8601, weeks start on Monday and the first Thursday of a year is always in week 1 of that year. Most years have 52 weeks, but some have 53. \a *yearNumber is not always the same as year(). For example, 1 January 2000 has week number 52 in the year 1999, and 31 December 2002 has week number 1 in the year 2003. \sa isValid() */ int QDate::weekNumber( int *yearNumber ) const @@ -514,1843 +513,1890 @@ QString QDate::shortMonthName( int month ) /*! Returns the long name of the \a month. 1 = "January", 2 = "February", ... 12 = "December" The month names will be localized according to the system's locale settings. \sa toString(), shortMonthName(), shortDayName(), longDayName() */ QString QDate::longMonthName( int month ) { #if defined(QT_CHECK_RANGE) if ( month < 1 || month > 12 ) { qWarning( "QDate::longMonthName: Parameter out ouf range." ); month = 1; } #endif #ifndef Q_WS_WIN char buffer[255]; tm tt; memset( &tt, 0, sizeof( tm ) ); tt.tm_mon = month - 1; if ( strftime( buffer, sizeof( buffer ), "%B", &tt ) ) return QString::fromLocal8Bit( buffer ); #else SYSTEMTIME st; memset( &st, 0, sizeof(SYSTEMTIME) ); st.wYear = 2000; st.wMonth = month; st.wDay = 1 ; const wchar_t mmmm_t[] = L"MMMM"; // workaround for Borland QT_WA( { TCHAR buf[255]; if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, mmmm_t, buf, 255 ) ) return QString::fromUcs2( (ushort*)buf ); } , { char buf[255]; if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "MMMM", (char*)&buf, 255 ) ) return QString::fromLocal8Bit( buf ); } ) #endif return QString::null; } /*! \fn QString QDate::dayName( int weekday ) \obsolete Use shortDayName() instead. */ /*! Returns the name of the \a weekday. 1 = "Mon", 2 = "Tue", ... 7 = "Sun" The day names will be localized according to the system's locale settings. \sa toString(), shortMonthName(), longMonthName(), longDayName() */ QString QDate::shortDayName( int weekday ) { #if defined(QT_CHECK_RANGE) if ( weekday < 1 || weekday > 7 ) { qWarning( "QDate::shortDayName: Parameter out of range." ); weekday = 1; } #endif #ifndef Q_WS_WIN char buffer[255]; tm tt; memset( &tt, 0, sizeof( tm ) ); tt.tm_wday = ( weekday == 7 ) ? 0 : weekday; if ( strftime( buffer, sizeof( buffer ), "%a", &tt ) ) return QString::fromLocal8Bit( buffer ); #else SYSTEMTIME st; memset( &st, 0, sizeof(SYSTEMTIME) ); st.wYear = 2001; st.wMonth = 10; st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday; st.wDay = 21 + st.wDayOfWeek; const wchar_t ddd_t[] = L"ddd"; // workaround for Borland QT_WA( { TCHAR buf[255]; if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, ddd_t, buf, 255 ) ) return QString::fromUcs2( (ushort*)buf ); } , { char buf[255]; if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "ddd", (char*)&buf, 255 ) ) return QString::fromLocal8Bit( buf ); } ); #endif return QString::null; } /*! Returns the long name of the \a weekday. 1 = "Monday", 2 = "Tuesday", ... 7 = "Sunday" The day names will be localized according to the system's locale settings. \sa toString(), shortDayName(), shortMonthName(), longMonthName() */ QString QDate::longDayName( int weekday ) { #if defined(QT_CHECK_RANGE) if ( weekday < 1 || weekday > 7 ) { qWarning( "QDate::longDayName: Parameter out of range." ); weekday = 1; } #endif #ifndef Q_WS_WIN char buffer[255]; tm tt; memset( &tt, 0, sizeof( tm ) ); tt.tm_wday = ( weekday == 7 ) ? 0 : weekday; if ( strftime( buffer, sizeof( buffer ), "%A", &tt ) ) return QString::fromLocal8Bit( buffer ); #else SYSTEMTIME st; memset( &st, 0, sizeof(SYSTEMTIME) ); st.wYear = 2001; st.wMonth = 10; st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday; st.wDay = 21 + st.wDayOfWeek; const wchar_t dddd_t[] = L"dddd"; // workaround for Borland QT_WA( { TCHAR buf[255]; if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, dddd_t, buf, 255 ) ) return QString::fromUcs2( (ushort*)buf ); } , { char buf[255]; if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "dddd", (char*)&buf, 255 ) ) return QString::fromLocal8Bit( buf ); } ); #endif return QString::null; } #endif //QT_NO_TEXTDATE #ifndef QT_NO_DATESTRING #if !defined(QT_NO_SPRINTF) /*! \overload Returns the date as a string. The \a f parameter determines the format of the string. If \a f is \c Qt::TextDate, the string format is "Sat May 20 1995" (using the shortDayName() and shortMonthName() functions to generate the string, so the day and month names are locale specific). If \a f is \c Qt::ISODate, the string format corresponds to the ISO 8601 specification for representations of dates, which is YYYY-MM-DD where YYYY is the year, MM is the month of the year (between 01 and 12), and DD is the day of the month between 01 and 31. If \a f is \c Qt::LocalDate, the string format depends on the locale settings of the system. \sa shortDayName(), shortMonthName() */ QString QDate::toString( Qt::DateFormat f ) const { int y, m, d; julianToGregorian( jd, y, m, d ); switch ( f ) { case Qt::LocalDate: { #ifndef Q_WS_WIN tm tt; memset( &tt, 0, sizeof( tm ) ); char buf[255]; tt.tm_mday = day(); tt.tm_mon = month() - 1; tt.tm_year = year() - 1900; static const char * avoidEgcsWarning = "%x"; if ( strftime( buf, sizeof(buf), avoidEgcsWarning, &tt ) ) return QString::fromLocal8Bit( buf ); #else SYSTEMTIME st; memset( &st, 0, sizeof(SYSTEMTIME) ); st.wYear = year(); st.wMonth = month(); st.wDay = day(); QT_WA( { TCHAR buf[255]; if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) ) return QString::fromUcs2( (ushort*)buf ); } , { char buf[255]; if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) ) return QString::fromLocal8Bit( buf ); } ); #endif return QString::null; } default: #ifndef QT_NO_TEXTDATE case Qt::TextDate: { QString buf = shortDayName( dayOfWeek() ); buf += ' '; buf += shortMonthName( m ); QString t; t.sprintf( " %d %d", d, y ); buf += t; return buf; } #endif case Qt::ISODate: { QString month( QString::number( m ).rightJustify( 2, '0' ) ); QString day( QString::number( d ).rightJustify( 2, '0' ) ); return QString::number( y ) + "-" + month + "-" + day; } } } #endif //QT_NO_SPRINTF /*! Returns the date as a string. The \a format parameter determines the format of the result string. These expressions may be used: \table \header \i Expression \i Output \row \i d \i the day as number without a leading zero (1-31) \row \i dd \i the day as number with a leading zero (01-31) \row \i ddd \i the abbreviated localized day name (e.g. 'Mon'..'Sun'). Uses QDate::shortDayName(). \row \i dddd \i the long localized day name (e.g. 'Monday'..'Sunday'). Uses QDate::longDayName(). \row \i M \i the month as number without a leading zero (1-12) \row \i MM \i the month as number with a leading zero (01-12) \row \i MMM \i the abbreviated localized month name (e.g. 'Jan'..'Dec'). Uses QDate::shortMonthName(). \row \i MMMM \i the long localized month name (e.g. 'January'..'December'). Uses QDate::longMonthName(). \row \i yy \i the year as two digit number (00-99) \row \i yyyy \i the year as four digit number (1752-8000) \endtable All other input characters will be ignored. Example format strings (assuming that the QDate is the 20<sup><small>th</small></sup> July 1969): \table \header \i Format \i Result \row \i dd.MM.yyyy \i11 20.07.1969 \row \i ddd MMMM d yy \i11 Sun July 20 69 \endtable \sa QDate::toString() QTime::toString() */ QString QDate::toString( const QString& format ) const { return fmtDateTime( format, 0, this ); } #endif //QT_NO_DATESTRING /*! Sets the date's year \a y, month \a m and day \a d. \a y must be in the range 1752..8000, \a m must be in the range 1..12, and \a d must be in the range 1..31. \warning If \a y is in the range 0..99, it is interpreted as 1900..1999. Returns TRUE if the date is valid; otherwise returns FALSE. */ bool QDate::setYMD( int y, int m, int d ) { if ( year() == y && month() == m && day() == d ) return isValid(); if ( !isValid(y,m,d) ) { #if defined(QT_CHECK_RANGE) qWarning( "QDate::setYMD: Invalid date %04d-%02d-%02d", y, m, d ); #endif return FALSE; } jd = gregorianToJulian( y, m, d ); return TRUE; } /*! Returns a QDate object containing a date \a ndays later than the date of this object (or earlier if \a ndays is negative). \sa addMonths() addYears() daysTo() */ QDate QDate::addDays( int ndays ) const { QDate d; d.jd = jd + ndays; return d; } /*! Returns a QDate object containing a date \a nmonths later than the date of this object (or earlier if \a nmonths is negative). \sa addDays() addYears() */ QDate QDate::addMonths( int nmonths ) const { int y, m, d; julianToGregorian( jd, y, m, d ); while ( nmonths != 0 ) { if ( nmonths < 0 && nmonths + 12 <= 0 ) { y--; nmonths+=12; } else if ( nmonths < 0 ) { m+= nmonths; nmonths = 0; if ( m <= 0 ) { --y; m+=12; } } else if ( nmonths - 12 >= 0 ) { y++; nmonths-=12; } else if ( m == 12 ) { y++; m = 0; } else { m+= nmonths; nmonths = 0; if ( m > 12 ) { ++y; m -= 12; } } } QDate tmp(y,m,1); if( d > tmp.daysInMonth() ) d = tmp.daysInMonth(); QDate date(y, m, d); return date; } /*! Returns a QDate object containing a date \a nyears later than the date of this object (or earlier if \a nyears is negative). \sa addDays(), addMonths() */ QDate QDate::addYears( int nyears ) const { int y, m, d; julianToGregorian( jd, y, m, d ); y += nyears; + + QDate tmp(y,m,1); + + if( d > tmp.daysInMonth() ) + d = tmp.daysInMonth(); + QDate date(y, m, d); return date; } /*! Returns the number of days from this date to \a d (which is negative if \a d is earlier than this date). Example: \code QDate d1( 1995, 5, 17 ); // May 17th 1995 QDate d2( 1995, 5, 20 ); // May 20th 1995 d1.daysTo( d2 ); // returns 3 d2.daysTo( d1 ); // returns -3 \endcode \sa addDays() */ int QDate::daysTo( const QDate &d ) const { return d.jd - jd; } /*! \fn bool QDate::operator==( const QDate &d ) const Returns TRUE if this date is equal to \a d; otherwise returns FALSE. */ /*! \fn bool QDate::operator!=( const QDate &d ) const Returns TRUE if this date is different from \a d; otherwise returns FALSE. */ /*! \fn bool QDate::operator<( const QDate &d ) const Returns TRUE if this date is earlier than \a d, otherwise returns FALSE. */ /*! \fn bool QDate::operator<=( const QDate &d ) const Returns TRUE if this date is earlier than or equal to \a d, otherwise returns FALSE. */ /*! \fn bool QDate::operator>( const QDate &d ) const Returns TRUE if this date is later than \a d, otherwise returns FALSE. */ /*! \fn bool QDate::operator>=( const QDate &d ) const Returns TRUE if this date is later than or equal to \a d, otherwise returns FALSE. */ /*! \overload Returns the current date, as reported by the system clock. \sa QTime::currentTime(), QDateTime::currentDateTime() */ QDate QDate::currentDate() { return currentDate( Qt::LocalTime ); } /*! Returns the current date, as reported by the system clock, for the TimeSpec \a ts. The default TimeSpec is LocalTime. \sa QTime::currentTime(), QDateTime::currentDateTime(), Qt::TimeSpec */ QDate QDate::currentDate( Qt::TimeSpec ts ) { QDate d; #if defined(Q_OS_WIN32) SYSTEMTIME t; memset( &t, 0, sizeof(SYSTEMTIME) ); if ( ts == Qt::LocalTime ) GetLocalTime( &t ); else GetSystemTime( &t ); d.jd = gregorianToJulian( t.wYear, t.wMonth, t.wDay ); #else + // posix compliant system time_t ltime; time( <ime ); tm *t; + +# if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant versions of localtime() and gmtime() where available + tm res; + if ( ts == Qt::LocalTime ) + t = localtime_r( <ime, &res ); + else + t = gmtime_r( <ime, &res ); +# else if ( ts == Qt::LocalTime ) t = localtime( <ime ); else t = gmtime( <ime ); +# endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS + d.jd = gregorianToJulian( t->tm_year + 1900, t->tm_mon + 1, t->tm_mday ); #endif return d; } #ifndef QT_NO_DATESTRING /*! Returns the QDate represented by the string \a s, using the format \a f, or an invalid date if the string cannot be parsed. Note for \c Qt::TextDate: It is recommended that you use the English short month names (e.g. "Jan"). Although localized month names can also be used, they depend on the user's locale settings. \warning \c Qt::LocalDate cannot be used here. */ QDate QDate::fromString( const QString& s, Qt::DateFormat f ) { if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { #if defined(QT_CHECK_RANGE) qWarning( "QDate::fromString: Parameter out of range." ); #endif return QDate(); } switch ( f ) { case Qt::ISODate: { int year( s.mid( 0, 4 ).toInt() ); int month( s.mid( 5, 2 ).toInt() ); int day( s.mid( 8, 2 ).toInt() ); if ( year && month && day ) return QDate( year, month, day ); } break; default: #ifndef QT_NO_TEXTDATE case Qt::TextDate: { /* This will fail gracefully if the input string doesn't contain any space. */ int monthPos = s.find( ' ' ) + 1; int dayPos = s.find( ' ', monthPos ) + 1; QString monthName( s.mid(monthPos, dayPos - monthPos - 1) ); int month = -1; // try English names first for ( int i = 0; i < 12; i++ ) { if ( monthName == qt_shortMonthNames[i] ) { month = i + 1; break; } } // try the localized names if ( month == -1 ) { for ( int i = 0; i < 12; i++ ) { if ( monthName == shortMonthName( i + 1 ) ) { month = i + 1; break; } } } #if defined(QT_CHECK_RANGE) if ( month < 1 || month > 12 ) { qWarning( "QDate::fromString: Parameter out of range." ); month = 1; } #endif int day = s.mid( dayPos, 2 ).stripWhiteSpace().toInt(); int year = s.right( 4 ).toInt(); return QDate( year, month, day ); } #else break; #endif } return QDate(); } #endif //QT_NO_DATESTRING /*! \overload Returns TRUE if the specified date (year \a y, month \a m and day \a d) is valid; otherwise returns FALSE. Example: \code QDate::isValid( 2002, 5, 17 ); // TRUE May 17th 2002 is valid QDate::isValid( 2002, 2, 30 ); // FALSE Feb 30th does not exist QDate::isValid( 2004, 2, 29 ); // TRUE 2004 is a leap year QDate::isValid( 1202, 6, 6 ); // FALSE 1202 is pre-Gregorian \endcode \warning A \a y value in the range 00..99 is interpreted as 1900..1999. \sa isNull(), setYMD() */ bool QDate::isValid( int y, int m, int d ) { if ( y >= 0 && y <= 99 ) y += 1900; else if ( y < FIRST_YEAR || (y == FIRST_YEAR && (m < 9 || (m == 9 && d < 14))) ) return FALSE; return (d > 0 && m > 0 && m <= 12) && (d <= monthDays[m] || (d == 29 && m == 2 && leapYear(y))); } /*! Returns TRUE if the specified year \a y is a leap year; otherwise returns FALSE. */ bool QDate::leapYear( int y ) { return y % 4 == 0 && y % 100 != 0 || y % 400 == 0; } /*! \internal Converts a Gregorian date to a Julian day. This algorithm is taken from Communications of the ACM, Vol 6, No 8. \sa julianToGregorian() */ uint QDate::gregorianToJulian( int y, int m, int d ) { uint c, ya; if ( y <= 99 ) y += 1900; if ( m > 2 ) { m -= 3; } else { m += 9; y--; } c = y; // NOTE: Sym C++ 6.0 bug c /= 100; ya = y - 100*c; return 1721119 + d + (146097*c)/4 + (1461*ya)/4 + (153*m+2)/5; } /*! \internal Converts a Julian day to a Gregorian date. This algorithm is taken from Communications of the ACM, Vol 6, No 8. \sa gregorianToJulian() */ void QDate::julianToGregorian( uint jd, int &y, int &m, int &d ) { uint x; uint j = jd - 1721119; y = (j*4 - 1)/146097; j = j*4 - 146097*y - 1; x = j/4; j = (x*4 + 3) / 1461; y = 100*y + j; x = (x*4) + 3 - 1461*j; x = (x + 4)/4; m = (5*x - 3)/153; x = 5*x - 3 - 153*m; d = (x + 5)/5; if ( m < 10 ) { m += 3; } else { m -= 9; y++; } } /***************************************************************************** QTime member functions *****************************************************************************/ /*! \class QTime qdatetime.h \reentrant \brief The QTime class provides clock time functions. \ingroup time \mainclass A QTime object contains a clock time, i.e. the number of hours, minutes, seconds, and milliseconds since midnight. It can read the current time from the system clock and measure a span of elapsed time. It provides functions for comparing times and for manipulating a time by adding a number of (milli)seconds. QTime uses the 24-hour clock format; it has no concept of AM/PM. It operates in local time; it knows nothing about time zones or daylight savings time. A QTime object is typically created either by giving the number of hours, minutes, seconds, and milliseconds explicitly, or by using the static function currentTime(), which creates a QTime object that contains the system's clock time. Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy. The hour(), minute(), second(), and msec() functions provide access to the number of hours, minutes, seconds, and milliseconds of the time. The same information is provided in textual format by the toString() function. QTime provides a full set of operators to compare two QTime objects. One time is considered smaller than another if it is earlier than the other. The time a given number of seconds or milliseconds later than a given time can be found using the addSecs() or addMSecs() functions. Correspondingly, the number of (milli)seconds between two times can be found using the secsTo() or msecsTo() functions. QTime can be used to measure a span of elapsed time using the start(), restart(), and elapsed() functions. \sa QDate, QDateTime */ /*! \fn QTime::QTime() Constructs the time 0 hours, minutes, seconds and milliseconds, i.e. 00:00:00.000 (midnight). This is a valid time. \sa isValid() */ /*! Constructs a time with hour \a h, minute \a m, seconds \a s and milliseconds \a ms. \a h must be in the range 0..23, \a m and \a s must be in the range 0..59, and \a ms must be in the range 0..999. \sa isValid() */ QTime::QTime( int h, int m, int s, int ms ) { setHMS( h, m, s, ms ); } /*! \fn bool QTime::isNull() const Returns TRUE if the time is equal to 00:00:00.000; otherwise returns FALSE. A null time is valid. \sa isValid() */ /*! Returns TRUE if the time is valid; otherwise returns FALSE. The time 23:30:55.746 is valid, whereas 24:12:30 is invalid. \sa isNull() */ bool QTime::isValid() const { return ds < MSECS_PER_DAY; } /*! Returns the hour part (0..23) of the time. */ int QTime::hour() const { return ds / MSECS_PER_HOUR; } /*! Returns the minute part (0..59) of the time. */ int QTime::minute() const { return (ds % MSECS_PER_HOUR)/MSECS_PER_MIN; } /*! Returns the second part (0..59) of the time. */ int QTime::second() const { return (ds / 1000)%SECS_PER_MIN; } /*! Returns the millisecond part (0..999) of the time. */ int QTime::msec() const { return ds % 1000; } #ifndef QT_NO_DATESTRING #ifndef QT_NO_SPRINTF /*! \overload Returns the time as a string. Milliseconds are not included. The \a f parameter determines the format of the string. If \a f is \c Qt::TextDate, the string format is HH:MM:SS; e.g. 1 second before midnight would be "23:59:59". If \a f is \c Qt::ISODate, the string format corresponds to the ISO 8601 extended specification for representations of dates, which is also HH:MM:SS. If \a f is Qt::LocalDate, the string format depends on the locale settings of the system. */ QString QTime::toString( Qt::DateFormat f ) const { switch ( f ) { case Qt::LocalDate: { #ifndef Q_WS_WIN tm tt; memset( &tt, 0, sizeof( tm ) ); char buf[255]; tt.tm_sec = second(); tt.tm_min = minute(); tt.tm_hour = hour(); if ( strftime( buf, sizeof(buf), "%X", &tt ) ) return QString::fromLocal8Bit( buf ); #else SYSTEMTIME st; memset( &st, 0, sizeof(SYSTEMTIME) ); st.wHour = hour(); st.wMinute = minute(); st.wSecond = second(); st.wMilliseconds = 0; QT_WA( { TCHAR buf[255]; if ( GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) ) return QString::fromUcs2( (ushort*)buf ); } , { char buf[255]; if ( GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) ) return QString::fromLocal8Bit( buf ); } ); #endif return QString::null; } default: case Qt::ISODate: case Qt::TextDate: QString buf; buf.sprintf( "%.2d:%.2d:%.2d", hour(), minute(), second() ); return buf; } } #endif /*! Returns the time as a string. The \a format parameter determines the format of the result string. These expressions may be used: \table \header \i Expression \i Output \row \i h \i the hour without a leading zero (0..23 or 1..12 if AM/PM display) \row \i hh \i the hour with a leading zero (00..23 or 01..12 if AM/PM display) \row \i m \i the minute without a leading zero (0..59) \row \i mm \i the minute with a leading zero (00..59) \row \i s \i the second whithout a leading zero (0..59) \row \i ss \i the second whith a leading zero (00..59) \row \i z \i the milliseconds without leading zeroes (0..999) \row \i zzz \i the milliseconds with leading zeroes (000..999) \row \i AP \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". \row \i ap \i use am/pm display. \e ap will be replaced by either "am" or "pm". \endtable All other input characters will be ignored. Example format strings (assuming that the QTime is 14:13:09.042) \table \header \i Format \i Result \row \i hh:mm:ss.zzz \i11 14:13:09.042 \row \i h:m:s ap \i11 2:13:9 pm \endtable \sa QDate::toString() QTime::toString() */ QString QTime::toString( const QString& format ) const { return fmtDateTime( format, this, 0 ); } #endif //QT_NO_DATESTRING /*! Sets the time to hour \a h, minute \a m, seconds \a s and milliseconds \a ms. \a h must be in the range 0..23, \a m and \a s must be in the range 0..59, and \a ms must be in the range 0..999. Returns TRUE if the set time is valid; otherwise returns FALSE. \sa isValid() */ bool QTime::setHMS( int h, int m, int s, int ms ) { if ( !isValid(h,m,s,ms) ) { #if defined(QT_CHECK_RANGE) qWarning( "QTime::setHMS Invalid time %02d:%02d:%02d.%03d", h, m, s, ms ); #endif ds = MSECS_PER_DAY; // make this invalid return FALSE; } ds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms; return TRUE; } /*! Returns a QTime object containing a time \a nsecs seconds later than the time of this object (or earlier if \a nsecs is negative). Note that the time will wrap if it passes midnight. Example: \code QTime n( 14, 0, 0 ); // n == 14:00:00 QTime t; t = n.addSecs( 70 ); // t == 14:01:10 t = n.addSecs( -70 ); // t == 13:58:50 t = n.addSecs( 10*60*60 + 5 ); // t == 00:00:05 t = n.addSecs( -15*60*60 ); // t == 23:00:00 \endcode \sa addMSecs(), secsTo(), QDateTime::addSecs() */ QTime QTime::addSecs( int nsecs ) const { return addMSecs( nsecs * 1000 ); } /*! Returns the number of seconds from this time to \a t (which is negative if \a t is earlier than this time). Because QTime measures time within a day and there are 86400 seconds in a day, the result is always between -86400 and 86400. \sa addSecs() QDateTime::secsTo() */ int QTime::secsTo( const QTime &t ) const { return ((int)t.ds - (int)ds)/1000; } /*! Returns a QTime object containing a time \a ms milliseconds later than the time of this object (or earlier if \a ms is negative). Note that the time will wrap if it passes midnight. See addSecs() for an example. \sa addSecs(), msecsTo() */ QTime QTime::addMSecs( int ms ) const { QTime t; if ( ms < 0 ) { // % not well-defined for -ve, but / is. int negdays = (MSECS_PER_DAY-ms) / MSECS_PER_DAY; t.ds = ((int)ds + ms + negdays*MSECS_PER_DAY) % MSECS_PER_DAY; } else { t.ds = ((int)ds + ms) % MSECS_PER_DAY; } return t; } /*! Returns the number of milliseconds from this time to \a t (which is negative if \a t is earlier than this time). Because QTime measures time within a day and there are 86400 seconds in a day, the result is always between -86400 and 86400s. \sa secsTo() */ int QTime::msecsTo( const QTime &t ) const { return (int)t.ds - (int)ds; } /*! \fn bool QTime::operator==( const QTime &t ) const Returns TRUE if this time is equal to \a t; otherwise returns FALSE. */ /*! \fn bool QTime::operator!=( const QTime &t ) const Returns TRUE if this time is different from \a t; otherwise returns FALSE. */ /*! \fn bool QTime::operator<( const QTime &t ) const Returns TRUE if this time is earlier than \a t; otherwise returns FALSE. */ /*! \fn bool QTime::operator<=( const QTime &t ) const Returns TRUE if this time is earlier than or equal to \a t; otherwise returns FALSE. */ /*! \fn bool QTime::operator>( const QTime &t ) const Returns TRUE if this time is later than \a t; otherwise returns FALSE. */ /*! \fn bool QTime::operator>=( const QTime &t ) const Returns TRUE if this time is later than or equal to \a t; otherwise returns FALSE. */ /*! \overload Returns the current time as reported by the system clock. Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy. */ QTime QTime::currentTime() { return currentTime( Qt::LocalTime ); } /*! Returns the current time as reported by the system clock, for the TimeSpec \a ts. The default TimeSpec is LocalTime. Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy. \sa Qt::TimeSpec */ QTime QTime::currentTime( Qt::TimeSpec ts ) { QTime t; currentTime( &t, ts ); return t; } #ifndef QT_NO_DATESTRING /*! Returns the representation \a s as a QTime using the format \a f, or an invalid time if this is not possible. \warning Note that \c Qt::LocalDate cannot be used here. */ QTime QTime::fromString( const QString& s, Qt::DateFormat f ) { if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { #if defined(QT_CHECK_RANGE) qWarning( "QTime::fromString: Parameter out of range." ); #endif return QTime(); } int hour( s.mid( 0, 2 ).toInt() ); int minute( s.mid( 3, 2 ).toInt() ); int second( s.mid( 6, 2 ).toInt() ); int msec( s.mid( 9, 3 ).toInt() ); return QTime( hour, minute, second, msec ); } #endif /*! \internal \obsolete Fetches the current time and returns TRUE if the time is within one minute after midnight, otherwise FALSE. The return value is used by QDateTime::currentDateTime() to ensure that the date there is correct. */ bool QTime::currentTime( QTime *ct ) { return currentTime( ct, Qt::LocalTime ); } /*! \internal Fetches the current time, for the TimeSpec \a ts, and returns TRUE if the time is within one minute after midnight, otherwise FALSE. The return value is used by QDateTime::currentDateTime() to ensure that the date there is correct. The default TimeSpec is LocalTime. \sa Qt::TimeSpec */ bool QTime::currentTime( QTime *ct, Qt::TimeSpec ts ) { if ( !ct ) { #if defined(QT_CHECK_NULL) qWarning( "QTime::currentTime(QTime *): Null pointer not allowed" ); #endif return FALSE; } #if defined(Q_OS_WIN32) SYSTEMTIME t; if ( ts == Qt::LocalTime ) { GetLocalTime( &t ); } else { GetSystemTime( &t ); } ct->ds = (uint)( MSECS_PER_HOUR*t.wHour + MSECS_PER_MIN*t.wMinute + 1000*t.wSecond + t.wMilliseconds ); #elif defined(Q_OS_UNIX) + // posix compliant system struct timeval tv; gettimeofday( &tv, 0 ); time_t ltime = tv.tv_sec; tm *t; - if ( ts == Qt::LocalTime ) { + +# if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant versions of localtime() and gmtime() where available + tm res; + if ( ts == Qt::LocalTime ) + t = localtime_r( <ime, &res ); + else + t = gmtime_r( <ime, &res ); +# else + if ( ts == Qt::LocalTime ) t = localtime( <ime ); - } else { + else t = gmtime( <ime ); - } +# endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS + ct->ds = (uint)( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec + tv.tv_usec / 1000 ); #else time_t ltime; // no millisecond resolution ::time( <ime ); tm *t; if ( ts == Qt::LocalTime ) localtime( <ime ); else gmtime( <ime ); ct->ds = (uint) ( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec ); #endif // 00:00.00 to 00:00.59.999 is considered as "midnight or right after" return ct->ds < (uint) MSECS_PER_MIN; } /*! \overload Returns TRUE if the specified time is valid; otherwise returns FALSE. The time is valid if \a h is in the range 0..23, \a m and \a s are in the range 0..59, and \a ms is in the range 0..999. Example: \code QTime::isValid(21, 10, 30); // returns TRUE QTime::isValid(22, 5, 62); // returns FALSE \endcode */ bool QTime::isValid( int h, int m, int s, int ms ) { return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000; } /*! Sets this time to the current time. This is practical for timing: \code QTime t; - t.start(); // start clock - ... // some lengthy task - qDebug( "%d\n", t.elapsed() ); // prints the number of msecs elapsed + t.start(); + some_lengthy_task(); + qDebug( "Time elapsed: %d ms", t.elapsed() ); \endcode \sa restart(), elapsed(), currentTime() */ void QTime::start() { *this = currentTime(); } /*! Sets this time to the current time and returns the number of milliseconds that have elapsed since the last time start() or restart() was called. This function is guaranteed to be atomic and is thus very handy for repeated measurements. Call start() to start the first measurement and then restart() for each later measurement. Note that the counter wraps to zero 24 hours after the last call to start() or restart(). \warning If the system's clock setting has been changed since the last time start() or restart() was called, the result is undefined. This can happen when daylight savings time is turned on or off. \sa start(), elapsed(), currentTime() */ int QTime::restart() { QTime t = currentTime(); int n = msecsTo( t ); if ( n < 0 ) // passed midnight n += 86400*1000; *this = t; return n; } /*! Returns the number of milliseconds that have elapsed since the last time start() or restart() was called. Note that the counter wraps to zero 24 hours after the last call to start() or restart. Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy. \warning If the system's clock setting has been changed since the last time start() or restart() was called, the result is undefined. This can happen when daylight savings time is turned on or off. \sa start(), restart() */ int QTime::elapsed() const { int n = msecsTo( currentTime() ); if ( n < 0 ) // passed midnight n += 86400*1000; return n; } /***************************************************************************** QDateTime member functions *****************************************************************************/ /*! \class QDateTime qdatetime.h \reentrant \brief The QDateTime class provides date and time functions. \ingroup time \mainclass A QDateTime object contains a calendar date and a clock time (a "datetime"). It is a combination of the QDate and QTime classes. It can read the current datetime from the system clock. It provides functions for comparing datetimes and for manipulating a datetime by adding a number of seconds, days, months or years. A QDateTime object is typically created either by giving a date and time explicitly in the constructor, or by using the static function currentDateTime(), which returns a QDateTime object set to the system clock's time. The date and time can be changed with setDate() and setTime(). A datetime can also be set using the setTime_t() function, which takes a POSIX-standard "number of seconds since 00:00:00 on January 1, 1970" value. The fromString() function returns a QDateTime given a string and a date format which is used to interpret the date within the string. The date() and time() functions provide access to the date and time parts of the datetime. The same information is provided in textual format by the toString() function. QDateTime provides a full set of operators to compare two QDateTime objects where smaller means earlier and larger means later. You can increment (or decrement) a datetime by a given number of seconds using addSecs() or days using addDays(). Similarly you can use addMonths() and addYears(). The daysTo() function returns the number of days between two datetimes, and secsTo() returns the number of seconds between two datetimes. The range of a datetime object is constrained to the ranges of the QDate and QTime objects which it embodies. \sa QDate QTime QDateTimeEdit */ /*! \fn QDateTime::QDateTime() Constructs a null datetime (i.e. null date and null time). A null datetime is invalid, since the date is invalid. \sa isValid() */ /*! Constructs a datetime with date \a date and null (but valid) time (00:00:00.000). */ QDateTime::QDateTime( const QDate &date ) : d(date) { } /*! Constructs a datetime with date \a date and time \a time. */ QDateTime::QDateTime( const QDate &date, const QTime &time ) : d(date), t(time) { } /*! \fn bool QDateTime::isNull() const Returns TRUE if both the date and the time are null; otherwise returns FALSE. A null datetime is invalid. \sa QDate::isNull(), QTime::isNull() */ /*! \fn bool QDateTime::isValid() const Returns TRUE if both the date and the time are valid; otherwise returns FALSE. \sa QDate::isValid(), QTime::isValid() */ /*! \fn QDate QDateTime::date() const Returns the date part of the datetime. \sa setDate(), time() */ /*! \fn QTime QDateTime::time() const Returns the time part of the datetime. \sa setTime(), date() */ /*! \fn void QDateTime::setDate( const QDate &date ) Sets the date part of this datetime to \a date. \sa date(), setTime() */ /*! \fn void QDateTime::setTime( const QTime &time ) Sets the time part of this datetime to \a time. \sa time(), setDate() */ /*! Returns the datetime as the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (UTC). On systems that do not support timezones, this function will behave as if local time were UTC. \sa setTime_t() */ uint QDateTime::toTime_t() const { tm brokenDown; brokenDown.tm_sec = t.second(); brokenDown.tm_min = t.minute(); brokenDown.tm_hour = t.hour(); brokenDown.tm_mday = d.day(); brokenDown.tm_mon = d.month() - 1; brokenDown.tm_year = d.year() - 1900; brokenDown.tm_isdst = -1; int secsSince1Jan1970UTC = (int) mktime( &brokenDown ); if ( secsSince1Jan1970UTC < -1 ) secsSince1Jan1970UTC = -1; return (uint) secsSince1Jan1970UTC; } /*! \overload Convenience function that sets the date and time to local time based on the given UTC time. */ void QDateTime::setTime_t( uint secsSince1Jan1970UTC ) { setTime_t( secsSince1Jan1970UTC, Qt::LocalTime ); } /*! Sets the date and time to \a ts time (\c Qt::LocalTime or \c Qt::UTC) given the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (UTC). On systems that do not support timezones this function will behave as if local time were UTC. On Windows, only a subset of \a secsSince1Jan1970UTC values are supported, as Windows starts counting from 1980. \sa toTime_t() */ void QDateTime::setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec ts ) { time_t tmp = (time_t) secsSince1Jan1970UTC; tm *brokenDown = 0; + +#if defined(Q_OS_UNIX) && defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // posix compliant system + // use the reentrant versions of localtime() and gmtime() where available + tm res; + if ( ts == Qt::LocalTime ) + brokenDown = localtime_r( &tmp, &res ); + if ( !brokenDown ) { + brokenDown = gmtime_r( &tmp, &res ); + if ( !brokenDown ) { + d.jd = QDate::gregorianToJulian( 1970, 1, 1 ); + t.ds = 0; + return; + } + } +#else if ( ts == Qt::LocalTime ) brokenDown = localtime( &tmp ); if ( !brokenDown ) { brokenDown = gmtime( &tmp ); if ( !brokenDown ) { d.jd = QDate::gregorianToJulian( 1970, 1, 1 ); t.ds = 0; return; } } +#endif + d.jd = QDate::gregorianToJulian( brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday ); t.ds = MSECS_PER_HOUR * brokenDown->tm_hour + MSECS_PER_MIN * brokenDown->tm_min + 1000 * brokenDown->tm_sec; } #ifndef QT_NO_DATESTRING #ifndef QT_NO_SPRINTF /*! \overload Returns the datetime as a string. The \a f parameter determines the format of the string. If \a f is \c Qt::TextDate, the string format is "Wed May 20 03:40:13 1998" (using QDate::shortDayName(), QDate::shortMonthName(), and QTime::toString() to generate the string, so the day and month names will have localized names). If \a f is \c Qt::ISODate, the string format corresponds to the ISO 8601 extended specification for representations of dates and times, which is YYYY-MM-DDTHH:MM:SS. If \a f is \c Qt::LocalDate, the string format depends on the locale settings of the system. If the format \a f is invalid, toString() returns a null string. \sa QDate::toString() QTime::toString() */ QString QDateTime::toString( Qt::DateFormat f ) const { if ( f == Qt::ISODate ) { return d.toString( Qt::ISODate ) + "T" + t.toString( Qt::ISODate ); } #ifndef QT_NO_TEXTDATE else if ( f == Qt::TextDate ) { #ifndef Q_WS_WIN QString buf = d.shortDayName( d.dayOfWeek() ); buf += ' '; buf += d.shortMonthName( d.month() ); buf += ' '; buf += QString().setNum( d.day() ); buf += ' '; #else QString buf; QString winstr; QT_WA( { TCHAR out[255]; GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255 ); winstr = QString::fromUcs2( (ushort*)out ); } , { char out[255]; GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255 ); winstr = QString::fromLocal8Bit( out ); } ); switch ( winstr.toInt() ) { case 1: buf = d.shortDayName( d.dayOfWeek() ) + " " + QString().setNum( d.day() ) + ". " + d.shortMonthName( d.month() ) + " "; break; default: buf = d.shortDayName( d.dayOfWeek() ) + " " + d.shortMonthName( d.month() ) + " " + QString().setNum( d.day() ) + " "; break; } #endif buf += t.toString(); buf += ' '; buf += QString().setNum( d.year() ); return buf; } #endif else if ( f == Qt::LocalDate ) { return d.toString( Qt::LocalDate ) + " " + t.toString( Qt::LocalDate ); } return QString::null; } #endif /*! Returns the datetime as a string. The \a format parameter determines the format of the result string. These expressions may be used for the date: \table \header \i Expression \i Output \row \i d \i the day as number without a leading zero (1-31) \row \i dd \i the day as number with a leading zero (01-31) \row \i ddd \i the abbreviated localized day name (e.g. 'Mon'..'Sun'). Uses QDate::shortDayName(). \row \i dddd \i the long localized day name (e.g. 'Monday'..'Sunday'). Uses QDate::longDayName(). \row \i M \i the month as number without a leading zero (1-12) \row \i MM \i the month as number with a leading zero (01-12) \row \i MMM \i the abbreviated localized month name (e.g. 'Jan'..'Dec'). Uses QDate::shortMonthName(). \row \i MMMM \i the long localized month name (e.g. 'January'..'December'). Uses QDate::longMonthName(). \row \i yy \i the year as two digit number (00-99) \row \i yyyy \i the year as four digit number (1752-8000) \endtable These expressions may be used for the time: \table \header \i Expression \i Output \row \i h \i the hour without a leading zero (0..23 or 1..12 if AM/PM display) \row \i hh \i the hour with a leading zero (00..23 or 01..12 if AM/PM display) \row \i m \i the minute without a leading zero (0..59) \row \i mm \i the minute with a leading zero (00..59) \row \i s \i the second whithout a leading zero (0..59) \row \i ss \i the second whith a leading zero (00..59) \row \i z \i the milliseconds without leading zeroes (0..999) \row \i zzz \i the milliseconds with leading zeroes (000..999) \row \i AP \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". \row \i ap \i use am/pm display. \e ap will be replaced by either "am" or "pm". \endtable All other input characters will be ignored. Example format strings (assumed that the QDateTime is 21<small><sup>st</sup></small> May 2001 14:13:09) \table \header \i Format \i Result \row \i dd.MM.yyyy \i11 21.05.2001 \row \i ddd MMMM d yy \i11 Tue May 21 01 \row \i hh:mm:ss.zzz \i11 14:13:09.042 \row \i h:m:s ap \i11 2:13:9 pm \endtable \sa QDate::toString() QTime::toString() */ QString QDateTime::toString( const QString& format ) const { return fmtDateTime( format, &t, &d ); } #endif //QT_NO_DATESTRING /*! Returns a QDateTime object containing a datetime \a ndays days later than the datetime of this object (or earlier if \a ndays is negative). \sa daysTo(), addMonths(), addYears(), addSecs() */ QDateTime QDateTime::addDays( int ndays ) const { return QDateTime( d.addDays(ndays), t ); } /*! Returns a QDateTime object containing a datetime \a nmonths months later than the datetime of this object (or earlier if \a nmonths is negative). \sa daysTo(), addDays(), addYears(), addSecs() */ QDateTime QDateTime::addMonths( int nmonths ) const { return QDateTime( d.addMonths(nmonths), t ); } /*! Returns a QDateTime object containing a datetime \a nyears years later than the datetime of this object (or earlier if \a nyears is negative). \sa daysTo(), addDays(), addMonths(), addSecs() */ QDateTime QDateTime::addYears( int nyears ) const { return QDateTime( d.addYears(nyears), t ); } /*! Returns a QDateTime object containing a datetime \a nsecs seconds later than the datetime of this object (or earlier if \a nsecs is negative). \sa secsTo(), addDays(), addMonths(), addYears() */ QDateTime QDateTime::addSecs( int nsecs ) const { uint dd = d.jd; int tt = t.ds; int sign = 1; if ( nsecs < 0 ) { nsecs = -nsecs; sign = -1; } if ( nsecs >= (int)SECS_PER_DAY ) { dd += sign*(nsecs/SECS_PER_DAY); nsecs %= SECS_PER_DAY; } tt += sign*nsecs*1000; if ( tt < 0 ) { tt = MSECS_PER_DAY - tt - 1; dd -= tt / MSECS_PER_DAY; tt = tt % MSECS_PER_DAY; tt = MSECS_PER_DAY - tt - 1; } else if ( tt >= (int)MSECS_PER_DAY ) { dd += ( tt / MSECS_PER_DAY ); tt = tt % MSECS_PER_DAY; } QDateTime ret; ret.t.ds = tt; ret.d.jd = dd; return ret; } /*! Returns the number of days from this datetime to \a dt (which is negative if \a dt is earlier than this datetime). \sa addDays(), secsTo() */ int QDateTime::daysTo( const QDateTime &dt ) const { return d.daysTo( dt.d ); } /*! Returns the number of seconds from this datetime to \a dt (which is negative if \a dt is earlier than this datetime). Example: \code QDateTime dt = QDateTime::currentDateTime(); QDateTime xmas( QDate(dt.year(),12,24), QTime(17,00) ); qDebug( "There are %d seconds to Christmas", dt.secsTo(xmas) ); \endcode \sa addSecs(), daysTo(), QTime::secsTo() */ int QDateTime::secsTo( const QDateTime &dt ) const { return t.secsTo(dt.t) + d.daysTo(dt.d)*SECS_PER_DAY; } /*! Returns TRUE if this datetime is equal to \a dt; otherwise returns FALSE. \sa operator!=() */ bool QDateTime::operator==( const QDateTime &dt ) const { return t == dt.t && d == dt.d; } /*! Returns TRUE if this datetime is different from \a dt; otherwise returns FALSE. \sa operator==() */ bool QDateTime::operator!=( const QDateTime &dt ) const { return t != dt.t || d != dt.d; } /*! Returns TRUE if this datetime is earlier than \a dt; otherwise returns FALSE. */ bool QDateTime::operator<( const QDateTime &dt ) const { if ( d < dt.d ) return TRUE; return d == dt.d ? t < dt.t : FALSE; } /*! Returns TRUE if this datetime is earlier than or equal to \a dt; otherwise returns FALSE. */ bool QDateTime::operator<=( const QDateTime &dt ) const { if ( d < dt.d ) return TRUE; return d == dt.d ? t <= dt.t : FALSE; } /*! Returns TRUE if this datetime is later than \a dt; otherwise returns FALSE. */ bool QDateTime::operator>( const QDateTime &dt ) const { if ( d > dt.d ) return TRUE; return d == dt.d ? t > dt.t : FALSE; } /*! Returns TRUE if this datetime is later than or equal to \a dt; otherwise returns FALSE. */ bool QDateTime::operator>=( const QDateTime &dt ) const { if ( d > dt.d ) return TRUE; return d == dt.d ? t >= dt.t : FALSE; } /*! \overload Returns the current datetime, as reported by the system clock. \sa QDate::currentDate(), QTime::currentTime() */ QDateTime QDateTime::currentDateTime() { return currentDateTime( Qt::LocalTime ); } /*! Returns the current datetime, as reported by the system clock, for the TimeSpec \a ts. The default TimeSpec is LocalTime. \sa QDate::currentDate(), QTime::currentTime(), Qt::TimeSpec */ QDateTime QDateTime::currentDateTime( Qt::TimeSpec ts ) { QDateTime dt; QTime t; dt.setDate( QDate::currentDate(ts) ); if ( QTime::currentTime(&t, ts) ) // midnight or right after? dt.setDate( QDate::currentDate(ts) ); // fetch date again dt.setTime( t ); return dt; } #ifndef QT_NO_DATESTRING /*! Returns the QDateTime represented by the string \a s, using the format \a f, or an invalid datetime if this is not possible. Note for \c Qt::TextDate: It is recommended that you use the English short month names (e.g. "Jan"). Although localized month names can also be used, they depend on the user's locale settings. \warning Note that \c Qt::LocalDate cannot be used here. */ QDateTime QDateTime::fromString( const QString& s, Qt::DateFormat f ) { if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) { #if defined(QT_CHECK_RANGE) qWarning( "QDateTime::fromString: Parameter out of range" ); #endif return QDateTime(); } if ( f == Qt::ISODate ) { return QDateTime( QDate::fromString( s.mid(0,10), Qt::ISODate ), QTime::fromString( s.mid(11), Qt::ISODate ) ); } #if !defined(QT_NO_REGEXP) && !defined(QT_NO_TEXTDATE) else if ( f == Qt::TextDate ) { diff --git a/qmake/tools/qdir.cpp b/qmake/tools/qdir.cpp index 418ea49..5714878 100644 --- a/qmake/tools/qdir.cpp +++ b/qmake/tools/qdir.cpp @@ -1,1294 +1,1342 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QDir class ** ** Created : 950427 ** -** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include "qdir.h" #ifndef QT_NO_DIR #include <private/qdir_p.h> #include "qfileinfo.h" #include "qregexp.h" #include "qstringlist.h" -#include <stdlib.h> -#include <ctype.h> +#include <limits.h> +#if defined(Q_FS_FAT) && !defined(Q_OS_UNIX) +const bool CaseSensitiveFS = FALSE; +#else +const bool CaseSensitiveFS = TRUE; +#endif /*! \class QDir + \reentrant \brief The QDir class provides access to directory structures and their contents in a platform-independent way. \ingroup io \mainclass A QDir is used to manipulate path names, access information regarding paths and files, and manipulate the underlying file system. A QDir can point to a file using either a relative or an absolute path. Absolute paths begin with the directory separator "/" (optionally preceded by a drive specification under Windows). If you always use "/" as a directory separator, Qt will translate your paths to conform to the underlying operating system. Relative file names begin with a directory name or a file name and specify a path relative to the current directory. The "current" path refers to the application's working directory. A QDir's own path is set and retrieved with setPath() and path(). An example of an absolute path is the string "/tmp/quartz", a relative path might look like "src/fatlib". You can use the function isRelative() to check if a QDir is using a relative or an absolute file path. Call convertToAbs() to convert a relative QDir to an absolute one. For a simplified path use cleanDirPath(). To obtain a path which has no symbolic links or redundant ".." elements use canonicalPath(). The path can be set with setPath(), and changed with cd() and cdUp(). QDir provides several static functions, for example, setCurrent() to set the application's working directory and currentDirPath() to retrieve the application's working directory. Access to some common paths is provided with the static functions, current(), home() and root() which return QDir objects or currentDirPath(), homeDirPath() and rootDirPath() which return the path as a string. The number of entries in a directory is returned by count(). Obtain a string list of the names of all the files and directories in a directory with entryList(). If you prefer a list of QFileInfo pointers use entryInfoList(). Both these functions can apply a name filter, an attributes filter (e.g. read-only, files not directories, etc.), and a sort order. The filters and sort may be set with calls to setNameFilter(), setFilter() and setSorting(). They may also be specified in the entryList() and entryInfoList()'s arguments. Create a new directory with mkdir(), rename a directory with rename() and remove an existing directory with rmdir(). Remove a file with remove(). You can interrogate a directory with exists(), isReadable() and isRoot(). To get a path with a filename use filePath(), and to get a directory name use dirName(); neither of these functions checks for the existence of the file or directory. The list of root directories is provided by drives(); on Unix systems this returns a list containing one root directory, "/"; on Windows the list will usually contain "C:/", and possibly "D:/", etc. If you need the path in a form suitable for the underlying operating system use convertSeparators(). Examples: See if a directory exists. \code QDir d( "example" ); // "./example" if ( !d.exists() ) qWarning( "Cannot find the example directory" ); \endcode Traversing directories and reading a file. \code QDir d = QDir::root(); // "/" if ( !d.cd("tmp") ) { // "/tmp" qWarning( "Cannot find the \"/tmp\" directory" ); } else { QFile f( d.filePath("ex1.txt") ); // "/tmp/ex1.txt" if ( !f.open(IO_ReadWrite) ) qWarning( "Cannot create the file %s", f.name() ); } \endcode A program that lists all the files in the current directory (excluding symbolic links), sorted by size, smallest first: \code #include <stdio.h> #include <qdir.h> int main( int argc, char **argv ) { QDir d; d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); d.setSorting( QDir::Size | QDir::Reversed ); const QFileInfoList *list = d.entryInfoList(); QFileInfoListIterator it( *list ); QFileInfo *fi; printf( " Bytes Filename\n" ); while ( (fi = it.current()) != 0 ) { printf( "%10li %s\n", fi->size(), fi->fileName().latin1() ); ++it; } return 0; } \endcode */ /*! Constructs a QDir pointing to the current directory. \sa currentDirPath() */ QDir::QDir() { dPath = QString::fromLatin1("."); init(); } /*! Constructs a QDir with path \a path, that filters its entries by name using \a nameFilter and by attributes using \a filterSpec. It also sorts the names using \a sortSpec. The default \a nameFilter is an empty string, which excludes nothing; the default \a filterSpec is \c All, which also means exclude nothing. The default \a sortSpec is \c Name|IgnoreCase, i.e. sort by name case-insensitively. Example that lists all the files in "/tmp": \code QDir d( "/tmp" ); for ( int i = 0; i < d.count(); i++ ) printf( "%s\n", d[i] ); \endcode If \a path is "" or QString::null, QDir uses "." (the current directory). If \a nameFilter is "" or QString::null, QDir uses the name filter "*" (all files). Note that \a path need not exist. \sa exists(), setPath(), setNameFilter(), setFilter(), setSorting() */ QDir::QDir( const QString &path, const QString &nameFilter, int sortSpec, int filterSpec ) { init(); dPath = cleanDirPath( path ); if ( dPath.isEmpty() ) dPath = QString::fromLatin1("."); nameFilt = nameFilter; if ( nameFilt.isEmpty() ) nameFilt = QString::fromLatin1("*"); filtS = (FilterSpec)filterSpec; sortS = (SortSpec)sortSpec; } /*! Constructs a QDir that is a copy of the directory \a d. \sa operator=() */ QDir::QDir( const QDir &d ) { dPath = d.dPath; fList = 0; fiList = 0; nameFilt = d.nameFilt; dirty = TRUE; allDirs = d.allDirs; filtS = d.filtS; sortS = d.sortS; } +/*! + Refreshes the directory information. +*/ +void QDir::refresh() const +{ + QDir* that = (QDir*) this; + that->dirty = TRUE; +} void QDir::init() { fList = 0; fiList = 0; nameFilt = QString::fromLatin1("*"); dirty = TRUE; allDirs = FALSE; filtS = All; sortS = SortSpec(Name | IgnoreCase); } /*! Destroys the QDir frees up its resources. */ QDir::~QDir() { delete fList; delete fiList; } /*! Sets the path of the directory to \a path. The path is cleaned of redundant ".", ".." and of multiple separators. No check is made to ensure that a directory with this path exists. The path can be either absolute or relative. Absolute paths begin with the directory separator "/" (optionally preceded by a drive specification under Windows). Relative file names begin with a directory name or a file name and specify a path relative to the current directory. An example of an absolute path is the string "/tmp/quartz", a relative path might look like "src/fatlib". \sa path(), absPath(), exists(), cleanDirPath(), dirName(), absFilePath(), isRelative(), convertToAbs() */ void QDir::setPath( const QString &path ) { dPath = cleanDirPath( path ); if ( dPath.isEmpty() ) dPath = QString::fromLatin1("."); dirty = TRUE; } /*! \fn QString QDir::path() const Returns the path, this may contain symbolic links, but never contains redundant ".", ".." or multiple separators. The returned path can be either absolute or relative (see setPath()). \sa setPath(), absPath(), exists(), cleanDirPath(), dirName(), absFilePath(), convertSeparators() */ /*! Returns the absolute path (a path that starts with "/" or with a drive specification), which may contain symbolic links, but never contains redundant ".", ".." or multiple separators. \sa setPath(), canonicalPath(), exists(), cleanDirPath(), dirName(), absFilePath() */ QString QDir::absPath() const { if ( QDir::isRelativePath(dPath) ) { QString tmp = currentDirPath(); if ( tmp.right(1) != QString::fromLatin1("/") ) tmp += '/'; tmp += dPath; return cleanDirPath( tmp ); } else { return cleanDirPath( dPath ); } } /*! Returns the name of the directory; this is \e not the same as the path, e.g. a directory with the name "mail", might have the path "/var/spool/mail". If the directory has no name (e.g. it is the root directory) QString::null is returned. No check is made to ensure that a directory with this name actually exists. \sa path(), absPath(), absFilePath(), exists(), QString::isNull() */ QString QDir::dirName() const { int pos = dPath.findRev( '/' ); if ( pos == -1 ) return dPath; return dPath.right( dPath.length() - pos - 1 ); } /*! Returns the path name of a file in the directory. Does \e not check if the file actually exists in the directory. If the QDir is relative the returned path name will also be relative. Redundant multiple separators or "." and ".." directories in \a fileName will not be removed (see cleanDirPath()). If \a acceptAbsPath is TRUE a \a fileName starting with a separator "/" will be returned without change. If \a acceptAbsPath is FALSE an absolute path will be prepended to the fileName and the resultant string returned. \sa absFilePath(), isRelative(), canonicalPath() */ QString QDir::filePath( const QString &fileName, bool acceptAbsPath ) const { if ( acceptAbsPath && !isRelativePath(fileName) ) return QString(fileName); QString tmp = dPath; if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName && fileName[0] != '/') ) tmp += '/'; tmp += fileName; return tmp; } /*! Returns the absolute path name of a file in the directory. Does \e not check if the file actually exists in the directory. Redundant multiple separators or "." and ".." directories in \a fileName will not be removed (see cleanDirPath()). If \a acceptAbsPath is TRUE a \a fileName starting with a separator "/" will be returned without change. If \a acceptAbsPath is FALSE an absolute path will be prepended to the fileName and the resultant string returned. \sa filePath() */ QString QDir::absFilePath( const QString &fileName, bool acceptAbsPath ) const { if ( acceptAbsPath && !isRelativePath( fileName ) ) return fileName; QString tmp = absPath(); +#ifdef Q_OS_WIN32 + if ( fileName[0].isLetter() && fileName[1] == ':' ) { + int drv = fileName.upper()[0].latin1() - 'A' + 1; + if ( _getdrive() != drv ) { + if ( qt_winunicode ) { + TCHAR buf[PATH_MAX]; + ::_tgetdcwd( drv, buf, PATH_MAX ); + tmp.setUnicodeCodes( (ushort*)buf, ::_tcslen(buf) ); + } else { + char buf[PATH_MAX]; + ::_getdcwd( drv, buf, PATH_MAX ); + tmp = buf; + } + if ( !tmp.endsWith("\\") ) + tmp += "\\"; + tmp += fileName.right( fileName.length() - 2 ); + int x; + for ( x = 0; x < (int) tmp.length(); x++ ) { + if ( tmp[x] == '\\' ) + tmp[x] = '/'; + } + } + } else +#endif + { if ( tmp.isEmpty() || (tmp[(int)tmp.length()-1] != '/' && !!fileName && fileName[0] != '/') ) tmp += '/'; tmp += fileName; + } return tmp; } /*! Returns \a pathName with the '/' separators converted to separators that are appropriate for the underlying operating system. On Windows, convertSeparators("c:/winnt/system32") returns "c:\winnt\system32". The returned string may be the same as the argument on some operating systems, for example on Unix. */ QString QDir::convertSeparators( const QString &pathName ) { QString n( pathName ); #if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) for ( int i=0; i<(int)n.length(); i++ ) { if ( n[i] == '/' ) n[i] = '\\'; } #elif defined(Q_OS_MAC9) while(n.length() && n[0] == '/' ) n = n.right(n.length()-1); for ( int i=0; i<(int)n.length(); i++ ) { if ( n[i] == '/' ) n[i] = ':'; } if(n.contains(':') && n.left(1) != ':') n.prepend(':'); #endif return n; } /*! Changes the QDir's directory to \a dirName. If \a acceptAbsPath is TRUE a path starting with separator "/" will cause the function to change to the absolute directory. If \a acceptAbsPath is FALSE any number of separators at the beginning of \a dirName will be removed and the function will descend into \a dirName. Returns TRUE if the new directory exists and is readable; otherwise returns FALSE. Note that the logical cd() operation is not performed if the new directory does not exist. Calling cd( ".." ) is equivalent to calling cdUp(). \sa cdUp(), isReadable(), exists(), path() */ bool QDir::cd( const QString &dirName, bool acceptAbsPath ) { if ( dirName.isEmpty() || dirName==QString::fromLatin1(".") ) return TRUE; QString old = dPath; if ( acceptAbsPath && !isRelativePath(dirName) ) { dPath = cleanDirPath( dirName ); } else { if ( !isRoot() ) { dPath += '/'; } else if ( dirName == ".." ) { dPath = old; return FALSE; } dPath += dirName; if ( dirName.find('/') >= 0 || old == QString::fromLatin1(".") || dirName == QString::fromLatin1("..") ) dPath = cleanDirPath( dPath ); } if ( !exists() ) { dPath = old; // regret return FALSE; } dirty = TRUE; return TRUE; } /*! Changes directory by moving one directory up from the QDir's current directory. Returns TRUE if the new directory exists and is readable; otherwise returns FALSE. Note that the logical cdUp() operation is not performed if the new directory does not exist. \sa cd(), isReadable(), exists(), path() */ bool QDir::cdUp() { return cd( QString::fromLatin1("..") ); } /*! \fn QString QDir::nameFilter() const Returns the string set by setNameFilter() */ /*! Sets the name filter used by entryList() and entryInfoList() to \a nameFilter. The \a nameFilter is a wildcard (globbing) filter that understands "*" and "?" wildcards. (See \link qregexp.html#wildcard-matching QRegExp wildcard matching\endlink.) You may specify several filter entries all separated by a single space " " or by a semi-colon ";". For example, if you want entryList() and entryInfoList() to list all files ending with either ".cpp" or ".h", you would use either dir.setNameFilter("*.cpp *.h") or dir.setNameFilter("*.cpp;*.h"). \sa nameFilter(), setFilter() */ void QDir::setNameFilter( const QString &nameFilter ) { nameFilt = nameFilter; if ( nameFilt.isEmpty() ) nameFilt = QString::fromLatin1("*"); dirty = TRUE; } /*! \fn QDir::FilterSpec QDir::filter() const Returns the value set by setFilter() */ /*! \enum QDir::FilterSpec This enum describes the filtering options available to QDir, e.g. for entryList() and entryInfoList(). The filter value is specified by OR-ing together values from the following list: \value Dirs List directories only. \value Files List files only. \value Drives List disk drives (ignored under Unix). \value NoSymLinks Do not list symbolic links (ignored by operating systems that don't support symbolic links). \value All List directories, files, drives and symlinks (this does not list broken symlinks unless you specify System). \value TypeMask A mask for the the Dirs, Files, Drives and NoSymLinks flags. \value Readable List files for which the application has read access. \value Writable List files for which the application has write access. \value Executable List files for which the application has execute access. Executables needs to be combined with Dirs or Files. \value RWEMask A mask for the Readable, Writable and Executable flags. \value Modified Only list files that have been modified (ignored under Unix). \value Hidden List hidden files (on Unix, files starting with a .). \value System List system files (on Unix, FIFOs, sockets and device files) \value AccessMask A mask for the Readable, Writable, Executable Modified, Hidden and System flags \value DefaultFilter Internal flag. If you do not set any of \c Readable, \c Writable or \c Executable, QDir will set all three of them. This makes the default easy to write and at the same time useful. Examples: \c Readable|Writable means list all files for which the application has read access, write access or both. \c Dirs|Drives means list drives, directories, all files that the application can read, write or execute, and also symlinks to such files/directories. */ /*! Sets the filter used by entryList() and entryInfoList() to \a filterSpec. The filter is used to specify the kind of files that should be returned by entryList() and entryInfoList(). See \l{QDir::FilterSpec}. \sa filter(), setNameFilter() */ void QDir::setFilter( int filterSpec ) { if ( filtS == (FilterSpec) filterSpec ) return; filtS = (FilterSpec) filterSpec; dirty = TRUE; } /*! \fn QDir::SortSpec QDir::sorting() const Returns the value set by setSorting() \sa setSorting() SortSpec */ /*! \enum QDir::SortSpec This enum describes the sort options available to QDir, e.g. for entryList() and entryInfoList(). The sort value is specified by OR-ing together values from the following list: \value Name Sort by name. \value Time Sort by time (modification time). \value Size Sort by file size. \value Unsorted Do not sort. \value SortByMask A mask for Name, Time and Size. \value DirsFirst Put the directories first, then the files. \value Reversed Reverse the sort order. \value IgnoreCase Sort case-insensitively. \value DefaultSort Internal flag. You can only specify one of the first four. If you specify both \c DirsFirst and \c Reversed, directories are still put first, but in reverse order; the files will be listed after the directories, again in reverse order. */ // ### Unsorted+DirsFirst ? Unsorted+Reversed? /*! Sets the sort order used by entryList() and entryInfoList(). The \a sortSpec is specified by OR-ing values from the enum \l{QDir::SortSpec}. \sa sorting() SortSpec */ void QDir::setSorting( int sortSpec ) { if ( sortS == (SortSpec) sortSpec ) return; sortS = (SortSpec) sortSpec; dirty = TRUE; } /*! \fn bool QDir::matchAllDirs() const Returns the value set by setMatchAllDirs() \sa setMatchAllDirs() */ /*! If \a enable is TRUE then all directories are included (e.g. in entryList()), and the nameFilter() is only applied to the files. If \a enable is FALSE then the nameFilter() is applied to both directories and files. \sa matchAllDirs() */ void QDir::setMatchAllDirs( bool enable ) { if ( (bool)allDirs == enable ) return; allDirs = enable; dirty = TRUE; } /*! Returns the total number of directories and files that were found. Equivalent to entryList().count(). \sa operator[](), entryList() */ uint QDir::count() const { return (uint)entryList().count(); } /*! Returns the file name at position \a index in the list of file names. Equivalent to entryList().at(index). Returns a QString::null if the \a index is out of range or if the entryList() function failed. \sa count(), entryList() */ QString QDir::operator[]( int index ) const { entryList(); return fList && index >= 0 && index < (int)fList->count() ? (*fList)[index] : QString::null; } /*! \obsolete This function is included to easy porting from Qt 1.x to Qt 2.0, it is the same as entryList(), but encodes the filenames as 8-bit strings using QFile::encodedName(). It is more efficient to use entryList(). */ QStrList QDir::encodedEntryList( int filterSpec, int sortSpec ) const { QStrList r; QStringList l = entryList(filterSpec,sortSpec); for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { r.append( QFile::encodeName(*it) ); } return r; } /*! \obsolete \overload This function is included to easy porting from Qt 1.x to Qt 2.0, it is the same as entryList(), but encodes the filenames as 8-bit strings using QFile::encodedName(). It is more efficient to use entryList(). */ QStrList QDir::encodedEntryList( const QString &nameFilter, int filterSpec, int sortSpec ) const { QStrList r; QStringList l = entryList(nameFilter,filterSpec,sortSpec); for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) { r.append( QFile::encodeName(*it) ); } return r; } /*! \overload Returns a list of the names of all the files and directories in the directory, ordered in accordance with setSorting() and filtered in accordance with setFilter() and setNameFilter(). The filter and sorting specifications can be overridden using the \a filterSpec and \a sortSpec arguments. Returns an empty list if the directory is unreadable or does not exist. \sa entryInfoList(), setNameFilter(), setSorting(), setFilter() */ QStringList QDir::entryList( int filterSpec, int sortSpec ) const { if ( !dirty && filterSpec == (int)DefaultFilter && sortSpec == (int)DefaultSort ) return *fList; return entryList( nameFilt, filterSpec, sortSpec ); } /*! Returns a list of the names of all the files and directories in the directory, ordered in accordance with setSorting() and filtered in accordance with setFilter() and setNameFilter(). The filter and sorting specifications can be overridden using the \a nameFilter, \a filterSpec and \a sortSpec arguments. Returns an empty list if the directory is unreadable or does not exist. \sa entryInfoList(), setNameFilter(), setSorting(), setFilter() */ QStringList QDir::entryList( const QString &nameFilter, int filterSpec, int sortSpec ) const { if ( filterSpec == (int)DefaultFilter ) filterSpec = filtS; if ( sortSpec == (int)DefaultSort ) sortSpec = sortS; QDir *that = (QDir*)this; // mutable function if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) { if ( that->fList ) return *that->fList; } return QStringList(); } /*! \overload Returns a list of QFileInfo objects for all the files and directories in the directory, ordered in accordance with setSorting() and filtered in accordance with setFilter() and setNameFilter(). The filter and sorting specifications can be overridden using the \a filterSpec and \a sortSpec arguments. Returns 0 if the directory is unreadable or does not exist. The returned pointer is a const pointer to a QFileInfoList. The list is owned by the QDir object and will be reused on the next call to entryInfoList() for the same QDir instance. If you want to keep the entries of the list after a subsequent call to this function you must copy them. \sa entryList(), setNameFilter(), setSorting(), setFilter() */ const QFileInfoList *QDir::entryInfoList( int filterSpec, int sortSpec ) const { if ( !dirty && filterSpec == (int)DefaultFilter && sortSpec == (int)DefaultSort ) return fiList; return entryInfoList( nameFilt, filterSpec, sortSpec ); } /*! Returns a list of QFileInfo objects for all the files and directories in the directory, ordered in accordance with setSorting() and filtered in accordance with setFilter() and setNameFilter(). The filter and sorting specifications can be overridden using the \a nameFilter, \a filterSpec and \a sortSpec arguments. Returns 0 if the directory is unreadable or does not exist. The returned pointer is a const pointer to a QFileInfoList. The list is owned by the QDir object and will be reused on the next call to entryInfoList() for the same QDir instance. If you want to keep the entries of the list after a subsequent call to this function you must copy them. \sa entryList(), setNameFilter(), setSorting(), setFilter() */ const QFileInfoList *QDir::entryInfoList( const QString &nameFilter, int filterSpec, int sortSpec ) const { if ( filterSpec == (int)DefaultFilter ) filterSpec = filtS; if ( sortSpec == (int)DefaultSort ) sortSpec = sortS; QDir *that = (QDir*)this; // mutable function if ( that->readDirEntries(nameFilter, filterSpec, sortSpec) ) return that->fiList; else return 0; } /*! \overload Returns TRUE if the \e directory exists; otherwise returns FALSE. (If a file with the same name is found this function will return FALSE). \sa QFileInfo::exists(), QFile::exists() */ bool QDir::exists() const { QFileInfo fi( dPath ); return fi.exists() && fi.isDir(); } /*! Returns TRUE if the directory path is relative to the current directory and returns FALSE if the path is absolute (e.g. under UNIX a path is relative if it does not start with a "/"). \sa convertToAbs() */ bool QDir::isRelative() const { return isRelativePath( dPath ); } /*! Converts the directory path to an absolute path. If it is already absolute nothing is done. \sa isRelative() */ void QDir::convertToAbs() { dPath = absPath(); } /*! Makes a copy of QDir \a d and assigns it to this QDir. */ QDir &QDir::operator=( const QDir &d ) { dPath = d.dPath; delete fList; fList = 0; delete fiList; fiList = 0; nameFilt = d.nameFilt; dirty = TRUE; allDirs = d.allDirs; filtS = d.filtS; sortS = d.sortS; return *this; } /*! \overload Sets the directory path to be the given \a path. */ QDir &QDir::operator=( const QString &path ) { dPath = cleanDirPath( path ); dirty = TRUE; return *this; } /*! \fn bool QDir::operator!=( const QDir &d ) const Returns TRUE if directory \a d and this directory have different paths or different sort or filter settings; otherwise returns FALSE. Example: \code // The current directory is "/usr/local" QDir d1( "/usr/local/bin" ); QDir d2( "bin" ); - if ( d1 != d2 ) qDebug( "They differ\n" ); // This is printed + if ( d1 != d2 ) + qDebug( "They differ" ); \endcode */ /*! Returns TRUE if directory \a d and this directory have the same path and their sort and filter settings are the same; otherwise returns FALSE. Example: \code // The current directory is "/usr/local" QDir d1( "/usr/local/bin" ); QDir d2( "bin" ); d2.convertToAbs(); - if ( d1 == d2 ) qDebug( "They're the same\n" ); // This is printed + if ( d1 == d2 ) + qDebug( "They're the same" ); \endcode */ bool QDir::operator==( const QDir &d ) const { return dPath == d.dPath && nameFilt == d.nameFilt && allDirs == d.allDirs && filtS == d.filtS && sortS == d.sortS; } /*! Removes the file, \a fileName. If \a acceptAbsPath is TRUE a path starting with separator "/" will remove the file with the absolute path. If \a acceptAbsPath is FALSE any number of separators at the beginning of \a fileName will be removed and the resultant file name will be removed. Returns TRUE if the file is removed successfully; otherwise returns FALSE. */ bool QDir::remove( const QString &fileName, bool acceptAbsPath ) { if ( fileName.isEmpty() ) { #if defined(QT_CHECK_NULL) qWarning( "QDir::remove: Empty or null file name" ); #endif return FALSE; } QString p = filePath( fileName, acceptAbsPath ); return QFile::remove( p ); } /*! Checks for the existence of the file \a name. If \a acceptAbsPath is TRUE a path starting with separator "/" will check the file with the absolute path. If \a acceptAbsPath is FALSE any number of separators at the beginning of \a name will be removed and the resultant file name will be checked. Returns TRUE if the file exists; otherwise returns FALSE. \sa QFileInfo::exists(), QFile::exists() */ bool QDir::exists( const QString &name, bool acceptAbsPath ) //### const in 4.0 { if ( name.isEmpty() ) { #if defined(QT_CHECK_NULL) qWarning( "QDir::exists: Empty or null file name" ); #endif return FALSE; } QString tmp = filePath( name, acceptAbsPath ); return QFile::exists( tmp ); } /*! Returns the native directory separator; "/" under UNIX (including Mac OS X) and "\" under Windows. You do not need to use this function to build file paths. If you always use "/", Qt will translate your paths to conform to the underlying operating system. */ char QDir::separator() { #if defined(Q_OS_UNIX) return '/'; #elif defined (Q_FS_FAT) || defined(Q_WS_WIN) return '\\'; #elif defined (Q_OS_MAC) return ':'; #else return '/'; #endif } /*! Returns the application's current directory. Use path() to access a QDir object's path. \sa currentDirPath(), QDir::QDir() */ QDir QDir::current() { return QDir( currentDirPath() ); } /*! Returns the home directory. Under Windows the \c HOME environment variable is used. If this does not exist the \c USERPROFILE environment variable is used. If that does not exist the path is formed by concatenating the \c HOMEDRIVE and \c HOMEPATH environment variables. If they don't exist the rootDirPath() is used (this uses the \c SystemDrive environment variable). If none of these exist "C:\" is used. Under non-Windows operating systems the \c HOME environment variable is used if it exists, otherwise rootDirPath() is used. \sa homeDirPath() */ QDir QDir::home() { return QDir( homeDirPath() ); } /*! Returns the root directory. \sa rootDirPath() drives() */ QDir QDir::root() { return QDir( rootDirPath() ); } /*! \fn QString QDir::homeDirPath() Returns the absolute path of the user's home directory. \sa home() */ -QStringList qt_makeFilterList( const QString &filter ) +QValueList<QRegExp> qt_makeFilterList( const QString &filter ) { + QValueList<QRegExp> regExps; if ( filter.isEmpty() ) - return QStringList(); + return regExps; QChar sep( ';' ); int i = filter.find( sep, 0 ); if ( i == -1 && filter.find( ' ', 0 ) != -1 ) sep = QChar( ' ' ); QStringList list = QStringList::split( sep, filter ); QStringList::Iterator it = list.begin(); - QStringList list2; + while ( it != list.end() ) { + regExps << QRegExp( (*it).stripWhiteSpace(), CaseSensitiveFS, TRUE ); + ++it; + } + return regExps; +} - for ( ; it != list.end(); ++it ) { - QString s = *it; - list2 << s.stripWhiteSpace(); +bool qt_matchFilterList( const QValueList<QRegExp>& filters, + const QString &fileName ) +{ + QValueList<QRegExp>::ConstIterator rit = filters.begin(); + while ( rit != filters.end() ) { + if ( (*rit).exactMatch(fileName) ) + return TRUE; + ++rit; } - return list2; + return FALSE; } + /*! \overload Returns TRUE if the \a fileName matches any of the wildcard (glob) patterns in the list of \a filters; otherwise returns FALSE. (See \link qregexp.html#wildcard-matching QRegExp wildcard matching.\endlink) \sa QRegExp::match() */ bool QDir::match( const QStringList &filters, const QString &fileName ) { QStringList::ConstIterator sit = filters.begin(); while ( sit != filters.end() ) { -#if defined(Q_FS_FAT) && !defined(Q_OS_UNIX) - QRegExp rx( *sit, FALSE, TRUE ); // The FAT FS is not case sensitive.. -#else - QRegExp rx( *sit, TRUE, TRUE ); // ..while others are. -#endif + QRegExp rx( *sit, CaseSensitiveFS, TRUE ); if ( rx.exactMatch(fileName) ) return TRUE; ++sit; } return FALSE; } /*! Returns TRUE if the \a fileName matches the wildcard (glob) pattern \a filter; otherwise returns FALSE. The \a filter may contain multiple patterns separated by spaces or semicolons. (See \link qregexp.html#wildcard-matching QRegExp wildcard matching.\endlink) \sa QRegExp::match() */ bool QDir::match( const QString &filter, const QString &fileName ) { - QStringList lst = qt_makeFilterList( filter ); - return match( lst, fileName ); + return qt_matchFilterList( qt_makeFilterList(filter), fileName ); } /*! Removes all multiple directory separators "/" and resolves any "."s or ".."s found in the path, \a filePath. Symbolic links are kept. This function does not return the canonical path, but rather the simplest version of the input. For example, "./local" becomes "local", "local/../bin" becomes "bin" and "/local/usr/../bin" becomes "/local/bin". \sa absPath() canonicalPath() */ QString QDir::cleanDirPath( const QString &filePath ) { QString name = filePath; QString newPath; if ( name.isEmpty() ) return name; slashify( name ); bool addedSeparator; if ( isRelativePath(name) ) { addedSeparator = TRUE; name.insert( 0, '/' ); } else { addedSeparator = FALSE; } int ePos, pos, upLevel; pos = ePos = name.length(); upLevel = 0; int len; while ( pos && (pos = name.findRev('/',--pos)) != -1 ) { len = ePos - pos - 1; if ( len == 2 && name.at(pos + 1) == '.' && name.at(pos + 2) == '.' ) { upLevel++; } else { if ( len != 0 && (len != 1 || name.at(pos + 1) != '.') ) { if ( !upLevel ) newPath = QString::fromLatin1("/") + name.mid(pos + 1, len) + newPath; else upLevel--; } } ePos = pos; } if ( addedSeparator ) { while ( upLevel-- ) newPath.insert( 0, QString::fromLatin1("/..") ); if ( !newPath.isEmpty() ) newPath.remove( 0, 1 ); else newPath = QString::fromLatin1("."); } else { if ( newPath.isEmpty() ) newPath = QString::fromLatin1("/"); #if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) if ( name[0] == '/' ) { if ( name[1] == '/' ) // "\\machine\x\ ..." newPath.insert( 0, '/' ); } else { newPath = name.left(2) + newPath; } #endif } return newPath; } int qt_cmp_si_sortSpec; #if defined(Q_C_CALLBACKS) extern "C" { #endif #ifdef Q_OS_TEMP int __cdecl qt_cmp_si( const void *n1, const void *n2 ) #else int qt_cmp_si( const void *n1, const void *n2 ) #endif { if ( !n1 || !n2 ) return 0; QDirSortItem* f1 = (QDirSortItem*)n1; QDirSortItem* f2 = (QDirSortItem*)n2; if ( qt_cmp_si_sortSpec & QDir::DirsFirst ) if ( f1->item->isDir() != f2->item->isDir() ) return f1->item->isDir() ? -1 : 1; int r = 0; int sortBy = qt_cmp_si_sortSpec & QDir::SortByMask; switch ( sortBy ) { case QDir::Time: r = f1->item->lastModified().secsTo(f2->item->lastModified()); break; case QDir::Size: r = f2->item->size() - f1->item->size(); break; default: ; } if ( r == 0 && sortBy != QDir::Unsorted ) { // Still not sorted - sort by name bool ic = qt_cmp_si_sortSpec & QDir::IgnoreCase; if ( f1->filename_cache.isNull() ) f1->filename_cache = ic ? f1->item->fileName().lower() : f1->item->fileName(); if ( f2->filename_cache.isNull() ) f2->filename_cache = ic ? f2->item->fileName().lower() : f2->item->fileName(); r = f1->filename_cache.compare(f2->filename_cache); } if ( r == 0 ) { // Enforce an order - the order the items appear in the array r = (char*)n1 - (char*)n2; } if ( qt_cmp_si_sortSpec & QDir::Reversed ) return -r; else return r; } #if defined(Q_C_CALLBACKS) } #endif #endif // QT_NO_DIR diff --git a/qmake/tools/qdir_unix.cpp b/qmake/tools/qdir_unix.cpp index 57fe3c5..6a7adda 100644 --- a/qmake/tools/qdir_unix.cpp +++ b/qmake/tools/qdir_unix.cpp @@ -1,291 +1,297 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QDir class ** ** Created : 950628 ** -** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance ** with the Qt Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include "qdir.h" #ifndef QT_NO_DIR #include "qdir_p.h" #include "qfileinfo.h" #include "qregexp.h" #include "qstringlist.h" #ifdef QT_THREAD_SUPPORT # include <private/qmutexpool_p.h> #endif // QT_THREAD_SUPPORT #include <stdlib.h> #include <limits.h> +#include <errno.h> void QDir::slashify( QString& ) { } QString QDir::homeDirPath() { QString d; d = QFile::decodeName(getenv("HOME")); slashify( d ); if ( d.isNull() ) d = rootDirPath(); return d; } QString QDir::canonicalPath() const { QString r; - char cur[PATH_MAX+1]; - if ( ::getcwd( cur, PATH_MAX ) ) - if ( ::chdir(QFile::encodeName(dPath)) >= 0 ) { + if ( ::getcwd( cur, PATH_MAX ) ) { char tmp[PATH_MAX+1]; - if ( ::getcwd( tmp, PATH_MAX ) ) + if( ::realpath( QFile::encodeName( dPath ), tmp ) ) r = QFile::decodeName(tmp); + slashify( r ); + + // always make sure we go back to the current dir ::chdir( cur ); } - - slashify( r ); return r; } bool QDir::mkdir( const QString &dirName, bool acceptAbsPath ) const { #if defined(Q_OS_MACX) // Mac X doesn't support trailing /'s QString name = dirName; if (dirName[dirName.length() - 1] == "/") name = dirName.left( dirName.length() - 1 ); - return ::mkdir( QFile::encodeName(filePath(name,acceptAbsPath)), 0777 ) - == 0; + int status = + ::mkdir( QFile::encodeName(filePath(name,acceptAbsPath)), 0777 ); #else - return ::mkdir( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ) - == 0; + int status = + ::mkdir( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ); #endif + return status == 0; } bool QDir::rmdir( const QString &dirName, bool acceptAbsPath ) const { return ::rmdir( QFile::encodeName(filePath(dirName,acceptAbsPath)) ) == 0; } bool QDir::isReadable() const { return ::access( QFile::encodeName(dPath), R_OK | X_OK ) == 0; } bool QDir::isRoot() const { return dPath == QString::fromLatin1("/"); } bool QDir::rename( const QString &name, const QString &newName, bool acceptAbsPaths ) { if ( name.isEmpty() || newName.isEmpty() ) { #if defined(QT_CHECK_NULL) qWarning( "QDir::rename: Empty or null file name(s)" ); #endif return FALSE; } QString fn1 = filePath( name, acceptAbsPaths ); QString fn2 = filePath( newName, acceptAbsPaths ); return ::rename( QFile::encodeName(fn1), QFile::encodeName(fn2) ) == 0; } bool QDir::setCurrent( const QString &path ) { int r; r = ::chdir( QFile::encodeName(path) ); return r >= 0; } QString QDir::currentDirPath() { QString result; struct stat st; if ( ::stat( ".", &st ) == 0 ) { char currentName[PATH_MAX+1]; if ( ::getcwd( currentName, PATH_MAX ) ) result = QFile::decodeName(currentName); #if defined(QT_DEBUG) if ( result.isNull() ) qWarning( "QDir::currentDirPath: getcwd() failed" ); #endif } else { #if defined(QT_DEBUG) qWarning( "QDir::currentDirPath: stat(\".\") failed" ); #endif } slashify( result ); return result; } QString QDir::rootDirPath() { QString d = QString::fromLatin1( "/" ); return d; } bool QDir::isRelativePath( const QString &path ) { int len = path.length(); if ( len == 0 ) return TRUE; return path[0] != '/'; } bool QDir::readDirEntries( const QString &nameFilter, int filterSpec, int sortSpec ) { int i; if ( !fList ) { fList = new QStringList; Q_CHECK_PTR( fList ); fiList = new QFileInfoList; Q_CHECK_PTR( fiList ); fiList->setAutoDelete( TRUE ); } else { fList->clear(); fiList->clear(); } - QStringList filters = qt_makeFilterList( nameFilter ); + QValueList<QRegExp> filters = qt_makeFilterList( nameFilter ); bool doDirs = (filterSpec & Dirs) != 0; bool doFiles = (filterSpec & Files) != 0; bool noSymLinks = (filterSpec & NoSymLinks) != 0; bool doReadable = (filterSpec & Readable) != 0; bool doWritable = (filterSpec & Writable) != 0; bool doExecable = (filterSpec & Executable) != 0; bool doHidden = (filterSpec & Hidden) != 0; bool doSystem = (filterSpec & System) != 0; -#if defined(Q_OS_OS2EMX) - //QRegExp wc( nameFilter, FALSE, TRUE ); // wild card, case insensitive -#else - //QRegExp wc( nameFilter, TRUE, TRUE ); // wild card, case sensitive -#endif QFileInfo fi; DIR *dir; dirent *file; dir = opendir( QFile::encodeName(dPath) ); if ( !dir ) return FALSE; // cannot read the directory - while ( (file = readdir(dir)) ) { +#if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) + union { + struct dirent mt_file; + char b[sizeof(struct dirent) + MAXNAMLEN + 1]; + } u; + while ( readdir_r(dir, &u.mt_file, &file ) == 0 && file ) +#else + while ( (file = readdir(dir)) ) +#endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS + { QString fn = QFile::decodeName(file->d_name); fi.setFile( *this, fn ); - if ( !match( filters, fn ) && !(allDirs && fi.isDir()) ) + if ( !qt_matchFilterList(filters, fn) && !(allDirs && fi.isDir()) ) continue; if ( (doDirs && fi.isDir()) || (doFiles && fi.isFile()) || (doSystem && (!fi.isFile() && !fi.isDir())) ) { if ( noSymLinks && fi.isSymLink() ) continue; if ( (filterSpec & RWEMask) != 0 ) if ( (doReadable && !fi.isReadable()) || (doWritable && !fi.isWritable()) || (doExecable && !fi.isExecutable()) ) continue; if ( !doHidden && fn[0] == '.' && fn != QString::fromLatin1(".") && fn != QString::fromLatin1("..") ) continue; fiList->append( new QFileInfo( fi ) ); } } if ( closedir(dir) != 0 ) { #if defined(QT_CHECK_NULL) qWarning( "QDir::readDirEntries: Cannot close the directory: %s", dPath.local8Bit().data() ); #endif } // Sort... if(fiList->count()) { QDirSortItem* si= new QDirSortItem[fiList->count()]; QFileInfo* itm; i=0; for (itm = fiList->first(); itm; itm = fiList->next()) si[i++].item = itm; qt_cmp_si_sortSpec = sortSpec; qsort( si, i, sizeof(si[0]), qt_cmp_si ); // put them back in the list fiList->setAutoDelete( FALSE ); fiList->clear(); int j; for ( j=0; j<i; j++ ) { fiList->append( si[j].item ); fList->append( si[j].item->fileName() ); } delete [] si; fiList->setAutoDelete( TRUE ); } if ( filterSpec == (FilterSpec)filtS && sortSpec == (SortSpec)sortS && nameFilter == nameFilt ) dirty = FALSE; else dirty = TRUE; return TRUE; } const QFileInfoList * QDir::drives() { // at most one instance of QFileInfoList is leaked, and this variable // points to that list static QFileInfoList * knownMemoryLeak = 0; if ( !knownMemoryLeak ) { #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &knownMemoryLeak ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &knownMemoryLeak ) : 0 ); #endif // QT_THREAD_SUPPORT if ( !knownMemoryLeak ) { knownMemoryLeak = new QFileInfoList; // non-win32 versions both use just one root directory knownMemoryLeak->append( new QFileInfo( rootDirPath() ) ); } } return knownMemoryLeak; } #endif //QT_NO_DIR diff --git a/qmake/tools/qfile.cpp b/qmake/tools/qfile.cpp index a578b49..c088b55 100644 --- a/qmake/tools/qfile.cpp +++ b/qmake/tools/qfile.cpp @@ -1,614 +1,615 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QFile class ** ** Created : 930812 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" // POSIX Large File Support redefines open -> open64 #if defined(open) # undef open #endif // POSIX Large File Support redefines truncate -> truncate64 #if defined(truncate) # undef truncate #endif #include "qfile.h" extern bool qt_file_access( const QString& fn, int t ); /*! \class QFile qfile.h \reentrant \brief The QFile class is an I/O device that operates on files. \ingroup io \mainclass QFile is an I/O device for reading and writing binary and text files. A QFile may be used by itself or more conveniently with a QDataStream or QTextStream. The file name is usually passed in the constructor but can be changed with setName(). You can check for a file's existence with exists() and remove a file with remove(). The file is opened with open(), closed with close() and flushed with flush(). Data is usually read and written using QDataStream or QTextStream, but you can read with readBlock() and readLine() and write with writeBlock(). QFile also supports getch(), ungetch() and putch(). The size of the file is returned by size(). You can get the current file position or move to a new file position using the at() functions. If you've reached the end of the file, atEnd() returns TRUE. The file handle is returned by handle(). Here is a code fragment that uses QTextStream to read a text file line by line. It prints each line with a line number. \code QStringList lines; QFile file( "file.txt" ); if ( file.open( IO_ReadOnly ) ) { QTextStream stream( &file ); QString line; int i = 1; - while ( !stream.eof() ) { + while ( !stream.atEnd() ) { line = stream.readLine(); // line of text excluding '\n' printf( "%3d: %s\n", i++, line.latin1() ); lines += line; } file.close(); } \endcode Writing text is just as easy. The following example shows how to write the data we read into the string list from the previous example: \code QFile file( "file.txt" ); if ( file.open( IO_WriteOnly ) ) { QTextStream stream( &file ); for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) stream << *it << "\n"; file.close(); } \endcode The QFileInfo class holds detailed information about a file, such as access permissions, file dates and file types. The QDir class manages directories and lists of file names. Qt uses Unicode file names. If you want to do your own I/O on Unix systems you may want to use encodeName() (and decodeName()) to convert the file name into the local encoding. \important readAll() \sa QDataStream, QTextStream */ /*! \fn Q_LONG QFile::writeBlock( const QByteArray& data ) \overload */ /*! Constructs a QFile with no name. */ QFile::QFile() { init(); } /*! Constructs a QFile with a file name \a name. \sa setName() */ QFile::QFile( const QString &name ) : fn(name) { init(); } /*! Destroys a QFile. Calls close(). */ QFile::~QFile() { close(); } /*! \internal Initialize internal data. */ void QFile::init() { setFlags( IO_Direct ); setStatus( IO_Ok ); fh = 0; fd = 0; length = 0; ioIndex = 0; ext_f = FALSE; // not an external file handle } /*! \fn QString QFile::name() const Returns the name set by setName(). \sa setName(), QFileInfo::fileName() */ /*! Sets the name of the file to \a name. The name can have no path, a relative path or an absolute absolute path. Do not call this function if the file has already been opened. If the file name has no path or a relative path, the path used will be whatever the application's current directory path is \e{at the time of the open()} call. Example: \code QFile file; QDir::setCurrent( "/tmp" ); file.setName( "readme.txt" ); QDir::setCurrent( "/home" ); file.open( IO_ReadOnly ); // opens "/home/readme.txt" under Unix \endcode Note that the directory separator "/" works for all operating systems supported by Qt. \sa name(), QFileInfo, QDir */ void QFile::setName( const QString &name ) { if ( isOpen() ) { #if defined(QT_CHECK_STATE) qWarning( "QFile::setName: File is open" ); #endif close(); } fn = name; } /*! \overload Returns TRUE if this file exists; otherwise returns FALSE. \sa name() */ bool QFile::exists() const { return qt_file_access( fn, F_OK ); } /*! Returns TRUE if the file given by \a fileName exists; otherwise returns FALSE. */ bool QFile::exists( const QString &fileName ) { return qt_file_access( fileName, F_OK ); } /*! Removes the file specified by the file name currently set. Returns TRUE if successful; otherwise returns FALSE. The file is closed before it is removed. */ bool QFile::remove() { close(); return remove( fn ); } #if defined(Q_OS_MAC) || defined(Q_OS_MSDOS) || defined(Q_OS_WIN32) || defined(Q_OS_OS2) # define HAS_TEXT_FILEMODE // has translate/text filemode #endif #if defined(O_NONBLOCK) # define HAS_ASYNC_FILEMODE # define OPEN_ASYNC O_NONBLOCK #elif defined(O_NDELAY) # define HAS_ASYNC_FILEMODE # define OPEN_ASYNC O_NDELAY #endif /*! Flushes the file buffer to the disk. close() also flushes the file buffer. */ void QFile::flush() { if ( isOpen() && fh ) // can only flush open/buffered fflush( fh ); // file } /*! \reimp \fn QIODevice::Offset QFile::at() const */ /*! Returns TRUE if the end of file has been reached; otherwise returns FALSE. + If QFile has not been open()'d, then the behavior is undefined. \sa size() */ bool QFile::atEnd() const { if ( !isOpen() ) { #if defined(QT_CHECK_STATE) qWarning( "QFile::atEnd: File is not open" ); #endif return FALSE; } if ( isDirectAccess() && !isTranslated() ) { if ( at() < length ) return FALSE; } return QIODevice::atEnd(); } /*! Reads a line of text. Reads bytes from the file into the char* \a p, until end-of-line or \a maxlen bytes have been read, whichever occurs first. Returns the number of bytes read, or -1 if there was an error. Any terminating newline is not stripped. This function is only efficient for buffered files. Avoid readLine() for files that have been opened with the \c IO_Raw flag. \sa readBlock(), QTextStream::readLine() */ Q_LONG QFile::readLine( char *p, Q_ULONG maxlen ) { if ( maxlen == 0 ) // application bug? return 0; #if defined(QT_CHECK_STATE) Q_CHECK_PTR( p ); if ( !isOpen() ) { // file not open qWarning( "QFile::readLine: File not open" ); return -1; } if ( !isReadable() ) { // reading not permitted qWarning( "QFile::readLine: Read operation not permitted" ); return -1; } #endif Q_LONG nread; // number of bytes read if ( isRaw() ) { // raw file nread = QIODevice::readLine( p, maxlen ); } else { // buffered file p = fgets( p, maxlen, fh ); if ( p ) { nread = qstrlen( p ); if ( !isSequentialAccess() ) ioIndex += nread; } else { nread = -1; setStatus(IO_ReadError); } } return nread; } /*! \overload Reads a line of text. Reads bytes from the file into string \a s, until end-of-line or \a maxlen bytes have been read, whichever occurs first. Returns the number of bytes read, or -1 if there was an error, e.g. end of file. Any terminating newline is not stripped. This function is only efficient for buffered files. Avoid using readLine() for files that have been opened with the \c IO_Raw flag. Note that the string is read as plain Latin1 bytes, not Unicode. \sa readBlock(), QTextStream::readLine() */ Q_LONG QFile::readLine( QString& s, Q_ULONG maxlen ) { QByteArray ba(maxlen); Q_LONG l = readLine(ba.data(),maxlen); if ( l >= 0 ) { ba.truncate(l); s = QString(ba); } return l; } /*! Reads a single byte/character from the file. Returns the byte/character read, or -1 if the end of the file has been reached. \sa putch(), ungetch() */ int QFile::getch() { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // file not open qWarning( "QFile::getch: File not open" ); return EOF; } if ( !isReadable() ) { // reading not permitted qWarning( "QFile::getch: Read operation not permitted" ); return EOF; } #endif int ch; if ( !ungetchBuffer.isEmpty() ) { int len = ungetchBuffer.length(); ch = ungetchBuffer[ len-1 ]; ungetchBuffer.truncate( len - 1 ); return ch; } if ( isRaw() ) { // raw file (inefficient) char buf[1]; ch = readBlock( buf, 1 ) == 1 ? buf[0] : EOF; } else { // buffered file if ( (ch = getc( fh )) != EOF ) if ( !isSequentialAccess() ) ioIndex++; else setStatus(IO_ReadError); } return ch; } /*! Writes the character \a ch to the file. Returns \a ch, or -1 if some error occurred. \sa getch(), ungetch() */ int QFile::putch( int ch ) { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // file not open qWarning( "QFile::putch: File not open" ); return EOF; } if ( !isWritable() ) { // writing not permitted qWarning( "QFile::putch: Write operation not permitted" ); return EOF; } #endif if ( isRaw() ) { // raw file (inefficient) char buf[1]; buf[0] = ch; ch = writeBlock( buf, 1 ) == 1 ? ch : EOF; } else { // buffered file if ( (ch = putc( ch, fh )) != EOF ) { if ( !isSequentialAccess() ) ioIndex++; if ( ioIndex > length ) // update file length length = ioIndex; } else { setStatus(IO_WriteError); } } return ch; } /*! Puts the character \a ch back into the file and decrements the index if it is not zero. This function is normally called to "undo" a getch() operation. Returns \a ch, or -1 if an error occurred. \sa getch(), putch() */ int QFile::ungetch( int ch ) { #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // file not open qWarning( "QFile::ungetch: File not open" ); return EOF; } if ( !isReadable() ) { // reading not permitted qWarning( "QFile::ungetch: Read operation not permitted" ); return EOF; } #endif if ( ch == EOF ) // cannot unget EOF return ch; if ( isSequentialAccess() && !fh) { // pipe or similar => we cannot ungetch, so do it manually ungetchBuffer +=ch; return ch; } if ( isRaw() ) { // raw file (very inefficient) char buf[1]; at( ioIndex-1 ); buf[0] = ch; if ( writeBlock(buf, 1) == 1 ) at ( ioIndex-1 ); else ch = EOF; } else { // buffered file if ( (ch = ungetc(ch, fh)) != EOF ) if ( !isSequentialAccess() ) ioIndex--; else setStatus( IO_ReadError ); } return ch; } static QCString locale_encoder( const QString &fileName ) { return fileName.local8Bit(); } static QFile::EncoderFn encoder = locale_encoder; /*! When you use QFile, QFileInfo, and QDir to access the file system with Qt, you can use Unicode file names. On Unix, these file names are converted to an 8-bit encoding. If you want to do your own file I/O on Unix, you should convert the file name using this function. On Windows NT/2000, Unicode file names are supported directly in the file system and this function should be avoided. On Windows 95, non-Latin1 locales are not supported. By default, this function converts \a fileName to the local 8-bit encoding determined by the user's locale. This is sufficient for file names that the user chooses. File names hard-coded into the application should only use 7-bit ASCII filename characters. The conversion scheme can be changed using setEncodingFunction(). This might be useful if you wish to give the user an option to store file names in UTF-8, etc., but be aware that such file names would probably then be unrecognizable when seen by other programs. \sa decodeName() */ QCString QFile::encodeName( const QString &fileName ) { return (*encoder)(fileName); } /*! \enum QFile::EncoderFn This is used by QFile::setEncodingFunction(). */ /*! \nonreentrant Sets the function for encoding Unicode file names to \a f. The default encodes in the locale-specific 8-bit encoding. \sa encodeName() */ void QFile::setEncodingFunction( EncoderFn f ) { encoder = f; } static QString locale_decoder( const QCString &localFileName ) { return QString::fromLocal8Bit(localFileName); } static QFile::DecoderFn decoder = locale_decoder; /*! This does the reverse of QFile::encodeName() using \a localFileName. \sa setDecodingFunction() */ QString QFile::decodeName( const QCString &localFileName ) { return (*decoder)(localFileName); } /*! \enum QFile::DecoderFn This is used by QFile::setDecodingFunction(). */ /*! \nonreentrant Sets the function for decoding 8-bit file names to \a f. The default uses the locale-specific 8-bit encoding. \sa encodeName(), decodeName() */ void QFile::setDecodingFunction( DecoderFn f ) { decoder = f; } diff --git a/qmake/tools/qfile_unix.cpp b/qmake/tools/qfile_unix.cpp index 2d5a856..460bf06 100644 --- a/qmake/tools/qfile_unix.cpp +++ b/qmake/tools/qfile_unix.cpp @@ -54,634 +54,639 @@ static inline int qt_open(const char *pathname, int flags, mode_t mode) #include <limits.h> bool qt_file_access( const QString& fn, int t ) { if ( fn.isEmpty() ) return FALSE; return ::access( QFile::encodeName(fn), t ) == 0; } /*! \overload Removes the file \a fileName. Returns TRUE if successful, otherwise FALSE. */ bool QFile::remove( const QString &fileName ) { if ( fileName.isEmpty() ) { #if defined(QT_CHECK_NULL) qWarning( "QFile::remove: Empty or null file name" ); #endif return FALSE; } return unlink( QFile::encodeName(fileName) ) == 0; } #if defined(O_NONBLOCK) # define HAS_ASYNC_FILEMODE # define OPEN_ASYNC O_NONBLOCK #elif defined(O_NDELAY) # define HAS_ASYNC_FILEMODE # define OPEN_ASYNC O_NDELAY #endif /*! Opens the file specified by the file name currently set, using the mode \a m. Returns TRUE if successful, otherwise FALSE. \keyword IO_Raw \keyword IO_ReadOnly \keyword IO_WriteOnly \keyword IO_ReadWrite \keyword IO_Append \keyword IO_Truncate \keyword IO_Translate The mode parameter \a m must be a combination of the following flags: \table \header \i Flag \i Meaning \row \i IO_Raw \i Raw (non-buffered) file access. \row \i IO_ReadOnly \i Opens the file in read-only mode. \row \i IO_WriteOnly \i Opens the file in write-only mode. If this flag is used with another flag, e.g. \c IO_ReadOnly or \c IO_Raw or \c IO_Append, the file is \e not truncated; but if used on its own (or with \c IO_Truncate), the file is truncated. \row \i IO_ReadWrite \i Opens the file in read/write mode, equivalent to \c (IO_ReadOnly | IO_WriteOnly). \row \i IO_Append \i Opens the file in append mode. (You must actually use \c (IO_WriteOnly | IO_Append) to make the file writable and to go into append mode.) This mode is very useful when you want to write something to a log file. The file index is set to the end of the file. Note that the result is undefined if you position the file index manually using at() in append mode. \row \i IO_Truncate \i Truncates the file. \row \i IO_Translate \i Enables carriage returns and linefeed translation for text files under Windows. \endtable The raw access mode is best when I/O is block-operated using a 4KB block size or greater. Buffered access works better when reading small portions of data at a time. \warning When working with buffered files, data may not be written to the file at once. Call flush() to make sure that the data is really written. \warning If you have a buffered file opened for both reading and writing you must not perform an input operation immediately after an output operation or vice versa. You should always call flush() or a file positioning operation, e.g. at(), between input and output operations, otherwise the buffer may contain garbage. If the file does not exist and \c IO_WriteOnly or \c IO_ReadWrite is specified, it is created. Example: \code QFile f1( "/tmp/data.bin" ); f1.open( IO_Raw | IO_ReadWrite ); QFile f2( "readme.txt" ); f2.open( IO_ReadOnly | IO_Translate ); QFile f3( "audit.log" ); f3.open( IO_WriteOnly | IO_Append ); \endcode \sa name(), close(), isOpen(), flush() */ bool QFile::open( int m ) { if ( isOpen() ) { // file already open #if defined(QT_CHECK_STATE) qWarning( "QFile::open: File already open" ); #endif return FALSE; } if ( fn.isNull() ) { // no file name defined #if defined(QT_CHECK_NULL) qWarning( "QFile::open: No file name specified" ); #endif return FALSE; } init(); // reset params setMode( m ); if ( !(isReadable() || isWritable()) ) { #if defined(QT_CHECK_RANGE) qWarning( "QFile::open: File access not specified" ); #endif return FALSE; } bool ok = TRUE; struct stat st; if ( isRaw() ) { int oflags = O_RDONLY; if ( isReadable() && isWritable() ) oflags = O_RDWR; else if ( isWritable() ) oflags = O_WRONLY; if ( flags() & IO_Append ) { // append to end of file? if ( flags() & IO_Truncate ) oflags |= (O_CREAT | O_TRUNC); else oflags |= (O_APPEND | O_CREAT); setFlags( flags() | IO_WriteOnly ); // append implies write } else if ( isWritable() ) { // create/trunc if writable if ( flags() & IO_Truncate ) oflags |= (O_CREAT | O_TRUNC); else oflags |= O_CREAT; } #if defined(HAS_TEXT_FILEMODE) if ( isTranslated() ) oflags |= OPEN_TEXT; else oflags |= OPEN_BINARY; #endif #if defined(HAS_ASYNC_FILEMODE) if ( isAsynchronous() ) oflags |= OPEN_ASYNC; #endif fd = qt_open( QFile::encodeName(fn), oflags, 0666 ); if ( fd != -1 ) { // open successful ::fstat( fd, &st ); // get the stat for later usage } else { ok = FALSE; } } else { // buffered file I/O QCString perm; char perm2[4]; bool try_create = FALSE; if ( flags() & IO_Append ) { // append to end of file? setFlags( flags() | IO_WriteOnly ); // append implies write perm = isReadable() ? "a+" : "a"; } else { if ( isReadWrite() ) { if ( flags() & IO_Truncate ) { perm = "w+"; } else { perm = "r+"; try_create = TRUE; // try to create if not exists } } else if ( isReadable() ) { perm = "r"; } else if ( isWritable() ) { perm = "w"; } } qstrcpy( perm2, perm ); #if defined(HAS_TEXT_FILEMODE) if ( isTranslated() ) strcat( perm2, "t" ); else strcat( perm2, "b" ); #endif for (;;) { // At most twice fh = fopen( QFile::encodeName(fn), perm2 ); if ( !fh && try_create ) { perm2[0] = 'w'; // try "w+" instead of "r+" try_create = FALSE; } else { break; } } if ( fh ) { ::fstat( fileno(fh), &st ); // get the stat for later usage } else { ok = FALSE; } } if ( ok ) { setState( IO_Open ); // on successful open the file stat was got; now test what type // of file we have if ( (st.st_mode & S_IFMT) != S_IFREG ) { // non-seekable setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } else { length = (Offset)st.st_size; ioIndex = (flags() & IO_Append) == 0 ? 0 : length; if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { // try if you can read from it (if you can, it's a sequential // device; e.g. a file in the /proc filesystem) int c = getch(); if ( c != -1 ) { ungetch(c); setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } } } } else { init(); if ( errno == EMFILE ) // no more file handles/descrs setStatus( IO_ResourceError ); else setStatus( IO_OpenError ); } return ok; } /*! \overload Opens a file in the mode \a m using an existing file handle \a f. Returns TRUE if successful, otherwise FALSE. Example: \code #include <stdio.h> void printError( const char* msg ) { QFile f; f.open( IO_WriteOnly, stderr ); f.writeBlock( msg, qstrlen(msg) ); // write to stderr f.close(); } \endcode When a QFile is opened using this function, close() does not actually close the file, only flushes it. \warning If \a f is \c stdin, \c stdout, \c stderr, you may not be able to seek. See QIODevice::isSequentialAccess() for more information. \sa close() */ bool QFile::open( int m, FILE *f ) { if ( isOpen() ) { #if defined(QT_CHECK_RANGE) qWarning( "QFile::open: File already open" ); #endif return FALSE; } init(); setMode( m &~IO_Raw ); setState( IO_Open ); fh = f; ext_f = TRUE; struct stat st; ::fstat( fileno(fh), &st ); #if defined(QT_LARGEFILE_SUPPORT) ioIndex = (Offset)ftello( fh ); #else ioIndex = (Offset)ftell( fh ); #endif if ( (st.st_mode & S_IFMT) != S_IFREG || f == stdin ) { //stdin is non seekable // non-seekable setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } else { length = (Offset)st.st_size; if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { // try if you can read from it (if you can, it's a sequential // device; e.g. a file in the /proc filesystem) int c = getch(); if ( c != -1 ) { ungetch(c); setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } } } return TRUE; } /*! \overload Opens a file in the mode \a m using an existing file descriptor \a f. Returns TRUE if successful, otherwise FALSE. When a QFile is opened using this function, close() does not actually close the file. The QFile that is opened using this function, is automatically set to be in raw mode; this means that the file input/output functions are slow. If you run into performance issues, you should try to use one of the other open functions. \warning If \a f is one of 0 (stdin), 1 (stdout) or 2 (stderr), you may not be able to seek. size() is set to \c INT_MAX (in limits.h). \sa close() */ bool QFile::open( int m, int f ) { if ( isOpen() ) { #if defined(QT_CHECK_RANGE) qWarning( "QFile::open: File already open" ); #endif return FALSE; } init(); setMode( m |IO_Raw ); setState( IO_Open ); fd = f; ext_f = TRUE; struct stat st; ::fstat( fd, &st ); ioIndex = (Offset)::lseek(fd, 0, SEEK_CUR); if ( (st.st_mode & S_IFMT) != S_IFREG || f == 0 ) { // stdin is not seekable... // non-seekable setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } else { length = (Offset)st.st_size; if ( length == 0 && isReadable() ) { // try if you can read from it (if you can, it's a sequential // device; e.g. a file in the /proc filesystem) int c = getch(); if ( c != -1 ) { ungetch(c); setType( IO_Sequential ); length = INT_MAX; ioIndex = 0; } resetStatus(); } } return TRUE; } /*! Returns the file size. \sa at() */ QIODevice::Offset QFile::size() const { struct stat st; + int ret = 0; if ( isOpen() ) { - ::fstat( fh ? fileno(fh) : fd, &st ); + ret = ::fstat( fh ? fileno(fh) : fd, &st ); } else { - ::stat( QFile::encodeName(fn), &st ); + ret = ::stat( QFile::encodeName(fn), &st ); } + if ( ret == -1 ) + return 0; #if defined(QT_LARGEFILE_SUPPORT) && !defined(QT_ABI_64BITOFFSET) return (uint)st.st_size > UINT_MAX ? UINT_MAX : (QIODevice::Offset)st.st_size; #else return st.st_size; #endif } /*! \overload Sets the file index to \a pos. Returns TRUE if successful; otherwise returns FALSE. Example: \code QFile f( "data.bin" ); f.open( IO_ReadOnly ); // index set to 0 f.at( 100 ); // set index to 100 f.at( f.at()+50 ); // set index to 150 f.at( f.size()-80 ); // set index to 80 before EOF f.close(); \endcode Use \c at() without arguments to retrieve the file offset. \warning The result is undefined if the file was open()'ed using the \c IO_Append specifier. \sa size(), open() */ bool QFile::at( Offset pos ) { if ( !isOpen() ) { #if defined(QT_CHECK_STATE) qWarning( "QFile::at: File is not open" ); #endif return FALSE; } if ( isSequentialAccess() ) return FALSE; bool ok; if ( isRaw() ) { off_t l = ::lseek( fd, pos, SEEK_SET ); ok = ( l != -1 ); pos = (Offset)l; } else { // buffered file #if defined(QT_LARGEFILE_SUPPORT) ok = ( ::fseeko(fh, pos, SEEK_SET) == 0 ); #else ok = ( ::fseek(fh, pos, SEEK_SET) == 0 ); #endif } if ( ok ) ioIndex = pos; #if defined(QT_CHECK_RANGE) else #if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) qWarning( "QFile::at: Cannot set file position %llu", pos ); #else qWarning( "QFile::at: Cannot set file position %lu", pos ); #endif #endif return ok; } /*! \reimp \warning We have experienced problems with some C libraries when a buffered file is opened for both reading and writing. If a read operation takes place immediately after a write operation, the read buffer contains garbage data. Worse, the same garbage is written to the file. Calling flush() before readBlock() solved this problem. */ Q_LONG QFile::readBlock( char *p, Q_ULONG len ) { #if defined(QT_CHECK_NULL) if ( !p ) qWarning( "QFile::readBlock: Null pointer error" ); #endif #if defined(QT_CHECK_STATE) if ( !isOpen() ) { qWarning( "QFile::readBlock: File not open" ); return -1; } if ( !isReadable() ) { qWarning( "QFile::readBlock: Read operation not permitted" ); return -1; } #endif Q_ULONG nread = 0; // number of bytes read if ( !ungetchBuffer.isEmpty() ) { // need to add these to the returned string. uint l = ungetchBuffer.length(); while( nread < l ) { - *p = ungetchBuffer[ l - nread - 1 ]; + *p = ungetchBuffer.at( l - nread - 1 ); p++; nread++; } ungetchBuffer.truncate( l - nread ); } if ( nread < len ) { if ( isRaw() ) { // raw file nread += ::read( fd, p, len-nread ); if ( len && nread <= 0 ) { nread = 0; setStatus(IO_ReadError); } } else { // buffered file nread += fread( p, 1, len-nread, fh ); if ( (uint)nread != len ) { if ( ferror( fh ) || nread==0 ) setStatus(IO_ReadError); } } } if ( !isSequentialAccess() ) ioIndex += nread; return nread; } /*! \reimp Writes \a len bytes from \a p to the file and returns the number of bytes actually written. Returns -1 if a serious error occurred. \warning When working with buffered files, data may not be written to the file at once. Call flush() to make sure the data is really written. \sa readBlock() */ Q_LONG QFile::writeBlock( const char *p, Q_ULONG len ) { #if defined(QT_CHECK_NULL) if ( p == 0 && len != 0 ) qWarning( "QFile::writeBlock: Null pointer error" ); #endif #if defined(QT_CHECK_STATE) if ( !isOpen() ) { // file not open qWarning( "QFile::writeBlock: File not open" ); return -1; } if ( !isWritable() ) { // writing not permitted qWarning( "QFile::writeBlock: Write operation not permitted" ); return -1; } #endif Q_ULONG nwritten; // number of bytes written if ( isRaw() ) // raw file nwritten = ::write( fd, (void *)p, len ); else // buffered file nwritten = fwrite( p, 1, len, fh ); if ( nwritten != len ) { // write error if ( errno == ENOSPC ) // disk is full setStatus( IO_ResourceError ); else setStatus( IO_WriteError ); if ( !isSequentialAccess() ) { if ( isRaw() ) // recalc file position ioIndex = (Offset)::lseek( fd, 0, SEEK_CUR ); else #if defined(QT_LARGEFILE_SUPPORT) ioIndex = (Offset)::fseeko( fh, 0, SEEK_CUR ); #else ioIndex = (Offset)::fseek( fh, 0, SEEK_CUR ); #endif } } else { if ( !isSequentialAccess() ) ioIndex += nwritten; } if ( ioIndex > length ) // update file length length = ioIndex; return nwritten; } /*! Returns the file handle of the file. This is a small positive integer, suitable for use with C library - functions such as fdopen() and fcntl(), as well as with QSocketNotifier. + functions such as fdopen() and fcntl(). On systems that use file + descriptors for sockets (ie. Unix systems, but not Windows) the handle + can be used with QSocketNotifier as well. If the file is not open or there is an error, handle() returns -1. \sa QSocketNotifier */ int QFile::handle() const { if ( !isOpen() ) return -1; else if ( fh ) return fileno( fh ); else return fd; } /*! Closes an open file. The file is not closed if it was opened with an existing file handle. If the existing file handle is a \c FILE*, the file is flushed. If the existing file handle is an \c int file descriptor, nothing is done to the file. Some "write-behind" filesystems may report an unspecified error on closing the file. These errors only indicate that something may have gone wrong since the previous open(). In such a case status() reports IO_UnspecifiedError after close(), otherwise IO_Ok. \sa open(), flush() */ void QFile::close() { bool ok = FALSE; if ( isOpen() ) { // file is not open if ( fh ) { // buffered file if ( ext_f ) ok = fflush( fh ) != -1; // flush instead of closing else ok = fclose( fh ) != -1; } else { // raw file if ( ext_f ) ok = TRUE; // cannot close else ok = ::close( fd ) != -1; } init(); // restore internal state } if (!ok) setStatus( IO_UnspecifiedError ); return; } diff --git a/qmake/tools/qfileinfo.cpp b/qmake/tools/qfileinfo.cpp index 3af7932..a78f4fa 100644 --- a/qmake/tools/qfileinfo.cpp +++ b/qmake/tools/qfileinfo.cpp @@ -254,406 +254,408 @@ QFileInfo &QFileInfo::operator=( const QFileInfo &fi ) Absolute paths begin with the directory separator (e.g. "/" under Unix) or a drive specification (under Windows). Relative file names begin with a directory name or a file name and specify a path relative to the current directory. Example: \code QString absolute = "/local/bin"; QString relative = "local/bin"; QFileInfo absFile( absolute ); QFileInfo relFile( relative ); QDir::setCurrent( QDir::rootDirPath() ); // absFile and relFile now point to the same file QDir::setCurrent( "/tmp" ); // absFile now points to "/local/bin", // while relFile points to "/tmp/local/bin" \endcode \sa isRelative(), QDir::setCurrent(), QDir::isRelativePath() */ void QFileInfo::setFile( const QString &file ) { fn = file; slashify( fn ); delete fic; fic = 0; } /*! \overload Sets the file that the QFileInfo provides information about to \a file. If \a file includes a relative path, the QFileInfo will also have a relative path. \sa isRelative() */ void QFileInfo::setFile( const QFile &file ) { fn = file.name(); slashify( fn ); delete fic; fic = 0; } /*! \overload Sets the file that the QFileInfo provides information about to \a fileName in directory \a d. If \a fileName includes a relative path, the QFileInfo will also have a relative path. \sa isRelative() */ #ifndef QT_NO_DIR void QFileInfo::setFile( const QDir &d, const QString &fileName ) { fn = d.filePath( fileName ); slashify( fn ); delete fic; fic = 0; } #endif /*! Returns TRUE if the file exists; otherwise returns FALSE. */ bool QFileInfo::exists() const { return qt_file_access( fn, F_OK ); } /*! Refreshes the information about the file, i.e. reads in information from the file system the next time a cached property is fetched. \sa setCaching() */ void QFileInfo::refresh() const { QFileInfo *that = (QFileInfo*)this; // Mutable function delete that->fic; that->fic = 0; } /*! \fn bool QFileInfo::caching() const Returns TRUE if caching is enabled; otherwise returns FALSE. \sa setCaching(), refresh() */ /*! If \a enable is TRUE, enables caching of file information. If \a enable is FALSE caching is disabled. When caching is enabled, QFileInfo reads the file information from the file system the first time it's needed, but generally not later. Caching is enabled by default. \sa refresh(), caching() */ void QFileInfo::setCaching( bool enable ) { if ( cache == enable ) return; cache = enable; if ( cache ) { delete fic; fic = 0; } } /*! Returns the file name, including the path (which may be absolute or relative). \sa isRelative(), absFilePath() */ QString QFileInfo::filePath() const { return fn; } /*! Returns the base name of the file. If \a complete is FALSE (the default) the base name consists of all characters in the file name up to (but not including) the \e first '.' character. If \a complete is TRUE the base name consists of all characters in the file up to (but not including) the \e last '.' character. The path is not included in either case. Example: \code QFileInfo fi( "/tmp/archive.tar.gz" ); QString base = fi.baseName(); // base = "archive" base = fi.baseName( TRUE ); // base = "archive.tar" \endcode \sa fileName(), extension() */ QString QFileInfo::baseName( bool complete ) const { QString tmp = fileName(); int pos = complete ? tmp.findRev( '.' ) : tmp.find( '.' ); if ( pos == -1 ) return tmp; else return tmp.left( pos ); } /*! Returns the file's extension name. If \a complete is TRUE (the default), extension() returns the string of all characters in the file name after (but not including) the first '.' character. If \a complete is FALSE, extension() returns the string of all characters in the file name after (but not including) the last '.' character. Example: \code QFileInfo fi( "/tmp/archive.tar.gz" ); QString ext = fi.extension(); // ext = "tar.gz" ext = fi.extension( FALSE ); // ext = "gz" \endcode \sa fileName(), baseName() */ QString QFileInfo::extension( bool complete ) const { QString s = fileName(); int pos = complete ? s.find( '.' ) : s.findRev( '.' ); if ( pos < 0 ) return QString::fromLatin1( "" ); else return s.right( s.length() - pos - 1 ); } /*! Returns the file's path as a QDir object. If the QFileInfo is relative and \a absPath is FALSE, the QDir will be relative; otherwise it will be absolute. \sa dirPath(), filePath(), fileName(), isRelative() */ #ifndef QT_NO_DIR QDir QFileInfo::dir( bool absPath ) const { return QDir( dirPath(absPath) ); } #endif /*! Returns TRUE if the file is readable; otherwise returns FALSE. \sa isWritable(), isExecutable(), permission() */ bool QFileInfo::isReadable() const { return qt_file_access( fn, R_OK ) && permission( ReadUser ); } /*! Returns TRUE if the file is writable; otherwise returns FALSE. \sa isReadable(), isExecutable(), permission() */ bool QFileInfo::isWritable() const { return qt_file_access( fn, W_OK ) && permission( WriteUser ); } /*! Returns TRUE if the file is executable; otherwise returns FALSE. \sa isReadable(), isWritable(), permission() */ bool QFileInfo::isExecutable() const { return qt_file_access( fn, X_OK ) && permission( ExeUser ); } #ifndef Q_WS_WIN bool QFileInfo::isHidden() const { return fileName()[ 0 ] == QChar( '.' ); } #endif /*! Returns TRUE if the file path name is relative. Returns FALSE if the path is absolute (e.g. under Unix a path is absolute if it begins with a "/"). */ #ifndef QT_NO_DIR bool QFileInfo::isRelative() const { return QDir::isRelativePath( fn ); } /*! Converts the file's path to an absolute path. If it is already absolute, nothing is done. \sa filePath(), isRelative() */ bool QFileInfo::convertToAbs() { if ( isRelative() ) fn = absFilePath(); return QDir::isRelativePath( fn ); } #endif /*! Returns the file size in bytes, or 0 if the file does not exist or if the size is 0 or if the size cannot be fetched. */ #if defined(QT_ABI_QT4) QIODevice::Offset QFileInfo::size() const #else uint QFileInfo::size() const #endif { if ( !fic || !cache ) doStat(); if ( fic ) #if defined(QT_ABI_QT4) return (QIODevice::Offset)fic->st.st_size; #elif defined(QT_LARGEFILE_SUPPORT) return (uint)fic->st.st_size > UINT_MAX ? UINT_MAX : (uint)fic->st.st_size; #else return (uint)fic->st.st_size; #endif else return 0; } /*! Returns the date and time when the file was created. On platforms where this information is not available, returns the same as lastModified(). \sa created() lastModified() lastRead() */ QDateTime QFileInfo::created() const { QDateTime dt; if ( !fic || !cache ) doStat(); if ( fic && fic->st.st_ctime != 0 ) { dt.setTime_t( fic->st.st_ctime ); return dt; } else { return lastModified(); } } /*! Returns the date and time when the file was last modified. \sa created() lastModified() lastRead() */ QDateTime QFileInfo::lastModified() const { QDateTime dt; if ( !fic || !cache ) doStat(); if ( fic ) dt.setTime_t( fic->st.st_mtime ); return dt; } /*! Returns the date and time when the file was last read (accessed). On platforms where this information is not available, returns the same as lastModified(). \sa created() lastModified() lastRead() */ QDateTime QFileInfo::lastRead() const { QDateTime dt; if ( !fic || !cache ) doStat(); if ( fic && fic->st.st_atime != 0 ) { dt.setTime_t( fic->st.st_atime ); return dt; } else { return lastModified(); } } #ifndef QT_NO_DIR /*! Returns the absolute path including the file name. The absolute path name consists of the full path and the file name. On Unix this will always begin with the root, '/', directory. On Windows this will always begin 'D:/' where D is a drive letter, except for network shares that are not mapped to a drive letter, in which case the path will begin '//sharename/'. This function returns the same as filePath(), unless isRelative() is TRUE. + If the QFileInfo is empty it returns QDir::currentDirPath(). + This function can be time consuming under Unix (in the order of milliseconds). \sa isRelative(), filePath() */ QString QFileInfo::absFilePath() const { QString tmp; if ( QDir::isRelativePath(fn) -#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) +#if defined(Q_OS_WIN32) && fn[1] != ':' #endif ) { tmp = QDir::currentDirPath(); tmp += '/'; } tmp += fn; makeAbs( tmp ); return QDir::cleanDirPath( tmp ); } #endif diff --git a/qmake/tools/qfileinfo_unix.cpp b/qmake/tools/qfileinfo_unix.cpp index f7c3a97..364f219 100644 --- a/qmake/tools/qfileinfo_unix.cpp +++ b/qmake/tools/qfileinfo_unix.cpp @@ -1,331 +1,331 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QFileInfo class ** ** Created : 950628 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance ** with the Qt Commercial License Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include "qfileinfo.h" #include "qfiledefs_p.h" #include "qdatetime.h" #include "qdir.h" #include <limits.h> void QFileInfo::slashify( QString& ) { return; } void QFileInfo::makeAbs( QString & ) { return; } /*! Returns TRUE if this object points to a file. Returns FALSE if the object points to something which isn't a file, e.g. a directory or a symlink. \sa isDir(), isSymLink() */ bool QFileInfo::isFile() const { if ( !fic || !cache ) doStat(); return fic ? (fic->st.st_mode & S_IFMT) == S_IFREG : FALSE; } /*! Returns TRUE if this object points to a directory or to a symbolic link to a directory; otherwise returns FALSE. \sa isFile(), isSymLink() */ bool QFileInfo::isDir() const { if ( !fic || !cache ) doStat(); return fic ? (fic->st.st_mode & S_IFMT) == S_IFDIR : FALSE; } /*! Returns TRUE if this object points to a symbolic link (or to a shortcut on Windows); otherwise returns FALSE. \sa isFile(), isDir(), readLink() */ bool QFileInfo::isSymLink() const { if ( !fic || !cache ) doStat(); return symLink; } /*! Returns the name a symlink (or shortcut on Windows) points to, or a QString::null if the object isn't a symbolic link. This name may not represent an existing file; it is only a string. QFileInfo::exists() returns TRUE if the symlink points to an existing file. \sa exists(), isSymLink(), isDir(), isFile() */ QString QFileInfo::readLink() const { QString r; #if defined(Q_OS_UNIX) && !defined(Q_OS_OS2EMX) char s[PATH_MAX+1]; if ( !isSymLink() ) return QString(); int len = readlink( QFile::encodeName(fn).data(), s, PATH_MAX ); if ( len >= 0 ) { s[len] = '\0'; r = QFile::decodeName(s); } #endif return r; } static const uint nobodyID = (uint) -2; /*! Returns the owner of the file. On Windows, on systems where files do not have owners, or if an error occurs, QString::null is returned. This function can be time consuming under Unix (in the order of milliseconds). \sa ownerId(), group(), groupId() */ QString QFileInfo::owner() const { passwd *pw = getpwuid( ownerId() ); if ( pw ) return QFile::decodeName( pw->pw_name ); return QString::null; } /*! Returns the id of the owner of the file. On Windows and on systems where files do not have owners this function returns ((uint) -2). \sa owner(), group(), groupId() */ uint QFileInfo::ownerId() const { if ( !fic || !cache ) doStat(); if ( fic ) return fic->st.st_uid; return nobodyID; } /*! Returns the group of the file. On Windows, on systems where files do not have groups, or if an error occurs, QString::null is returned. This function can be time consuming under Unix (in the order of milliseconds). \sa groupId(), owner(), ownerId() */ QString QFileInfo::group() const { struct group *gr = getgrgid( groupId() ); if ( gr ) return QFile::decodeName( gr->gr_name ); return QString::null; } /*! Returns the id of the group the file belongs to. On Windows and on systems where files do not have groups this function always returns (uint) -2. \sa group(), owner(), ownerId() */ uint QFileInfo::groupId() const { if ( !fic || !cache ) doStat(); if ( fic ) return fic->st.st_gid; return nobodyID; } /*! Tests for file permissions. The \a permissionSpec argument can be several flags of type \c PermissionSpec OR-ed together to check for permission combinations. On systems where files do not have permissions this function always returns TRUE. Example: \code QFileInfo fi( "/tmp/archive.tar.gz" ); if ( fi.permission( QFileInfo::WriteUser | QFileInfo::ReadGroup ) ) - qWarning( "I can change the file; my group can read the file."); + qWarning( "I can change the file; my group can read the file" ); if ( fi.permission( QFileInfo::WriteGroup | QFileInfo::WriteOther ) ) - qWarning( "The group or others can change the file!" ); + qWarning( "The group or others can change the file" ); \endcode \sa isReadable(), isWritable(), isExecutable() */ bool QFileInfo::permission( int permissionSpec ) const { if ( !fic || !cache ) doStat(); if ( fic ) { uint mask = 0; if ( permissionSpec & ReadUser ) mask |= S_IRUSR; if ( permissionSpec & WriteUser ) mask |= S_IWUSR; if ( permissionSpec & ExeUser ) mask |= S_IXUSR; if ( permissionSpec & ReadGroup ) mask |= S_IRGRP; if ( permissionSpec & WriteGroup ) mask |= S_IWGRP; if ( permissionSpec & ExeGroup ) mask |= S_IXGRP; if ( permissionSpec & ReadOther ) mask |= S_IROTH; if ( permissionSpec & WriteOther ) mask |= S_IWOTH; if ( permissionSpec & ExeOther ) mask |= S_IXOTH; if ( mask ) { return (fic->st.st_mode & mask) == mask; } else { #if defined(QT_CHECK_NULL) qWarning( "QFileInfo::permission: permissionSpec is 0" ); #endif return TRUE; } } else { return FALSE; } } void QFileInfo::doStat() const { QFileInfo *that = ((QFileInfo*)this); // mutable function if ( !that->fic ) that->fic = new QFileInfoCache; that->symLink = FALSE; struct stat *b = &that->fic->st; #if defined(Q_OS_UNIX) && defined(S_IFLNK) if ( ::lstat( QFile::encodeName(fn), b ) == 0 ) { if ( S_ISLNK( b->st_mode ) ) that->symLink = TRUE; else return; } #endif int r = ::stat( QFile::encodeName(fn), b ); if ( r != 0 && !that->symLink ) { delete that->fic; that->fic = 0; } } /*! Returns the file's path. If \a absPath is TRUE an absolute path is returned. \sa dir(), filePath(), fileName(), isRelative() */ #ifndef QT_NO_DIR QString QFileInfo::dirPath( bool absPath ) const { QString s; if ( absPath ) s = absFilePath(); else s = fn; int pos = s.findRev( '/' ); if ( pos == -1 ) { return QString::fromLatin1( "." ); } else { if ( pos == 0 ) return QString::fromLatin1( "/" ); return s.left( pos ); } } #endif /*! Returns the name of the file, excluding the path. Example: \code QFileInfo fi( "/tmp/archive.tar.gz" ); QString name = fi.fileName(); // name = "archive.tar.gz" \endcode \sa isRelative(), filePath(), baseName(), extension() */ QString QFileInfo::fileName() const { int p = fn.findRev( '/' ); if ( p == -1 ) { return fn; } else { return fn.mid( p + 1 ); } } diff --git a/qmake/tools/qgarray.cpp b/qmake/tools/qgarray.cpp index 45c45ce..0a522e4 100644 --- a/qmake/tools/qgarray.cpp +++ b/qmake/tools/qgarray.cpp @@ -1,754 +1,817 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QGArray class ** ** Created : 930906 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#include "qglobal.h" // needed to define Q_WS_WIN -#ifdef Q_WS_WIN -#include "qt_windows.h" // needed for bsearch on some platforms +#include "qglobal.h" +#if defined(Q_CC_BOR) + // needed for qsort() because of a std namespace problem on Borland +# include "qplatformdefs.h" +#elif defined(Q_WS_WIN) + // needed for bsearch on some platforms +# include "qt_windows.h" #endif #define QGARRAY_CPP #include "qgarray.h" #include <stdlib.h> #include <string.h> #ifdef QT_THREAD_SUPPORT # include <private/qmutexpool_p.h> #endif // QT_THREAD_SUPPORT -#define USE_MALLOC // comment to use new/delete +/* + If USE_MALLOC isn't defined, we use new[] and delete[] to allocate + memory. The documentation for QMemArray<T>::assign() explicitly + mentions that the array is freed using free(), so don't mess around + with USE_MALLOC unless you know what you're doing. +*/ +#define USE_MALLOC #undef NEW #undef DELETE #if defined(USE_MALLOC) #define NEW(type,size) ((type*)malloc(size*sizeof(type))) #define DELETE(array) (free((char*)array)) #else #define NEW(type,size) (new type[size]) #define DELETE(array) (delete[] array) #define DONT_USE_REALLOC // comment to use realloc() #endif /*! \class QShared qshared.h \reentrant \ingroup shared \brief The QShared class is used internally for implementing shared classes. \internal It only contains a reference count and member functions to increment and decrement it. Shared classes normally have internal classes that inherit QShared and add the shared data. \sa \link shclass.html Shared Classes\endlink */ /*! \class QGArray qgarray.h \reentrant \ingroup shared \ingroup collection \brief The QGArray class is an internal class for implementing the QMemArray class. \internal QGArray is a strictly internal class that acts as base class for the QMemArray template array. It contains an array of bytes and has no notion of an array element. */ /*! Constructs a null array. */ QGArray::QGArray() { shd = newData(); Q_CHECK_PTR( shd ); } /*! Dummy constructor; does not allocate any data. This constructor does not initialize any array data so subclasses must do it. The intention is to make the code more efficient. */ QGArray::QGArray( int, int ) { } /*! Constructs an array with room for \a size bytes. */ QGArray::QGArray( int size ) { if ( size < 0 ) { #if defined(QT_CHECK_RANGE) qWarning( "QGArray: Cannot allocate array with negative length" ); #endif size = 0; } shd = newData(); Q_CHECK_PTR( shd ); if ( size == 0 ) // zero length return; shd->data = NEW(char,size); Q_CHECK_PTR( shd->data ); - shd->len = size; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + size; } /*! Constructs a shallow copy of \a a. */ QGArray::QGArray( const QGArray &a ) { shd = a.shd; shd->ref(); } /*! Dereferences the array data and deletes it if this was the last reference. */ QGArray::~QGArray() { if ( shd && shd->deref() ) { // delete when last reference if ( shd->data ) // is lost DELETE(shd->data); deleteData( shd ); shd = 0; } } /*! \fn QGArray &QGArray::operator=( const QGArray &a ) Assigns a shallow copy of \a a to this array and returns a reference to this array. Equivalent to assign(). */ /*! \fn void QGArray::detach() Detaches this array from shared array data. */ /*! \fn char *QGArray::data() const Returns a pointer to the actual array data. */ /*! \fn uint QGArray::nrefs() const Returns the reference count. */ /*! \fn uint QGArray::size() const Returns the size of the array, in bytes. */ /*! Returns TRUE if this array is equal to \a a, otherwise FALSE. The comparison is bitwise, of course. */ bool QGArray::isEqual( const QGArray &a ) const { if ( size() != a.size() ) // different size return FALSE; if ( data() == a.data() ) // has same data return TRUE; return (size() ? memcmp( data(), a.data(), size() ) : 0) == 0; } /*! - Resizes the array to \a newsize bytes. + Resizes the array to \a newsize bytes. \a optim is either + MemOptim (the default) or SpeedOptim. */ - -bool QGArray::resize( uint newsize ) +bool QGArray::resize( uint newsize, Optimization optim ) { - if ( newsize == shd->len ) // nothing to do +#ifndef QT_QGARRAY_SPEED_OPTIM + Q_UNUSED(optim); +#endif + + if ( newsize == shd->len +#ifdef QT_QGARRAY_SPEED_OPTIM + && newsize == shd->maxl +#endif + ) // nothing to do return TRUE; if ( newsize == 0 ) { // remove array duplicate( 0, 0 ); return TRUE; } + + uint newmaxl = newsize; +#ifdef QT_QGARRAY_SPEED_OPTIM + if ( optim == SpeedOptim ) { + if ( newsize <= shd->maxl && + ( newsize * 4 > shd->maxl || shd->maxl <= 4 ) ) { + shd->len = newsize; + return TRUE; + } + newmaxl = 4; + while ( newmaxl < newsize ) + newmaxl *= 2; + // try to spare some memory + if ( newmaxl >= 1024 * 1024 && newsize <= newmaxl - (newmaxl >> 2) ) + newmaxl -= newmaxl >> 2; + } + shd->maxl = newmaxl; +#endif + if ( shd->data ) { // existing data #if defined(DONT_USE_REALLOC) char *newdata = NEW(char,newsize); // manual realloc - memcpy( newdata, shd->data, QMIN(shd->len,newsize) ); + memcpy( newdata, shd->data, QMIN(shd->len,newmaxl) ); DELETE(shd->data); shd->data = newdata; #else - shd->data = (char *)realloc( shd->data, newsize ); + shd->data = (char *)realloc( shd->data, newmaxl ); #endif } else { - shd->data = NEW(char,newsize); + shd->data = NEW(char,newmaxl); } if ( !shd->data ) // no memory return FALSE; shd->len = newsize; return TRUE; } +/*!\overload +*/ +bool QGArray::resize( uint newsize ) +{ + return resize( newsize, MemOptim ); +} + + /*! Fills the array with the repeated occurrences of \a d, which is \a sz bytes long. If \a len is specified as different from -1, then the array will be resized to \a len*sz before it is filled. Returns TRUE if successful, or FALSE if the memory cannot be allocated (only when \a len != -1). \sa resize() */ bool QGArray::fill( const char *d, int len, uint sz ) { if ( len < 0 ) len = shd->len/sz; // default: use array length else if ( !resize( len*sz ) ) return FALSE; if ( sz == 1 ) // 8 bit elements memset( data(), *d, len ); else if ( sz == 4 ) { // 32 bit elements register Q_INT32 *x = (Q_INT32*)data(); Q_INT32 v = *((Q_INT32*)d); while ( len-- ) *x++ = v; } else if ( sz == 2 ) { // 16 bit elements register Q_INT16 *x = (Q_INT16*)data(); Q_INT16 v = *((Q_INT16*)d); while ( len-- ) *x++ = v; } else { // any other size elements register char *x = data(); while ( len-- ) { // more complicated memcpy( x, d, sz ); x += sz; } } return TRUE; } /*! \overload Shallow copy. Dereference the current array and references the data contained in \a a instead. Returns a reference to this array. \sa operator=() */ QGArray &QGArray::assign( const QGArray &a ) { a.shd->ref(); // avoid 'a = a' if ( shd->deref() ) { // delete when last reference if ( shd->data ) // is lost DELETE(shd->data); deleteData( shd ); } shd = a.shd; return *this; } /*! Shallow copy. Dereference the current array and references the array data \a d, which contains \a len bytes. Returns a reference to this array. Do not delete \a d later, because QGArray takes care of that. */ QGArray &QGArray::assign( const char *d, uint len ) { if ( shd->count > 1 ) { // disconnect this shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { if ( shd->data ) DELETE(shd->data); } shd->data = (char *)d; - shd->len = len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + len; return *this; } /*! Deep copy. Dereference the current array and obtains a copy of the data contained in \a a instead. Returns a reference to this array. \sa assign(), operator=() */ QGArray &QGArray::duplicate( const QGArray &a ) { if ( a.shd == shd ) { // a.duplicate(a) ! if ( shd->count > 1 ) { shd->count--; register array_data *n = newData(); Q_CHECK_PTR( n ); if ( (n->len=shd->len) ) { n->data = NEW(char,n->len); Q_CHECK_PTR( n->data ); if ( n->data ) memcpy( n->data, shd->data, n->len ); } else { n->data = 0; } shd = n; } return *this; } char *oldptr = 0; if ( shd->count > 1 ) { // disconnect this shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { // delete after copy was made oldptr = shd->data; } if ( a.shd->len ) { // duplicate data shd->data = NEW(char,a.shd->len); Q_CHECK_PTR( shd->data ); if ( shd->data ) memcpy( shd->data, a.shd->data, a.shd->len ); } else { shd->data = 0; } - shd->len = a.shd->len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + a.shd->len; if ( oldptr ) DELETE(oldptr); return *this; } /*! \overload Deep copy. Dereferences the current array and obtains a copy of \a len characters from array data \a d instead. Returns a reference to this array. \sa assign(), operator=() */ QGArray &QGArray::duplicate( const char *d, uint len ) { char *data; if ( d == 0 || len == 0 ) { data = 0; len = 0; } else { if ( shd->count == 1 && shd->len == len ) { memcpy( shd->data, d, len ); // use same buffer return *this; } data = NEW(char,len); Q_CHECK_PTR( data ); memcpy( data, d, len ); } if ( shd->count > 1 ) { // detach shd->count--; shd = newData(); Q_CHECK_PTR( shd ); } else { // just a single reference if ( shd->data ) DELETE(shd->data); } shd->data = data; - shd->len = len; + shd->len = +#ifdef QT_QGARRAY_SPEED_OPTIM + shd->maxl = +#endif + len; return *this; } /*! Resizes this array to \a len bytes and copies the \a len bytes at address \a d into it. \warning This function disregards the reference count mechanism. If other QGArrays reference the same data as this, all will be updated. */ void QGArray::store( const char *d, uint len ) { // store, but not deref resize( len ); memcpy( shd->data, d, len ); } /*! \fn array_data *QGArray::sharedBlock() const Returns a pointer to the shared array block. \warning Do not use this function. Using it is begging for trouble. We dare not remove it, for fear of breaking code, but we \e strongly discourage new use of it. */ /*! \fn void QGArray::setSharedBlock( array_data *p ) Sets the shared array block to \a p. \warning Do not use this function. Using it is begging for trouble. We dare not remove it, for fear of breaking code, but we \e strongly discourage new use of it. */ /*! Sets raw data and returns a reference to the array. Dereferences the current array and sets the new array data to \a d and the new array size to \a len. Do not attempt to resize or re-assign the array data when raw data has been set. Call resetRawData(d,len) to reset the array. Setting raw data is useful because it sets QMemArray data without allocating memory or copying data. Example of intended use: \code static uchar bindata[] = { 231, 1, 44, ... }; QByteArray a; a.setRawData( bindata, sizeof(bindata) ); // a points to bindata QDataStream s( a, IO_ReadOnly ); // open on a's data s >> <something>; // read raw bindata s.close(); a.resetRawData( bindata, sizeof(bindata) ); // finished \endcode Example of misuse (do not do this): \code static uchar bindata[] = { 231, 1, 44, ... }; QByteArray a, b; a.setRawData( bindata, sizeof(bindata) ); // a points to bindata a.resize( 8 ); // will crash b = a; // will crash a[2] = 123; // might crash // forget to resetRawData - will crash \endcode \warning If you do not call resetRawData(), QGArray will attempt to deallocate or reallocate the raw data, which might not be too good. Be careful. */ QGArray &QGArray::setRawData( const char *d, uint len ) { duplicate( 0, 0 ); // set null data shd->data = (char *)d; shd->len = len; return *this; } /*! Resets raw data. The arguments must be the data, \a d, and length \a len, that were passed to setRawData(). This is for consistency checking. */ void QGArray::resetRawData( const char *d, uint len ) { if ( d != shd->data || len != shd->len ) { #if defined(QT_CHECK_STATE) qWarning( "QGArray::resetRawData: Inconsistent arguments" ); #endif return; } shd->data = 0; shd->len = 0; } /*! Finds the first occurrence of \a d in the array from position \a index, where \a sz is the size of the \a d element. Note that \a index is given in units of \a sz, not bytes. This function only compares whole cells, not bytes. */ int QGArray::find( const char *d, uint index, uint sz ) const { index *= sz; if ( index >= shd->len ) { #if defined(QT_CHECK_RANGE) qWarning( "QGArray::find: Index %d out of range", index/sz ); #endif return -1; } register uint i; uint ii; switch ( sz ) { case 1: { // 8 bit elements register char *x = data() + index; char v = *d; for ( i=index; i<shd->len; i++ ) { if ( *x++ == v ) break; } ii = i; } break; case 2: { // 16 bit elements register Q_INT16 *x = (Q_INT16*)(data() + index); Q_INT16 v = *((Q_INT16*)d); for ( i=index; i<shd->len; i+=2 ) { if ( *x++ == v ) break; } ii = i/2; } break; case 4: { // 32 bit elements register Q_INT32 *x = (Q_INT32*)(data() + index); Q_INT32 v = *((Q_INT32*)d); for ( i=index; i<shd->len; i+=4 ) { if ( *x++ == v ) break; } ii = i/4; } break; default: { // any size elements for ( i=index; i<shd->len; i+=sz ) { if ( memcmp( d, &shd->data[i], sz ) == 0 ) break; } ii = i/sz; } break; } return i<shd->len ? (int)ii : -1; } /*! Returns the number of occurrences of \a d in the array, where \a sz is the size of the \a d element. This function only compares whole cells, not bytes. */ int QGArray::contains( const char *d, uint sz ) const { register uint i = shd->len; int count = 0; switch ( sz ) { case 1: { // 8 bit elements register char *x = data(); char v = *d; while ( i-- ) { if ( *x++ == v ) count++; } } break; case 2: { // 16 bit elements register Q_INT16 *x = (Q_INT16*)data(); Q_INT16 v = *((Q_INT16*)d); i /= 2; while ( i-- ) { if ( *x++ == v ) count++; } } break; case 4: { // 32 bit elements register Q_INT32 *x = (Q_INT32*)data(); Q_INT32 v = *((Q_INT32*)d); i /= 4; while ( i-- ) { if ( *x++ == v ) count++; } } break; default: { // any size elements for ( i=0; i<shd->len; i+=sz ) { if ( memcmp(d, &shd->data[i], sz) == 0 ) count++; } } break; } return count; } static int cmp_item_size = 0; #if defined(Q_C_CALLBACKS) extern "C" { #endif #ifdef Q_OS_TEMP static int __cdecl cmp_arr( const void *n1, const void *n2 ) #else static int cmp_arr( const void *n1, const void *n2 ) #endif { return ( n1 && n2 ) ? memcmp( n1, n2, cmp_item_size ) : ( n1 ? 1 : ( n2 ? -1 : 0 ) ); // ### Qt 3.0: Add a virtual compareItems() method and call that instead } #if defined(Q_C_CALLBACKS) } #endif /*! Sorts the first \a sz items of the array. */ void QGArray::sort( uint sz ) { int numItems = size() / sz; if ( numItems < 2 ) return; #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &cmp_item_size ) : 0 ); #endif // QT_THREAD_SUPPORT cmp_item_size = sz; qsort( shd->data, numItems, sz, cmp_arr ); } /*! Binary search; assumes that \a d is a sorted array of size \a sz. */ int QGArray::bsearch( const char *d, uint sz ) const { int numItems = size() / sz; if ( !numItems ) return -1; #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &cmp_item_size ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &cmp_item_size ) : 0 ); #endif // QT_THREAD_SUPPORT cmp_item_size = sz; char* r = (char*)::bsearch( d, shd->data, numItems, sz, cmp_arr ); if ( !r ) return -1; while( (r >= shd->data + sz) && (cmp_arr( r - sz, d ) == 0) ) r -= sz; // search to first of equal elements; bsearch is undef return (int)(( r - shd->data ) / sz); } /*! \fn char *QGArray::at( uint index ) const Returns a pointer to the byte at offset \a index in the array. */ /*! Expand the array if necessary, and copies (the first part of) its contents from the \a index * \a sz bytes at \a d. Returns TRUE if the operation succeeds, FALSE if it runs out of memory. \warning This function disregards the reference count mechanism. If other QGArrays reference the same data as this, all will be changed. */ bool QGArray::setExpand( uint index, const char *d, uint sz ) { index *= sz; if ( index >= shd->len ) { if ( !resize( index+sz ) ) // no memory return FALSE; } memcpy( data() + index, d, sz ); return TRUE; } /*! Prints a warning message if at() or [] is given a bad index. */ void QGArray::msg_index( uint index ) { #if defined(QT_CHECK_RANGE) qWarning( "QGArray::at: Absolute index %d out of range", index ); #else Q_UNUSED( index ) #endif } /*! Returns a new shared array block. */ QGArray::array_data * QGArray::newData() { return new array_data; } /*! Deletes the shared array block, \a p. */ void QGArray::deleteData( array_data *p ) { delete p; p = 0; } diff --git a/qmake/tools/qgdict.cpp b/qmake/tools/qgdict.cpp index c431ff8..3d49fc7 100644 --- a/qmake/tools/qgdict.cpp +++ b/qmake/tools/qgdict.cpp @@ -1,591 +1,594 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QGDict and QGDictIterator classes ** ** Created : 920529 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qgdict.h" #include "qptrlist.h" #include "qstring.h" #include "qdatastream.h" #include <ctype.h> /*! \class QGDict \reentrant \ingroup collection \brief The QGDict class is an internal class for implementing QDict template classes. \internal QGDict is a strictly internal class that acts as a base class for the \link collection.html collection classes\endlink QDict and QIntDict. QGDict has some virtual functions that can be reimplemented to customize the subclasses. \list \i read() reads a collection/dictionary item from a QDataStream. \i write() writes a collection/dictionary item to a QDataStream. \endlist Normally, you do not have to reimplement any of these functions. */ static const int op_find = 0; static const int op_insert = 1; static const int op_replace = 2; class QGDItList : public QPtrList<QGDictIterator> { public: QGDItList() : QPtrList<QGDictIterator>() {} QGDItList( const QGDItList &list ) : QPtrList<QGDictIterator>(list) {} ~QGDItList() { clear(); } QGDItList &operator=(const QGDItList &list) { return (QGDItList&)QPtrList<QGDictIterator>::operator=(list); } }; /***************************************************************************** Default implementation of special and virtual functions *****************************************************************************/ /*! Returns the hash key for \a key, when key is a string. */ int QGDict::hashKeyString( const QString &key ) { #if defined(QT_CHECK_NULL) if ( key.isNull() ) qWarning( "QGDict::hashKeyString: Invalid null key" ); #endif int i; register uint h=0; uint g; const QChar *p = key.unicode(); if ( cases ) { // case sensitive for ( i=0; i<(int)key.length(); i++ ) { h = (h<<4) + p[i].cell(); if ( (g = h & 0xf0000000) ) h ^= g >> 24; h &= ~g; } } else { // case insensitive for ( i=0; i<(int)key.length(); i++ ) { h = (h<<4) + p[i].lower().cell(); if ( (g = h & 0xf0000000) ) h ^= g >> 24; h &= ~g; } } int index = h; if ( index < 0 ) // adjust index to table size index = -index; return index; } /*! Returns the hash key for \a key, which is a C string. */ int QGDict::hashKeyAscii( const char *key ) { #if defined(QT_CHECK_NULL) if ( key == 0 ) qWarning( "QGDict::hashAsciiKey: Invalid null key" ); #endif register const char *k = key; register uint h=0; uint g; if ( cases ) { // case sensitive while ( *k ) { h = (h<<4) + *k++; if ( (g = h & 0xf0000000) ) h ^= g >> 24; h &= ~g; } } else { // case insensitive while ( *k ) { h = (h<<4) + tolower((uchar) *k); if ( (g = h & 0xf0000000) ) h ^= g >> 24; h &= ~g; k++; } } int index = h; if ( index < 0 ) // adjust index to table size index = -index; return index; } #ifndef QT_NO_DATASTREAM /*! \overload Reads a collection/dictionary item from the stream \a s and returns a reference to the stream. The default implementation sets \a item to 0. \sa write() */ QDataStream& QGDict::read( QDataStream &s, QPtrCollection::Item &item ) { item = 0; return s; } /*! \overload Writes a collection/dictionary item to the stream \a s and returns a reference to the stream. \sa read() */ QDataStream& QGDict::write( QDataStream &s, QPtrCollection::Item ) const { return s; } #endif //QT_NO_DATASTREAM /***************************************************************************** QGDict member functions *****************************************************************************/ /*! Constructs a dictionary. \a len is the initial size of the dictionary. The key type is \a kt which may be \c StringKey, \c AsciiKey, \c IntKey or \c PtrKey. The case-sensitivity of lookups is set with \a caseSensitive. Keys are copied if \a copyKeys is TRUE. */ QGDict::QGDict( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) { init( len, kt, caseSensitive, copyKeys ); } void QGDict::init( uint len, KeyType kt, bool caseSensitive, bool copyKeys ) { - vec = new QBaseBucket *[vlen = len]; // allocate hash table + vlen = len; + if ( vlen == 0 ) + vlen = 17; + vec = new QBaseBucket *[vlen]; Q_CHECK_PTR( vec ); memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) ); numItems = 0; iterators = 0; // The caseSensitive and copyKey options don't make sense for // all dict types. switch ( (keytype = (uint)kt) ) { case StringKey: cases = caseSensitive; copyk = FALSE; break; case AsciiKey: cases = caseSensitive; copyk = copyKeys; break; default: cases = FALSE; copyk = FALSE; break; } } /*! Constructs a copy of \a dict. */ QGDict::QGDict( const QGDict & dict ) : QPtrCollection( dict ) { init( dict.vlen, (KeyType)dict.keytype, dict.cases, dict.copyk ); QGDictIterator it( dict ); while ( it.get() ) { // copy from other dict switch ( keytype ) { case StringKey: look_string( it.getKeyString(), it.get(), op_insert ); break; case AsciiKey: look_ascii( it.getKeyAscii(), it.get(), op_insert ); break; case IntKey: look_int( it.getKeyInt(), it.get(), op_insert ); break; case PtrKey: look_ptr( it.getKeyPtr(), it.get(), op_insert ); break; } ++it; } } /*! Removes all items from the dictionary and destroys it. */ QGDict::~QGDict() { clear(); // delete everything delete [] vec; if ( !iterators ) // no iterators for this dict return; QGDictIterator *i = iterators->first(); while ( i ) { // notify all iterators that i->dict = 0; // this dict is deleted i = iterators->next(); } delete iterators; } /*! Assigns \a dict to this dictionary. */ QGDict &QGDict::operator=( const QGDict &dict ) { if ( &dict == this ) return *this; clear(); QGDictIterator it( dict ); while ( it.get() ) { // copy from other dict switch ( keytype ) { case StringKey: look_string( it.getKeyString(), it.get(), op_insert ); break; case AsciiKey: look_ascii( it.getKeyAscii(), it.get(), op_insert ); break; case IntKey: look_int( it.getKeyInt(), it.get(), op_insert ); break; case PtrKey: look_ptr( it.getKeyPtr(), it.get(), op_insert ); break; } ++it; } return *this; } /*! \fn uint QGDict::count() const Returns the number of items in the dictionary. */ /*! \fn uint QGDict::size() const Returns the size of the hash array. */ /*! The do-it-all function; \a op is one of op_find, op_insert, op_replace. The key is \a key and the item is \a d. */ QPtrCollection::Item QGDict::look_string( const QString &key, QPtrCollection::Item d, int op ) { QStringBucket *n = 0; int index = hashKeyString(key) % vlen; if ( op == op_find ) { // find if ( cases ) { n = (QStringBucket*)vec[index]; while( n != 0 ) { if ( key == n->getKey() ) return n->getData(); // item found n = (QStringBucket*)n->getNext(); } } else { QString k = key.lower(); n = (QStringBucket*)vec[index]; while( n != 0 ) { if ( k == n->getKey().lower() ) return n->getData(); // item found n = (QStringBucket*)n->getNext(); } } return 0; // not found } if ( op == op_replace ) { // replace if ( vec[index] != 0 ) // maybe something there remove_string( key ); } // op_insert or op_replace n = new QStringBucket(key,newItem(d),vec[index]); Q_CHECK_PTR( n ); #if defined(QT_CHECK_NULL) if ( n->getData() == 0 ) qWarning( "QDict: Cannot insert null item" ); #endif vec[index] = n; numItems++; return n->getData(); } QPtrCollection::Item QGDict::look_ascii( const char *key, QPtrCollection::Item d, int op ) { QAsciiBucket *n; int index = hashKeyAscii(key) % vlen; if ( op == op_find ) { // find if ( cases ) { for ( n=(QAsciiBucket*)vec[index]; n; n=(QAsciiBucket*)n->getNext() ) { if ( qstrcmp(n->getKey(),key) == 0 ) return n->getData(); // item found } } else { for ( n=(QAsciiBucket*)vec[index]; n; n=(QAsciiBucket*)n->getNext() ) { if ( qstricmp(n->getKey(),key) == 0 ) return n->getData(); // item found } } return 0; // not found } if ( op == op_replace ) { // replace if ( vec[index] != 0 ) // maybe something there remove_ascii( key ); } // op_insert or op_replace n = new QAsciiBucket(copyk ? qstrdup(key) : key,newItem(d),vec[index]); Q_CHECK_PTR( n ); #if defined(QT_CHECK_NULL) if ( n->getData() == 0 ) qWarning( "QAsciiDict: Cannot insert null item" ); #endif vec[index] = n; numItems++; return n->getData(); } QPtrCollection::Item QGDict::look_int( long key, QPtrCollection::Item d, int op ) { QIntBucket *n; int index = (int)((ulong)key % vlen); // simple hash if ( op == op_find ) { // find for ( n=(QIntBucket*)vec[index]; n; n=(QIntBucket*)n->getNext() ) { if ( n->getKey() == key ) return n->getData(); // item found } return 0; // not found } if ( op == op_replace ) { // replace if ( vec[index] != 0 ) // maybe something there remove_int( key ); } // op_insert or op_replace n = new QIntBucket(key,newItem(d),vec[index]); Q_CHECK_PTR( n ); #if defined(QT_CHECK_NULL) if ( n->getData() == 0 ) qWarning( "QIntDict: Cannot insert null item" ); #endif vec[index] = n; numItems++; return n->getData(); } QPtrCollection::Item QGDict::look_ptr( void *key, QPtrCollection::Item d, int op ) { QPtrBucket *n; int index = (int)((ulong)key % vlen); // simple hash if ( op == op_find ) { // find for ( n=(QPtrBucket*)vec[index]; n; n=(QPtrBucket*)n->getNext() ) { if ( n->getKey() == key ) return n->getData(); // item found } return 0; // not found } if ( op == op_replace ) { // replace if ( vec[index] != 0 ) // maybe something there remove_ptr( key ); } // op_insert or op_replace n = new QPtrBucket(key,newItem(d),vec[index]); Q_CHECK_PTR( n ); #if defined(QT_CHECK_NULL) if ( n->getData() == 0 ) qWarning( "QPtrDict: Cannot insert null item" ); #endif vec[index] = n; numItems++; return n->getData(); } /*! Changes the size of the hashtable to \a newsize. The contents of the dictionary are preserved, but all iterators on the dictionary become invalid. */ void QGDict::resize( uint newsize ) { // Save old information QBaseBucket **old_vec = vec; uint old_vlen = vlen; bool old_copyk = copyk; vec = new QBaseBucket *[vlen = newsize]; Q_CHECK_PTR( vec ); memset( (char*)vec, 0, vlen*sizeof(QBaseBucket*) ); numItems = 0; copyk = FALSE; // Reinsert every item from vec, deleting vec as we go for ( uint index = 0; index < old_vlen; index++ ) { switch ( keytype ) { case StringKey: { QStringBucket *n=(QStringBucket *)old_vec[index]; while ( n ) { look_string( n->getKey(), n->getData(), op_insert ); QStringBucket *t=(QStringBucket *)n->getNext(); delete n; n = t; } } break; case AsciiKey: { QAsciiBucket *n=(QAsciiBucket *)old_vec[index]; while ( n ) { look_ascii( n->getKey(), n->getData(), op_insert ); QAsciiBucket *t=(QAsciiBucket *)n->getNext(); delete n; n = t; } } break; case IntKey: { QIntBucket *n=(QIntBucket *)old_vec[index]; while ( n ) { look_int( n->getKey(), n->getData(), op_insert ); QIntBucket *t=(QIntBucket *)n->getNext(); delete n; n = t; } } break; case PtrKey: { QPtrBucket *n=(QPtrBucket *)old_vec[index]; while ( n ) { look_ptr( n->getKey(), n->getData(), op_insert ); QPtrBucket *t=(QPtrBucket *)n->getNext(); delete n; n = t; } } break; } } delete [] old_vec; // Restore state copyk = old_copyk; // Invalidate all iterators, since order is lost if ( iterators && iterators->count() ) { QGDictIterator *i = iterators->first(); while ( i ) { i->toFirst(); i = iterators->next(); } } } /*! Unlinks the bucket with the specified key (and specified data pointer, if it is set). */ void QGDict::unlink_common( int index, QBaseBucket *node, QBaseBucket *prev ) { if ( iterators && iterators->count() ) { // update iterators QGDictIterator *i = iterators->first(); while ( i ) { // invalidate all iterators if ( i->curNode == node ) // referring to pending node i->operator++(); i = iterators->next(); } } if ( prev ) // unlink node prev->setNext( node->getNext() ); else vec[index] = node->getNext(); numItems--; } QStringBucket *QGDict::unlink_string( const QString &key, QPtrCollection::Item d ) { if ( numItems == 0 ) // nothing in dictionary return 0; QStringBucket *n; QStringBucket *prev = 0; int index = hashKeyString(key) % vlen; if ( cases ) { for ( n=(QStringBucket*)vec[index]; n; n=(QStringBucket*)n->getNext() ) { bool found = (key == n->getKey()); if ( found && d ) found = (n->getData() == d); if ( found ) { unlink_common(index,n,prev); return n; } prev = n; } } else { QString k = key.lower(); for ( n=(QStringBucket*)vec[index]; n; n=(QStringBucket*)n->getNext() ) { bool found = (k == n->getKey().lower()); if ( found && d ) found = (n->getData() == d); if ( found ) { unlink_common(index,n,prev); return n; diff --git a/qmake/tools/qglist.cpp b/qmake/tools/qglist.cpp index 155d585..bd27f8a 100644 --- a/qmake/tools/qglist.cpp +++ b/qmake/tools/qglist.cpp @@ -1,721 +1,717 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QGList and QGListIterator classes ** ** Created : 920624 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qglist.h" #include "qgvector.h" #include "qdatastream.h" #include "qvaluelist.h" /*! \class QLNode qglist.h \reentrant \ingroup collection \brief The QLNode class is an internal class for the QPtrList template collection. \internal QLNode is a doubly-linked list node. It has three pointers: \list 1 \i Pointer to the previous node. \i Pointer to the next node. \i Pointer to the actual data. \endlist It might sometimes be practical to have direct access to the list nodes in a QPtrList, but it is seldom required. Be very careful if you want to access the list nodes. The heap can easily get corrupted if you make a mistake. \sa QPtrList::currentNode(), QPtrList::removeNode(), QPtrList::takeNode() */ /*! \fn QPtrCollection::Item QLNode::getData() Returns a pointer (\c void*) to the actual data in the list node. */ /*! \class QGList qglist.h \reentrant \ingroup collection \brief The QGList class is an internal class for implementing Qt collection classes. \internal QGList is a strictly internal class that acts as a base class for several collection classes; QPtrList, QPtrQueue and QPtrStack. QGList has some virtual functions that can be reimplemented to customize the subclasses, namely compareItems(), read() and write. Normally, you do not have to reimplement any of these functions. If you still want to reimplement them, see the QStrList class (qstrlist.h) for an example. */ /* Internal helper class for QGList. Contains some optimization for the typically case where only one iterators is activre on the list. */ class QGListIteratorList { public: QGListIteratorList() : list(0), iterator(0) { } ~QGListIteratorList() { notifyClear( TRUE ); delete list; } void add( QGListIterator* i ) { if ( !iterator ) { iterator = i; } else if ( list ) { list->push_front( i ); } else { list = new QValueList<QGListIterator*>; list->push_front( i ); } } void remove( QGListIterator* i ) { if ( iterator == i ) { iterator = 0; } else if ( list ) { list->remove( i ); if ( list->isEmpty() ) { delete list; list = 0; } } } void notifyClear( bool zeroList ) { if ( iterator ) { if ( zeroList ) iterator->list = 0; iterator->curNode = 0; } if ( list ) { for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) { if ( zeroList ) (*i)->list = 0; (*i)->curNode = 0; } } } void notifyRemove( QLNode* n, QLNode* curNode ) { if ( iterator ) { if ( iterator->curNode == n ) iterator->curNode = curNode; } if ( list ) { for ( QValueList<QGListIterator*>::Iterator i = list->begin(); i != list->end(); ++i ) { if ( (*i)->curNode == n ) (*i)->curNode = curNode; } } } private: QValueList<QGListIterator*>* list; QGListIterator* iterator; }; /***************************************************************************** Default implementation of virtual functions *****************************************************************************/ /*! Documented as QPtrList::compareItems(). Compares \a item1 with \a item2. */ int QGList::compareItems( QPtrCollection::Item item1, QPtrCollection::Item item2 ) { return item1 != item2; // compare pointers } #ifndef QT_NO_DATASTREAM /*! \overload Reads a collection/list item from the stream \a s and returns a reference to the stream. The default implementation sets \a item to 0. \sa write() */ QDataStream &QGList::read( QDataStream &s, QPtrCollection::Item &item ) { item = 0; return s; } /*! \overload Writes a collection/list item to the stream \a s and returns a reference to the stream. The default implementation does nothing. \sa read() */ QDataStream &QGList::write( QDataStream &s, QPtrCollection::Item ) const { return s; } #endif // QT_NO_DATASTREAM /***************************************************************************** QGList member functions *****************************************************************************/ /*! Constructs an empty list. */ QGList::QGList() { firstNode = lastNode = curNode = 0; // initialize list numNodes = 0; curIndex = -1; iterators = 0; // initialize iterator list } /*! Constructs a copy of \a list. */ QGList::QGList( const QGList & list ) : QPtrCollection( list ) { firstNode = lastNode = curNode = 0; // initialize list numNodes = 0; curIndex = -1; iterators = 0; // initialize iterator list QLNode *n = list.firstNode; while ( n ) { // copy all items from list append( n->data ); n = n->next; } } /*! Removes all items from the list and destroys the list. */ QGList::~QGList() { clear(); delete iterators; // Workaround for GCC 2.7.* bug. Compiler constructs 'static' QGList // instances twice on the same address and therefore tries to destruct // twice on the same address! This is insane but let's try not to crash // here. iterators = 0; } /*! Assigns \a list to this list. */ QGList& QGList::operator=( const QGList &list ) { if ( &list == this ) return *this; clear(); if ( list.count() > 0 ) { QLNode *n = list.firstNode; while ( n ) { // copy all items from list append( n->data ); n = n->next; } curNode = firstNode; curIndex = 0; } return *this; } /*! Compares this list with \a list. Returns TRUE if the lists contain the same data, otherwise FALSE. */ bool QGList::operator==( const QGList &list ) const { if ( count() != list.count() ) return FALSE; if ( count() == 0 ) return TRUE; QLNode *n1 = firstNode; QLNode *n2 = list.firstNode; while ( n1 && n2 ) { // should be mutable if ( ( (QGList*)this )->compareItems( n1->data, n2->data ) != 0 ) return FALSE; n1 = n1->next; n2 = n2->next; } return TRUE; } /*! \fn uint QGList::count() const Returns the number of items in the list. */ /*! Returns the node at position \a index. Sets this node to current. */ QLNode *QGList::locate( uint index ) { if ( index == (uint)curIndex ) // current node ? return curNode; if ( !curNode && firstNode ) { // set current node curNode = firstNode; curIndex = 0; } register QLNode *node; int distance = index - curIndex; // node distance to cur node bool forward; // direction to traverse - if ( index >= numNodes ) { -#if defined(QT_CHECK_RANGE) - qWarning( "QGList::locate: Index %d out of range", index ); -#endif + if ( index >= numNodes ) return 0; - } if ( distance < 0 ) distance = -distance; if ( (uint)distance < index && (uint)distance < numNodes - index ) { node = curNode; // start from current node forward = index > (uint)curIndex; } else if ( index < numNodes - index ) { // start from first node node = firstNode; distance = index; forward = TRUE; } else { // start from last node node = lastNode; distance = numNodes - index - 1; if ( distance < 0 ) distance = 0; forward = FALSE; } if ( forward ) { // now run through nodes while ( distance-- ) node = node->next; } else { while ( distance-- ) node = node->prev; } curIndex = index; // must update index return curNode = node; } /*! Inserts item \a d at its sorted position in the list. */ void QGList::inSort( QPtrCollection::Item d ) { int index = 0; register QLNode *n = firstNode; while ( n && compareItems(n->data,d) < 0 ){ // find position in list n = n->next; index++; } insertAt( index, d ); } /*! Inserts item \a d at the start of the list. */ void QGList::prepend( QPtrCollection::Item d ) { register QLNode *n = new QLNode( newItem(d) ); Q_CHECK_PTR( n ); n->prev = 0; if ( (n->next = firstNode) ) // list is not empty firstNode->prev = n; else // initialize list lastNode = n; firstNode = curNode = n; // curNode affected numNodes++; curIndex = 0; } /*! Inserts item \a d at the end of the list. */ void QGList::append( QPtrCollection::Item d ) { register QLNode *n = new QLNode( newItem(d) ); Q_CHECK_PTR( n ); n->next = 0; if ( (n->prev = lastNode) ) // list is not empty lastNode->next = n; else // initialize list firstNode = n; lastNode = curNode = n; // curNode affected curIndex = numNodes; numNodes++; } /*! Inserts item \a d at position \a index in the list. */ bool QGList::insertAt( uint index, QPtrCollection::Item d ) { if ( index == 0 ) { prepend( d ); return TRUE; } else if ( index == numNodes ) { append( d ); return TRUE; } QLNode *nextNode = locate( index ); if ( !nextNode ) return FALSE; QLNode *prevNode = nextNode->prev; register QLNode *n = new QLNode( newItem(d) ); Q_CHECK_PTR( n ); nextNode->prev = n; prevNode->next = n; n->prev = prevNode; // link new node into list n->next = nextNode; curNode = n; // curIndex set by locate() numNodes++; return TRUE; } /*! Relinks node \a n and makes it the first node in the list. */ void QGList::relinkNode( QLNode *n ) { if ( n == firstNode ) // already first return; curNode = n; unlink(); n->prev = 0; if ( (n->next = firstNode) ) // list is not empty firstNode->prev = n; else // initialize list lastNode = n; firstNode = curNode = n; // curNode affected numNodes++; curIndex = 0; } /*! Unlinks the current list node and returns a pointer to this node. */ QLNode *QGList::unlink() { if ( curNode == 0 ) // null current node return 0; register QLNode *n = curNode; // unlink this node if ( n == firstNode ) { // removing first node ? if ( (firstNode = n->next) ) { firstNode->prev = 0; } else { lastNode = curNode = 0; // list becomes empty curIndex = -1; } } else { if ( n == lastNode ) { // removing last node ? lastNode = n->prev; lastNode->next = 0; } else { // neither last nor first node n->prev->next = n->next; n->next->prev = n->prev; } } if ( n->next ) { // change current node curNode = n->next; } else if ( n->prev ) { curNode = n->prev; curIndex--; } if ( iterators ) iterators->notifyRemove( n, curNode ); numNodes--; return n; } /*! Removes the node \a n from the list. */ bool QGList::removeNode( QLNode *n ) { #if defined(QT_CHECK_NULL) if ( n == 0 || (n->prev && n->prev->next != n) || (n->next && n->next->prev != n) ) { qWarning( "QGList::removeNode: Corrupted node" ); return FALSE; } #endif curNode = n; unlink(); // unlink node deleteItem( n->data ); // deallocate this node delete n; curNode = firstNode; curIndex = curNode ? 0 : -1; return TRUE; } /*! Removes the item \a d from the list. Uses compareItems() to find the item. If \a d is 0, removes the current item. */ bool QGList::remove( QPtrCollection::Item d ) { if ( d && find(d) == -1 ) return FALSE; QLNode *n = unlink(); if ( !n ) return FALSE; deleteItem( n->data ); delete n; return TRUE; } /*! Removes the item \a d from the list. */ bool QGList::removeRef( QPtrCollection::Item d ) { if ( findRef(d) == -1 ) return FALSE; QLNode *n = unlink(); if ( !n ) return FALSE; deleteItem( n->data ); delete n; return TRUE; } /*! \fn bool QGList::removeFirst() Removes the first item in the list. */ /*! \fn bool QGList::removeLast() Removes the last item in the list. */ /*! Removes the item at position \a index from the list. */ bool QGList::removeAt( uint index ) { if ( !locate(index) ) return FALSE; QLNode *n = unlink(); if ( !n ) return FALSE; deleteItem( n->data ); delete n; return TRUE; } /*! Replaces the item at index \a index with \a d. */ bool QGList::replaceAt( uint index, QPtrCollection::Item d ) { QLNode *n = locate( index ); if ( !n ) return FALSE; if ( n->data != d ) { deleteItem( n->data ); n->data = newItem( d ); } return TRUE; } /*! Takes the node \a n out of the list. */ QPtrCollection::Item QGList::takeNode( QLNode *n ) { #if defined(QT_CHECK_NULL) if ( n == 0 || (n->prev && n->prev->next != n) || (n->next && n->next->prev != n) ) { qWarning( "QGList::takeNode: Corrupted node" ); return 0; } #endif curNode = n; unlink(); // unlink node Item d = n->data; delete n; // delete the node, not data curNode = firstNode; curIndex = curNode ? 0 : -1; return d; } /*! Takes the current item out of the list. */ QPtrCollection::Item QGList::take() { QLNode *n = unlink(); // unlink node Item d = n ? n->data : 0; delete n; // delete node, keep contents return d; } /*! Takes the item at position \a index out of the list. */ QPtrCollection::Item QGList::takeAt( uint index ) { if ( !locate(index) ) return 0; QLNode *n = unlink(); // unlink node Item d = n ? n->data : 0; delete n; // delete node, keep contents return d; } /*! Takes the first item out of the list. */ QPtrCollection::Item QGList::takeFirst() { first(); QLNode *n = unlink(); // unlink node Item d = n ? n->data : 0; delete n; return d; } /*! Takes the last item out of the list. */ QPtrCollection::Item QGList::takeLast() { last(); QLNode *n = unlink(); // unlink node Item d = n ? n->data : 0; delete n; return d; } /*! Removes all items from the list. */ void QGList::clear() { register QLNode *n = firstNode; firstNode = lastNode = curNode = 0; // initialize list numNodes = 0; curIndex = -1; if ( iterators ) iterators->notifyClear( FALSE ); QLNode *prevNode; while ( n ) { // for all nodes ... deleteItem( n->data ); // deallocate data prevNode = n; n = n->next; delete prevNode; // deallocate node } } /*! Finds item \a d in the list. If \a fromStart is TRUE the search begins at the first node; otherwise it begins at the current node. */ int QGList::findRef( QPtrCollection::Item d, bool fromStart ) { register QLNode *n; int index; diff --git a/qmake/tools/qglobal.cpp b/qmake/tools/qglobal.cpp index 47cd6bd..342005d 100644 --- a/qmake/tools/qglobal.cpp +++ b/qmake/tools/qglobal.cpp @@ -1,835 +1,868 @@ /**************************************************************************** ** $Id$ ** ** Global functions ** ** Created : 920604 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include "qasciidict.h" #include <limits.h> #include <stdio.h> #include <limits.h> #include <stdarg.h> #include <stdlib.h> /*! \relates QApplication Returns the Qt version number as a string, for example, "2.3.0" or "3.0.5". The \c QT_VERSION define has the numeric value in the form: 0xmmiibb (m = major, i = minor, b = bugfix). For example, Qt 3.0.5's \c QT_VERSION is 0x030005. */ const char *qVersion() { return QT_VERSION_STR; } /***************************************************************************** System detection routines *****************************************************************************/ static bool si_alreadyDone = FALSE; static int si_wordSize; static bool si_bigEndian; /*! \relates QApplication Obtains information about the system. The system's word size in bits (typically 32) is returned in \a *wordSize. The \a *bigEndian is set to TRUE if this is a big-endian machine, or to FALSE if this is a little-endian machine. In debug mode, this function calls qFatal() with a message if the computer is truly weird (i.e. different endianness for 16 bit and 32 bit integers); in release mode it returns FALSE. */ bool qSysInfo( int *wordSize, bool *bigEndian ) { #if defined(QT_CHECK_NULL) Q_ASSERT( wordSize != 0 ); Q_ASSERT( bigEndian != 0 ); #endif if ( si_alreadyDone ) { // run it only once *wordSize = si_wordSize; *bigEndian = si_bigEndian; return TRUE; } si_wordSize = 0; Q_ULONG n = (Q_ULONG)(~0); while ( n ) { // detect word size si_wordSize++; n /= 2; } *wordSize = si_wordSize; if ( *wordSize != 64 && *wordSize != 32 && *wordSize != 16 ) { // word size: 16, 32 or 64 #if defined(QT_CHECK_RANGE) qFatal( "qSysInfo: Unsupported system word size %d", *wordSize ); #endif return FALSE; } if ( sizeof(Q_INT8) != 1 || sizeof(Q_INT16) != 2 || sizeof(Q_INT32) != 4 || sizeof(Q_ULONG)*8 != si_wordSize || sizeof(float) != 4 || sizeof(double) != 8 ) { #if defined(QT_CHECK_RANGE) qFatal( "qSysInfo: Unsupported system data type size" ); #endif return FALSE; } bool be16, be32; // determine byte ordering short ns = 0x1234; int nl = 0x12345678; unsigned char *p = (unsigned char *)(&ns); // 16-bit integer be16 = *p == 0x12; p = (unsigned char *)(&nl); // 32-bit integer if ( p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78 ) be32 = TRUE; else if ( p[0] == 0x78 && p[1] == 0x56 && p[2] == 0x34 && p[3] == 0x12 ) be32 = FALSE; else be32 = !be16; if ( be16 != be32 ) { // strange machine! #if defined(QT_CHECK_RANGE) qFatal( "qSysInfo: Inconsistent system byte order" ); #endif return FALSE; } *bigEndian = si_bigEndian = be32; si_alreadyDone = TRUE; return TRUE; } -#if defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN) +#if !defined(QWS) && defined(Q_OS_MAC) + +#include "qt_mac.h" + +int qMacVersion() +{ + static int macver = Qt::MV_Unknown; + static bool first = TRUE; + if(first) { + first = FALSE; + long gestalt_version; + if(Gestalt(gestaltSystemVersion, &gestalt_version) == noErr) { + if(gestalt_version >= 0x1020 && gestalt_version < 0x1030) + macver = Qt::MV_10_DOT_2; + else if(gestalt_version >= 0x1010 && gestalt_version < 0x1020) + macver = Qt::MV_10_DOT_1; + } + } + return macver; +} +Qt::MacintoshVersion qt_macver = (Qt::MacintoshVersion)qMacVersion(); +#elif defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN) bool qt_winunicode; #include "qt_windows.h" int qWinVersion() { #ifndef VER_PLATFORM_WIN32s #define VER_PLATFORM_WIN32s 0 #endif #ifndef VER_PLATFORM_WIN32_WINDOWS #define VER_PLATFORM_WIN32_WINDOWS 1 #endif #ifndef VER_PLATFORM_WIN32_NT #define VER_PLATFORM_WIN32_NT 2 #endif static int winver = Qt::WV_NT; static int t=0; if ( !t ) { t=1; #ifdef Q_OS_TEMP OSVERSIONINFOW osver; osver.dwOSVersionInfoSize = sizeof(osver); GetVersionEx( &osver ); #else OSVERSIONINFOA osver; osver.dwOSVersionInfoSize = sizeof(osver); GetVersionExA( &osver ); #endif switch ( osver.dwPlatformId ) { case VER_PLATFORM_WIN32s: winver = Qt::WV_32s; break; case VER_PLATFORM_WIN32_WINDOWS: // We treat Windows Me (minor 90) the same as Windows 98 if ( ( osver.dwMinorVersion == 10 ) || ( osver.dwMinorVersion == 90 ) ) winver = Qt::WV_98; else winver = Qt::WV_95; break; default: // VER_PLATFORM_WIN32_NT if ( osver.dwMajorVersion < 5 ) { winver = Qt::WV_NT; } else if ( osver.dwMinorVersion == 0 ) { winver = Qt::WV_2000; } else { winver = Qt::WV_XP; } } } #if defined(UNICODE) if ( winver & Qt::WV_NT_based ) qt_winunicode = TRUE; else #endif qt_winunicode = FALSE; return winver; } Qt::WindowsVersion qt_winver = (Qt::WindowsVersion)qWinVersion(); #endif /***************************************************************************** Debug output routines *****************************************************************************/ /*! \fn void qDebug( const char *msg, ... ) \relates QApplication Prints a debug message \a msg, or calls the message handler (if it has been installed). This function takes a format string and a list of arguments, similar to the C printf() function. Example: \code qDebug( "my window handle = %x", myWidget->id() ); \endcode Under X11, the text is printed to stderr. Under Windows, the text is sent to the debugger. \warning The internal buffer is limited to 8196 bytes (including the '\0'-terminator). \warning Passing (const char *)0 as argument to qDebug might lead to crashes on certain platforms due to the platforms printf implementation. \sa qWarning(), qFatal(), qInstallMsgHandler(), \link debug.html Debugging\endlink */ /*! \fn void qWarning( const char *msg, ... ) \relates QApplication Prints a warning message \a msg, or calls the message handler (if it has been installed). This function takes a format string and a list of arguments, similar to the C printf() function. Example: \code void f( int c ) { if ( c > 200 ) qWarning( "f: bad argument, c == %d", c ); } \endcode Under X11, the text is printed to stderr. Under Windows, the text is sent to the debugger. \warning The internal buffer is limited to 8196 bytes (including the '\0'-terminator). \warning Passing (const char *)0 as argument to qWarning might lead to crashes on certain platforms due to the platforms printf implementation. \sa qDebug(), qFatal(), qInstallMsgHandler(), \link debug.html Debugging\endlink */ /*! \fn void qFatal( const char *msg, ... ) \relates QApplication Prints a fatal error message \a msg and exits, or calls the message handler (if it has been installed). This function takes a format string and a list of arguments, similar to the C printf() function. Example: \code int divide( int a, int b ) { if ( b == 0 ) // program error qFatal( "divide: cannot divide by zero" ); return a/b; } \endcode Under X11, the text is printed to stderr. Under Windows, the text is sent to the debugger. \warning The internal buffer is limited to 8196 bytes (including the '\0'-terminator). \warning Passing (const char *)0 as argument to qFatal might lead to crashes on certain platforms due to the platforms printf implementation. \sa qDebug(), qWarning(), qInstallMsgHandler(), \link debug.html Debugging\endlink */ static QtMsgHandler handler = 0; // pointer to debug handler static const int QT_BUFFER_LENGTH = 8196; // internal buffer length #ifdef Q_OS_MAC -const unsigned char * p_str(const char * c, int len=-1) +QString cfstring2qstring(CFStringRef str) +{ + CFIndex length = CFStringGetLength(str); + if(const UniChar *chars = CFStringGetCharactersPtr(str)) + return QString((QChar *)chars, length); + UniChar *buffer = (UniChar*)malloc(length * sizeof(UniChar)); + CFStringGetCharacters(str, CFRangeMake(0, length), buffer); + QString ret((QChar *)buffer, length); + free(buffer); + return ret; +} + +unsigned char * p_str(const char * c, int len=-1) { const int maxlen = 255; if(len == -1) len = qstrlen(c); if(len > maxlen) { qWarning( "p_str len must never exceed %d", maxlen ); len = maxlen; } unsigned char *ret = (unsigned char*)malloc(len+2); *ret=len; memcpy(((char *)ret)+1,c,len); *(ret+len+1) = '\0'; return ret; } -const unsigned char * p_str(const QString &s) +unsigned char * p_str(const QString &s) { return p_str(s, s.length()); } QCString p2qstring(const unsigned char *c) { char *arr = (char *)malloc(c[0] + 1); memcpy(arr, c+1, c[0]); arr[c[0]] = '\0'; QCString ret = arr; delete arr; return ret; } #endif #ifdef Q_CC_MWERKS #include "qt_mac.h" extern bool qt_is_gui_used; static void mac_default_handler( const char *msg ) { if ( qt_is_gui_used ) { const char *p = p_str(msg); DebugStr(p); free(p); } else { fprintf( stderr, msg ); } } #endif void qDebug( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtDebugMsg, buf ); } else { #if defined(Q_CC_MWERKS) vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif } } // copied... this looks really bad. void debug( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtDebugMsg, buf ); } else { #ifdef Q_CC_MWERKS vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif } } void qWarning( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtWarningMsg, buf ); } else { #ifdef Q_CC_MWERKS vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif } } // again, copied void warning( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtWarningMsg, buf ); } else { #ifdef Q_CC_MWERKS vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif } } void qFatal( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtFatalMsg, buf ); } else { #ifdef Q_CC_MWERKS vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif #if defined(Q_OS_UNIX) && defined(QT_DEBUG) abort(); // trap; generates core dump #else exit( 1 ); // goodbye cruel world #endif } } // yet again, copied void fatal( const char *msg, ... ) { char buf[QT_BUFFER_LENGTH]; va_list ap; va_start( ap, msg ); // use variable arg list if ( handler ) { #if defined(QT_VSNPRINTF) QT_VSNPRINTF( buf, QT_BUFFER_LENGTH, msg, ap ); #else vsprintf( buf, msg, ap ); #endif va_end( ap ); (*handler)( QtFatalMsg, buf ); } else { #ifdef Q_CC_MWERKS vsprintf( buf, msg, ap ); // ### is there no vsnprintf()? va_end( ap ); mac_default_handler(buf); #else vfprintf( stderr, msg, ap ); va_end( ap ); fprintf( stderr, "\n" ); // add newline #endif #if defined(Q_OS_UNIX) && defined(QT_DEBUG) abort(); // trap; generates core dump #else exit( 1 ); // goodbye cruel world #endif } } /*! \relates QApplication Prints the message \a msg and uses \a code to get a system specific error message. When \a code is -1 (the default), the system's last error code will be used if possible. Use this method to handle failures in platform specific API calls. This function does nothing when Qt is built with \c QT_NO_DEBUG defined. */ void qSystemWarning( const char* msg, int code ) { #ifndef QT_NO_DEBUG #if defined(Q_OS_WIN32) if ( code == -1 ) code = GetLastError(); if ( !code ) return; #ifdef Q_OS_TEMP unsigned short *string; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&string, 0, NULL ); qWarning( "%s\n\tError code %d - %s (###may need fixing in qglobal.h)", msg, code, (const char *)string ); #else char* string; FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&string, 0, NULL ); qWarning( "%s\n\tError code %d - %s", msg, code, (const char*)string ); #endif LocalFree( (HLOCAL)string ); #else if ( code != -1 ) qWarning( "%s\n\tError code %d - %s", msg, code, strerror( code ) ); else qWarning( msg ); #endif #endif } /*! \fn void Q_ASSERT( bool test ) \relates QApplication Prints a warning message containing the source code file name and line number if \a test is FALSE. This is really a macro defined in \c qglobal.h. Q_ASSERT is useful for testing pre- and post-conditions. Example: \code // // File: div.cpp // #include <qglobal.h> int divide( int a, int b ) { Q_ASSERT( b != 0 ); // this is line 9 return a/b; } \endcode If \c b is zero, the Q_ASSERT statement will output the following message using the qWarning() function: \code ASSERT: "b == 0" in div.cpp (9) \endcode \sa qWarning(), \link debug.html Debugging\endlink */ /*! \fn void Q_CHECK_PTR( void *p ) \relates QApplication - If \a p is null, a fatal messages says that the program ran out of - memory and exits. If \e p is not null, nothing happens. + If \a p is 0, a fatal messages says that the program ran out of + memory and exits. If \e p is not 0, nothing happens. This is really a macro defined in \c qglobal.h. Example: \code int *a; Q_CHECK_PTR( a = new int[80] ); // WRONG! - a = new int[80]; // Right + a = new (nothrow) int[80]; // Right Q_CHECK_PTR( a ); \endcode \sa qFatal(), \link debug.html Debugging\endlink */ // // The Q_CHECK_PTR macro calls this function to check if an allocation went ok. // #if (QT_VERSION-0 >= 0x040000) #if defined(Q_CC_GNU) #warning "Change Q_CHECK_PTR to '{if ((p)==0) qt_check_pointer(__FILE__,__LINE__);}'" #warning "No need for qt_check_pointer() to return a value - make it void!" #endif #endif bool qt_check_pointer( bool c, const char *n, int l ) { if ( c ) qWarning( "In file %s, line %d: Out of memory", n, l ); return TRUE; } static bool firstObsoleteWarning(const char *obj, const char *oldfunc ) { static QAsciiDict<int> *obsoleteDict = 0; if ( !obsoleteDict ) { // first time func is called obsoleteDict = new QAsciiDict<int>; #if defined(QT_DEBUG) qDebug( "You are using obsolete functions in the Qt library. Call the function\n" "qSuppressObsoleteWarnings() to suppress obsolete warnings.\n" ); #endif } QCString s( obj ); s += "::"; s += oldfunc; if ( obsoleteDict->find(s.data()) == 0 ) { obsoleteDict->insert( s.data(), (int*)1 ); // anything different from 0 return TRUE; } return FALSE; } static bool suppressObsolete = FALSE; void qSuppressObsoleteWarnings( bool suppress ) { suppressObsolete = suppress; } void qObsolete( const char *obj, const char *oldfunc, const char *newfunc ) { if ( suppressObsolete ) return; if ( !firstObsoleteWarning(obj, oldfunc) ) return; if ( obj ) qDebug( "%s::%s: This function is obsolete, use %s instead.", obj, oldfunc, newfunc ); else qDebug( "%s: This function is obsolete, use %s instead.", oldfunc, newfunc ); } void qObsolete( const char *obj, const char *oldfunc ) { if ( suppressObsolete ) return; if ( !firstObsoleteWarning(obj, oldfunc) ) return; if ( obj ) qDebug( "%s::%s: This function is obsolete.", obj, oldfunc ); else qDebug( "%s: This function is obsolete.", oldfunc ); } void qObsolete( const char *message ) { if ( suppressObsolete ) return; if ( !firstObsoleteWarning( "Qt", message) ) return; qDebug( "%s", message ); } /*! \relates QApplication Installs a Qt message handler \a h. Returns a pointer to the message handler previously defined. The message handler is a function that prints out debug messages, warnings and fatal error messages. The Qt library (debug version) contains hundreds of warning messages that are printed when internal errors (usually invalid function arguments) occur. If you implement your own message handler, you get total control of these messages. The default message handler prints the message to the standard output under X11 or to the debugger under Windows. If it is a fatal message, the application aborts immediately. Only one message handler can be defined, since this is usually done on an application-wide basis to control debug output. To restore the message handler, call \c qInstallMsgHandler(0). Example: \code #include <qapplication.h> #include <stdio.h> #include <stdlib.h> void myMessageOutput( QtMsgType type, const char *msg ) { switch ( type ) { case QtDebugMsg: fprintf( stderr, "Debug: %s\n", msg ); break; case QtWarningMsg: fprintf( stderr, "Warning: %s\n", msg ); break; case QtFatalMsg: fprintf( stderr, "Fatal: %s\n", msg ); abort(); // deliberately core dump } } int main( int argc, char **argv ) { qInstallMsgHandler( myMessageOutput ); QApplication a( argc, argv ); ... return a.exec(); } \endcode \sa qDebug(), qWarning(), qFatal(), \link debug.html Debugging\endlink */ QtMsgHandler qInstallMsgHandler( QtMsgHandler h ) { QtMsgHandler old = handler; handler = h; return old; } /* Dijkstra's bisection algorithm to find the square root as an integer. Deliberately not exported as part of the Qt API, but used in both qsimplerichtext.cpp and qgfxraster_qws.cpp */ unsigned int qt_int_sqrt( unsigned int n ) { // n must be in the range 0...UINT_MAX/2-1 if ( n >= ( UINT_MAX>>2 ) ) { unsigned int r = 2 * qt_int_sqrt( n / 4 ); unsigned int r2 = r + 1; return ( n >= r2 * r2 ) ? r2 : r; } uint h, p= 0, q= 1, r= n; while ( q <= n ) q <<= 2; while ( q != 1 ) { q >>= 2; h= p + q; p >>= 1; if ( r >= h ) { p += q; r -= h; } } return p; } diff --git a/qmake/tools/qgpluginmanager.cpp b/qmake/tools/qgpluginmanager.cpp index 46c85f5..72246ac 100644 --- a/qmake/tools/qgpluginmanager.cpp +++ b/qmake/tools/qgpluginmanager.cpp @@ -1,544 +1,544 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QGPluginManager class ** -** Copyright (C) 2000-2001 Trolltech AS. All rights reserved. +** Copyright (C) 2000-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qgpluginmanager_p.h" #ifndef QT_NO_COMPONENT #include "qcomlibrary_p.h" #include "qmap.h" #include "qdir.h" /* The following co-occurrence code is borrowed from Qt Linguist. How similar are two texts? The approach used here relies on co-occurrence matrices and is very efficient. Let's see with an example: how similar are "here" and "hither"? The co-occurrence matrix M for "here" is M[h,e] = 1, M[e,r] = 1, M[r,e] = 1 and 0 elsewhere; the matrix N for "hither" is N[h,i] = 1, N[i,t] = 1, ..., N[h,e] = 1, N[e,r] = 1 and 0 elsewhere. The union U of both matrices is the matrix U[i,j] = max { M[i,j], N[i,j] }, and the intersection V is V[i,j] = min { M[i,j], N[i,j] }. The score for a pair of texts is score = (sum of V[i,j] over all i, j) / (sum of U[i,j] over all i, j), a formula suggested by Arnt Gulbrandsen. Here we have score = 2 / 6, or one third. The implementation differs from this in a few details. Most importantly, repetitions are ignored; for input "xxx", M[x,x] equals 1, not 2. */ /* Every character is assigned to one of 20 buckets so that the co-occurrence matrix requires only 20 * 20 = 400 bits, not 256 * 256 = 65536 bits or even more if we want the whole Unicode. Which character falls in which bucket is arbitrary. The second half of the table is a replica of the first half, because of laziness. */ static const char indexOf[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ! " # $ % & ' ( ) * + , - . / 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, // @ A B C D E F G H I J K L M N O 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, // P Q R S T U V W X Y Z [ \ ] ^ _ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, // ` a b c d e f g h i j k l m n o 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, // p q r s t u v w x y z { | } ~ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0 }; /* The entry bitCount[i] (for i between 0 and 255) is the number of bits used to represent i in binary. */ static const char bitCount[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; class QCoMatrix { public: /* The matrix has 20 * 20 = 400 entries. This requires 50 bytes, or 13 words. Some operations are performed on words for more efficiency. */ union { Q_UINT8 b[52]; Q_UINT32 w[13]; }; QCoMatrix() { memset( b, 0, 52 ); } QCoMatrix( const char *text ) { char c = '\0', d; memset( b, 0, 52 ); while ( (d = *text) != '\0' ) { setCoocc( c, d ); if ( (c = *++text) != '\0' ) { setCoocc( d, c ); text++; } } } void setCoocc( char c, char d ) { int k = indexOf[(uchar) c] + 20 * indexOf[(uchar) d]; b[k >> 3] |= k & 0x7; } int worth() const { int result = 0; for ( int i = 0; i < 50; i++ ) result += bitCount[b[i]]; return result; } static QCoMatrix reunion( const QCoMatrix& m, const QCoMatrix& n ) { QCoMatrix p; for ( int i = 0; i < 13; i++ ) p.w[i] = m.w[i] | n.w[i]; return p; } static QCoMatrix intersection( const QCoMatrix& m, const QCoMatrix& n ) { QCoMatrix p; for ( int i = 0; i < 13; i++ ) p.w[i] = m.w[i] & n.w[i]; return p; } }; /* Returns an integer between 0 (dissimilar) and 15 (very similar) depending on how similar the string is to \a target. This function is efficient, but its results might change in future versions of Qt as the algorithm evolves. \code QString s( "color" ); a = similarity( s, "color" ); // a == 15 a = similarity( s, "colour" ); // a == 8 a = similarity( s, "flavor" ); // a == 4 a = similarity( s, "dahlia" ); // a == 0 \endcode */ static int similarity( const QString& s1, const QString& s2 ) { QCoMatrix m1( s1 ); QCoMatrix m2( s2 ); return ( 15 * (QCoMatrix::intersection(m1, m2).worth() + 1) ) / ( QCoMatrix::reunion(m1, m2).worth() + 1 ); } /*! \class QPluginManager qpluginmanager.h \reentrant \brief The QPluginManager class provides basic functions to access a certain kind of functionality in libraries. \ingroup componentmodel \internal A common usage of components is to extend the existing functionality in an application using plugins. The application defines interfaces that abstract a certain group of functionality, and a plugin provides a specialized implementation of one or more of those interfaces. The QPluginManager template has to be instantiated with an interface definition and the IID for this interface. \code QPluginManager<MyPluginInterface> *manager = new QPluginManager<MyPluginInterface>( IID_MyPluginInterface ); \endcode It searches a specified directory for all shared libraries, queries for components that implement the specific interface and reads information about the features the plugin wants to add to the application. The component can provide the set of features provided by implementing either the QFeatureListInterface or the QComponentInformationInterface. The strings returned by the implementations of \code QStringList QFeatureListInterface::featureList() const \endcode or \code QString QComponentInformationInterface::name() const \endcode respectively, can then be used to access the component that provides the requested feature: \code MyPluginInterface *iface; manager->queryInterface( "feature", &iface ); if ( iface ) iface->execute( "feature" ); \endcode The application can use a QPluginManager instance to create parts of the user interface based on the list of features found in plugins: \code QPluginManager<MyPluginInterface> *manager = new QPluginManager<MyPluginInterface>( IID_ImageFilterInterface ); manager->addLibraryPath(...); QStringList features = manager->featureList(); for ( QStringList::Iterator it = features.begin(); it != features.end(); ++it ) { MyPluginInterface *iface; manager->queryInterface( *it, &iface ); // use QAction to provide toolbuttons and menuitems for each feature... } \endcode */ /*! \fn QPluginManager::QPluginManager( const QUuid& id, const QStringList& paths = QString::null, const QString &suffix = QString::null, bool cs = TRUE ) Creates an QPluginManager for interfaces \a id that will load all shared library files in the \a paths + \a suffix. If \a cs is FALSE the manager will handle feature strings case insensitive. \warning Setting the cs flag to FALSE requires that components also convert to lower case when comparing with passed strings, so this has to be handled with care and documented very well. \sa QApplication::libraryPaths() */ /*! \fn QRESULT QPluginManager::queryInterface(const QString& feature, Type** iface) const Sets \a iface to point to the interface providing \a feature. \sa featureList(), library() */ #include <qptrlist.h> QGPluginManager::QGPluginManager( const QUuid& id, const QStringList& paths, const QString &suffix, bool cs ) : interfaceId( id ), plugDict( 17, cs ), casesens( cs ), autounload( TRUE ) { // Every QLibrary object is destroyed on destruction of the manager libDict.setAutoDelete( TRUE ); for ( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) { QString path = *it; addLibraryPath( path + suffix ); } } QGPluginManager::~QGPluginManager() { if ( !autounload ) { QDictIterator<QLibrary> it( libDict ); while ( it.current() ) { QLibrary *lib = it.current(); ++it; lib->setAutoUnload( FALSE ); } } } void QGPluginManager::addLibraryPath( const QString& path ) { if ( !enabled() || !QDir( path ).exists( ".", TRUE ) ) return; #if defined(Q_OS_WIN32) QString filter = "dll"; #elif defined(Q_OS_MACX) QString filter = "dylib"; #elif defined(Q_OS_UNIX) QString filter = "so"; #endif QStringList plugins = QDir(path).entryList( "*." + filter ); for ( QStringList::Iterator p = plugins.begin(); p != plugins.end(); ++p ) { QString lib = QDir::cleanDirPath( path + "/" + *p ); if ( libList.contains( lib ) ) continue; libList.append( lib ); } } const QLibrary* QGPluginManager::library( const QString& feature ) const { if ( !enabled() || feature.isEmpty() ) return 0; // We already have a QLibrary object for this feature QLibrary *library = 0; if ( ( library = plugDict[feature] ) ) return library; // Find the filename that matches the feature request best QMap<int, QStringList> map; QStringList::ConstIterator it = libList.begin(); int best = 0; int worst = 15; while ( it != libList.end() ) { if ( (*it).isEmpty() || libDict[*it] ) { ++it; continue; } QString basename = QFileInfo(*it).baseName(); int s = similarity( feature, basename ); if ( s < worst ) worst = s; if ( s > best ) best = s; map[s].append( basename + QChar(0xfffd) + *it ); ++it; } if ( map.isEmpty() ) return 0; // no libraries to add // Start with the best match to get the library object QGPluginManager *that = (QGPluginManager*)this; for ( int s = best; s >= worst; --s ) { QStringList group = map[s]; group.sort(); // sort according to the base name QStringList::ConstIterator git = group.begin(); while ( git != group.end() ) { QString lib = (*git).mid( (*git).find( QChar(0xfffd) ) + 1 ); QString basename = (*git).left( (*git).find( QChar(0xfffd) ) ); ++git; QStringList sameBasename; while( git != group.end() && basename == (*git).left( (*git).find( QChar(0xfffd) ) ) ) { sameBasename << (*git).mid( (*git).find( QChar(0xfffd) ) + 1 ); ++git; } if ( sameBasename.isEmpty() ) { that->addLibrary( new QComLibrary( lib ) ); } else { QPtrList<QComLibrary> same; same.setAutoDelete( TRUE ); for ( QStringList::ConstIterator bit = sameBasename.begin(); bit != sameBasename.end(); ++bit ) same.append( new QComLibrary( *bit ) ); QComLibrary* bestMatch = 0; for ( QComLibrary* candidate = same.first(); candidate; candidate = same.next() ) if ( candidate->qtVersion() && candidate->qtVersion() <= QT_VERSION && ( !bestMatch || candidate->qtVersion() > bestMatch->qtVersion() ) ) bestMatch = candidate; if ( bestMatch ) { same.find( bestMatch ); that->addLibrary( same.take() ); } } if ( ( library = that->plugDict[feature] ) ) return library; } } return 0; } QStringList QGPluginManager::featureList() const { QStringList features; if ( !enabled() ) return features; QGPluginManager *that = (QGPluginManager*)this; QStringList theLibs = libList; QStringList phase2Libs; QStringList phase2Deny; /* In order to get the feature list we need to add all interesting libraries. If there are libraries with the same base name, we prioritze the one that fits our Qt version number and ignore the others */ QStringList::Iterator it; for ( it = theLibs.begin(); it != theLibs.end(); ++it ) { if ( (*it).isEmpty() || libDict[*it] ) continue; QComLibrary* library = new QComLibrary( *it ); if ( library->qtVersion() == QT_VERSION ) { that->addLibrary( library ); phase2Deny << QFileInfo( *it ).baseName(); } else { delete library; phase2Libs << *it; } } for ( it = phase2Libs.begin(); it != phase2Libs.end(); ++it ) if ( !phase2Deny.contains( QFileInfo( *it ).baseName() ) ) that->addLibrary( new QComLibrary( *it ) ); for ( QDictIterator<QLibrary> pit( plugDict ); pit.current(); ++pit ) features << pit.currentKey(); return features; } bool QGPluginManager::addLibrary( QLibrary* lib ) { if ( !enabled() || !lib ) return FALSE; QComLibrary* plugin = (QComLibrary*)lib; bool useful = FALSE; QUnknownInterface* iFace = 0; plugin->queryInterface( interfaceId, &iFace ); if ( iFace ) { QFeatureListInterface *fliFace = 0; QComponentInformationInterface *cpiFace = 0; iFace->queryInterface( IID_QFeatureList, (QUnknownInterface**)&fliFace ); if ( !fliFace ) plugin->queryInterface( IID_QFeatureList, (QUnknownInterface**)&fliFace ); if ( !fliFace ) { iFace->queryInterface( IID_QComponentInformation, (QUnknownInterface**)&cpiFace ); if ( !cpiFace ) plugin->queryInterface( IID_QComponentInformation, (QUnknownInterface**)&cpiFace ); } QStringList fl; if ( fliFace ) // Map all found features to the library fl = fliFace->featureList(); else if ( cpiFace ) fl << cpiFace->name(); - for ( QStringList::Iterator f = fl.begin(); f != fl.end(); f++ ) { + for ( QStringList::Iterator f = fl.begin(); f != fl.end(); ++f ) { QLibrary *old = plugDict[*f]; if ( !old ) { useful = TRUE; plugDict.replace( *f, plugin ); } else { // we have old *and* plugin, which one to pick? QComLibrary* first = (QComLibrary*)old; QComLibrary* second = (QComLibrary*)plugin; bool takeFirst = TRUE; if ( first->qtVersion() != QT_VERSION ) { if ( second->qtVersion() == QT_VERSION ) takeFirst = FALSE; else if ( second->qtVersion() < QT_VERSION && first->qtVersion() > QT_VERSION ) takeFirst = FALSE; } if ( !takeFirst ) { useful = TRUE; plugDict.replace( *f, plugin ); qWarning("%s: Discarding feature %s in %s!", (const char*) QFile::encodeName( plugin->library()), (*f).latin1(), (const char*) QFile::encodeName( old->library() ) ); } else { qWarning("%s: Feature %s already defined in %s!", (const char*) QFile::encodeName( old->library() ), (*f).latin1(), (const char*) QFile::encodeName( plugin->library() ) ); } } } if ( fliFace ) fliFace->release(); if ( cpiFace ) cpiFace->release(); iFace->release(); } if ( useful ) { libDict.replace( plugin->library(), plugin ); if ( !libList.contains( plugin->library() ) ) libList.append( plugin->library() ); return TRUE; } delete plugin; return FALSE; } bool QGPluginManager::enabled() const { #ifdef QT_SHARED return TRUE; #else return FALSE; #endif } QRESULT QGPluginManager::queryUnknownInterface(const QString& feature, QUnknownInterface** iface) const { QComLibrary* plugin = 0; plugin = (QComLibrary*)library( feature ); return plugin ? plugin->queryInterface( interfaceId, (QUnknownInterface**)iface ) : QE_NOINTERFACE; } #endif //QT_NO_COMPONENT diff --git a/qmake/tools/qgvector.cpp b/qmake/tools/qgvector.cpp index 1985f03..3c903ed 100644 --- a/qmake/tools/qgvector.cpp +++ b/qmake/tools/qgvector.cpp @@ -1,584 +1,591 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QGVector class ** ** Created : 930907 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ +#include "qglobal.h" +#if defined(Q_CC_BOR) +// needed for qsort() because of a std namespace problem on Borland +#include "qplatformdefs.h" +#endif + #define QGVECTOR_CPP #include "qgvector.h" #include "qglist.h" #include "qstring.h" #include "qdatastream.h" #include <stdlib.h> #ifdef QT_THREAD_SUPPORT # include <private/qmutexpool_p.h> #endif // QT_THREAD_SUPPORT #define USE_MALLOC // comment to use new/delete #undef NEW #undef DELETE #if defined(USE_MALLOC) #define NEW(type,size) ((type*)malloc(size*sizeof(type))) #define DELETE(array) (free((char*)array)) #else #define NEW(type,size) (new type[size]) #define DELETE(array) (delete[] array) #define DONT_USE_REALLOC // comment to use realloc() #endif /*! \class QGVector \reentrant \ingroup collection \brief The QGVector class is an internal class for implementing Qt collection classes. \internal QGVector is an internal class that acts as a base class for the QPtrVector collection class. QGVector has some virtual functions that may be reimplemented in subclasses to customize behavior. \list \i compareItems() compares two collection/vector items. \i read() reads a collection/vector item from a QDataStream. \i write() writes a collection/vector item to a QDataStream. \endlist */ /***************************************************************************** Default implementation of virtual functions *****************************************************************************/ /*! This virtual function compares two list items. Returns: <ul> <li> 0 if \a d1 == \a d2 <li> non-zero if \a d1 != \a d2 </ul> This function returns \e int rather than \e bool so that reimplementations can return one of three values and use it to sort by: <ul> <li> 0 if \a d1 == \a d2 <li> \> 0 (positive integer) if \a d1 \> \a d2 <li> \< 0 (negative integer) if \a d1 \< \a d2 </ul> The QPtrVector::sort() and QPtrVector::bsearch() functions require that compareItems() is implemented as described here. This function should not modify the vector because some const functions call compareItems(). */ int QGVector::compareItems( Item d1, Item d2 ) { return d1 != d2; // compare pointers } #ifndef QT_NO_DATASTREAM /*! Reads a collection/vector item from the stream \a s and returns a reference to the stream. The default implementation sets \a d to 0. \sa write() */ QDataStream &QGVector::read( QDataStream &s, Item &d ) { // read item from stream d = 0; return s; } /*! Writes a collection/vector item to the stream \a s and returns a reference to the stream. The default implementation does nothing. \sa read() */ QDataStream &QGVector::write( QDataStream &s, Item ) const { // write item to stream return s; } #endif // QT_NO_DATASTREAM /***************************************************************************** QGVector member functions *****************************************************************************/ QGVector::QGVector() // create empty vector { vec = 0; len = numItems = 0; } QGVector::QGVector( uint size ) // create vectors with nullptrs { len = size; numItems = 0; if ( len == 0 ) { // zero length vec = 0; return; } vec = NEW(Item,len); Q_CHECK_PTR( vec ); memset( (void*)vec, 0, len*sizeof(Item) ); // fill with nulls } QGVector::QGVector( const QGVector &a ) // make copy of other vector : QPtrCollection( a ) { len = a.len; numItems = a.numItems; if ( len == 0 ) { vec = 0; return; } vec = NEW( Item, len ); Q_CHECK_PTR( vec ); for ( uint i = 0; i < len; i++ ) { if ( a.vec[i] ) { vec[i] = newItem( a.vec[i] ); Q_CHECK_PTR( vec[i] ); } else { vec[i] = 0; } } } QGVector::~QGVector() { clear(); } QGVector& QGVector::operator=( const QGVector &v ) { if ( &v == this ) return *this; clear(); len = v.len; numItems = v.numItems; if ( len == 0 ) { vec = 0; return *this; } vec = NEW( Item, len ); Q_CHECK_PTR( vec ); for ( uint i = 0; i < len; i++ ) { if ( v.vec[i] ) { vec[i] = newItem( v.vec[i] ); Q_CHECK_PTR( vec[i] ); } else { vec[i] = 0; } } return *this; } bool QGVector::insert( uint index, Item d ) // insert item at index { #if defined(QT_CHECK_RANGE) if ( index >= len ) { // range error qWarning( "QGVector::insert: Index %d out of range", index ); return FALSE; } #endif if ( vec[index] ) { // remove old item deleteItem( vec[index] ); numItems--; } if ( d ) { vec[index] = newItem( d ); Q_CHECK_PTR( vec[index] ); numItems++; return vec[index] != 0; } else { vec[index] = 0; // reset item } return TRUE; } bool QGVector::remove( uint index ) // remove item at index { #if defined(QT_CHECK_RANGE) if ( index >= len ) { // range error qWarning( "QGVector::remove: Index %d out of range", index ); return FALSE; } #endif if ( vec[index] ) { // valid item deleteItem( vec[index] ); // delete it vec[index] = 0; // reset pointer numItems--; } return TRUE; } QPtrCollection::Item QGVector::take( uint index ) // take out item { #if defined(QT_CHECK_RANGE) if ( index >= len ) { // range error qWarning( "QGVector::take: Index %d out of range", index ); return 0; } #endif Item d = vec[index]; // don't delete item if ( d ) numItems--; vec[index] = 0; return d; } void QGVector::clear() // clear vector { if ( vec ) { for ( uint i=0; i<len; i++ ) { // delete each item if ( vec[i] ) deleteItem( vec[i] ); } DELETE(vec); vec = 0; len = numItems = 0; } } bool QGVector::resize( uint newsize ) // resize array { if ( newsize == len ) // nothing to do return TRUE; if ( vec ) { // existing data if ( newsize < len ) { // shrink vector uint i = newsize; while ( i < len ) { // delete lost items if ( vec[i] ) { deleteItem( vec[i] ); numItems--; } i++; } } if ( newsize == 0 ) { // vector becomes empty DELETE(vec); vec = 0; len = numItems = 0; return TRUE; } #if defined(DONT_USE_REALLOC) if ( newsize == 0 ) { DELETE(vec); vec = 0; return FALSE; } Item *newvec = NEW(Item,newsize); // manual realloc memcpy( newvec, vec, (len < newsize ? len : newsize)*sizeof(Item) ); DELETE(vec); vec = newvec; #else vec = (Item*)realloc( (char *)vec, newsize*sizeof(Item) ); #endif } else { // create new vector vec = NEW(Item,newsize); len = numItems = 0; } Q_CHECK_PTR( vec ); if ( !vec ) // no memory return FALSE; if ( newsize > len ) // init extra space added memset( (void*)&vec[len], 0, (newsize-len)*sizeof(Item) ); len = newsize; return TRUE; } bool QGVector::fill( Item d, int flen ) // resize and fill vector { if ( flen < 0 ) flen = len; // default: use vector length else if ( !resize( flen ) ) return FALSE; for ( uint i=0; i<(uint)flen; i++ ) // insert d at every index insert( i, d ); return TRUE; } static QGVector *sort_vec=0; // current sort vector #if defined(Q_C_CALLBACKS) extern "C" { #endif #ifdef Q_OS_TEMP static int _cdecl cmp_vec( const void *n1, const void *n2 ) #else static int cmp_vec( const void *n1, const void *n2 ) #endif { return sort_vec->compareItems( *((QPtrCollection::Item*)n1), *((QPtrCollection::Item*)n2) ); } #if defined(Q_C_CALLBACKS) } #endif void QGVector::sort() // sort vector { if ( count() == 0 ) // no elements return; register Item *start = &vec[0]; register Item *end = &vec[len-1]; Item tmp; for (;;) { // put all zero elements behind while ( start < end && *start != 0 ) start++; while ( end > start && *end == 0 ) end--; if ( start < end ) { tmp = *start; *start = *end; *end = tmp; } else { break; } } #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &sort_vec ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &sort_vec ) : 0 ); #endif // QT_THREAD_SUPPORT sort_vec = (QGVector*)this; qsort( vec, count(), sizeof(Item), cmp_vec ); sort_vec = 0; } int QGVector::bsearch( Item d ) const // binary search; when sorted { if ( !len ) return -1; if ( !d ) { #if defined(QT_CHECK_NULL) qWarning( "QGVector::bsearch: Cannot search for null object" ); #endif return -1; } int n1 = 0; int n2 = len - 1; int mid = 0; bool found = FALSE; while ( n1 <= n2 ) { int res; mid = (n1 + n2)/2; if ( vec[mid] == 0 ) // null item greater res = -1; else res = ((QGVector*)this)->compareItems( d, vec[mid] ); if ( res < 0 ) n2 = mid - 1; else if ( res > 0 ) n1 = mid + 1; else { // found it found = TRUE; break; } } if ( !found ) return -1; // search to first of equal items while ( (mid - 1 >= 0) && !((QGVector*)this)->compareItems(d, vec[mid-1]) ) mid--; return mid; } int QGVector::findRef( Item d, uint index) const // find exact item in vector { #if defined(QT_CHECK_RANGE) if ( index > len ) { // range error qWarning( "QGVector::findRef: Index %d out of range", index ); return -1; } #endif for ( uint i=index; i<len; i++ ) { if ( vec[i] == d ) return i; } return -1; } int QGVector::find( Item d, uint index ) const // find equal item in vector { #if defined(QT_CHECK_RANGE) if ( index >= len ) { // range error qWarning( "QGVector::find: Index %d out of range", index ); return -1; } #endif for ( uint i=index; i<len; i++ ) { if ( vec[i] == 0 && d == 0 ) // found null item return i; if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) return i; } return -1; } uint QGVector::containsRef( Item d ) const // get number of exact matches { uint count = 0; for ( uint i=0; i<len; i++ ) { if ( vec[i] == d ) count++; } return count; } uint QGVector::contains( Item d ) const // get number of equal matches { uint count = 0; for ( uint i=0; i<len; i++ ) { if ( vec[i] == 0 && d == 0 ) // count null items count++; if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) count++; } return count; } bool QGVector::insertExpand( uint index, Item d )// insert and grow if necessary { if ( index >= len ) { if ( !resize( index+1 ) ) // no memory return FALSE; } insert( index, d ); return TRUE; } void QGVector::toList( QGList *list ) const // store items in list { list->clear(); for ( uint i=0; i<len; i++ ) { if ( vec[i] ) list->append( vec[i] ); } } void QGVector::warningIndexRange( uint i ) { #if defined(QT_CHECK_RANGE) qWarning( "QGVector::operator[]: Index %d out of range", i ); #else Q_UNUSED( i ) #endif } /***************************************************************************** QGVector stream functions *****************************************************************************/ #ifndef QT_NO_DATASTREAM QDataStream &operator>>( QDataStream &s, QGVector &vec ) { // read vector return vec.read( s ); } QDataStream &operator<<( QDataStream &s, const QGVector &vec ) { // write vector return vec.write( s ); } QDataStream &QGVector::read( QDataStream &s ) // read vector from stream { uint num; s >> num; // read number of items clear(); // clear vector resize( num ); for (uint i=0; i<num; i++) { // read all items Item d; read( s, d ); Q_CHECK_PTR( d ); if ( !d ) // no memory break; vec[i] = d; } return s; } QDataStream &QGVector::write( QDataStream &s ) const { // write vector to stream uint num = count(); s << num; // number of items to write num = size(); for (uint i=0; i<num; i++) { // write non-null items if ( vec[i] ) write( s, vec[i] ); } return s; } /* Returns whether v equals this vector or not */ bool QGVector::operator==( const QGVector &v ) const { if ( size() != v.size() ) return FALSE; if ( count() != v.count() ) return FALSE; for ( int i = 0; i < (int)size(); ++i ) { if ( ( (QGVector*)this )->compareItems( at( i ), v.at( i ) ) != 0 ) return FALSE; } return TRUE; } #endif // QT_NO_DATASTREAM diff --git a/qmake/tools/qlibrary.cpp b/qmake/tools/qlibrary.cpp index 564db30..be1d54b 100644 --- a/qmake/tools/qlibrary.cpp +++ b/qmake/tools/qlibrary.cpp @@ -1,343 +1,344 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QLibrary class ** -** Created : 2000-01-01 +** Created : 000101 ** -** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** Copyright (C) 2000-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include <private/qlibrary_p.h> #ifndef QT_NO_LIBRARY // uncomment this to get error messages //#define QT_DEBUG_COMPONENT 1 // uncomment this to get error and success messages //#define QT_DEBUG_COMPONENT 2 #ifndef QT_DEBUG_COMPONENT # if defined(QT_DEBUG) # define QT_DEBUG_COMPONENT 1 # endif #endif #if defined(QT_DEBUG_COMPONENT) #include <qfile.h> #endif #if defined(Q_WS_WIN) && !defined(QT_MAKEDLL) #define QT_NO_LIBRARY_UNLOAD #endif QLibraryPrivate::QLibraryPrivate( QLibrary *lib ) : pHnd( 0 ), library( lib ) { } /*! \class QLibrary qlibrary.h \reentrant \brief The QLibrary class provides a wrapper for handling shared libraries. \mainclass - \group plugins + \ingroup plugins An instance of a QLibrary object can handle a single shared library and provide access to the functionality in the library in a platform independent way. If the library is a component server, QLibrary provides access to the exported component and can directly query this component for interfaces. QLibrary ensures that the shared library is loaded and stays in memory whilst it is in use. QLibrary can also unload the library on destruction and release unused resources. A typical use of QLibrary is to resolve an exported symbol in a shared object, and to call the function that this symbol represents. This is called "explicit linking" in contrast to "implicit linking", which is done by the link step in the build process when linking an executable against a library. The following code snippet loads a library, resolves the symbol "mysymbol", and calls the function if everything succeeded. If something went wrong, e.g. the library file does not exist or the symbol is not defined, the function pointer will be 0 and won't be called. When the QLibrary object is destroyed the library will be unloaded, making all references to memory allocated in the library invalid. \code typedef void (*MyPrototype)(); MyPrototype myFunction; QLibrary myLib( "mylib" ); myFunction = (MyProtoype) myLib.resolve( "mysymbol" ); if ( myFunction ) { myFunction(); } \endcode */ /*! Creates a QLibrary object for the shared library \a filename. The library will be unloaded in the destructor. Note that \a filename does not need to include the (platform specific) file extension, so calling \code QLibrary lib( "mylib" ); \endcode is equivalent to calling \code QLibrary lib( "mylib.dll" ); \endcode on Windows, and \code QLibrary lib( "libmylib.so" ); \endcode on Unix. Specifying the extension is not recommended, since doing so introduces a platform dependency. If \a filename does not include a path, the library loader will look for the file in the platform specific search paths. \sa load() unload(), setAutoUnload() */ QLibrary::QLibrary( const QString& filename ) : libfile( filename ), aunload( TRUE ) { libfile.replace( '\\', '/' ); d = new QLibraryPrivate( this ); } /*! Deletes the QLibrary object. The library will be unloaded if autoUnload() is TRUE (the default), otherwise it stays in memory until the application exits. \sa unload(), setAutoUnload() */ QLibrary::~QLibrary() { if ( autoUnload() ) unload(); delete d; } /*! Returns the address of the exported symbol \a symb. The library is loaded if necessary. The function returns 0 if the symbol could not be resolved or the library could not be loaded. \code typedef int (*avgProc)( int, int ); avgProc avg = (avgProc) library->resolve( "avg" ); if ( avg ) return avg( 5, 8 ); else return -1; \endcode */ void *QLibrary::resolve( const char* symb ) { if ( !d->pHnd ) load(); if ( !d->pHnd ) return 0; void *address = d->resolveSymbol( symb ); return address; } /*! \overload Loads the library \a filename and returns the address of the exported symbol \a symb. Note that like the constructor, \a filename does not need to include the (platform specific) file extension. The library remains loaded until the process exits. The function returns 0 if the symbol could not be resolved or the library could not be loaded. This function is useful only if you want to resolve a single symbol, e.g. a function pointer from a specific library once: \code typedef void (*FunctionType)(); static FunctionType *ptrFunction = 0; static bool triedResolve = FALSE; if ( !ptrFunction && !triedResolve ) ptrFunction = QLibrary::resolve( "mylib", "mysymb" ); if ( ptrFunction ) ptrFunction(); else ... \endcode If you want to resolve multiple symbols, use a QLibrary object and call the non-static version of resolve(). \sa resolve() */ void *QLibrary::resolve( const QString &filename, const char *symb ) { QLibrary lib( filename ); lib.setAutoUnload( FALSE ); return lib.resolve( symb ); } /*! Returns TRUE if the library is loaded; otherwise returns FALSE. \sa unload() */ bool QLibrary::isLoaded() const { return d->pHnd != 0; } /*! Loads the library. Since resolve() always calls this function before resolving any symbols it is not necessary to call it explicitly. In some situations you might want the library loaded in advance, in which case you would use this function. */ bool QLibrary::load() { return d->loadLibrary(); } /*! Unloads the library and returns TRUE if the library could be unloaded; otherwise returns FALSE. This function is called by the destructor if autoUnload() is enabled. \sa resolve() */ bool QLibrary::unload() { if ( !d->pHnd ) return TRUE; #if !defined(QT_NO_LIBRARY_UNLOAD) if ( !d->freeLibrary() ) { # if defined(QT_DEBUG_COMPONENT) qWarning( "%s could not be unloaded", (const char*) QFile::encodeName(library()) ); # endif return FALSE; } # if defined(QT_DEBUG_COMPONENT) && QT_DEBUG_COMPONENT == 2 qWarning( "%s has been unloaded", (const char*) QFile::encodeName(library()) ); # endif d->pHnd = 0; #endif return TRUE; } /*! Returns TRUE if the library will be automatically unloaded when this wrapper object is destructed; otherwise returns FALSE. The default is TRUE. \sa setAutoUnload() */ bool QLibrary::autoUnload() const { return (bool)aunload; } /*! If \a enabled is TRUE (the default), the wrapper object is set to automatically unload the library upon destruction. If \a enabled is FALSE, the wrapper object is not unloaded unless you explicitly call unload(). \sa autoUnload() */ void QLibrary::setAutoUnload( bool enabled ) { aunload = enabled; } /*! Returns the filename of the shared library this QLibrary object handles, including the platform specific file extension. For example: \code QLibrary lib( "mylib" ); QString str = lib.library(); \endcode will set \e str to "mylib.dll" on Windows, and "libmylib.so" on Linux. */ QString QLibrary::library() const { if ( libfile.isEmpty() ) return libfile; QString filename = libfile; #if defined(Q_WS_WIN) if ( filename.findRev( '.' ) <= filename.findRev( '/' ) ) filename += ".dll"; #elif defined(Q_OS_MACX) if ( filename.find( ".dylib" ) == -1 ) filename += ".dylib"; #else - if ( filename.find( ".so" ) == -1 ) { + QString filter = ".so"; + if ( filename.find(filter) == -1 ) { const int x = filename.findRev( "/" ); if ( x != -1 ) { QString path = filename.left( x + 1 ); QString file = filename.right( filename.length() - x - 1 ); - filename = QString( "%1lib%2.so" ).arg( path ).arg( file ); + filename = QString( "%1lib%2.%3" ).arg( path ).arg( file ).arg( filter ); } else { - filename = QString( "lib%1.so" ).arg( filename ); + filename = QString( "lib%1.%2" ).arg( filename ).arg( filter ); } } #endif return filename; } #endif //QT_NO_LIBRARY diff --git a/qmake/tools/qlibrary_unix.cpp b/qmake/tools/qlibrary_unix.cpp index f0fbdf6..12b9310 100644 --- a/qmake/tools/qlibrary_unix.cpp +++ b/qmake/tools/qlibrary_unix.cpp @@ -1,163 +1,180 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QLibraryPrivate class ** -** Created : 2000-01-01 +** Created : 000101 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" #include "private/qlibrary_p.h" #ifndef QT_NO_LIBRARY #if defined(QT_AOUT_UNDERSCORE) #include <string.h> #endif /* The platform dependent implementations of - loadLibrary - freeLibrary - resolveSymbol It's not too hard to guess what the functions do. */ -#if defined(QT_HPUX_LD) // for HP-UX < 11.x and 32 bit +#if defined(Q_OS_MAC) + +bool QLibraryPrivate::loadLibrary() +{ + return FALSE; +} + +bool QLibraryPrivate::freeLibrary() +{ + return FALSE; +} + +void* QLibraryPrivate::resolveSymbol( const char* ) +{ + return 0; +} + +#elif defined(QT_HPUX_LD) // for HP-UX < 11.x and 32 bit bool QLibraryPrivate::loadLibrary() { if ( pHnd ) return TRUE; QString filename = library->library(); pHnd = (void*)shl_load( filename.latin1(), BIND_DEFERRED | BIND_NONFATAL | DYNAMIC_PATH, 0 ); #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) if ( !pHnd ) qWarning( "%s: failed to load library!", filename.latin1() ); #endif return pHnd != 0; } bool QLibraryPrivate::freeLibrary() { if ( !pHnd ) return TRUE; if ( shl_unload( (shl_t)pHnd ) ) { #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) QString filename = library->library(); qWarning( "%s: Failed to unload library!", filename.latin1() ); #endif return FALSE; } pHnd = 0; return TRUE; } void* QLibraryPrivate::resolveSymbol( const char* symbol ) { if ( !pHnd ) return 0; void* address = 0; if ( shl_findsym( (shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address ) < 0 ) { #if defined(QT_DEBUG_COMPONENT) QString filename = library->library(); qWarning( "%s: couldn't resolve symbol \"%s\"", filename.latin1(), symbol ); #endif } return address; } #else // POSIX #include <dlfcn.h> bool QLibraryPrivate::loadLibrary() { if ( pHnd ) return TRUE; QString filename = library->library(); pHnd = dlopen( filename.latin1(), RTLD_LAZY ); #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) if ( !pHnd ) qWarning( "%s", dlerror() ); #endif return pHnd != 0; } bool QLibraryPrivate::freeLibrary() { if ( !pHnd ) return TRUE; if ( dlclose( pHnd ) ) { #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT) qWarning( "%s", dlerror() ); #endif return FALSE; } pHnd = 0; return TRUE; } void* QLibraryPrivate::resolveSymbol( const char* symbol ) { if ( !pHnd ) return 0; #if defined(QT_AOUT_UNDERSCORE) // older a.out systems add an underscore in front of symbols char* undrscr_symbol = new char[strlen(symbol)+2]; undrscr_symbol[0] = '_'; strcpy(undrscr_symbol+1, symbol); void* address = dlsym( pHnd, undrscr_symbol ); delete [] undrscr_symbol; #else void* address = dlsym( pHnd, symbol ); #endif #if defined(QT_DEBUG_COMPONENT) const char* error = dlerror(); if ( error ) qWarning( "%s", error ); #endif return address; } #endif // POSIX #endif diff --git a/qmake/tools/qmutex_unix.cpp b/qmake/tools/qmutex_unix.cpp index c861b2d..3eb59cf 100644 --- a/qmake/tools/qmutex_unix.cpp +++ b/qmake/tools/qmutex_unix.cpp @@ -1,687 +1,689 @@ /**************************************************************************** ** $Id$ ** ** QMutex class for Unix ** ** Created : 20010725 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #if defined(QT_THREAD_SUPPORT) #include "qplatformdefs.h" typedef pthread_mutex_t Q_MUTEX_T; // POSIX threads mutex types #if ((defined(PTHREAD_MUTEX_RECURSIVE) && defined(PTHREAD_MUTEX_DEFAULT)) || \ - defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) + defined(Q_OS_FREEBSD)) && !defined(Q_OS_UNIXWARE) && !defined(Q_OS_SOLARIS) && \ + !defined(Q_OS_MAC) // POSIX 1003.1c-1995 - We love this OS # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_settype((a), (b)) # if defined(QT_CHECK_RANGE) # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK # else # define Q_NORMAL_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT # endif # define Q_RECURSIVE_MUTEX_TYPE PTHREAD_MUTEX_RECURSIVE #elif defined(MUTEX_NONRECURSIVE_NP) && defined(MUTEX_RECURSIVE_NP) // POSIX 1003.4a pthreads draft extensions # define Q_MUTEX_SET_TYPE(a, b) pthread_mutexattr_setkind_np((a), (b)); # define Q_NORMAL_MUTEX_TYPE MUTEX_NONRECURSIVE_NP # define Q_RECURSIVE_MUTEX_TYPE MUTEX_RECURSIVE_NP #else // Unknown mutex types - skip them # define Q_MUTEX_SET_TYPE(a, b) # undef Q_NORMAL_MUTEX_TYPE # undef Q_RECURSIVE_MUTEX_TYPE #endif #include "qmutex.h" #include "qmutex_p.h" #include <errno.h> #include <string.h> // Private class declarations class QRealMutexPrivate : public QMutexPrivate { public: QRealMutexPrivate(bool = FALSE); void lock(); void unlock(); bool locked(); bool trylock(); int type() const; bool recursive; }; #ifndef Q_RECURSIVE_MUTEX_TYPE class QRecursiveMutexPrivate : public QMutexPrivate { public: QRecursiveMutexPrivate(); ~QRecursiveMutexPrivate(); void lock(); void unlock(); bool locked(); bool trylock(); int type() const; int count; unsigned long owner; pthread_mutex_t handle2; }; #endif // !Q_RECURSIVE_MUTEX_TYPE // Private class implementation // base destructor QMutexPrivate::~QMutexPrivate() { int ret = pthread_mutex_destroy(&handle); #ifdef QT_CHECK_RANGE if ( ret ) qWarning( "Mutex destroy failure: %s", strerror( ret ) ); #endif } // real mutex class QRealMutexPrivate::QRealMutexPrivate(bool recurs) : recursive(recurs) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); Q_MUTEX_SET_TYPE(&attr, recursive ? Q_RECURSIVE_MUTEX_TYPE : Q_NORMAL_MUTEX_TYPE); Q_UNUSED(recursive); int ret = pthread_mutex_init(&handle, &attr); pthread_mutexattr_destroy(&attr); #ifdef QT_CHECK_RANGE if( ret ) qWarning( "Mutex init failure: %s", strerror( ret ) ); #endif // QT_CHECK_RANGE } void QRealMutexPrivate::lock() { int ret = pthread_mutex_lock(&handle); #ifdef QT_CHECK_RANGE if (ret) qWarning("Mutex lock failure: %s", strerror(ret)); #endif } void QRealMutexPrivate::unlock() { int ret = pthread_mutex_unlock(&handle); #ifdef QT_CHECK_RANGE if (ret) qWarning("Mutex unlock failure: %s", strerror(ret)); #endif } bool QRealMutexPrivate::locked() { int ret = pthread_mutex_trylock(&handle); if (ret == EBUSY) { return TRUE; } else if (ret) { #ifdef QT_CHECK_RANGE qWarning("Mutex locktest failure: %s", strerror(ret)); #endif } else pthread_mutex_unlock(&handle); return FALSE; } bool QRealMutexPrivate::trylock() { int ret = pthread_mutex_trylock(&handle); if (ret == EBUSY) { return FALSE; } else if (ret) { #ifdef QT_CHECK_RANGE qWarning("Mutex trylock failure: %s", strerror(ret)); #endif return FALSE; } return TRUE; } int QRealMutexPrivate::type() const { return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; } #ifndef Q_RECURSIVE_MUTEX_TYPE QRecursiveMutexPrivate::QRecursiveMutexPrivate() : count(0), owner(0) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); Q_MUTEX_SET_TYPE(&attr, Q_NORMAL_MUTEX_TYPE); int ret = pthread_mutex_init(&handle, &attr); pthread_mutexattr_destroy(&attr); # ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex init failure: %s", strerror(ret) ); # endif pthread_mutexattr_init(&attr); ret = pthread_mutex_init( &handle2, &attr ); pthread_mutexattr_destroy(&attr); # ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex init failure: %s", strerror(ret) ); # endif } QRecursiveMutexPrivate::~QRecursiveMutexPrivate() { int ret = pthread_mutex_destroy(&handle2); # ifdef QT_CHECK_RANGE if (ret) qWarning( "Mutex destroy failure: %s", strerror(ret) ); # endif } void QRecursiveMutexPrivate::lock() { pthread_mutex_lock(&handle2); if (count > 0 && owner == (unsigned long) pthread_self()) { count++; } else { pthread_mutex_unlock(&handle2); pthread_mutex_lock(&handle); pthread_mutex_lock(&handle2); count = 1; owner = (unsigned long) pthread_self(); } pthread_mutex_unlock(&handle2); } void QRecursiveMutexPrivate::unlock() { pthread_mutex_lock(&handle2); if (owner == (unsigned long) pthread_self()) { // do nothing if the count is already 0... to reflect the behaviour described // in the docs if (count && (--count) < 1) { count = 0; pthread_mutex_unlock(&handle); } } else { #ifdef QT_CHECK_RANGE qWarning("QMutex::unlock: unlock from different thread than locker"); qWarning(" was locked by %d, unlock attempt from %d", (int)owner, (int)pthread_self()); #endif } pthread_mutex_unlock(&handle2); } bool QRecursiveMutexPrivate::locked() { pthread_mutex_lock(&handle2); bool ret; int code = pthread_mutex_trylock(&handle); if (code == EBUSY) { ret = TRUE; } else { #ifdef QT_CHECK_RANGE if (code) qWarning("Mutex trylock failure: %s", strerror(code)); #endif pthread_mutex_unlock(&handle); ret = FALSE; } pthread_mutex_unlock(&handle2); return ret; } bool QRecursiveMutexPrivate::trylock() { bool ret = TRUE; pthread_mutex_lock(&handle2); if ( count > 0 && owner == (unsigned long) pthread_self() ) { count++; } else { int code = pthread_mutex_trylock(&handle); if (code == EBUSY) { ret = FALSE; } else if (code) { #ifdef QT_CHECK_RANGE qWarning("Mutex trylock failure: %s", strerror(code)); #endif ret = FALSE; } else { count = 1; owner = (unsigned long) pthread_self(); } } pthread_mutex_unlock(&handle2); return ret; } int QRecursiveMutexPrivate::type() const { return Q_MUTEX_RECURSIVE; } #endif // !Q_RECURSIVE_MUTEX_TYPE /*! \class QMutex qmutex.h \threadsafe \brief The QMutex class provides access serialization between threads. \ingroup thread \ingroup environment The purpose of a QMutex is to protect an object, data structure or section of code so that only one thread can access it at a time (This is similar to the Java \c synchronized keyword). For example, say there is a method which prints a message to the user on two lines: \code int number = 6; void method1() { number *= 5; number /= 4; } void method1() { number *= 3; number /= 2; } \endcode If these two methods are called in succession, the following happens: \code // method1() number *= 5; // number is now 30 number /= 4; // number is now 7 // method2() number *= 3; // nubmer is now 21 number /= 2; // number is now 10 \endcode If these two methods are called simultaneously from two threads then the following sequence could result: \code // Thread 1 calls method1() number *= 5; // number is now 30 // Thread 2 calls method2(). // // Most likely Thread 1 has been put to sleep by the operating // system to allow Thread 2 to run. number *= 3; // number is now 90 number /= 2; // number is now 45 // Thread 1 finishes executing. number /= 4; // number is now 11, instead of 10 \endcode If we add a mutex, we should get the result we want: \code QMutex mutex; int number = 6; void method1() { mutex.lock(); number *= 5; number /= 4; mutex.unlock(); } void method2() { mutex.lock(); number *= 3; number /= 2; mutex.unlock(); } \endcode Then only one thread can modify \c number at any given time and the result is correct. This is a trivial example, of course, but applies to any other case where things need to happen in a particular sequence. When you call lock() in a thread, other threads that try to call lock() in the same place will block until the thread that got the lock calls unlock(). A non-blocking alternative to lock() is tryLock(). */ /*! Constructs a new mutex. The mutex is created in an unlocked state. A recursive mutex is created if \a recursive is TRUE; a normal mutex is created if \a recursive is FALSE (the default). With a recursive mutex, a thread can lock the same mutex multiple times and it will not be unlocked until a corresponding number of unlock() calls have been made. */ QMutex::QMutex(bool recursive) { #ifndef Q_RECURSIVE_MUTEX_TYPE if ( recursive ) d = new QRecursiveMutexPrivate(); else #endif // !Q_RECURSIVE_MUTEX_TYPE d = new QRealMutexPrivate(recursive); } /*! Destroys the mutex. \warning If you destroy a mutex that still holds a lock the resultant behavior is undefined. */ QMutex::~QMutex() { delete d; } /*! Attempt to lock the mutex. If another thread has locked the mutex then this call will \e block until that thread has unlocked it. \sa unlock(), locked() */ void QMutex::lock() { d->lock(); } /*! Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked it results in an error. Unlocking a mutex that is not locked results in undefined behaviour (varies between different Operating Systems' thread implementations). \sa lock(), locked() */ void QMutex::unlock() { d->unlock(); } /*! Returns TRUE if the mutex is locked by another thread; otherwise returns FALSE. \warning Due to differing implementations of recursive mutexes on various platforms, calling this function from the same thread that previously locked the mutex will return undefined results. \sa lock(), unlock() */ bool QMutex::locked() { return d->locked(); } /*! Attempt to lock the mutex. If the lock was obtained, this function returns TRUE. If another thread has locked the mutex, this function returns FALSE, instead of waiting for the mutex to become available, i.e. it does not block. If the lock was obtained, the mutex must be unlocked with unlock() before another thread can successfully lock it. \sa lock(), unlock(), locked() */ bool QMutex::tryLock() { return d->trylock(); } /*! \class QMutexLocker qmutex.h \brief The QMutexLocker class simplifies locking and unlocking QMutexes. \threadsafe \ingroup thread \ingroup environment The purpose of QMutexLocker is to simplify QMutex locking and unlocking. Locking and unlocking a QMutex in complex functions and statements or in exception handling code is error prone and difficult to debug. QMutexLocker should be used in such situations to ensure that the state of the mutex is well defined and always locked and unlocked properly. QMutexLocker should be created within a function where a QMutex needs to be locked. The mutex is locked when QMutexLocker is created, and unlocked when QMutexLocker is destroyed. For example, this complex function locks a QMutex upon entering the function and unlocks the mutex at all the exit points: \code int complexFunction( int flag ) { mutex.lock(); int return_value = 0; switch ( flag ) { case 0: case 1: { mutex.unlock(); return moreComplexFunction( flag ); } case 2: { int status = anotherFunction(); if ( status < 0 ) { mutex.unlock(); return -2; } return_value = status + flag; break; } default: { if ( flag > 10 ) { mutex.unlock(); return -1; } break; } } mutex.unlock(); return return_value; } \endcode This example function will get more complicated as it is developed, which increases the likelihood that errors will occur. Using QMutexLocker greatly simplifies the code, and makes it more readable: \code int complexFunction( int flag ) { QMutexLocker locker( &mutex ); int return_value = 0; switch ( flag ) { case 0: case 1: { return moreComplexFunction( flag ); } case 2: { int status = anotherFunction(); if ( status < 0 ) return -2; return_value = status + flag; break; } default: { if ( flag > 10 ) return -1; break; } } return return_value; } \endcode Now, the mutex will always be unlocked when the QMutexLocker object is destroyed (when the function returns since \c locker is an auto variable). The same principle applies to code that throws and catches exceptions. An exception that is not caught in the function that has locked the mutex has no way of unlocking the mutex before the exception is passed up the stack to the calling function. QMutexLocker also provides a mutex() member function that returns the mutex on which the QMutexLocker is operating. This is useful for code that needs access to the mutex, such as QWaitCondition::wait(). For example: \code class SignalWaiter { private: QMutexLocker locker; public: SignalWaiter( QMutex *mutex ) : locker( mutex ) { } void waitForSignal() { ... ... ... while ( ! signalled ) waitcondition.wait( locker.mutex() ); ... ... ... } }; \endcode \sa QMutex, QWaitCondition */ /*! \fn QMutexLocker::QMutexLocker( QMutex *mutex ) Constructs a QMutexLocker and locks \a mutex. The mutex will be - unlocked when the QMutexLocker is destroyed. + unlocked when the QMutexLocker is destroyed. If \a mutex is zero, + QMutexLocker does nothing. \sa QMutex::lock() */ /*! \fn QMutexLocker::~QMutexLocker() Destroys the QMutexLocker and unlocks the mutex which was locked in the constructor. \sa QMutexLocker::QMutexLocker(), QMutex::unlock() */ /*! \fn QMutex *QMutexLocker::mutex() const Returns a pointer to the mutex which was locked in the constructor. \sa QMutexLocker::QMutexLocker() */ #endif // QT_THREAD_SUPPORT diff --git a/qmake/tools/qmutexpool.cpp b/qmake/tools/qmutexpool.cpp index 9ed2829..a8e7402 100644 --- a/qmake/tools/qmutexpool.cpp +++ b/qmake/tools/qmutexpool.cpp @@ -1,130 +1,152 @@ +/**************************************************************************** +** $Id$ +** +** ... +** +** Copyright (C) 2002 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + #include "qmutexpool_p.h" #ifdef QT_THREAD_SUPPORT #include <qthread.h> -#include <stdio.h> QMutexPool *qt_global_mutexpool = 0; -// this is an internal class used only for inititalizing the global mutexpool -class QGlobalMutexPoolInitializer -{ -public: - inline QGlobalMutexPoolInitializer() - { - /* - Purify will report a leak here. However, this mutex pool must be alive - until *everything* in Qt has been destructed. Unfortunately there is - no way to guarantee this, so we never destroy this mutex pool. - */ - qt_global_mutexpool = new QMutexPool( TRUE ); - } -}; -QGlobalMutexPoolInitializer qt_global_mutexpool_initializer; /*! \class QMutexPool qmutexpool_p.h \brief The QMutexPool class provides a pool of QMutex objects. \internal \ingroup thread QMutexPool is a convenience class that provides access to a fixed number of QMutex objects. Typical use of a QMutexPool is in situations where it is not possible or feasible to use one QMutex for every protected object. The mutex pool will return a mutex based on the address of the object that needs protection. For example, consider this simple class: \code class Number { public: Number( double n ) : num ( n ) { } void setNumber( double n ) { num = n; } double number() const { return num; } private: double num; }; \endcode Adding a QMutex member to the Number class does not make sense, because it is so small. However, in order to ensure that access to each Number is protected, you need to use a mutex. In this case, a QMutexPool would be ideal. Code to calculate the square of a number would then look something like this: \code void calcSquare( Number *num ) { QMutexLocker locker( mutexpool.get( num ) ); num.setNumber( num.number() * num.number() ); } \endcode This function will safely calculate the square of a number, since it uses a mutex from a QMutexPool. The mutex is locked and unlocked automatically by the QMutexLocker class. See the QMutexLocker documentation for more details. */ /*! Constructs a QMutexPool, reserving space for \a size QMutexes. If \a recursive is TRUE, all QMutexes in the pool will be recursive mutexes; otherwise they will all be non-recursive (the default). The QMutexes are created when needed, and deleted when the QMutexPool is destructed. */ QMutexPool::QMutexPool( bool recursive, int size ) - : mutex( FALSE ), mutexes( size ), recurs( recursive ) + : mutex( FALSE ), count( size ), recurs( recursive ) { - mutexes.fill( 0 ); + mutexes = new QMutex*[count]; + for ( int index = 0; index < count; ++index ) { + mutexes[index] = 0; + } } /*! Destructs a QMutexPool. All QMutexes that were created by the pool are deleted. */ QMutexPool::~QMutexPool() { QMutexLocker locker( &mutex ); - QMutex **d = mutexes.data(); - for ( int index = 0; (uint) index < mutexes.size(); index++ ) { - delete d[index]; - d[index] = 0; + for ( int index = 0; index < count; ++index ) { + delete mutexes[index]; + mutexes[index] = 0; } + delete [] mutexes; + mutexes = 0; } /*! Returns a QMutex from the pool. QMutexPool uses the value \a address to determine which mutex is retured from the pool. */ QMutex *QMutexPool::get( void *address ) { - QMutex **d = mutexes.data(); - int index = (int)( (ulong) address % mutexes.size() ); + int index = (int) ( (unsigned long) address % count ); - if ( ! d[index] ) { + if ( ! mutexes[index] ) { // mutex not created, create one QMutexLocker locker( &mutex ); // we need to check once again that the mutex hasn't been created, since // 2 threads could be trying to create a mutex as the same index... - if ( ! d[index] ) { - d[index] = new QMutex( recurs ); + if ( ! mutexes[index] ) { + mutexes[index] = new QMutex( recurs ); } } - return d[index]; + return mutexes[index]; } #endif diff --git a/qmake/tools/qregexp.cpp b/qmake/tools/qregexp.cpp index 500efed..0c1f060 100644 --- a/qmake/tools/qregexp.cpp +++ b/qmake/tools/qregexp.cpp @@ -1,1101 +1,1113 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QRegExp class ** ** Created : 950126 ** ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qregexp.h" #ifndef QT_NO_REGEXP #include "qmemarray.h" #include "qbitarray.h" #include "qcache.h" #include "qcleanuphandler.h" #include "qintdict.h" #include "qmap.h" #include "qptrvector.h" #include "qstring.h" #include "qtl.h" #ifdef QT_THREAD_SUPPORT #include "qmutexpool_p.h" #endif // QT_THREAD_SUPPORT #undef QT_TRANSLATE_NOOP #define QT_TRANSLATE_NOOP( context, sourceText ) sourceText #include <limits.h> // error strings for the regexp parser #define RXERR_OK QT_TRANSLATE_NOOP( "QRegExp", "no error occurred" ) #define RXERR_DISABLED QT_TRANSLATE_NOOP( "QRegExp", "disabled feature used" ) #define RXERR_CHARCLASS QT_TRANSLATE_NOOP( "QRegExp", "bad char class syntax" ) #define RXERR_LOOKAHEAD QT_TRANSLATE_NOOP( "QRegExp", "bad lookahead syntax" ) #define RXERR_REPETITION QT_TRANSLATE_NOOP( "QRegExp", "bad repetition syntax" ) #define RXERR_OCTAL QT_TRANSLATE_NOOP( "QRegExp", "invalid octal value" ) #define RXERR_LEFTDELIM QT_TRANSLATE_NOOP( "QRegExp", "missing left delim" ) #define RXERR_END QT_TRANSLATE_NOOP( "QRegExp", "unexpected end" ) #define RXERR_LIMIT QT_TRANSLATE_NOOP( "QRegExp", "met internal limit" ) /* WARNING! Be sure to read qregexp.tex before modifying this file. */ /*! \class QRegExp qregexp.h \reentrant \brief The QRegExp class provides pattern matching using regular expressions. \ingroup tools \ingroup misc \ingroup shared \mainclass \keyword regular expression Regular expressions, or "regexps", provide a way to find patterns within text. This is useful in many contexts, for example: \table \row \i Validation \i A regexp can be used to check whether a piece of text meets some criteria, e.g. is an integer or contains no whitespace. \row \i Searching \i Regexps provide a much more powerful means of searching text than simple string matching does. For example we can create a regexp which says "find one of the words 'mail', 'letter' or 'correspondence' but not any of the words 'email', 'mailman' 'mailer', 'letterbox' etc." \row \i Search and Replace \i A regexp can be used to replace a pattern with a piece of text, for example replace all occurrences of '&' with '\&' except where the '&' is already followed by 'amp;'. \row \i String Splitting \i A regexp can be used to identify where a string should be split into its component fields, e.g. splitting tab-delimited strings. \endtable We present a very brief introduction to regexps, a description of Qt's regexp language, some code examples, and finally the function documentation itself. QRegExp is modeled on Perl's regexp language, and also fully supports Unicode. QRegExp can also be used in the weaker 'wildcard' (globbing) mode which works in a similar way to command shells. A good text on regexps is \e {Mastering Regular Expressions: Powerful Techniques for Perl and Other Tools} by Jeffrey E. Friedl, ISBN 1565922573. Experienced regexp users may prefer to skip the introduction and go directly to the relevant information. \tableofcontents \section1 Introduction Regexps are built up from expressions, quantifiers, and assertions. The simplest form of expression is simply a character, e.g. <b>x</b> or <b>5</b>. An expression can also be a set of characters. For example, <b>[ABCD]</b>, will match an <b>A</b> or a <b>B</b> or a <b>C</b> or a <b>D</b>. As a shorthand we could write this as <b>[A-D]</b>. If we want to match any of the captital letters in the English alphabet we can write <b>[A-Z]</b>. A quantifier tells the regexp engine how many occurrences of the expression we want, e.g. <b>x{1,1}</b> means match an <b>x</b> which occurs at least once and at most once. We'll look at assertions and more complex expressions later. Note that in general regexps cannot be used to check for balanced brackets or tags. For example if you want to match an opening html \c <b> and its closing \c </b> you can only use a regexp if you know that these tags are not nested; the html fragment, \c{<b>bold <b>bolder</b></b>} will not match as expected. If you know the maximum level of nesting it is possible to create a regexp that will match correctly, but for an unknown level of nesting, regexps will fail. We'll start by writing a regexp to match integers in the range 0 to 99. We will require at least one digit so we will start with <b>[0-9]{1,1}</b> which means match a digit exactly once. This regexp alone will match integers in the range 0 to 9. To match one or two digits we can increase the maximum number of occurrences so the regexp becomes <b>[0-9]{1,2}</b> meaning match a digit at least once and at most twice. However, this regexp as it stands will not match correctly. This regexp will match one or two digits \e within a string. To ensure that we match against the whole string we must use the anchor assertions. We need <b>^</b> (caret) which when it is the first character in the regexp means that the regexp must match from the beginning of the string. And we also need <b>$</b> (dollar) which when it is the last character in the regexp means that the regexp must match until the end of the string. So now our regexp is <b>^[0-9]{1,2}$</b>. Note that assertions, such as <b>^</b> and <b>$</b>, do not match any characters. If you've seen regexps elsewhere they may have looked different from the ones above. This is because some sets of characters and some quantifiers are so common that they have special symbols to represent them. <b>[0-9]</b> can be replaced with the symbol <b>\d</b>. The quantifier to match exactly one occurrence, <b>{1,1}</b>, can be replaced with the expression itself. This means that <b>x{1,1}</b> is exactly the same as <b>x</b> alone. So our 0 to 99 matcher could be written <b>^\d{1,2}$</b>. Another way of writing it would be <b>^\d\d{0,1}$</b>, i.e. from the start of the string match a digit followed by zero or one digits. In practice most people would write it <b>^\d\d?$</b>. The <b>?</b> is a shorthand for the quantifier <b>{0,1}</b>, i.e. a minimum of no occurrences a maximum of one occurrence. This is used to make an expression optional. The regexp <b>^\d\d?$</b> means "from the beginning of the string match one digit followed by zero or one digits and then the end of the string". Our second example is matching the words 'mail', 'letter' or 'correspondence' but without matching 'email', 'mailman', 'mailer', 'letterbox' etc. We'll start by just matching 'mail'. In full the regexp is, <b>m{1,1}a{1,1}i{1,1}l{1,1}</b>, but since each expression itself is automatically quantified by <b>{1,1}</b> we can simply write this as <b>mail</b>; an 'm' followed by an 'a' followed by an 'i' followed by an 'l'. The symbol '|' (bar) is used for \e alternation, so our regexp now becomes <b>mail|letter|correspondence</b> which means match 'mail' \e or 'letter' \e or 'correspondence'. Whilst this regexp will find the words we want it will also find words we don't want such as 'email'. We will start by putting our regexp in parentheses, <b>(mail|letter|correspondence)</b>. Parentheses have two effects, firstly they group expressions together and secondly they identify parts of the regexp that we wish to \link #capturing-text capture \endlink. Our regexp still matches any of the three words but now they are grouped together as a unit. This is useful for building up more complex regexps. It is also useful because it allows us to examine which of the words actually matched. We need to use another assertion, this time <b>\b</b> "word boundary": <b>\b(mail|letter|correspondence)\b</b>. This regexp means "match a word boundary followed by the expression in parentheses followed by another word boundary". The <b>\b</b> assertion matches at a \e position in the regexp not a \e character in the regexp. A word boundary is any non-word character such as a space a newline or the beginning or end of the string. For our third example we want to replace ampersands with the HTML entity '\&'. The regexp to match is simple: <b>\&</b>, i.e. match one ampersand. Unfortunately this will mess up our text if some of the ampersands have already been turned into HTML entities. So what we really want to say is replace an ampersand providing it is not followed by 'amp;'. For this we need the negative lookahead assertion and our regexp becomes: <b>\&(?!amp;)</b>. The negative lookahead assertion is introduced with '(?!' and finishes at the ')'. It means that the text it contains, 'amp;' in our example, must \e not follow the expression that preceeds it. Regexps provide a rich language that can be used in a variety of ways. For example suppose we want to count all the occurrences of 'Eric' and 'Eirik' in a string. Two valid regexps to match these are <b>\\b(Eric|Eirik)\\b</b> and <b>\\bEi?ri[ck]\\b</b>. We need the word boundary '\b' so we don't get 'Ericsson' etc. The second regexp actually matches more than we want, 'Eric', 'Erik', 'Eiric' and 'Eirik'. We will implement some the examples above in the \link #code-examples code examples \endlink section. \target characters-and-abbreviations-for-sets-of-characters \section1 Characters and Abbreviations for Sets of Characters \table \header \i Element \i Meaning \row \i <b>c</b> \i Any character represents itself unless it has a special regexp meaning. Thus <b>c</b> matches the character \e c. \row \i <b>\\c</b> \i A character that follows a backslash matches the character itself except where mentioned below. For example if you wished to match a literal caret at the beginning of a string you would write <b>\^</b>. \row \i <b>\\a</b> \i This matches the ASCII bell character (BEL, 0x07). \row \i <b>\\f</b> \i This matches the ASCII form feed character (FF, 0x0C). \row \i <b>\\n</b> \i This matches the ASCII line feed character (LF, 0x0A, Unix newline). \row \i <b>\\r</b> \i This matches the ASCII carriage return character (CR, 0x0D). \row \i <b>\\t</b> \i This matches the ASCII horizontal tab character (HT, 0x09). \row \i <b>\\v</b> \i This matches the ASCII vertical tab character (VT, 0x0B). \row \i <b>\\xhhhh</b> \i This matches the Unicode character corresponding to the hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo (i.e., \zero ooo) matches the ASCII/Latin-1 character corresponding to the octal number ooo (between 0 and 0377). \row \i <b>. (dot)</b> \i This matches any character (including newline). \row \i <b>\\d</b> - \i This matches a digit (see QChar::isDigit()). + \i This matches a digit (QChar::isDigit()). \row \i <b>\\D</b> \i This matches a non-digit. \row \i <b>\\s</b> - \i This matches a whitespace (see QChar::isSpace()). + \i This matches a whitespace (QChar::isSpace()). \row \i <b>\\S</b> \i This matches a non-whitespace. \row \i <b>\\w</b> - \i This matches a word character (see QChar::isLetterOrNumber()). + \i This matches a word character (QChar::isLetterOrNumber() or '_'). \row \i <b>\\W</b> \i This matches a non-word character. \row \i <b>\\n</b> \i The n-th \link #capturing-text backreference \endlink, e.g. \1, \2, etc. \endtable \e {Note that the C++ compiler transforms backslashes in strings so to include a <b>\\</b> in a regexp you will need to enter it twice, i.e. <b>\\\\</b>.} \target sets-of-characters \section1 Sets of Characters Square brackets are used to match any character in the set of characters contained within the square brackets. All the character set abbreviations described above can be used within square brackets. Apart from the character set abbreviations and the following two exceptions no characters have special meanings in square brackets. \table \row \i <b>^</b> \i The caret negates the character set if it occurs as the first character, i.e. immediately after the opening square bracket. For example, <b>[abc]</b> matches 'a' or 'b' or 'c', but <b>[^abc]</b> matches anything \e except 'a' or 'b' or 'c'. \row \i <b>-</b> \i The dash is used to indicate a range of characters, for example <b>[W-Z]</b> matches 'W' or 'X' or 'Y' or 'Z'. \endtable Using the predefined character set abbreviations is more portable than using character ranges across platforms and languages. For example, <b>[0-9]</b> matches a digit in Western alphabets but <b>\d</b> matches a digit in \e any alphabet. Note that in most regexp literature sets of characters are called "character classes". \target quantifiers \section1 Quantifiers By default an expression is automatically quantified by <b>{1,1}</b>, i.e. it should occur exactly once. In the following list <b>\e {E}</b> stands for any expression. An expression is a character or an abbreviation for a set of characters or a set of characters in square brackets or any parenthesised expression. \table \row \i <b>\e {E}?</b> \i Matches zero or one occurrence of \e E. This quantifier means "the previous expression is optional" since it will match whether or not the expression occurs in the string. It is the same as <b>\e {E}{0,1}</b>. For example <b>dents?</b> will match 'dent' and 'dents'. \row \i <b>\e {E}+</b> \i Matches one or more occurrences of \e E. This is the same as <b>\e {E}{1,MAXINT}</b>. For example, <b>0+</b> will match '0', '00', '000', etc. \row \i <b>\e {E}*</b> \i Matches zero or more occurrences of \e E. This is the same as <b>\e {E}{0,MAXINT}</b>. The <b>*</b> quantifier is often used by a mistake. Since it matches \e zero or more occurrences it will match no occurrences at all. For example if we want to match strings that end in whitespace and use the regexp <b>\s*$</b> we would get a match on every string. This is because we have said find zero or more whitespace followed by the end of string, so even strings that don't end in whitespace will match. The regexp we want in this case is <b>\s+$</b> to match strings that have at least one whitespace at the end. \row \i <b>\e {E}{n}</b> \i Matches exactly \e n occurrences of the expression. This is the same as repeating the expression \e n times. For example, <b>x{5}</b> is the same as <b>xxxxx</b>. It is also the same as <b>\e {E}{n,n}</b>, e.g. <b>x{5,5}</b>. \row \i <b>\e {E}{n,}</b> \i Matches at least \e n occurrences of the expression. This is the same as <b>\e {E}{n,MAXINT}</b>. \row \i <b>\e {E}{,m}</b> \i Matches at most \e m occurrences of the expression. This is the same as <b>\e {E}{0,m}</b>. \row \i <b>\e {E}{n,m}</b> \i Matches at least \e n occurrences of the expression and at most \e m occurrences of the expression. \endtable (MAXINT is implementation dependent but will not be smaller than 1024.) If we wish to apply a quantifier to more than just the preceding character we can use parentheses to group characters together in an expression. For example, <b>tag+</b> matches a 't' followed by an 'a' followed by at least one 'g', whereas <b>(tag)+</b> matches at least one occurrence of 'tag'. Note that quantifiers are "greedy". They will match as much text as they can. For example, <b>0+</b> will match as many zeros as it can from the first zero it finds, e.g. '2.<u>000</u>5'. Quantifiers can be made non-greedy, see setMinimal(). \target capturing-text \section1 Capturing Text Parentheses allow us to group elements together so that we can quantify and capture them. For example if we have the expression <b>mail|letter|correspondence</b> that matches a string we know that \e one of the words matched but not which one. Using parentheses allows us to "capture" whatever is matched within their bounds, so if we used <b>(mail|letter|correspondence)</b> and matched this regexp against the string "I sent you some email" we can use the cap() or capturedTexts() functions to extract the matched characters, in this case 'mail'. We can use captured text within the regexp itself. To refer to the captured text we use \e backreferences which are indexed from 1, the same as for cap(). For example we could search for duplicate words in a string using <b>\b(\w+)\W+\1\b</b> which means match a word boundary followed by one or more word characters followed by one or more non-word characters followed by the same text as the first parenthesised expression followed by a word boundary. If we want to use parentheses purely for grouping and not for capturing we can use the non-capturing syntax, e.g. <b>(?:green|blue)</b>. Non-capturing parentheses begin '(?:' and end ')'. In this example we match either 'green' or 'blue' but we do not capture the match so we only know whether or not we matched but not which color we actually found. Using non-capturing parentheses is more efficient than using capturing parentheses since the regexp engine has to do less book-keeping. Both capturing and non-capturing parentheses may be nested. \target assertions \section1 Assertions Assertions make some statement about the text at the point where they occur in the regexp but they do not match any characters. In the following list <b>\e {E}</b> stands for any expression. \table \row \i <b>^</b> \i The caret signifies the beginning of the string. If you wish to match a literal \c{^} you must escape it by writing \c{\\^}. For example, <b>^#include</b> will only match strings which \e begin with the characters '#include'. (When the caret is the first character of a character set it has a special meaning, see \link #sets-of-characters Sets of Characters \endlink.) \row \i <b>$</b> \i The dollar signifies the end of the string. For example <b>\d\s*$</b> will match strings which end with a digit optionally followed by whitespace. If you wish to match a literal \c{$} you must escape it by writing \c{\\$}. \row \i <b>\\b</b> \i A word boundary. For example the regexp <b>\\bOK\\b</b> means match immediately after a word boundary (e.g. start of string or whitespace) the letter 'O' then the letter 'K' immediately before another word boundary (e.g. end of string or whitespace). But note that the assertion does not actually match any whitespace so if we write <b>(\\bOK\\b)</b> and we have a match it will only contain 'OK' even if the string is "Its <u>OK</u> now". \row \i <b>\\B</b> \i A non-word boundary. This assertion is true wherever <b>\\b</b> is false. For example if we searched for <b>\\Bon\\B</b> in "Left on" the match would fail (space and end of string aren't non-word boundaries), but it would match in "t<u>on</u>ne". \row \i <b>(?=\e E)</b> \i Positive lookahead. This assertion is true if the expression matches at this point in the regexp. For example, <b>const(?=\\s+char)</b> matches 'const' whenever it is followed by 'char', as in 'static <u>const</u> char *'. (Compare with <b>const\\s+char</b>, which matches 'static <u>const char</u> *'.) \row \i <b>(?!\e E)</b> \i Negative lookahead. This assertion is true if the expression does not match at this point in the regexp. For example, <b>const(?!\\s+char)</b> matches 'const' \e except when it is followed by 'char'. \endtable \target wildcard-matching \section1 Wildcard Matching (globbing) Most command shells such as \e bash or \e cmd.exe support "file globbing", the ability to identify a group of files by using wildcards. The setWildcard() function is used to switch between regexp and wildcard mode. Wildcard matching is much simpler than full regexps and has only four features: \table \row \i <b>c</b> \i Any character represents itself apart from those mentioned below. Thus <b>c</b> matches the character \e c. \row \i <b>?</b> \i This matches any single character. It is the same as <b>.</b> in full regexps. \row \i <b>*</b> \i This matches zero or more of any characters. It is the same as <b>.*</b> in full regexps. \row \i <b>[...]</b> \i Sets of characters can be represented in square brackets, similar to full regexps. Within the character class, like outside, backslash has no special meaning. \endtable For example if we are in wildcard mode and have strings which contain filenames we could identify HTML files with <b>*.html</b>. This will match zero or more characters followed by a dot followed by 'h', 't', 'm' and 'l'. \target perl-users \section1 Notes for Perl Users Most of the character class abbreviations supported by Perl are supported by QRegExp, see \link #characters-and-abbreviations-for-sets-of-characters characters and abbreviations for sets of characters \endlink. In QRegExp, apart from within character classes, \c{^} always signifies the start of the string, so carets must always be escaped unless used for that purpose. In Perl the meaning of caret varies automagically depending on where it occurs so escaping it is rarely necessary. The same applies to \c{$} which in QRegExp always signifies the end of the string. QRegExp's quantifiers are the same as Perl's greedy quantifiers. Non-greedy matching cannot be applied to individual quantifiers, but can be applied to all the quantifiers in the pattern. For example, to match the Perl regexp <b>ro+?m</b> requires: \code QRegExp rx( "ro+m" ); rx.setMinimal( TRUE ); \endcode The equivalent of Perl's \c{/i} option is setCaseSensitive(FALSE). Perl's \c{/g} option can be emulated using a \link #cap_in_a_loop loop \endlink. In QRegExp <b>.</b> matches any character, therefore all QRegExp regexps have the equivalent of Perl's \c{/s} option. QRegExp does not have an equivalent to Perl's \c{/m} option, but this can be emulated in various ways for example by splitting the input into lines or by looping with a regexp that searches for newlines. Because QRegExp is string oriented there are no \A, \Z or \z assertions. The \G assertion is not supported but can be emulated in a loop. Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp equivalents for $`, $' or $+. Perl's capturing variables, $1, $2, ... correspond to cap(1) or capturedTexts()[1], cap(2) or capturedTexts()[2], etc. To substitute a pattern use QString::replace(). Perl's extended \c{/x} syntax is not supported, nor are - regexp comments (?#comment) or directives, e.g. (?i). + directives, e.g. (?i), or regexp comments, e.g. (?#comment). On + the other hand, C++'s rules for literal strings can be used to + achieve the same: + \code + QRegExp mark( "\\b" // word boundary + "[Mm]ark" // the word we want to match + ); + \endcode Both zero-width positive and zero-width negative lookahead assertions (?=pattern) and (?!pattern) are supported with the same syntax as Perl. Perl's lookbehind assertions, "independent" subexpressions and conditional expressions are not supported. Non-capturing parentheses are also supported, with the same (?:pattern) syntax. See QStringList::split() and QStringList::join() for equivalents to Perl's split and join functions. Note: because C++ transforms \\'s they must be written \e twice in code, e.g. <b>\\b</b> must be written <b>\\\\b</b>. \target code-examples \section1 Code Examples \code QRegExp rx( "^\\d\\d?$" ); // match integers 0 to 99 rx.search( "123" ); // returns -1 (no match) rx.search( "-6" ); // returns -1 (no match) rx.search( "6" ); // returns 0 (matched as position 0) \endcode The third string matches '<u>6</u>'. This is a simple validation regexp for integers in the range 0 to 99. \code QRegExp rx( "^\\S+$" ); // match strings without whitespace rx.search( "Hello world" ); // returns -1 (no match) rx.search( "This_is-OK" ); // returns 0 (matched at position 0) \endcode The second string matches '<u>This_is-OK</u>'. We've used the character set abbreviation '\S' (non-whitespace) and the anchors to match strings which contain no whitespace. In the following example we match strings containing 'mail' or 'letter' or 'correspondence' but only match whole words i.e. not 'email' \code QRegExp rx( "\\b(mail|letter|correspondence)\\b" ); rx.search( "I sent you an email" ); // returns -1 (no match) rx.search( "Please write the letter" ); // returns 17 \endcode The second string matches "Please write the <u>letter</u>". The word 'letter' is also captured (because of the parentheses). We can see what text we've captured like this: \code QString captured = rx.cap( 1 ); // captured == "letter" \endcode This will capture the text from the first set of capturing parentheses (counting capturing left parentheses from left to right). The parentheses are counted from 1 since cap( 0 ) is the whole matched regexp (equivalent to '&' in most regexp engines). \code QRegExp rx( "&(?!amp;)" ); // match ampersands but not & QString line1 = "This & that"; line1.replace( rx, "&" ); // line1 == "This & that" QString line2 = "His & hers & theirs"; line2.replace( rx, "&" ); // line2 == "His & hers & theirs" \endcode Here we've passed the QRegExp to QString's replace() function to replace the matched text with new text. \code QString str = "One Eric another Eirik, and an Ericsson." " How many Eiriks, Eric?"; QRegExp rx( "\\b(Eric|Eirik)\\b" ); // match Eric or Eirik int pos = 0; // where we are in the string int count = 0; // how many Eric and Eirik's we've counted while ( pos >= 0 ) { pos = rx.search( str, pos ); if ( pos >= 0 ) { pos++; // move along in str count++; // count our Eric or Eirik } } \endcode We've used the search() function to repeatedly match the regexp in the string. Note that instead of moving forward by one character at a time \c pos++ we could have written \c {pos += rx.matchedLength()} to skip over the already matched string. The count will equal 3, matching 'One <u>Eric</u> another <u>Eirik</u>, and an Ericsson. How many Eiriks, <u>Eric</u>?'; it doesn't match 'Ericsson' or 'Eiriks' because they are not bounded by non-word boundaries. One common use of regexps is to split lines of delimited data into their component fields. \code str = "Trolltech AS\twww.trolltech.com\tNorway"; QString company, web, country; rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" ); if ( rx.search( str ) != -1 ) { company = rx.cap( 1 ); web = rx.cap( 2 ); country = rx.cap( 3 ); } \endcode In this example our input lines have the format company name, web address and country. Unfortunately the regexp is rather long and not very versatile -- the code will break if we add any more fields. A simpler and better solution is to look for the separator, '\t' in this case, and take the surrounding text. The QStringList split() function can take a separator string or regexp as an argument and split a string accordingly. \code QStringList field = QStringList::split( "\t", str ); \endcode Here field[0] is the company, field[1] the web address and so on. To imitate the matching of a shell we can use wildcard mode. \code QRegExp rx( "*.html" ); // invalid regexp: * doesn't quantify anything rx.setWildcard( TRUE ); // now it's a valid wildcard regexp - rx.search( "index.html" ); // returns 0 (matched at position 0) - rx.search( "default.htm" ); // returns -1 (no match) - rx.search( "readme.txt" ); // returns -1 (no match) + rx.exactMatch( "index.html" ); // returns TRUE + rx.exactMatch( "default.htm" ); // returns FALSE + rx.exactMatch( "readme.txt" ); // returns FALSE \endcode Wildcard matching can be convenient because of its simplicity, but any wildcard regexp can be defined using full regexps, e.g. <b>.*\.html$</b>. Notice that we can't match both \c .html and \c .htm files with a wildcard unless we use <b>*.htm*</b> which will also match 'test.html.bak'. A full regexp gives us the precision we need, <b>.*\\.html?$</b>. QRegExp can match case insensitively using setCaseSensitive(), and can use non-greedy matching, see setMinimal(). By default QRegExp uses full regexps but this can be changed with setWildcard(). Searching can be forward with search() or backward with searchRev(). Captured text can be accessed using capturedTexts() which returns a string list of all captured strings, or using cap() which returns the captured string for the given index. The pos() function takes a match index and returns the position in the string where the match was made (or -1 if there was no match). \sa QRegExpValidator QString QStringList \target member-function-documentation */ const int NumBadChars = 64; #define BadChar( ch ) ( (ch).unicode() % NumBadChars ) const int NoOccurrence = INT_MAX; const int EmptyCapture = INT_MAX; const int InftyLen = INT_MAX; const int InftyRep = 1025; const int EOS = -1; +static bool isWord( QChar ch ) +{ + return ch.isLetterOrNumber() || ch == QChar( '_' ); +} + /* Merges two QMemArrays of ints and puts the result into the first one. */ static void mergeInto( QMemArray<int> *a, const QMemArray<int>& b ) { int asize = a->size(); int bsize = b.size(); if ( asize == 0 ) { *a = b.copy(); #ifndef QT_NO_REGEXP_OPTIM } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) { a->resize( asize + 1 ); (*a)[asize] = b[0]; #endif } else if ( bsize >= 1 ) { int csize = asize + bsize; QMemArray<int> c( csize ); int i = 0, j = 0, k = 0; while ( i < asize ) { if ( j < bsize ) { if ( (*a)[i] == b[j] ) { i++; csize--; } else if ( (*a)[i] < b[j] ) { c[k++] = (*a)[i++]; } else { c[k++] = b[j++]; } } else { memcpy( c.data() + k, (*a).data() + i, (asize - i) * sizeof(int) ); break; } } c.resize( csize ); if ( j < bsize ) memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) ); *a = c; } } /* Merges two disjoint QMaps of (int, int) pairs and puts the result into the first one. */ static void mergeInto( QMap<int, int> *a, const QMap<int, int>& b ) { QMap<int, int>::ConstIterator it; for ( it = b.begin(); it != b.end(); ++it ) a->insert( it.key(), *it ); } /* Returns the value associated to key k in QMap m of (int, int) pairs, or 0 if no such value is explicitly present. */ static int at( const QMap<int, int>& m, int k ) { QMap<int, int>::ConstIterator it = m.find( k ); if ( it == m.end() ) return 0; else return *it; } #ifndef QT_NO_REGEXP_WILDCARD /* Translates a wildcard pattern to an equivalent regular expression pattern (e.g., *.cpp to .*\.cpp). */ static QString wc2rx( const QString& wc_str ) { int wclen = wc_str.length(); QString rx = QString::fromLatin1( "" ); int i = 0; const QChar *wc = wc_str.unicode(); while ( i < wclen ) { QChar c = wc[i++]; switch ( c.unicode() ) { case '*': rx += QString::fromLatin1( ".*" ); break; case '?': rx += QChar( '.' ); break; case '$': case '(': case ')': case '+': case '.': case '\\': case '^': case '{': case '|': case '}': rx += QChar( '\\' ); rx += c; break; case '[': rx += c; if ( wc[i] == QChar('^') ) rx += wc[i++]; if ( i < wclen ) { if ( rx[i] == ']' ) rx += wc[i++]; while ( i < wclen && wc[i] != QChar(']') ) { if ( wc[i] == '\\' ) rx += QChar( '\\' ); rx += wc[i++]; } } break; default: rx += c; } } return rx; } #endif /* The class QRegExpEngine encapsulates a modified nondeterministic finite automaton (NFA). */ class QRegExpEngine : public QShared { public: #ifndef QT_NO_REGEXP_CCLASS /* The class CharClass represents a set of characters, such as can be found in regular expressions (e.g., [a-z] denotes the set {a, b, ..., z}). */ class CharClass { public: CharClass(); CharClass( const CharClass& cc ) { operator=( cc ); } CharClass& operator=( const CharClass& cc ); void clear(); bool negative() const { return n; } void setNegative( bool negative ); void addCategories( int cats ); void addRange( ushort from, ushort to ); void addSingleton( ushort ch ) { addRange( ch, ch ); } bool in( QChar ch ) const; #ifndef QT_NO_REGEXP_OPTIM const QMemArray<int>& firstOccurrence() const { return occ1; } #endif #if defined(QT_DEBUG) void dump() const; #endif private: /* The struct Range represents a range of characters (e.g., [0-9] denotes range 48 to 57). */ struct Range { ushort from; // 48 ushort to; // 57 }; int c; // character classes QMemArray<Range> r; // character ranges bool n; // negative? #ifndef QT_NO_REGEXP_OPTIM QMemArray<int> occ1; // first-occurrence array #endif }; #else struct CharClass { int dummy; #ifndef QT_NO_REGEXP_OPTIM CharClass() { occ1.fill( 0, NumBadChars ); } const QMemArray<int>& firstOccurrence() const { return occ1; } QMemArray<int> occ1; #endif }; #endif QRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); } QRegExpEngine( const QString& rx, bool caseSensitive ); #ifndef QT_NO_REGEXP_OPTIM ~QRegExpEngine(); #endif bool isValid() const { return valid; } const QString& errorString() const { return yyError; } bool caseSensitive() const { return cs; } int numCaptures() const { return officialncap; } QMemArray<int> match( const QString& str, int pos, bool minimal, bool oneTest, int caretIndex ); int matchedLength() const { return mmMatchedLen; } int createState( QChar ch ); int createState( const CharClass& cc ); #ifndef QT_NO_REGEXP_BACKREF int createState( int bref ); #endif void addCatTransitions( const QMemArray<int>& from, const QMemArray<int>& to ); #ifndef QT_NO_REGEXP_CAPTURE void addPlusTransitions( const QMemArray<int>& from, const QMemArray<int>& to, int atom ); #endif #ifndef QT_NO_REGEXP_ANCHOR_ALT int anchorAlternation( int a, int b ); int anchorConcatenation( int a, int b ); #else int anchorAlternation( int a, int b ) { return a & b; } int anchorConcatenation( int a, int b ) { return a | b; } #endif void addAnchors( int from, int to, int a ); #ifndef QT_NO_REGEXP_OPTIM void setupGoodStringHeuristic( int earlyStart, int lateStart, const QString& str ); void setupBadCharHeuristic( int minLen, const QMemArray<int>& firstOcc ); void heuristicallyChooseHeuristic(); #endif #if defined(QT_DEBUG) void dump() const; #endif private: enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; /* The struct State represents one state in a modified NFA. The input characters matched are stored in the state instead of on the transitions, something possible for an automaton constructed from a regular expression. */ struct State { #ifndef QT_NO_REGEXP_CAPTURE int atom; // which atom does this state belong to? #endif int match; // what does it match? (see CharClassBit and BackRefBit) QMemArray<int> outs; // out-transitions QMap<int, int> *reenter; // atoms reentered when transiting out QMap<int, int> *anchors; // anchors met when transiting out #ifndef QT_NO_REGEXP_CAPTURE State( int a, int m ) : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { } #else State( int m ) : match( m ), reenter( 0 ), anchors( 0 ) { } #endif ~State() { delete reenter; delete anchors; } }; #ifndef QT_NO_REGEXP_LOOKAHEAD /* The struct Lookahead represents a lookahead a la Perl (e.g., (?=foo) and (?!bar)). */ struct Lookahead { QRegExpEngine *eng; // NFA representing the embedded regular expression bool neg; // negative lookahead? Lookahead( QRegExpEngine *eng0, bool neg0 ) : eng( eng0 ), neg( neg0 ) { } ~Lookahead() { delete eng; } }; #endif #ifndef QT_NO_REGEXP_CAPTURE /* The struct Atom represents one node in the hierarchy of regular expression atoms. */ struct Atom { int parent; // index of parent in array of atoms int capture; // index of capture, from 1 to ncap }; #endif #ifndef QT_NO_REGEXP_ANCHOR_ALT /* The struct AnchorAlternation represents a pair of anchors with OR semantics. */ struct AnchorAlternation { int a; // this anchor... int b; // ...or this one }; #endif enum { InitialState = 0, FinalState = 1 }; void setup( bool caseSensitive ); int setupState( int match ); /* Let's hope that 13 lookaheads and 14 back-references are enough. */ enum { MaxLookaheads = 13, MaxBackRefs = 14 }; enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008, Anchor_FirstLookahead = 0x00000010, Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs, Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^ ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) }; #ifndef QT_NO_REGEXP_CAPTURE int startAtom( bool capture ); void finishAtom( int atom ) { cf = f[atom].parent; } #endif #ifndef QT_NO_REGEXP_LOOKAHEAD int addLookahead( QRegExpEngine *eng, bool negative ); #endif #ifndef QT_NO_REGEXP_CAPTURE bool isBetterCapture( const int *begin1, const int *end1, const int *begin2, const int *end2 ); #endif bool testAnchor( int i, int a, const int *capBegin ); #ifndef QT_NO_REGEXP_OPTIM bool goodStringMatch(); bool badCharMatch(); #else bool bruteMatch(); #endif bool matchHere(); QPtrVector<State> s; // array of states int ns; // number of states #ifndef QT_NO_REGEXP_CAPTURE QMemArray<Atom> f; // atom hierarchy int nf; // number of atoms int cf; // current atom #endif int officialncap; // number of captures, seen from the outside int ncap; // number of captures, seen from the inside #ifndef QT_NO_REGEXP_CCLASS QPtrVector<CharClass> cl; // array of character classes #endif #ifndef QT_NO_REGEXP_LOOKAHEAD QPtrVector<Lookahead> ahead; // array of lookaheads #endif #ifndef QT_NO_REGEXP_ANCHOR_ALT QMemArray<AnchorAlternation> aa; // array of (a, b) pairs of anchors #endif #ifndef QT_NO_REGEXP_OPTIM bool caretAnchored; // does the regexp start with ^? #endif bool valid; // is the regular expression valid? bool cs; // case sensitive? #ifndef QT_NO_REGEXP_BACKREF int nbrefs; // number of back-references #endif #ifndef QT_NO_REGEXP_OPTIM bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch int goodEarlyStart; // the index where goodStr can first occur in a match int goodLateStart; // the index where goodStr can last occur in a match QString goodStr; // the string that any match has to contain int minl; // the minimum length of a match QMemArray<int> occ1; // first-occurrence array #endif @@ -1299,771 +1311,771 @@ QMemArray<int> QRegExpEngine::match( const QString& str, int pos, bool minimal, mmCaptured[2 + 2 * j + 1] = len; } return mmCaptured; } else { return mmCapturedNoMatch; } } /* The three following functions add one state to the automaton and return the number of the state. */ int QRegExpEngine::createState( QChar ch ) { return setupState( ch.unicode() ); } int QRegExpEngine::createState( const CharClass& cc ) { #ifndef QT_NO_REGEXP_CCLASS int n = cl.size(); cl.resize( n + 1 ); cl.insert( n, new CharClass(cc) ); return setupState( CharClassBit | n ); #else Q_UNUSED( cc ); return setupState( CharClassBit ); #endif } #ifndef QT_NO_REGEXP_BACKREF int QRegExpEngine::createState( int bref ) { if ( bref > nbrefs ) { nbrefs = bref; if ( nbrefs > MaxBackRefs ) { error( RXERR_LIMIT ); return 0; } } return setupState( BackRefBit | bref ); } #endif /* The two following functions add a transition between all pairs of states (i, j) where i is fond in from, and j is found in to. Cat-transitions are distinguished from plus-transitions for capturing. */ void QRegExpEngine::addCatTransitions( const QMemArray<int>& from, const QMemArray<int>& to ) { for ( int i = 0; i < (int) from.size(); i++ ) { State *st = s[from[i]]; mergeInto( &st->outs, to ); } } #ifndef QT_NO_REGEXP_CAPTURE void QRegExpEngine::addPlusTransitions( const QMemArray<int>& from, const QMemArray<int>& to, int atom ) { for ( int i = 0; i < (int) from.size(); i++ ) { State *st = s[from[i]]; QMemArray<int> oldOuts = st->outs.copy(); mergeInto( &st->outs, to ); if ( f[atom].capture >= 0 ) { if ( st->reenter == 0 ) st->reenter = new QMap<int, int>; for ( int j = 0; j < (int) to.size(); j++ ) { if ( !st->reenter->contains(to[j]) && oldOuts.bsearch(to[j]) < 0 ) st->reenter->insert( to[j], atom ); } } } } #endif #ifndef QT_NO_REGEXP_ANCHOR_ALT /* Returns an anchor that means a OR b. */ int QRegExpEngine::anchorAlternation( int a, int b ) { if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 ) return a & b; int n = aa.size(); #ifndef QT_NO_REGEXP_OPTIM if ( n > 0 && aa[n - 1].a == a && aa[n - 1].b == b ) return Anchor_Alternation | ( n - 1 ); #endif aa.resize( n + 1 ); aa[n].a = a; aa[n].b = b; return Anchor_Alternation | n; } /* Returns an anchor that means a AND b. */ int QRegExpEngine::anchorConcatenation( int a, int b ) { if ( ((a | b) & Anchor_Alternation) == 0 ) return a | b; if ( (b & Anchor_Alternation) != 0 ) qSwap( a, b ); int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b ); int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b ); return anchorAlternation( aprime, bprime ); } #endif /* Adds anchor a on a transition caracterised by its from state and its to state. */ void QRegExpEngine::addAnchors( int from, int to, int a ) { State *st = s[from]; if ( st->anchors == 0 ) st->anchors = new QMap<int, int>; if ( st->anchors->contains(to) ) a = anchorAlternation( (*st->anchors)[to], a ); st->anchors->insert( to, a ); } #ifndef QT_NO_REGEXP_OPTIM /* The two following functions provide the engine with the information needed by its matching heuristics. */ void QRegExpEngine::setupGoodStringHeuristic( int earlyStart, int lateStart, const QString& str ) { goodEarlyStart = earlyStart; goodLateStart = lateStart; goodStr = cs ? str : str.lower(); } void QRegExpEngine::setupBadCharHeuristic( int minLen, const QMemArray<int>& firstOcc ) { minl = minLen; if ( cs ) { occ1 = firstOcc; } else { occ1.fill( 0, NumBadChars ); } } /* This function chooses between the good-string and the bad-character heuristics. It computes two scores and chooses the heuristic with the highest score. Here are some common-sense constraints on the scores that should be respected if the formulas are ever modified: (1) If goodStr is empty, the good-string heuristic scores 0. (2) If the search is case insensitive, the good-string heuristic should be used, unless it scores 0. (Case insensitivity turns all entries of occ1 to 0.) (3) If (goodLateStart - goodEarlyStart) is big, the good-string heuristic should score less. */ void QRegExpEngine::heuristicallyChooseHeuristic() { int i; if ( minl == 0 ) return; /* Magic formula: The good string has to constitute a good proportion of the minimum-length string, and appear at a more-or-less known index. */ int goodStringScore = ( 64 * goodStr.length() / minl ) - ( goodLateStart - goodEarlyStart ); /* Less magic formula: We pick a couple of characters at random, and check whether they are good or bad. */ int badCharScore = 0; int step = QMAX( 1, NumBadChars / 32 ); for ( i = 1; i < NumBadChars; i += step ) { if ( occ1[i] == NoOccurrence ) badCharScore += minl; else badCharScore += occ1[i]; } badCharScore /= minl; useGoodStringHeuristic = ( goodStringScore > badCharScore ); } #endif #if defined(QT_DEBUG) void QRegExpEngine::dump() const { int i, j; qDebug( "Case %ssensitive engine", cs ? "" : "in" ); qDebug( " States" ); for ( i = 0; i < ns; i++ ) { qDebug( " %d%s", i, i == InitialState ? " (initial)" : i == FinalState ? " (final)" : "" ); #ifndef QT_NO_REGEXP_CAPTURE qDebug( " in atom %d", s[i]->atom ); #endif int m = s[i]->match; if ( (m & CharClassBit) != 0 ) { qDebug( " match character class %d", m ^ CharClassBit ); #ifndef QT_NO_REGEXP_CCLASS cl[m ^ CharClassBit]->dump(); #else qDebug( " negative character class" ); #endif } else if ( (m & BackRefBit) != 0 ) { qDebug( " match back-reference %d", m ^ BackRefBit ); } else if ( m >= 0x20 && m <= 0x7e ) { qDebug( " match 0x%.4x (%c)", m, m ); } else { qDebug( " match 0x%.4x", m ); } for ( j = 0; j < (int) s[i]->outs.size(); j++ ) { int next = s[i]->outs[j]; qDebug( " -> %d", next ); if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) ) qDebug( " [reenter %d]", (*s[i]->reenter)[next] ); if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 ) qDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] ); } } #ifndef QT_NO_REGEXP_CAPTURE if ( nf > 0 ) { qDebug( " Atom Parent Capture" ); for ( i = 0; i < nf; i++ ) qDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture ); } #endif #ifndef QT_NO_REGEXP_ANCHOR_ALT for ( i = 0; i < (int) aa.size(); i++ ) qDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, aa[i].b ); #endif } #endif void QRegExpEngine::setup( bool caseSensitive ) { s.setAutoDelete( TRUE ); s.resize( 32 ); ns = 0; #ifndef QT_NO_REGEXP_CAPTURE f.resize( 32 ); nf = 0; cf = -1; #endif officialncap = 0; ncap = 0; #ifndef QT_NO_REGEXP_CCLASS cl.setAutoDelete( TRUE ); #endif #ifndef QT_NO_REGEXP_LOOKAHEAD ahead.setAutoDelete( TRUE ); #endif #ifndef QT_NO_REGEXP_OPTIM caretAnchored = TRUE; #endif valid = FALSE; cs = caseSensitive; #ifndef QT_NO_REGEXP_BACKREF nbrefs = 0; #endif #ifndef QT_NO_REGEXP_OPTIM useGoodStringHeuristic = FALSE; minl = 0; occ1.fill( 0, NumBadChars ); #endif mmCapturedNoMatch.fill( -1, 2 ); } int QRegExpEngine::setupState( int match ) { if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() ) s.resize( (ns + 1) << 1 ); #ifndef QT_NO_REGEXP_CAPTURE s.insert( ns, new State(cf, match) ); #else s.insert( ns, new State(match) ); #endif return ns++; } #ifndef QT_NO_REGEXP_CAPTURE /* Functions startAtom() and finishAtom() should be called to delimit atoms. When a state is created, it is assigned to the current atom. The information is later used for capturing. */ int QRegExpEngine::startAtom( bool capture ) { if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() ) f.resize( (nf + 1) << 1 ); f[nf].parent = cf; cf = nf++; f[cf].capture = capture ? ncap++ : -1; return cf; } #endif #ifndef QT_NO_REGEXP_LOOKAHEAD /* Creates a lookahead anchor. */ int QRegExpEngine::addLookahead( QRegExpEngine *eng, bool negative ) { int n = ahead.size(); if ( n == MaxLookaheads ) { error( RXERR_LIMIT ); return 0; } ahead.resize( n + 1 ); ahead.insert( n, new Lookahead(eng, negative) ); return Anchor_FirstLookahead << n; } #endif #ifndef QT_NO_REGEXP_CAPTURE /* We want the longest leftmost captures. */ bool QRegExpEngine::isBetterCapture( const int *begin1, const int *end1, const int *begin2, const int *end2 ) { for ( int i = 0; i < ncap; i++ ) { int delta = begin2[i] - begin1[i]; // it has to start early... if ( delta == 0 ) delta = end1[i] - end2[i]; // ...and end late (like a party) if ( delta != 0 ) return delta > 0; } return FALSE; } #endif /* Returns TRUE if anchor a matches at position mmPos + i in the input string, otherwise FALSE. */ bool QRegExpEngine::testAnchor( int i, int a, const int *capBegin ) { int j; #ifndef QT_NO_REGEXP_ANCHOR_ALT if ( (a & Anchor_Alternation) != 0 ) { return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) || testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin ); } #endif if ( (a & Anchor_Caret) != 0 ) { if ( mmPos + i != mmCaretPos ) return FALSE; } if ( (a & Anchor_Dollar) != 0 ) { if ( mmPos + i != mmLen ) return FALSE; } #ifndef QT_NO_REGEXP_ESCAPE if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) { bool before = FALSE; bool after = FALSE; if ( mmPos + i != 0 ) - before = mmIn[mmPos + i - 1].isLetterOrNumber(); + before = isWord( mmIn[mmPos + i - 1] ); if ( mmPos + i != mmLen ) - after = mmIn[mmPos + i].isLetterOrNumber(); + after = isWord( mmIn[mmPos + i] ); if ( (a & Anchor_Word) != 0 && (before == after) ) return FALSE; if ( (a & Anchor_NonWord) != 0 && (before != after) ) return FALSE; } #endif #ifndef QT_NO_REGEXP_LOOKAHEAD bool catchx = TRUE; if ( (a & Anchor_LookaheadMask) != 0 ) { QConstString cstr = QConstString( (QChar *) mmIn + mmPos + i, mmLen - mmPos - i ); for ( j = 0; j < (int) ahead.size(); j++ ) { if ( (a & (Anchor_FirstLookahead << j)) != 0 ) { catchx = ahead[j]->eng->match( cstr.string(), 0, TRUE, TRUE, mmCaretPos - mmPos - i )[0] == 0; if ( catchx == ahead[j]->neg ) return FALSE; } } } #endif #ifndef QT_NO_REGEXP_CAPTURE #ifndef QT_NO_REGEXP_BACKREF for ( j = 0; j < nbrefs; j++ ) { if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) { if ( capBegin[j] != EmptyCapture ) return FALSE; } } #endif #endif return TRUE; } #ifndef QT_NO_REGEXP_OPTIM /* The three following functions are what Jeffrey Friedl would call transmissions (or bump-alongs). Using one or the other should make no difference except in performance. */ bool QRegExpEngine::goodStringMatch() { int k = mmPos + goodEarlyStart; while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) { int from = k - goodLateStart; int to = k - goodEarlyStart; if ( from > mmPos ) mmPos = from; while ( mmPos <= to ) { if ( matchHere() ) return TRUE; mmPos++; } k++; } return FALSE; } bool QRegExpEngine::badCharMatch() { int slideHead = 0; int slideNext = 0; int i; int lastPos = mmLen - minl; memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) ); /* Set up the slide table, used for the bad-character heuristic, using the table of first occurrence of each character. */ for ( i = 0; i < minl; i++ ) { int sk = occ1[BadChar(mmIn[mmPos + i])]; if ( sk == NoOccurrence ) sk = i + 1; if ( sk > 0 ) { int k = i + 1 - sk; if ( k < 0 ) { sk = i + 1; k = 0; } if ( sk > mmSlideTab[k] ) mmSlideTab[k] = sk; } } if ( mmPos > lastPos ) return FALSE; for ( ;; ) { if ( ++slideNext >= mmSlideTabSize ) slideNext = 0; if ( mmSlideTab[slideHead] > 0 ) { if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] ) mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1; mmSlideTab[slideHead] = 0; } else { if ( matchHere() ) return TRUE; } if ( mmPos == lastPos ) break; /* Update the slide table. This code has much in common with the initialization code. */ int sk = occ1[BadChar(mmIn[mmPos + minl])]; if ( sk == NoOccurrence ) { mmSlideTab[slideNext] = minl; } else if ( sk > 0 ) { int k = slideNext + minl - sk; if ( k >= mmSlideTabSize ) k -= mmSlideTabSize; if ( sk > mmSlideTab[k] ) mmSlideTab[k] = sk; } slideHead = slideNext; mmPos++; } return FALSE; } #else bool QRegExpEngine::bruteMatch() { while ( mmPos <= mmLen ) { if ( matchHere() ) return TRUE; mmPos++; } return FALSE; } #endif /* Here's the core of the engine. It tries to do a match here and now. */ bool QRegExpEngine::matchHere() { int ncur = 1, nnext = 0; int i = 0, j, k, m; bool stop = FALSE; mmMatchLen = -1; mmMatchedLen = -1; mmCurStack[0] = InitialState; #ifndef QT_NO_REGEXP_CAPTURE if ( ncap > 0 ) { for ( j = 0; j < ncap; j++ ) { mmCurCapBegin[j] = EmptyCapture; mmCurCapEnd[j] = EmptyCapture; } } #endif #ifndef QT_NO_REGEXP_BACKREF int *zzZ = 0; while ( (ncur > 0 || !mmSleeping.isEmpty()) && i <= mmLen - mmPos && !stop ) #else while ( ncur > 0 && i <= mmLen - mmPos && !stop ) #endif { int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0; for ( j = 0; j < ncur; j++ ) { int cur = mmCurStack[j]; State *scur = s[cur]; QMemArray<int>& outs = scur->outs; for ( k = 0; k < (int) outs.size(); k++ ) { int next = outs[k]; State *snext = s[next]; bool in = TRUE; #ifndef QT_NO_REGEXP_BACKREF int needSomeSleep = 0; #endif /* First, check if the anchors are anchored properly. */ if ( scur->anchors != 0 ) { int a = at( *scur->anchors, next ); if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) ) in = FALSE; } /* If indeed they are, check if the input character is correct for this transition. */ if ( in ) { m = snext->match; if ( (m & (CharClassBit | BackRefBit)) == 0 ) { if ( cs ) in = ( m == ch ); else in = ( QChar(m).lower() == QChar(ch).lower() ); } else if ( next == FinalState ) { mmMatchLen = i; stop = mmMinimal; in = TRUE; } else if ( (m & CharClassBit) != 0 ) { #ifndef QT_NO_REGEXP_CCLASS const CharClass *cc = cl[m ^ CharClassBit]; if ( cs ) in = cc->in( ch ); else if ( cc->negative() ) in = cc->in( QChar(ch).lower() ) && cc->in( QChar(ch).upper() ); else in = cc->in( QChar(ch).lower() ) || cc->in( QChar(ch).upper() ); #endif #ifndef QT_NO_REGEXP_BACKREF } else { /* ( (m & BackRefBit) != 0 ) */ int bref = m ^ BackRefBit; int ell = j * ncap + ( bref - 1 ); in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture; if ( in ) { if ( cs ) in = ( mmIn[mmPos + mmCurCapBegin[ell]] == QChar(ch) ); else in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower() == QChar(ch).lower() ); } if ( in ) { int delta; if ( mmCurCapEnd[ell] == EmptyCapture ) delta = i - mmCurCapBegin[ell]; else delta = mmCurCapEnd[ell] - mmCurCapBegin[ell]; in = ( delta <= mmLen - (mmPos + i) ); if ( in && delta > 1 ) { int n = 1; if ( cs ) { while ( n < delta ) { if ( mmIn[mmPos + mmCurCapBegin[ell] + n] != mmIn[mmPos + i + n] ) break; n++; } } else { while ( n < delta ) { QChar a = mmIn[mmPos + mmCurCapBegin[ell] + n]; QChar b = mmIn[mmPos + i + n]; if ( a.lower() != b.lower() ) break; n++; } } in = ( n == delta ); if ( in ) needSomeSleep = delta - 1; } } #endif } } /* We must now update our data structures. */ if ( in ) { #ifndef QT_NO_REGEXP_CAPTURE int *capBegin, *capEnd; #endif /* If the next state was not encountered yet, all is fine. */ if ( (m = mmInNextStack[next]) == -1 ) { m = nnext++; mmNextStack[m] = next; mmInNextStack[next] = m; #ifndef QT_NO_REGEXP_CAPTURE capBegin = mmNextCapBegin + m * ncap; capEnd = mmNextCapEnd + m * ncap; /* Otherwise, we'll first maintain captures in temporary arrays, and decide at the end whether it's best to keep the previous capture zones or the new ones. */ } else { capBegin = mmTempCapBegin; capEnd = mmTempCapEnd; #endif } #ifndef QT_NO_REGEXP_CAPTURE /* Updating the capture zones is much of a task. */ if ( ncap > 0 ) { memcpy( capBegin, mmCurCapBegin + j * ncap, ncap * sizeof(int) ); memcpy( capEnd, mmCurCapEnd + j * ncap, ncap * sizeof(int) ); int c = scur->atom, n = snext->atom; int p = -1, q = -1; int cap; /* Lemma 1. For any x in the range [0..nf), we have f[x].parent < x. Proof. By looking at startAtom(), it is clear that cf < nf holds all the time, and thus that f[nf].parent < nf. */ /* If we are reentering an atom, we empty all capture zones inside it. */ if ( scur->reenter != 0 && (q = at(*scur->reenter, next)) != 0 ) { QBitArray b; b.fill( FALSE, nf ); b.setBit( q, TRUE ); for ( int ell = q + 1; ell < nf; ell++ ) { if ( b.testBit(f[ell].parent) ) { b.setBit( ell, TRUE ); cap = f[ell].capture; if ( cap >= 0 ) { capBegin[cap] = EmptyCapture; capEnd[cap] = EmptyCapture; } } } p = f[q].parent; /* Otherwise, close the capture zones we are leaving. We are leaving f[c].capture, f[f[c].parent].capture, f[f[f[c].parent].parent].capture, ..., until f[x].capture, with x such that f[x].parent is the youngest common ancestor for c and n. We go up along c's and n's ancestry until we find x. */ } else { p = c; q = n; while ( p != q ) { if ( p > q ) { cap = f[p].capture; if ( cap >= 0 ) { if ( capBegin[cap] == i ) { capBegin[cap] = EmptyCapture; capEnd[cap] = EmptyCapture; } else { capEnd[cap] = i; } } p = f[p].parent; } else { q = f[q].parent; } } } /* In any case, we now open the capture zones we are entering. We work upwards from n until we reach p (the parent of the atom we reenter or the youngest common ancestor). */ while ( n > p ) { cap = f[n].capture; @@ -2251,1685 +2263,1681 @@ void QRegExpEngine::CharClass::addRange( ushort from, ushort to ) occ1[i] = 0; } else { for ( i = 0; i <= to % NumBadChars; i++ ) occ1[i] = 0; for ( i = from % NumBadChars; i < NumBadChars; i++ ) occ1[i] = 0; } } else { occ1.fill( 0, NumBadChars ); } #endif } bool QRegExpEngine::CharClass::in( QChar ch ) const { #ifndef QT_NO_REGEXP_OPTIM if ( occ1[BadChar(ch)] == NoOccurrence ) return n; #endif if ( c != 0 && (c & (1 << (int) ch.category())) != 0 ) return !n; for ( int i = 0; i < (int) r.size(); i++ ) { if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to ) return !n; } return n; } #if defined(QT_DEBUG) void QRegExpEngine::CharClass::dump() const { int i; qDebug( " %stive character class", n ? "nega" : "posi" ); #ifndef QT_NO_REGEXP_CCLASS if ( c != 0 ) qDebug( " categories 0x%.8x", c ); #endif for ( i = 0; i < (int) r.size(); i++ ) qDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to ); } #endif #endif QRegExpEngine::Box::Box( QRegExpEngine *engine ) : eng( engine ), skipanchors( 0 ) #ifndef QT_NO_REGEXP_OPTIM , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ) #endif { #ifndef QT_NO_REGEXP_OPTIM occ1.fill( NoOccurrence, NumBadChars ); #endif minl = 0; } QRegExpEngine::Box& QRegExpEngine::Box::operator=( const Box& b ) { eng = b.eng; ls = b.ls; rs = b.rs; lanchors = b.lanchors; ranchors = b.ranchors; skipanchors = b.skipanchors; #ifndef QT_NO_REGEXP_OPTIM earlyStart = b.earlyStart; lateStart = b.lateStart; str = b.str; leftStr = b.leftStr; rightStr = b.rightStr; maxl = b.maxl; occ1 = b.occ1; #endif minl = b.minl; return *this; } void QRegExpEngine::Box::set( QChar ch ) { ls.resize( 1 ); ls[0] = eng->createState( ch ); rs = ls; rs.detach(); #ifndef QT_NO_REGEXP_OPTIM str = ch; leftStr = ch; rightStr = ch; maxl = 1; occ1.detach(); occ1[BadChar(ch)] = 0; #endif minl = 1; } void QRegExpEngine::Box::set( const CharClass& cc ) { ls.resize( 1 ); ls[0] = eng->createState( cc ); rs = ls; rs.detach(); #ifndef QT_NO_REGEXP_OPTIM maxl = 1; occ1 = cc.firstOccurrence(); #endif minl = 1; } #ifndef QT_NO_REGEXP_BACKREF void QRegExpEngine::Box::set( int bref ) { ls.resize( 1 ); ls[0] = eng->createState( bref ); rs = ls; rs.detach(); if ( bref >= 1 && bref <= MaxBackRefs ) skipanchors = Anchor_BackRef0Empty << bref; #ifndef QT_NO_REGEXP_OPTIM maxl = InftyLen; #endif minl = 0; } #endif void QRegExpEngine::Box::cat( const Box& b ) { eng->addCatTransitions( rs, b.ls ); addAnchorsToEngine( b ); if ( minl == 0 ) { mergeInto( &lanchors, b.lanchors ); if ( skipanchors != 0 ) { for ( int i = 0; i < (int) b.ls.size(); i++ ) { int a = eng->anchorConcatenation( at(lanchors, b.ls[i]), skipanchors ); lanchors.insert( b.ls[i], a ); } } mergeInto( &ls, b.ls ); } if ( b.minl == 0 ) { mergeInto( &ranchors, b.ranchors ); if ( b.skipanchors != 0 ) { for ( int i = 0; i < (int) rs.size(); i++ ) { int a = eng->anchorConcatenation( at(ranchors, rs[i]), b.skipanchors ); ranchors.insert( rs[i], a ); } } mergeInto( &rs, b.rs ); } else { ranchors = b.ranchors; rs = b.rs; } #ifndef QT_NO_REGEXP_OPTIM if ( maxl != InftyLen ) { if ( rightStr.length() + b.leftStr.length() > QMAX(str.length(), b.str.length()) ) { earlyStart = minl - rightStr.length(); lateStart = maxl - rightStr.length(); str = rightStr + b.leftStr; } else if ( b.str.length() > str.length() ) { earlyStart = minl + b.earlyStart; lateStart = maxl + b.lateStart; str = b.str; } } if ( (int) leftStr.length() == maxl ) leftStr += b.leftStr; if ( (int) b.rightStr.length() == b.maxl ) rightStr += b.rightStr; else rightStr = b.rightStr; if ( maxl == InftyLen || b.maxl == InftyLen ) maxl = InftyLen; else maxl += b.maxl; occ1.detach(); for ( int i = 0; i < NumBadChars; i++ ) { if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] ) occ1[i] = minl + b.occ1[i]; } #endif minl += b.minl; if ( minl == 0 ) skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors ); else skipanchors = 0; } void QRegExpEngine::Box::orx( const Box& b ) { mergeInto( &ls, b.ls ); mergeInto( &lanchors, b.lanchors ); mergeInto( &rs, b.rs ); mergeInto( &ranchors, b.ranchors ); if ( b.minl == 0 ) { if ( minl == 0 ) skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors ); else skipanchors = b.skipanchors; } #ifndef QT_NO_REGEXP_OPTIM occ1.detach(); for ( int i = 0; i < NumBadChars; i++ ) { if ( occ1[i] > b.occ1[i] ) occ1[i] = b.occ1[i]; } earlyStart = 0; lateStart = 0; str = QString(); leftStr = QString(); rightStr = QString(); if ( b.maxl > maxl ) maxl = b.maxl; #endif if ( b.minl < minl ) minl = b.minl; } void QRegExpEngine::Box::plus( int atom ) { #ifndef QT_NO_REGEXP_CAPTURE eng->addPlusTransitions( rs, ls, atom ); #else Q_UNUSED( atom ); eng->addCatTransitions( rs, ls ); #endif addAnchorsToEngine( *this ); #ifndef QT_NO_REGEXP_OPTIM maxl = InftyLen; #endif } void QRegExpEngine::Box::opt() { #ifndef QT_NO_REGEXP_OPTIM earlyStart = 0; lateStart = 0; str = QString(); leftStr = QString(); rightStr = QString(); #endif skipanchors = 0; minl = 0; } void QRegExpEngine::Box::catAnchor( int a ) { if ( a != 0 ) { for ( int i = 0; i < (int) rs.size(); i++ ) { a = eng->anchorConcatenation( at(ranchors, rs[i]), a ); ranchors.insert( rs[i], a ); } if ( minl == 0 ) skipanchors = eng->anchorConcatenation( skipanchors, a ); } } #ifndef QT_NO_REGEXP_OPTIM void QRegExpEngine::Box::setupHeuristics() { eng->setupGoodStringHeuristic( earlyStart, lateStart, str ); /* A regular expression such as 112|1 has occ1['2'] = 2 and minl = 1 at this point. An entry of occ1 has to be at most minl or infinity for the rest of the algorithm to go well. We waited until here before normalizing these cases (instead of doing it in Box::orx()) because sometimes things improve by themselves. Consider for example (112|1)34. */ for ( int i = 0; i < NumBadChars; i++ ) { if ( occ1[i] != NoOccurrence && occ1[i] >= minl ) occ1[i] = minl; } eng->setupBadCharHeuristic( minl, occ1 ); eng->heuristicallyChooseHeuristic(); } #endif #if defined(QT_DEBUG) void QRegExpEngine::Box::dump() const { int i; qDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" ); qDebug( " Left states:" ); for ( i = 0; i < (int) ls.size(); i++ ) { if ( at(lanchors, ls[i]) == 0 ) qDebug( " %d", ls[i] ); else qDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] ); } qDebug( " Right states:" ); for ( i = 0; i < (int) rs.size(); i++ ) { if ( at(ranchors, rs[i]) == 0 ) qDebug( " %d", rs[i] ); else qDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] ); } qDebug( " Skip anchors: 0x%.8x", skipanchors ); } #endif void QRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const { for ( int i = 0; i < (int) to.ls.size(); i++ ) { for ( int j = 0; j < (int) rs.size(); j++ ) { int a = eng->anchorConcatenation( at(ranchors, rs[j]), at(to.lanchors, to.ls[i]) ); eng->addAnchors( rs[j], to.ls[i], a ); } } } int QRegExpEngine::getChar() { return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode(); } int QRegExpEngine::getEscape() { #ifndef QT_NO_REGEXP_ESCAPE const char tab[] = "afnrtv"; // no b, as \b means word boundary const char backTab[] = "\a\f\n\r\t\v"; ushort low; int i; #endif ushort val; int prevCh = yyCh; if ( prevCh == EOS ) { error( RXERR_END ); return Tok_Char | '\\'; } yyCh = getChar(); #ifndef QT_NO_REGEXP_ESCAPE if ( (prevCh & ~0xff) == 0 ) { const char *p = strchr( tab, prevCh ); if ( p != 0 ) return Tok_Char | backTab[p - tab]; } #endif switch ( prevCh ) { #ifndef QT_NO_REGEXP_ESCAPE case '0': val = 0; for ( i = 0; i < 3; i++ ) { if ( yyCh >= '0' && yyCh <= '7' ) val = ( val << 3 ) | ( yyCh - '0' ); else break; yyCh = getChar(); } if ( (val & ~0377) != 0 ) error( RXERR_OCTAL ); return Tok_Char | val; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'B': return Tok_NonWord; #endif #ifndef QT_NO_REGEXP_CCLASS case 'D': // see QChar::isDigit() yyCharClass->addCategories( 0x7fffffef ); return Tok_CharClass; case 'S': // see QChar::isSpace() yyCharClass->addCategories( 0x7ffff87f ); yyCharClass->addRange( 0x0000, 0x0008 ); yyCharClass->addRange( 0x000e, 0x001f ); yyCharClass->addRange( 0x007f, 0x009f ); return Tok_CharClass; case 'W': // see QChar::isLetterOrNumber() - yyCharClass->addCategories( 0x7ff07f8f ); + yyCharClass->addCategories( 0x7fe07f8f ); + yyCharClass->addRange( 0x203f, 0x2040 ); + yyCharClass->addSingleton( 0x2040 ); + yyCharClass->addSingleton( 0x30fb ); + yyCharClass->addRange( 0xfe33, 0xfe34 ); + yyCharClass->addRange( 0xfe4d, 0xfe4f ); + yyCharClass->addSingleton( 0xff3f ); + yyCharClass->addSingleton( 0xff65 ); return Tok_CharClass; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'b': return Tok_Word; #endif #ifndef QT_NO_REGEXP_CCLASS case 'd': // see QChar::isDigit() yyCharClass->addCategories( 0x00000010 ); return Tok_CharClass; case 's': // see QChar::isSpace() yyCharClass->addCategories( 0x00000380 ); yyCharClass->addRange( 0x0009, 0x000d ); return Tok_CharClass; case 'w': // see QChar::isLetterOrNumber() yyCharClass->addCategories( 0x000f8070 ); + yyCharClass->addSingleton( 0x005f ); // '_' return Tok_CharClass; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'x': val = 0; for ( i = 0; i < 4; i++ ) { low = QChar( yyCh ).lower(); if ( low >= '0' && low <= '9' ) val = ( val << 4 ) | ( low - '0' ); else if ( low >= 'a' && low <= 'f' ) val = ( val << 4 ) | ( low - 'a' + 10 ); else break; yyCh = getChar(); } return Tok_Char | val; #endif default: if ( prevCh >= '1' && prevCh <= '9' ) { #ifndef QT_NO_REGEXP_BACKREF val = prevCh - '0'; while ( yyCh >= '0' && yyCh <= '9' ) { val = ( val *= 10 ) | ( yyCh - '0' ); yyCh = getChar(); } return Tok_BackRef | val; #else error( RXERR_DISABLED ); #endif } return Tok_Char | prevCh; } } #ifndef QT_NO_REGEXP_INTERVAL int QRegExpEngine::getRep( int def ) { if ( yyCh >= '0' && yyCh <= '9' ) { int rep = 0; do { rep = 10 * rep + yyCh - '0'; if ( rep >= InftyRep ) { error( RXERR_REPETITION ); rep = def; } yyCh = getChar(); } while ( yyCh >= '0' && yyCh <= '9' ); return rep; } else { return def; } } #endif #ifndef QT_NO_REGEXP_LOOKAHEAD void QRegExpEngine::skipChars( int n ) { if ( n > 0 ) { yyPos += n - 1; yyCh = getChar(); } } #endif void QRegExpEngine::error( const char *msg ) { if ( yyError.isEmpty() ) yyError = QString::fromLatin1( msg ); } void QRegExpEngine::startTokenizer( const QChar *rx, int len ) { yyIn = rx; yyPos0 = 0; yyPos = 0; yyLen = len; yyCh = getChar(); yyCharClass = new CharClass; yyMinRep = 0; yyMaxRep = 0; yyError = QString(); } int QRegExpEngine::getToken() { #ifndef QT_NO_REGEXP_CCLASS ushort pendingCh = 0; bool charPending; bool rangePending; int tok; #endif int prevCh = yyCh; yyPos0 = yyPos - 1; #ifndef QT_NO_REGEXP_CCLASS yyCharClass->clear(); #endif yyMinRep = 0; yyMaxRep = 0; yyCh = getChar(); switch ( prevCh ) { case EOS: yyPos0 = yyPos; return Tok_Eos; case '$': return Tok_Dollar; case '(': if ( yyCh == '?' ) { prevCh = getChar(); yyCh = getChar(); switch ( prevCh ) { #ifndef QT_NO_REGEXP_LOOKAHEAD case '!': return Tok_NegLookahead; case '=': return Tok_PosLookahead; #endif case ':': return Tok_MagicLeftParen; default: error( RXERR_LOOKAHEAD ); return Tok_MagicLeftParen; } } else { return Tok_LeftParen; } case ')': return Tok_RightParen; case '*': yyMinRep = 0; yyMaxRep = InftyRep; return Tok_Quantifier; case '+': yyMinRep = 1; yyMaxRep = InftyRep; return Tok_Quantifier; case '.': #ifndef QT_NO_REGEXP_CCLASS yyCharClass->setNegative( TRUE ); #endif return Tok_CharClass; case '?': yyMinRep = 0; yyMaxRep = 1; return Tok_Quantifier; case '[': #ifndef QT_NO_REGEXP_CCLASS if ( yyCh == '^' ) { yyCharClass->setNegative( TRUE ); yyCh = getChar(); } charPending = FALSE; rangePending = FALSE; do { if ( yyCh == '-' && charPending && !rangePending ) { rangePending = TRUE; yyCh = getChar(); } else { if ( charPending && !rangePending ) { yyCharClass->addSingleton( pendingCh ); charPending = FALSE; } if ( yyCh == '\\' ) { yyCh = getChar(); tok = getEscape(); if ( tok == Tok_Word ) tok = '\b'; } else { tok = Tok_Char | yyCh; yyCh = getChar(); } if ( tok == Tok_CharClass ) { if ( rangePending ) { yyCharClass->addSingleton( '-' ); yyCharClass->addSingleton( pendingCh ); charPending = FALSE; rangePending = FALSE; } } else if ( (tok & Tok_Char) != 0 ) { if ( rangePending ) { yyCharClass->addRange( pendingCh, tok ^ Tok_Char ); charPending = FALSE; rangePending = FALSE; } else { pendingCh = tok ^ Tok_Char; charPending = TRUE; } } else { error( RXERR_CHARCLASS ); } } } while ( yyCh != ']' && yyCh != EOS ); if ( rangePending ) yyCharClass->addSingleton( '-' ); if ( charPending ) yyCharClass->addSingleton( pendingCh ); if ( yyCh == EOS ) error( RXERR_END ); else yyCh = getChar(); return Tok_CharClass; #else error( RXERR_END ); return Tok_Char | '['; #endif case '\\': return getEscape(); case ']': error( RXERR_LEFTDELIM ); return Tok_Char | ']'; case '^': return Tok_Caret; case '{': #ifndef QT_NO_REGEXP_INTERVAL yyMinRep = getRep( 0 ); yyMaxRep = yyMinRep; if ( yyCh == ',' ) { yyCh = getChar(); yyMaxRep = getRep( InftyRep ); } if ( yyMaxRep < yyMinRep ) qSwap( yyMinRep, yyMaxRep ); if ( yyCh != '}' ) error( RXERR_REPETITION ); yyCh = getChar(); return Tok_Quantifier; #else error( RXERR_DISABLED ); return Tok_Char | '{'; #endif case '|': return Tok_Bar; case '}': error( RXERR_LEFTDELIM ); return Tok_Char | '}'; default: return Tok_Char | prevCh; } } int QRegExpEngine::parse( const QChar *pattern, int len ) { valid = TRUE; startTokenizer( pattern, len ); yyTok = getToken(); #ifndef QT_NO_REGEXP_CAPTURE yyMayCapture = TRUE; #else yyMayCapture = FALSE; #endif #ifndef QT_NO_REGEXP_CAPTURE int atom = startAtom( FALSE ); #endif CharClass anything; Box box( this ); // create InitialState box.set( anything ); Box rightBox( this ); // create FinalState rightBox.set( anything ); Box middleBox( this ); parseExpression( &middleBox ); #ifndef QT_NO_REGEXP_CAPTURE finishAtom( atom ); #endif #ifndef QT_NO_REGEXP_OPTIM middleBox.setupHeuristics(); #endif box.cat( middleBox ); box.cat( rightBox ); delete yyCharClass; yyCharClass = 0; officialncap = ncap; #ifndef QT_NO_REGEXP_BACKREF if ( nbrefs > ncap ) ncap = nbrefs; #endif mmCaptured.resize( 2 + 2 * officialncap ); mmCapturedNoMatch.fill( -1, 2 + 2 * officialncap ); /* We use one QMemArray<int> for all the big data used a lot in matchHere() and friends. */ #ifndef QT_NO_REGEXP_OPTIM mmSlideTabSize = QMAX( minl + 1, 16 ); #else mmSlideTabSize = 0; #endif mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize ); mmInNextStack = mmBigArray.data(); memset( mmInNextStack, -1, ns * sizeof(int) ); mmCurStack = mmInNextStack + ns; mmNextStack = mmInNextStack + 2 * ns; mmCurCapBegin = mmInNextStack + 3 * ns; mmNextCapBegin = mmCurCapBegin + ncap * ns; mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns; mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns; mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns; mmTempCapEnd = mmTempCapBegin + ncap; mmCapBegin = mmTempCapBegin + 2 * ncap; mmCapEnd = mmTempCapBegin + 3 * ncap; mmSlideTab = mmTempCapBegin + 4 * ncap; if ( !yyError.isEmpty() ) return -1; #ifndef QT_NO_REGEXP_OPTIM State *sinit = s[InitialState]; caretAnchored = ( sinit->anchors != 0 ); if ( caretAnchored ) { QMap<int, int>& anchors = *sinit->anchors; QMap<int, int>::ConstIterator a; for ( a = anchors.begin(); a != anchors.end(); ++a ) { #ifndef QT_NO_REGEXP_ANCHOR_ALT if ( (*a & Anchor_Alternation) != 0 ) break; #endif if ( (*a & Anchor_Caret) == 0 ) { caretAnchored = FALSE; break; } } } #endif return yyPos0; } void QRegExpEngine::parseAtom( Box *box ) { #ifndef QT_NO_REGEXP_LOOKAHEAD QRegExpEngine *eng = 0; bool neg; int len; #endif switch ( yyTok ) { case Tok_Dollar: box->catAnchor( Anchor_Dollar ); break; case Tok_Caret: box->catAnchor( Anchor_Caret ); break; #ifndef QT_NO_REGEXP_LOOKAHEAD case Tok_PosLookahead: case Tok_NegLookahead: neg = ( yyTok == Tok_NegLookahead ); eng = new QRegExpEngine( cs ); len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 ); if ( len >= 0 ) skipChars( len ); else error( RXERR_LOOKAHEAD ); box->catAnchor( addLookahead(eng, neg) ); yyTok = getToken(); if ( yyTok != Tok_RightParen ) error( RXERR_LOOKAHEAD ); break; #endif #ifndef QT_NO_REGEXP_ESCAPE case Tok_Word: box->catAnchor( Anchor_Word ); break; case Tok_NonWord: box->catAnchor( Anchor_NonWord ); break; #endif case Tok_LeftParen: case Tok_MagicLeftParen: yyTok = getToken(); parseExpression( box ); if ( yyTok != Tok_RightParen ) error( RXERR_END ); break; case Tok_CharClass: box->set( *yyCharClass ); break; case Tok_Quantifier: error( RXERR_REPETITION ); break; default: if ( (yyTok & Tok_Char) != 0 ) box->set( QChar(yyTok ^ Tok_Char) ); #ifndef QT_NO_REGEXP_BACKREF else if ( (yyTok & Tok_BackRef) != 0 ) box->set( yyTok ^ Tok_BackRef ); #endif else error( RXERR_DISABLED ); } yyTok = getToken(); } void QRegExpEngine::parseFactor( Box *box ) { #ifndef QT_NO_REGEXP_CAPTURE int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen ); #else static const int atom = 0; #endif #ifndef QT_NO_REGEXP_INTERVAL #define YYREDO() \ yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok const QChar *in = yyIn; int pos0 = yyPos0; int pos = yyPos; int len = yyLen; int ch = yyCh; CharClass charClass; if ( yyTok == Tok_CharClass ) charClass = *yyCharClass; int tok = yyTok; bool mayCapture = yyMayCapture; #endif parseAtom( box ); #ifndef QT_NO_REGEXP_CAPTURE finishAtom( atom ); #endif if ( yyTok == Tok_Quantifier ) { if ( yyMaxRep == InftyRep ) { box->plus( atom ); #ifndef QT_NO_REGEXP_INTERVAL } else if ( yyMaxRep == 0 ) { box->clear(); #endif } if ( yyMinRep == 0 ) box->opt(); #ifndef QT_NO_REGEXP_INTERVAL yyMayCapture = FALSE; int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1; int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 ); Box rightBox( this ); int i; for ( i = 0; i < beta; i++ ) { YYREDO(); Box leftBox( this ); parseAtom( &leftBox ); leftBox.cat( rightBox ); leftBox.opt(); rightBox = leftBox; } for ( i = 0; i < alpha; i++ ) { YYREDO(); Box leftBox( this ); parseAtom( &leftBox ); leftBox.cat( rightBox ); rightBox = leftBox; } rightBox.cat( *box ); *box = rightBox; #endif yyTok = getToken(); #ifndef QT_NO_REGEXP_INTERVAL yyMayCapture = mayCapture; #endif } #undef YYREDO } void QRegExpEngine::parseTerm( Box *box ) { #ifndef QT_NO_REGEXP_OPTIM if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) parseFactor( box ); #endif while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) { Box rightBox( this ); parseFactor( &rightBox ); box->cat( rightBox ); } } void QRegExpEngine::parseExpression( Box *box ) { parseTerm( box ); while ( yyTok == Tok_Bar ) { Box rightBox( this ); yyTok = getToken(); parseTerm( &rightBox ); box->orx( rightBox ); } } /* The struct QRegExpPrivate contains the private data of a regular expression other than the automaton. It makes it possible for many QRegExp objects to use the same QRegExpEngine object with different QRegExpPrivate objects. */ struct QRegExpPrivate { QString pattern; // regular-expression or wildcard pattern QString rxpattern; // regular-expression pattern #ifndef QT_NO_REGEXP_WILDCARD bool wc; // wildcard mode? #endif bool min; // minimal matching? (instead of maximal) #ifndef QT_NO_REGEXP_CAPTURE QString t; // last string passed to QRegExp::search() or searchRev() QStringList capturedCache; // what QRegExp::capturedTexts() returned last #endif QMemArray<int> captured; // what QRegExpEngine::search() returned last QRegExpPrivate() { captured.fill( -1, 2 ); } }; #ifndef QT_NO_REGEXP_OPTIM static QCache<QRegExpEngine> *engineCache = 0; static QSingleCleanupHandler<QCache<QRegExpEngine> > cleanup_cache; #endif static QRegExpEngine *newEngine( const QString& pattern, bool caseSensitive ) { #ifndef QT_NO_REGEXP_OPTIM if ( engineCache != 0 ) { #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &engineCache ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &engineCache ) : 0 ); #endif QRegExpEngine *eng = engineCache->take( pattern ); if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { delete eng; } else { eng->ref(); return eng; } } #endif return new QRegExpEngine( pattern, caseSensitive ); } static void derefEngine( QRegExpEngine *eng, const QString& pattern ) { - if ( eng != 0 && eng->deref() ) { -#ifndef QT_NO_REGEXP_OPTIM #ifdef QT_THREAD_SUPPORT - QMutexLocker locker( qt_global_mutexpool->get( &engineCache ) ); + QMutexLocker locker( qt_global_mutexpool ? + qt_global_mutexpool->get( &engineCache ) : 0 ); #endif + if ( eng != 0 && eng->deref() ) { +#ifndef QT_NO_REGEXP_OPTIM if ( engineCache == 0 ) { engineCache = new QCache<QRegExpEngine>; engineCache->setAutoDelete( TRUE ); cleanup_cache.set( &engineCache ); } if ( !pattern.isNull() && engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) return; #else Q_UNUSED( pattern ); #endif delete eng; } } /*! \enum QRegExp::CaretMode The CaretMode enum defines the different meanings of the caret (<b>^</b>) in a regular expression. The possible values are: \value CaretAtZero The caret corresponds to index 0 in the searched string. \value CaretAtOffset The caret corresponds to the start offset of the search. \value CaretWontMatch The caret never matches. */ /*! Constructs an empty regexp. \sa isValid() errorString() */ QRegExp::QRegExp() { eng = new QRegExpEngine( TRUE ); priv = new QRegExpPrivate; #ifndef QT_NO_REGEXP_WILDCARD priv->wc = FALSE; #endif priv->min = FALSE; compile( TRUE ); } /*! Constructs a regular expression object for the given \a pattern string. The pattern must be given using wildcard notation if \a wildcard is TRUE (default is FALSE). The pattern is case sensitive, unless \a caseSensitive is FALSE. Matching is greedy (maximal), but can be changed by calling setMinimal(). \sa setPattern() setCaseSensitive() setWildcard() setMinimal() */ QRegExp::QRegExp( const QString& pattern, bool caseSensitive, bool wildcard ) { eng = 0; priv = new QRegExpPrivate; priv->pattern = pattern; #ifndef QT_NO_REGEXP_WILDCARD priv->wc = wildcard; #endif priv->min = FALSE; compile( caseSensitive ); } /*! Constructs a regular expression as a copy of \a rx. \sa operator=() */ QRegExp::QRegExp( const QRegExp& rx ) { eng = 0; priv = new QRegExpPrivate; operator=( rx ); } /*! Destroys the regular expression and cleans up its internal data. */ QRegExp::~QRegExp() { derefEngine( eng, priv->rxpattern ); delete priv; } /*! Copies the regular expression \a rx and returns a reference to the copy. The case sensitivity, wildcard and minimal matching options are also copied. */ QRegExp& QRegExp::operator=( const QRegExp& rx ) { rx.eng->ref(); derefEngine( eng, priv->rxpattern ); eng = rx.eng; priv->pattern = rx.priv->pattern; priv->rxpattern = rx.priv->rxpattern; #ifndef QT_NO_REGEXP_WILDCARD priv->wc = rx.priv->wc; #endif priv->min = rx.priv->min; #ifndef QT_NO_REGEXP_CAPTURE priv->t = rx.priv->t; priv->capturedCache = rx.priv->capturedCache; #endif priv->captured = rx.priv->captured; return *this; } /*! Returns TRUE if this regular expression is equal to \a rx; otherwise returns FALSE. Two QRegExp objects are equal if they have the same pattern strings and the same settings for case sensitivity, wildcard and minimal matching. */ bool QRegExp::operator==( const QRegExp& rx ) const { return priv->pattern == rx.priv->pattern && eng->caseSensitive() == rx.eng->caseSensitive() && #ifndef QT_NO_REGEXP_WILDCARD priv->wc == rx.priv->wc && #endif priv->min == rx.priv->min; } /*! \fn bool QRegExp::operator!=( const QRegExp& rx ) const Returns TRUE if this regular expression is not equal to \a rx; otherwise returns FALSE. \sa operator==() */ /*! Returns TRUE if the pattern string is empty; otherwise returns FALSE. If you call exactMatch() with an empty pattern on an empty string it will return TRUE; otherwise it returns FALSE since it operates over the whole string. If you call search() with an empty pattern on \e any string it will return the start offset (0 by default) because the empty pattern matches the 'emptiness' at the start of the string. In this case the length of the match returned by matchedLength() will be 0. See QString::isEmpty(). */ bool QRegExp::isEmpty() const { return priv->pattern.isEmpty(); } /*! Returns TRUE if the regular expression is valid; otherwise returns FALSE. An invalid regular expression never matches. The pattern <b>[a-z</b> is an example of an invalid pattern, since it lacks a closing square bracket. Note that the validity of a regexp may also depend on the setting of the wildcard flag, for example <b>*.html</b> is a valid wildcard regexp but an invalid full regexp. \sa errorString() */ bool QRegExp::isValid() const { return eng->isValid(); } /*! Returns the pattern string of the regular expression. The pattern has either regular expression syntax or wildcard syntax, depending on wildcard(). \sa setPattern() */ QString QRegExp::pattern() const { return priv->pattern; } /*! Sets the pattern string to \a pattern. The case sensitivity, wildcard and minimal matching options are not changed. \sa pattern() */ void QRegExp::setPattern( const QString& pattern ) { if ( priv->pattern != pattern ) { priv->pattern = pattern; compile( caseSensitive() ); } } /*! Returns TRUE if case sensitivity is enabled; otherwise returns FALSE. The default is TRUE. \sa setCaseSensitive() */ bool QRegExp::caseSensitive() const { return eng->caseSensitive(); } /*! Sets case sensitive matching to \a sensitive. If \a sensitive is TRUE, <b>\\.txt$</b> matches \c{readme.txt} but not \c{README.TXT}. \sa caseSensitive() */ void QRegExp::setCaseSensitive( bool sensitive ) { if ( sensitive != eng->caseSensitive() ) compile( sensitive ); } #ifndef QT_NO_REGEXP_WILDCARD /*! Returns TRUE if wildcard mode is enabled; otherwise returns FALSE. The default is FALSE. \sa setWildcard() */ bool QRegExp::wildcard() const { return priv->wc; } /*! Sets the wildcard mode for the regular expression. The default is FALSE. Setting \a wildcard to TRUE enables simple shell-like wildcard matching. (See \link #wildcard-matching wildcard matching (globbing) \endlink.) For example, <b>r*.txt</b> matches the string \c{readme.txt} in wildcard mode, but does not match \c{readme}. \sa wildcard() */ void QRegExp::setWildcard( bool wildcard ) { if ( wildcard != priv->wc ) { priv->wc = wildcard; compile( caseSensitive() ); } } #endif /*! Returns TRUE if minimal (non-greedy) matching is enabled; otherwise returns FALSE. \sa setMinimal() */ bool QRegExp::minimal() const { return priv->min; } /*! Enables or disables minimal matching. If \a minimal is FALSE, matching is greedy (maximal) which is the default. For example, suppose we have the input string "We must be \<b>bold\</b>, very \<b>bold\</b>!" and the pattern <b>\<b>.*\</b></b>. With the default greedy (maximal) matching, the match is "We must be <u>\<b>bold\</b>, very \<b>bold\</b></u>!". But with minimal (non-greedy) matching the first match is: "We must be <u>\<b>bold\</b></u>, very \<b>bold\</b>!" and the second match is "We must be \<b>bold\</b>, very <u>\<b>bold\</b></u>!". In practice we might use the pattern <b>\<b>[^\<]+\</b></b> instead, although this will still fail for nested tags. \sa minimal() */ void QRegExp::setMinimal( bool minimal ) { priv->min = minimal; } /*! Returns TRUE if \a str is matched exactly by this regular expression; otherwise returns FALSE. You can determine how much of the string was matched by calling matchedLength(). For a given regexp string, R, exactMatch("R") is the equivalent of search("^R$") since exactMatch() effectively encloses the regexp in the start of string and end of string anchors, except that it sets matchedLength() differently. For example, if the regular expression is <b>blue</b>, then exactMatch() returns TRUE only for input \c blue. For inputs \c bluebell, \c blutak and \c lightblue, exactMatch() returns FALSE and matchedLength() will return 4, 3 and 0 respectively. Although const, this function sets matchedLength(), capturedTexts() and pos(). \sa search() searchRev() QRegExpValidator */ bool QRegExp::exactMatch( const QString& str ) const { #ifndef QT_NO_REGEXP_CAPTURE priv->t = str; priv->capturedCache.clear(); #endif priv->captured = eng->match( str, 0, priv->min, TRUE, 0 ); if ( priv->captured[1] == (int) str.length() ) { return TRUE; } else { priv->captured.detach(); priv->captured[0] = 0; priv->captured[1] = eng->matchedLength(); return FALSE; } } #ifndef QT_NO_COMPAT /*! \obsolete Attempts to match in \a str, starting from position \a index. Returns the position of the match, or -1 if there was no match. The length of the match is stored in \a *len, unless \a len is a null pointer. If \a indexIsStart is TRUE (the default), the position \a index in the string will match the start of string anchor, <b>^</b>, in the regexp, if present. Otherwise, position 0 in \a str will match. Use search() and matchedLength() instead of this function. \sa QString::mid() QConstString */ int QRegExp::match( const QString& str, int index, int *len, bool indexIsStart ) const { int pos = search( str, index, indexIsStart ? CaretAtOffset : CaretAtZero ); if ( len != 0 ) *len = matchedLength(); return pos; } #endif // QT_NO_COMPAT -/*! - \overload - - This convenience function searches with a \c CaretMode of \c - CaretAtZero which is the most common usage. -*/ - int QRegExp::search( const QString& str, int offset ) const { return search( str, offset, CaretAtZero ); } /*! Attempts to find a match in \a str from position \a offset (0 by default). If \a offset is -1, the search starts at the last character; if -2, at the next to last character; etc. Returns the position of the first match, or -1 if there was no match. The \a caretMode parameter can be used to instruct whether <b>^</b> should match at index 0 or at \a offset. You might prefer to use QString::find(), QString::contains() or even QStringList::grep(). To replace matches use QString::replace(). Example: \code QString str = "offsets: 1.23 .50 71.00 6.00"; QRegExp rx( "\\d*\\.\\d+" ); // primitive floating point matching int count = 0; int pos = 0; while ( (pos = rx.search(str, pos)) != -1 ) { count++; pos += rx.matchedLength(); } // pos will be 9, 14, 18 and finally 24; count will end up as 4 \endcode Although const, this function sets matchedLength(), capturedTexts() and pos(). \sa searchRev() exactMatch() */ int QRegExp::search( const QString& str, int offset, CaretMode caretMode ) const { if ( offset < 0 ) offset += str.length(); #ifndef QT_NO_REGEXP_CAPTURE priv->t = str; priv->capturedCache.clear(); #endif priv->captured = eng->match( str, offset, priv->min, FALSE, caretIndex(offset, caretMode) ); return priv->captured[0]; } -/*! - \overload - - This convenience function searches with a \c CaretMode of \c - CaretAtZero which is the most common usage. -*/ - int QRegExp::searchRev( const QString& str, int offset ) const { return searchRev( str, offset, CaretAtZero ); } /*! Attempts to find a match backwards in \a str from position \a offset. If \a offset is -1 (the default), the search starts at the last character; if -2, at the next to last character; etc. Returns the position of the first match, or -1 if there was no match. The \a caretMode parameter can be used to instruct whether <b>^</b> should match at index 0 or at \a offset. Although const, this function sets matchedLength(), capturedTexts() and pos(). \warning Searching backwards is much slower than searching forwards. \sa search() exactMatch() */ int QRegExp::searchRev( const QString& str, int offset, CaretMode caretMode ) const { if ( offset < 0 ) offset += str.length(); #ifndef QT_NO_REGEXP_CAPTURE priv->t = str; priv->capturedCache.clear(); #endif if ( offset < 0 || offset > (int) str.length() ) { priv->captured.detach(); priv->captured.fill( -1 ); return -1; } while ( offset >= 0 ) { priv->captured = eng->match( str, offset, priv->min, TRUE, caretIndex(offset, caretMode) ); if ( priv->captured[0] == offset ) return offset; offset--; } return -1; } /*! Returns the length of the last matched string, or -1 if there was no match. \sa exactMatch() search() searchRev() */ int QRegExp::matchedLength() const { return priv->captured[1]; } #ifndef QT_NO_REGEXP_CAPTURE /*! Returns the number of captures contained in the regular expression. */ int QRegExp::numCaptures() const { return eng->numCaptures(); } /*! Returns a list of the captured text strings. The first string in the list is the entire matched string. Each subsequent list element contains a string that matched a (capturing) subexpression of the regexp. For example: \code QRegExp rx( "(\\d+)(\\s*)(cm|inch(es)?)" ); int pos = rx.search( "Length: 36 inches" ); QStringList list = rx.capturedTexts(); // list is now ( "36 inches", "36", " ", "inches", "es" ) \endcode The above example also captures elements that may be present but which we have no interest in. This problem can be solved by using non-capturing parentheses: \code QRegExp rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" ); int pos = rx.search( "Length: 36 inches" ); QStringList list = rx.capturedTexts(); // list is now ( "36 inches", "36", "inches" ) \endcode Note that if you want to iterate over the list, you should iterate over a copy, e.g. \code QStringList list = rx.capturedTexts(); QStringList::Iterator it = list.begin(); while( it != list.end() ) { myProcessing( *it ); ++it; } \endcode Some regexps can match an indeterminate number of times. For example if the input string is "Offsets: 12 14 99 231 7" and the regexp, \c{rx}, is <b>(\\d+)+</b>, we would hope to get a list of all the numbers matched. However, after calling \c{rx.search(str)}, capturedTexts() will return the list ( "12", "12" ), i.e. the entire match was "12" and the first subexpression matched was "12". The correct approach is to use cap() in a \link #cap_in_a_loop loop \endlink. The order of elements in the string list is as follows. The first element is the entire matching string. Each subsequent element corresponds to the next capturing open left parentheses. Thus capturedTexts()[1] is the text of the first capturing parentheses, capturedTexts()[2] is the text of the second and so on (corresponding to $1, $2, etc., in some other regexp languages). \sa cap() pos() exactMatch() search() searchRev() */ QStringList QRegExp::capturedTexts() { if ( priv->capturedCache.isEmpty() ) { for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) { QString m; if ( priv->captured[i + 1] == 0 ) m = QString::fromLatin1( "" ); else if ( priv->captured[i] >= 0 ) m = priv->t.mid( priv->captured[i], priv->captured[i + 1] ); priv->capturedCache.append( m ); } priv->t = QString::null; } return priv->capturedCache; } /*! Returns the text captured by the \a nth subexpression. The entire match has index 0 and the parenthesized subexpressions have indices starting from 1 (excluding non-capturing parentheses). \code QRegExp rxlen( "(\\d+)(?:\\s*)(cm|inch)" ); int pos = rxlen.search( "Length: 189cm" ); if ( pos > -1 ) { QString value = rxlen.cap( 1 ); // "189" QString unit = rxlen.cap( 2 ); // "cm" // ... } \endcode The order of elements matched by cap() is as follows. The first element, cap(0), is the entire matching string. Each subsequent element corresponds to the next capturing open left parentheses. Thus cap(1) is the text of the first capturing parentheses, cap(2) is the text of the second, and so on. \target cap_in_a_loop Some patterns may lead to a number of matches which cannot be determined in advance, for example: \code QRegExp rx( "(\\d+)" ); str = "Offsets: 12 14 99 231 7"; QStringList list; pos = 0; while ( pos >= 0 ) { pos = rx.search( str, pos ); if ( pos > -1 ) { list += rx.cap( 1 ); pos += rx.matchedLength(); } } // list contains "12", "14", "99", "231", "7" \endcode \sa capturedTexts() pos() exactMatch() search() searchRev() */ QString QRegExp::cap( int nth ) { if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) return QString::null; else return capturedTexts()[nth]; } /*! Returns the position of the \a nth captured text in the searched string. If \a nth is 0 (the default), pos() returns the position of the whole match. Example: \code QRegExp rx( "/([a-z]+)/([a-z]+)" ); rx.search( "Output /dev/null" ); // returns 7 (position of /dev/null) rx.pos( 0 ); // returns 7 (position of /dev/null) rx.pos( 1 ); // returns 8 (position of dev) rx.pos( 2 ); // returns 12 (position of null) \endcode For zero-length matches, pos() always returns -1. (For example, if cap(4) would return an empty string, pos(4) returns -1.) This is due to an implementation tradeoff. \sa capturedTexts() exactMatch() search() searchRev() */ int QRegExp::pos( int nth ) { if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) return -1; else return priv->captured[2 * nth]; } /*! Returns a text string that explains why a regexp pattern is invalid the case being; otherwise returns "no error occurred". \sa isValid() */ QString QRegExp::errorString() { if ( isValid() ) { return QString( RXERR_OK ); } else { return eng->errorString(); } } #endif /*! Returns the string \a str with every regexp special character escaped with a backslash. The special characters are $, (, ), *, +, ., ?, [, \, ], ^, {, | and }. Example: \code s1 = QRegExp::escape( "bingo" ); // s1 == "bingo" s2 = QRegExp::escape( "f(x)" ); // s2 == "f\\(x\\)" \endcode This function is useful to construct regexp patterns dynamically: \code QRegExp rx( "(" + QRegExp::escape(name) + "|" + QRegExp::escape(alias) + ")" ); \endcode */ QString QRegExp::escape( const QString& str ) { static const char meta[] = "$()*+.?[\\]^{|}"; QString quoted = str; int i = 0; while ( i < (int) quoted.length() ) { if ( strchr(meta, quoted[i].latin1()) != 0 ) quoted.insert( i++, "\\" ); i++; } return quoted; } void QRegExp::compile( bool caseSensitive ) { derefEngine( eng, priv->rxpattern ); #ifndef QT_NO_REGEXP_WILDCARD if ( priv->wc ) priv->rxpattern = wc2rx( priv->pattern ); else #endif priv->rxpattern = priv->pattern.isNull() ? QString::fromLatin1( "" ) : priv->pattern; eng = newEngine( priv->rxpattern, caseSensitive ); #ifndef QT_NO_REGEXP_CAPTURE priv->t = QString(); priv->capturedCache.clear(); #endif priv->captured.detach(); priv->captured.fill( -1, 2 + 2 * eng->numCaptures() ); } int QRegExp::caretIndex( int offset, CaretMode caretMode ) { if ( caretMode == CaretAtZero ) { return 0; } else if ( caretMode == CaretAtOffset ) { return offset; } else { // CaretWontMatch return -1; } } #endif // QT_NO_REGEXP diff --git a/qmake/tools/qsemaphore_unix.cpp b/qmake/tools/qsemaphore_unix.cpp index fcf28da..4516049 100644 --- a/qmake/tools/qsemaphore_unix.cpp +++ b/qmake/tools/qsemaphore_unix.cpp @@ -1,292 +1,290 @@ /**************************************************************************** ** $Id$ ** ** QSemaphore class for Unix ** ** Created : 20010725 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #if defined(QT_THREAD_SUPPORT) #include "qsemaphore.h" #include "qmutex.h" #include "qwaitcondition.h" /*! \class QSemaphore qsemaphore.h \threadsafe \brief The QSemaphore class provides a robust integer semaphore. \ingroup thread \ingroup environment A QSemaphore can be used to serialize thread execution, in a similar way to a QMutex. A semaphore differs from a mutex, in that a semaphore can be accessed by more than one thread at a time. For example, suppose we have an application that stores data in a large tree structure. The application creates 10 threads (commonly called a thread pool) to perform searches on the tree. When the application searches the tree for some piece of data, it uses one thread per base node to do the searching. A semaphore could be used to make sure that two threads don't try to search the same branch of the tree at the same time. A non-computing example of a semaphore would be dining at a restuarant. A semaphore is initialized to have a maximum count equal to the number of chairs in the restuarant. As people arrive, they want a seat. As seats are filled, the semaphore is accessed, once per person. As people leave, the access is released, allowing more people to enter. If a party of 10 people want to be seated, but there are only 9 seats, those 10 people will wait, but a party of 4 people would be seated (taking the available seats to 5, making the party of 10 people wait longer). When a semaphore is created it is given a number which is the maximum number of concurrent accesses it will permit. This amount may be changed using operator++(), operator--(), operator+=() and operator-=(). The number of accesses allowed is retrieved with available(), and the total number with total(). Note that the incrementing functions will block if there aren't enough available accesses. Use tryAccess() if you want to acquire accesses without blocking. */ class QSemaphorePrivate { public: QSemaphorePrivate(int); QMutex mutex; QWaitCondition cond; int value, max; }; QSemaphorePrivate::QSemaphorePrivate(int m) : mutex(FALSE), value(0), max(m) { } /*! Creates a new semaphore. The semaphore can be concurrently accessed at most \a maxcount times. */ QSemaphore::QSemaphore(int maxcount) { d = new QSemaphorePrivate(maxcount); } /*! Destroys the semaphore. \warning If you destroy a semaphore that has accesses in use the resultant behavior is undefined. */ QSemaphore::~QSemaphore() { delete d; } /*! Postfix ++ operator. Try to get access to the semaphore. If \l available() == 0, this call will block until it can get access, i.e. until available() \> 0. */ int QSemaphore::operator++(int) { int ret; d->mutex.lock(); while (d->value >= d->max) d->cond.wait(&(d->mutex)); ++(d->value); if (d->value > d->max) d->value = d->max; ret = d->value; d->mutex.unlock(); return ret; } /*! Postfix -- operator. Release access of the semaphore. This wakes all threads waiting for access to the semaphore. */ int QSemaphore::operator--(int) { int ret; d->mutex.lock(); --(d->value); if (d->value < 0) d->value = 0; ret = d->value; d->cond.wakeAll(); d->mutex.unlock(); return ret; } /*! Try to get access to the semaphore. If \l available() \< \a n, this call will block until it can get all the accesses it wants, i.e. until available() \>= \a n. */ int QSemaphore::operator+=(int n) { int ret; d->mutex.lock(); + if ( n < 0 || n > d->max ) { +#ifdef QT_CHECK_RANGE + qWarning( "QSemaphore::operator+=: paramter %d out of range", n ); +#endif // QT_CHECK_RANGE + n = n < 0 ? 0 : d->max; + } + while (d->value + n > d->max) d->cond.wait(&(d->mutex)); d->value += n; - -#ifdef QT_CHECK_RANGE - if (d->value > d->max) { - qWarning("QSemaphore::operator+=: attempt to allocate more resources than available"); - d->value = d->max; - } -#endif - ret = d->value; d->mutex.unlock(); return ret; } /*! Release \a n accesses to the semaphore. */ int QSemaphore::operator-=(int n) { int ret; d->mutex.lock(); - d->value -= n; - + if ( n < 0 || n > d->value ) { #ifdef QT_CHECK_RANGE - if (d->value < 0) { - qWarning("QSemaphore::operator-=: attempt to deallocate more resources than taken"); - d->value = 0; + qWarning( "QSemaphore::operator-=: paramter %d out of range", n ); +#endif // QT_CHECK_RANGE + n = n < 0 ? 0 : d->value; } -#endif + d->value -= n; ret = d->value; d->cond.wakeOne(); d->mutex.unlock(); return ret; } /*! Returns the number of accesses currently available to the semaphore. */ int QSemaphore::available() const { int ret; d->mutex.lock(); ret = d->max - d->value; d->mutex.unlock(); return ret; } /*! Returns the total number of accesses to the semaphore. */ int QSemaphore::total() const { int ret; d->mutex.lock(); ret = d->max; d->mutex.unlock(); return ret; } /*! Try to get access to the semaphore. If \l available() \< \a n, this function will return FALSE immediately. If \l available() \>= \a n, this function will take \a n accesses and return TRUE. This function does \e not block. */ bool QSemaphore::tryAccess(int n) { if (! d->mutex.tryLock()) return FALSE; if (d->value + n > d->max) { d->mutex.unlock(); return FALSE; } d->value += n; #ifdef QT_CHECK_RANGE if (d->value > d->max) { qWarning("QSemaphore::operator+=: attempt to allocate more resources than available"); d->value = d->max; } #endif d->mutex.unlock(); return TRUE; } #endif // QT_THREAD_SUPPORT diff --git a/qmake/tools/qsettings.cpp b/qmake/tools/qsettings.cpp index 5de105c..35fc039 100644 --- a/qmake/tools/qsettings.cpp +++ b/qmake/tools/qsettings.cpp @@ -1,1955 +1,2060 @@ /**************************************************************************** ** $Id$ ** ** Implementation of QSettings class ** -** Created: 2000.06.26 +** Created : 000626 ** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qplatformdefs.h" // POSIX Large File Support redefines open -> open64 static inline int qt_open( const char *pathname, int flags, mode_t mode ) { return ::open( pathname, flags, mode ); } #if defined(open) # undef open #endif // POSIX Large File Support redefines truncate -> truncate64 #if defined(truncate) # undef truncate #endif #include "qsettings.h" #ifndef QT_NO_SETTINGS #include "qdir.h" #include "qfile.h" #include "qfileinfo.h" #include "qmap.h" #include "qtextstream.h" #include "qregexp.h" #include <private/qsettings_p.h> #include <errno.h> /*! \class QSettings \brief The QSettings class provides persistent platform-independent application settings. \ingroup io \ingroup misc \mainclass On Unix systems, QSettings uses text files to store settings. On Windows - systems, QSettings uses the system registry. On Mac OS X, QSettings will - behave as on Unix, and store to text files. + systems, QSettings uses the system registry. On Mac OS X, QSettings uses + the Carbon preferences API. Each setting comprises an identifying key and the data associated with the key. A key is a unicode string which consists of \e two or more subkeys. A subkey is a slash, '/', followed by one or more unicode characters (excluding slashes, newlines, carriage returns and equals, '=', signs). The associated data, called the entry or value, may be a boolean, an integer, a double, a string or a list of strings. Entry strings may contain any unicode characters. If you want to save and restore the entire desktop's settings, i.e. which applications are running, use QSettings to save the settings for each individual application and QSessionManager to save the desktop's session. Example settings: \code /MyCompany/MyApplication/background color /MyCompany/MyApplication/foreground color /MyCompany/MyApplication/geometry/x /MyCompany/MyApplication/geometry/y /MyCompany/MyApplication/geometry/width /MyCompany/MyApplication/geometry/height /MyCompany/MyApplication/recent files/1 /MyCompany/MyApplication/recent files/2 /MyCompany/MyApplication/recent files/3 \endcode Each line above is a complete key, made up of subkeys. - A typical usage pattern for application startup: + A typical usage pattern for reading application startup: \code QSettings settings; - settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); - // No search path needed for Unix; see notes further on. - // Use default values if the keys don't exist - QString bgColor = settings.readEntry( "/MyApplication/background color", "white" ); - int width = settings.readNumEntry( "/MyApplication/geometry/width", 640 ); + settings.setPath( "MyCompany.com", "MyApplication" ); + + QString bgColor = settings.readEntry( "/colors/background", "white" ); + int width = settings.readNumEntry( "/geometry/width", 640 ); // ... \endcode A typical usage pattern for application exit or 'save preferences': \code QSettings settings; - settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); - // No search path needed for Unix; see notes further on. - settings.writeEntry( "/MyApplication/background color", bgColor ); - settings.writeEntry( "/MyApplication/geometry/width", width ); + settings.setPath( "MyCompany.com", "MyApplication" ); + + settings.writeEntry( "/colors/background", bgColor ); + settings.writeEntry( "/geometry/width", width ); + // ... + \endcode + + QSettings can build a key prefix that is prepended to all keys. To + build the key prefix, use beginGroup() and endGroup(). + \code + QSettings settings; + + settings.beginGroup( "/MainWindow" ); + settings.beginGroup( "/Geometry" ); + int x = settings.readEntry( "/x" ); + // ... + settings.endGroup(); + settings.beginGroup( "/Toolbars" ); // ... + settings.endGroup(); + settings.endGroup(); \endcode You can get a list of entry-holding keys by calling entryList(), and a list of key-holding keys using subkeyList(). \code QStringList keys = entryList( "/MyApplication" ); // keys contains 'background color' and 'foreground color'. QStringList keys = entryList( "/MyApplication/recent files" ); // keys contains '1', '2' and '3'. QStringList subkeys = subkeyList( "/MyApplication" ); // subkeys contains 'geometry' and 'recent files' QStringList subkeys = subkeyList( "/MyApplication/recent files" ); // subkeys is empty. \endcode - If you wish to use a different search path call insertSearchPath() - as often as necessary to add your preferred paths. Call - removeSearchPath() to remove any unwanted paths. - Since settings for Windows are stored in the registry there are size limits as follows: \list \i A subkey may not exceed 255 characters. \i An entry's value may not exceed 16,300 characters. \i All the values of a key (for example, all the 'recent files' subkeys values), may not exceed 65,535 characters. \endlist - These limitations are not enforced on Unix. + These limitations are not enforced on Unix or Mac OS X. + + If you wish to use a different search path call insertSearchPath() + as often as necessary to add your preferred paths. Call + removeSearchPath() to remove any unwanted paths. + + \section1 Notes for Mac OS X Applications + + Internal to the CFPreferences API it is not defined (for Mac OS 9 + support) where the settings will ultimitely be stored. However, at the + time of this writing the settings will be stored (either on a global or + user basis, preferring locally) into a plist file in + $ROOT/System/Library/Preferences (in XML format). QSettings will create + an appropriate plist file (com.<first group name>.plist) out of the + full path to a key. + + For further information on CFPreferences see also + \link http://developer.apple.com/techpubs/macosx/CoreFoundation/PreferenceServices/preferenceservices_carbon.html + Apple's Specifications\endlink \section1 Notes for Unix Applications There is no universally accepted place for storing application settings under Unix. In the examples the settings file will be searched for in the following directories: \list 1 \i INSTALL/etc/settings \i /opt/MyCompany/share/etc \i /opt/MyCompany/share/MyApplication/etc \i $HOME/.qt \endlist When reading settings the files are searched in the order shown above, with later settings overriding earlier settings. Files for which the user doesn't have read permission are ignored. When saving settings QSettings works in the order shown above, writing to the first settings file for which the user has write permission. (\c INSTALL is the directory where Qt was installed. This can be modified by using the configure script's -prefix argument ) If you want to put the settings in a particular place in the filesystem you could do this: \code settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" ); \endcode But in practice you may prefer not to use a search path for Unix. For example the following code: \code settings.writeEntry( "/MyApplication/geometry/width", width ); \endcode will end up writing the "geometry/width" setting to the file \c{$HOME/.qt/myapplicationrc} (assuming that the application is being run by an ordinary user, i.e. not by root). For cross-platform applications you should ensure that the Windows size limitations are not exceeded. */ /*! \enum QSettings::System \value Mac Macintosh execution environments \value Unix Mac OS X, Unix, Linux and Unix-like execution environments \value Windows Windows execution environments */ /*! \enum QSettings::Format \value Native Store the settings in a platform dependent location \value Ini Store the settings in a text file */ /*! \enum QSettings::Scope \value Global Save settings as global as possible \value User Save settings in user space */ #if defined(Q_OS_UNIX) typedef int HANDLE; #define Q_LOCKREAD F_RDLCK #define Q_LOCKWRITE F_WRLCK /* Locks the file specified by name. The lockfile is created as a hidden file in the same directory as the target file, with .lock appended to the name. For example, "/etc/settings/onerc" uses a lockfile named "/etc/settings/.onerc.lock". The type argument controls the type of the lock, it can be either F_RDLCK for a read lock, or F_WRLCK for a write lock. A file descriptor for the lock file is returned, and should be closed with closelock() when the lock is no longer needed. */ static HANDLE openlock( const QString &name, int type ) { QFileInfo info( name ); // lockfile should be hidden, and never removed QString lockfile = info.dirPath() + "/." + info.fileName() + ".lock"; // open the lockfile HANDLE fd = qt_open( QFile::encodeName( lockfile ), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); if ( fd < 0 ) { // failed to open the lock file, most likely because of permissions return fd; } struct flock fl; fl.l_type = type; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; if ( fcntl( fd, F_SETLKW, &fl ) == -1 ) { // the lock failed, so we should fail silently, so that people // using filesystems that do not support locking don't see // numerous warnings about a failed lock close( fd ); fd = -1; } return fd; } /* Closes the lock file specified by fd. fd is the file descriptor returned by the openlock() function. */ static void closelock( HANDLE fd ) { if ( fd < 0 ) { // the lock file is not open return; } struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; // ignore the return value, so that the unlock fails silently (void) fcntl( fd, F_SETLKW, &fl ); close( fd ); } #elif defined(Q_WS_WIN) #define Q_LOCKREAD 1 #define Q_LOCKWRITE 2 static HANDLE openlock( const QString &name, int /*type*/ ) { if ( !QFile::exists( name ) ) return 0; return 0; HANDLE fd = 0; QT_WA( { fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); } , { fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); } ); - if ( !LockFile( fd, 0, 0, -1, -1 ) ) { + if ( !LockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ??? #ifdef QT_CHECK_STATE qWarning( "QSettings: openlock failed!" ); #endif } return fd; } -void closelock( HANDLE fd ) +static void closelock( HANDLE fd ) { if ( !fd ) return; - if ( !UnlockFile( fd, 0, 0, -1, -1 ) ) { + if ( !UnlockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ??? #ifdef QT_CHECK_STATE qWarning( "QSettings: closelock failed!"); #endif } CloseHandle( fd ); } #endif QSettingsGroup::QSettingsGroup() : modified(FALSE) { } void QSettingsHeading::read(const QString &filename) { if (! QFileInfo(filename).exists()) return; HANDLE lockfd = openlock( filename, Q_LOCKREAD ); QFile file(filename); if (! file.open(IO_ReadOnly)) { #if defined(QT_CHECK_STATE) qWarning("QSettings: failed to open file '%s'", filename.latin1()); #endif return; } git = end(); QTextStream stream(&file); stream.setEncoding(QTextStream::UnicodeUTF8); while (! stream.atEnd()) parseLine(stream); git = end(); file.close(); closelock( lockfd ); } void QSettingsHeading::parseLine(QTextStream &stream) { QString line = stream.readLine(); if (line.isEmpty()) // empty line... we'll allow it return; if (line[0] == QChar('#')) // commented line return; if (line[0] == QChar('[')) { QString gname = line; gname = gname.remove(0, 1); if (gname[(int)gname.length() - 1] == QChar(']')) gname = gname.remove(gname.length() - 1, 1); git = find(gname); if (git == end()) git = replace(gname, QSettingsGroup()); } else { if (git == end()) { #if defined(QT_CHECK_STATE) qWarning("QSettings: line '%s' out of group", line.latin1()); #endif return; } int i = line.find('='); if (i == -1) { #if defined(QT_CHECK_STATE) qWarning("QSettings: malformed line '%s' in group '%s'", line.latin1(), git.key().latin1()); #endif return; } else { QString key, value; key = line.left(i); value = ""; bool esc=TRUE; i++; while (esc) { esc = FALSE; for ( ; i < (int)line.length(); i++ ) { if ( esc ) { if ( line[i] == 'n' ) value.append('\n'); // escaped newline else if ( line[i] == '0' ) value = QString::null; // escaped empty string else value.append(line[i]); esc = FALSE; } else if ( line[i] == '\\' ) esc = TRUE; else value.append(line[i]); } if ( esc ) { // Backwards-compatiblity... // still escaped at EOL - manually escaped "newline" if (stream.atEnd()) { #if defined(QT_CHECK_STATE) qWarning("QSettings: reached end of file, expected continued line"); #endif break; } value.append('\n'); line = stream.readLine(); i = 0; } } (*git).insert(key, value); } } } #ifdef Q_WS_WIN // for homedirpath reading from registry #include "qt_windows.h" #include "qlibrary.h" #ifndef CSIDL_APPDATA #define CSIDL_APPDATA 0x001a // <user name>\Application Data #endif #ifndef CSIDL_COMMON_APPDATA #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data #endif #endif QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) : groupDirty( TRUE ), modified(FALSE), globalScope(TRUE) { -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( format != QSettings::Ini ) return; +#else + Q_UNUSED( format ); #endif QString appSettings(QDir::homeDirPath() + "/.qt/"); QString defPath; #ifdef Q_WS_WIN #ifdef Q_OS_TEMP TCHAR path[MAX_PATH]; SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); appSettings = QString::fromUcs2( path ); SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); defPath = QString::fromUcs2( path ); #else QLibrary library( "shell32" ); library.setAutoUnload( FALSE ); QT_WA( { typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathW" ); if ( SHGetSpecialFolderPath ) { TCHAR path[MAX_PATH]; SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); appSettings = QString::fromUcs2( (ushort*)path ); SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); defPath = QString::fromUcs2( (ushort*)path ); } } , { typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" ); if ( SHGetSpecialFolderPath ) { char path[MAX_PATH]; SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); appSettings = QString::fromLocal8Bit( path ); SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); defPath = QString::fromLocal8Bit( path ); } } ); #endif // Q_OS_TEMP #else // for now #define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings" defPath = qInstallPath(); defPath += QSETTINGS_DEFAULT_PATH_SUFFIX; #endif QDir dir(appSettings); if (! dir.exists()) { if (! dir.mkdir(dir.path())) #if defined(QT_CHECK_STATE) qWarning("QSettings: error creating %s", dir.path().latin1()); +#else + ; #endif } if ( !!defPath ) searchPaths.append(defPath); searchPaths.append(dir.path()); } QSettingsPrivate::~QSettingsPrivate() { } QSettingsGroup QSettingsPrivate::readGroup() { QSettingsHeading hd; QSettingsGroup grp; QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); if (headingsit != headings.end()) hd = *headingsit; QSettingsHeading::Iterator grpit = hd.find(group); if (grpit == hd.end()) { QStringList::Iterator it = searchPaths.begin(); + if ( !globalScope ) + ++it; while (it != searchPaths.end()) { QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); QString fn((*it++) + "/" + filebase + "rc"); if (! hd.contains(fn + "cached")) { hd.read(fn); hd.insert(fn + "cached", QSettingsGroup()); } } headings.replace(heading, hd); grpit = hd.find(group); if (grpit != hd.end()) grp = *grpit; } else if (hd.count() != 0) grp = *grpit; return grp; } void QSettingsPrivate::removeGroup(const QString &key) { QSettingsHeading hd; QSettingsGroup grp; bool found = FALSE; QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); if (headingsit != headings.end()) hd = *headingsit; QSettingsHeading::Iterator grpit = hd.find(group); if (grpit == hd.end()) { QStringList::Iterator it = searchPaths.begin(); + if ( !globalScope ) + ++it; while (it != searchPaths.end()) { QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); QString fn((*it++) + "/" + filebase + "rc"); if (! hd.contains(fn + "cached")) { hd.read(fn); hd.insert(fn + "cached", QSettingsGroup()); } } headings.replace(heading, hd); grpit = hd.find(group); if (grpit != hd.end()) { found = TRUE; grp = *grpit; } } else if (hd.count() != 0) { found = TRUE; grp = *grpit; } if (found) { grp.remove(key); if (grp.count() > 0) hd.replace(group, grp); else hd.remove(group); if (hd.count() > 0) headings.replace(heading, hd); else headings.remove(heading); modified = TRUE; } } void QSettingsPrivate::writeGroup(const QString &key, const QString &value) { QSettingsHeading hd; QSettingsGroup grp; QMap<QString,QSettingsHeading>::Iterator headingsit = headings.find(heading); if (headingsit != headings.end()) hd = *headingsit; QSettingsHeading::Iterator grpit = hd.find(group); if (grpit == hd.end()) { QStringList::Iterator it = searchPaths.begin(); + if ( !globalScope ) + ++it; while (it != searchPaths.end()) { QString filebase = heading.lower().replace(QRegExp("\\s+"), "_"); QString fn((*it++) + "/" + filebase + "rc"); if (! hd.contains(fn + "cached")) { hd.read(fn); hd.insert(fn + "cached", QSettingsGroup()); } } headings.replace(heading, hd); grpit = hd.find(group); if (grpit != hd.end()) grp = *grpit; } else if (hd.count() != 0) grp = *grpit; grp.modified = TRUE; grp.replace(key, value); hd.replace(group, grp); headings.replace(heading, hd); modified = TRUE; } QDateTime QSettingsPrivate::modificationTime() { QSettingsHeading hd = headings[heading]; QSettingsGroup grp = hd[group]; QDateTime datetime; QStringList::Iterator it = searchPaths.begin(); + if ( !globalScope ) + ++it; while (it != searchPaths.end()) { QFileInfo fi((*it++) + "/" + heading + "rc"); if (fi.exists() && fi.lastModified() > datetime) datetime = fi.lastModified(); } return datetime; } -static bool verifyKey( const QString &key ) +bool qt_verify_key( const QString &key ) { if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) ) return FALSE; return TRUE; } static inline QString groupKey( const QString &group, const QString &key ) { - if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) + if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) { + // group is empty, or it contains a single '/', so we just return the key + if ( key.startsWith( "/" ) ) + return key; + return "/" + key; + } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) { return group + key; + } return group + "/" + key; } /*! Inserts \a path into the settings search path. The semantics of \a path depends on the system \a s. When \a s is \e Windows and the execution environment is \e not Windows the function does nothing. Similarly when \a s is \e Unix and the execution environment is \e not Unix the function does nothing. When \a s is \e Windows, and the execution environment is Windows, the search path list will be used as the first subfolder of the "Software" folder in the registry. When reading settings the folders are searched forwards from the first folder (listed below) to the last, returning the first settings found, and ignoring any folders for which the user doesn't have read permission. \list 1 \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication \i HKEY_CURRENT_USER/Software/MyApplication \i HKEY_LOCAL_MACHINE/Software/MyApplication \endlist \code QSettings settings; settings.insertSearchPath( QSettings::Windows, "/MyCompany" ); settings.writeEntry( "/MyApplication/Tip of the day", TRUE ); \endcode The code above will write the subkey "Tip of the day" into the \e first of the registry folders listed below that is found and for which the user has write permission. \list 1 \i HKEY_LOCAL_MACHINE/Software/MyCompany/MyApplication \i HKEY_CURRENT_USER/Software/MyCompany/MyApplication \i HKEY_LOCAL_MACHINE/Software/MyApplication \i HKEY_CURRENT_USER/Software/MyApplication \endlist If a setting is found in the HKEY_CURRENT_USER space, this setting is overwritten independently of write permissions in the HKEY_LOCAL_MACHINE space. When \a s is \e Unix, and the execution environment is Unix, the search path list will be used when trying to determine a suitable filename for reading and writing settings files. By default, there are two entries in the search path: \list 1 \i INSTALL/etc - where \c INSTALL is the directory where Qt was installed. \i $HOME/.qt/ - where \c $HOME is the user's home directory. \endlist All insertions into the search path will go before $HOME/.qt/. For example: \code QSettings settings; settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/etc" ); settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/MyApplication/etc" ); // ... \endcode Will result in a search path of: \list 1 \i INSTALL/etc \i /opt/MyCompany/share/etc \i /opt/MyCompany/share/MyApplication/etc \i $HOME/.qt \endlist When reading settings the files are searched in the order shown above, with later settings overriding earlier settings. Files for which the user doesn't have read permission are ignored. When saving settings QSettings works in the order shown above, writing to the first settings file for which the user has write permission. Settings under Unix are stored in files whose names are based on the first subkey of the key (not including the search path). The algorithm for creating names is essentially: lowercase the first subkey, replace spaces with underscores and add 'rc', e.g. <tt>/MyCompany/MyApplication/background color</tt> will be stored in <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of the search path). \sa removeSearchPath() */ void QSettings::insertSearchPath( System s, const QString &path) { -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) { d->sysInsertSearchPath( s, path ); return; } #endif - if ( !verifyKey( path ) ) { +#if !defined(Q_WS_WIN) + if ( s == Windows ) + return; +#endif +#if !defined(Q_WS_WIN) + if ( s == Mac ) + return; +#endif + + if ( !qt_verify_key( path ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); #endif return; } -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd && s != Unix ) { #else if ( s != Unix ) { #endif -#ifdef Q_OS_MAC +#if !defined(QWS) && defined(Q_OS_MAC) if(s != Mac) //mac is respected on the mac as well #endif return; } + QString realPath = path; +#if defined(Q_WS_WIN) + QString defPath = d->globalScope ? d->searchPaths.first() : d->searchPaths.last(); + realPath = defPath + path; +#endif + QStringList::Iterator it = d->searchPaths.find(d->searchPaths.last()); if (it != d->searchPaths.end()) { - d->searchPaths.insert(it, path); + d->searchPaths.insert(it, realPath); } } /*! Removes all occurrences of \a path (using exact matching) from the settings search path for system \a s. Note that the default search paths cannot be removed. \sa insertSearchPath() */ void QSettings::removeSearchPath( System s, const QString &path) { - if ( !verifyKey( path ) ) { + if ( !qt_verify_key( path ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); #endif return; } #ifdef Q_WS_WIN if ( d->sysd ) { d->sysRemoveSearchPath( s, path ); return; } #endif -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd && s != Unix ) { #else if ( s != Unix ) { #endif -#ifdef Q_OS_MAC +#if !defined(QWS) && defined(Q_OS_MAC) if(s != Mac) //mac is respected on the mac as well #endif return; } if (path == d->searchPaths.first() || path == d->searchPaths.last()) return; d->searchPaths.remove(path); } /*! Creates a settings object. */ QSettings::QSettings() { d = new QSettingsPrivate( Native ); Q_CHECK_PTR(d); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) d->sysd = 0; d->sysInit(); #endif } /*! Creates a settings object. If \a format is 'Ini' the settings will be stored in a text file, using the Unix strategy (see above). If \a format is 'Native', the settings will be stored in a platform specific way (ie. the Windows registry). */ QSettings::QSettings( Format format ) { d = new QSettingsPrivate( format ); Q_CHECK_PTR(d); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) d->sysd = 0; if ( format == Native ) d->sysInit(); #else Q_UNUSED(format); #endif } /*! Destroys the settings object. All modifications made to the settings will automatically be saved. */ QSettings::~QSettings() { sync(); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) d->sysClear(); #endif delete d; } /*! \internal Writes all modifications to the settings to disk. If any errors are encountered, this function returns FALSE, otherwise it will return TRUE. */ bool QSettings::sync() { -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysSync(); #endif if (! d->modified) // fake success return TRUE; bool success = TRUE; QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); while (it != d->headings.end()) { // determine filename QSettingsHeading hd(*it); QSettingsHeading::Iterator hdit = hd.begin(); QFile file; QStringList::Iterator pit = d->searchPaths.begin(); + if ( !d->globalScope ) + ++pit; while (pit != d->searchPaths.end()) { QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_"); QFileInfo di(*pit); QFileInfo fi((*pit++) + "/" + filebase + "rc"); if ((fi.exists() && fi.isFile() && fi.isWritable()) || (! fi.exists() && di.isDir() && di.isWritable())) { file.setName(fi.filePath()); break; } } - it++; + ++it; - if (file.name().isNull() || file.name().isEmpty()) { + if ( file.name().isEmpty() ) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: filename is null/empty"); #endif // QT_CHECK_STATE success = FALSE; continue; } HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE ); if (! file.open(IO_WriteOnly)) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: failed to open '%s' for writing", file.name().latin1()); #endif // QT_CHECK_STATE success = FALSE; continue; } // spew to file QTextStream stream(&file); stream.setEncoding(QTextStream::UnicodeUTF8); while (hdit != hd.end()) { if ((*hdit).count() > 0) { stream << "[" << hdit.key() << "]" << endl; QSettingsGroup grp(*hdit); QSettingsGroup::Iterator grpit = grp.begin(); while (grpit != grp.end()) { QString v = grpit.data(); if ( v.isNull() ) { v = "\\0"; // escape null string } else { v.replace("\\", "\\\\"); // escape backslash v.replace("\n", "\\n"); // escape newlines } stream << grpit.key() << "=" << v << endl; - grpit++; + ++grpit; } stream << endl; } - hdit++; + ++hdit; } if (file.status() != IO_Ok) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: error at end of write"); #endif // QT_CHECK_STATE success = FALSE; } file.close(); closelock( lockfd ); } d->modified = FALSE; return success; } /*! \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const Reads the entry specified by \a key, and returns a bool, or the default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry() */ /*! \internal */ bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } - QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadBoolEntry( theKey, def, ok ); + return d->sysReadBoolEntry( groupKey( group(), key ), def, ok ); #endif - QString value = readEntry( theKey, ( def ? "true" : "false" ), ok ); + QString value = readEntry( key, ( def ? "true" : "false" ), ok ); if (value.lower() == "true") return TRUE; else if (value.lower() == "false") return FALSE; else if (value == "1") return TRUE; else if (value == "0") return FALSE; if (! value.isEmpty()) qWarning("QSettings::readBoolEntry: '%s' is not 'true' or 'false'", value.latin1()); if ( ok ) *ok = FALSE; return def; } /*! \fn double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) const Reads the entry specified by \a key, and returns a double, or the default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } - QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadDoubleEntry( theKey, def, ok ); + return d->sysReadDoubleEntry( groupKey( group(), key ), def, ok ); #endif - QString value = readEntry( theKey, QString::number(def), ok ); + QString value = readEntry( key, QString::number(def), ok ); bool conv_ok; double retval = value.toDouble( &conv_ok ); if ( conv_ok ) return retval; if ( ! value.isEmpty() ) qWarning( "QSettings::readDoubleEntry: '%s' is not a number", value.latin1() ); if ( ok ) *ok = FALSE; return def; } /*! \fn int QSettings::readNumEntry(const QString &key, int def, bool *ok ) const Reads the entry specified by \a key, and returns an integer, or the default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ int QSettings::readNumEntry(const QString &key, int def, bool *ok ) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } - QString theKey = groupKey( group(), key ); - -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadNumEntry( theKey, def, ok ); + return d->sysReadNumEntry( groupKey( group(), key ), def, ok ); #endif - QString value = readEntry( theKey, QString::number( def ), ok ); + QString value = readEntry( key, QString::number( def ), ok ); bool conv_ok; int retval = value.toInt( &conv_ok ); if ( conv_ok ) return retval; if ( ! value.isEmpty() ) qWarning( "QSettings::readNumEntry: '%s' is not a number", value.latin1() ); if ( ok ) *ok = FALSE; return def; } /*! \fn QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) const Reads the entry specified by \a key, and returns a QString, or the default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysReadEntry( theKey, def, ok ); #endif if ( ok ) // no, everything is not ok *ok = FALSE; QString realkey; if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 2) { #ifdef QT_CHECK_STATE qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE if ( ok ) *ok = FALSE; return def; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else realkey = theKey; QSettingsGroup grp = d->readGroup(); - QString retval = grp[realkey]; - if ( retval.isNull() ) - retval = def; - else if ( ok ) // everything is ok - *ok = TRUE; + QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end(); + QString retval = def; + if ( it != end ) { + // found the value we needed + retval = *it; + if ( ok ) *ok = TRUE; + } return retval; } #if !defined(Q_NO_BOOL_TYPE) /*! Writes the boolean entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, bool value) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( theKey, value ); + return d->sysWriteEntry( groupKey( group(), key ), value ); #endif QString s(value ? "true" : "false"); - return writeEntry(theKey, s); + return writeEntry(key, s); } #endif /*! \overload Writes the double entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, double value) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( theKey, value ); + return d->sysWriteEntry( groupKey( group(), key ), value ); #endif QString s(QString::number(value)); - return writeEntry(theKey, s); + return writeEntry(key, s); } /*! \overload Writes the integer entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, int value) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( theKey, value ); + return d->sysWriteEntry( groupKey( group(), key ), value ); #endif QString s(QString::number(value)); - return writeEntry(theKey, s); + return writeEntry(key, s); } /*! \internal Writes the entry specified by \a key with the string-literal \a value, replacing any previous setting. If \a value is zero-length or null, the entry is replaced by an empty setting. \e NOTE: This function is provided because some compilers use the writeEntry (const QString &, bool) overload for this code: writeEntry ("/foo/bar", "baz") If an error occurs, this functions returns FALSE and the object is left unchanged. \sa readEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const char *value) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - - return writeEntry(theKey, QString(value)); + return writeEntry(key, QString(value)); } /*! \overload Writes the string entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If \a value is an empty string or a null string the key's value will be an empty string. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const QString &value) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysWriteEntry( theKey, value ); #endif // NOTE: we *do* allow value to be a null/empty string QString realkey; if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 2) { #ifdef QT_CHECK_STATE qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE return FALSE; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else realkey = theKey; d->writeGroup(realkey, value); return TRUE; } /*! Removes the entry specified by \a key. Returns TRUE if the entry existed and was removed; otherwise returns FALSE. \sa readEntry(), writeEntry() */ bool QSettings::removeEntry(const QString &key) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return FALSE; } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysRemoveEntry( theKey ); #endif QString realkey; if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 2) { #ifdef QT_CHECK_STATE qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE return FALSE; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else realkey = theKey; d->removeGroup(realkey); return TRUE; } /*! Returns a list of the keys which contain entries under \a key. Does \e not return any keys that contain keys. Example settings: \code /MyCompany/MyApplication/background color /MyCompany/MyApplication/foreground color /MyCompany/MyApplication/geometry/x /MyCompany/MyApplication/geometry/y /MyCompany/MyApplication/geometry/width /MyCompany/MyApplication/geometry/height \endcode \code QStringList keys = entryList( "/MyCompany/MyApplication" ); \endcode \c keys contains 'background color' and 'foreground color'. It does not contain 'geometry' because this key contains keys not entries. To access the geometry values could either use subkeyList() to read the keys and then read each entry, or simply read each entry directly by specifying its full key, e.g. "/MyCompany/MyApplication/geometry/y". \sa subkeyList() */ QStringList QSettings::entryList(const QString &key) const { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); #endif return QStringList(); } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysEntryList( theKey ); #endif QString realkey; if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 1) { #ifdef QT_CHECK_STATE qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE return QStringList(); } if (list.count() == 1) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else realkey = theKey; QSettingsGroup grp = d->readGroup(); QSettingsGroup::Iterator it = grp.begin(); QStringList ret; QString itkey; while (it != grp.end()) { itkey = it.key(); - it++; + ++it; if ( realkey.length() > 0 ) { if ( itkey.left( realkey.length() ) != realkey ) continue; else itkey.remove( 0, realkey.length() + 1 ); } if ( itkey.find( '/' ) != -1 ) continue; ret << itkey; } return ret; } /*! Returns a list of the keys which contain keys under \a key. Does \e not return any keys that contain entries. Example settings: \code /MyCompany/MyApplication/background color /MyCompany/MyApplication/foreground color /MyCompany/MyApplication/geometry/x /MyCompany/MyApplication/geometry/y /MyCompany/MyApplication/geometry/width /MyCompany/MyApplication/geometry/height /MyCompany/MyApplication/recent files/1 /MyCompany/MyApplication/recent files/2 /MyCompany/MyApplication/recent files/3 \endcode \code QStringList keys = subkeyList( "/MyCompany/MyApplication" ); \endcode \c keys contains 'geometry' and 'recent files'. It does not contain 'background color' or 'foreground color' because they are keys which contain entries not keys. To get a list of keys that have values rather than subkeys use entryList(). \sa entryList() */ QStringList QSettings::subkeyList(const QString &key) const { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); #endif return QStringList(); } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return d->sysSubkeyList( theKey ); #endif QString realkey; + int subkeycount = 2; if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 1) { #ifdef QT_CHECK_STATE qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE return QStringList(); } + subkeycount = list.count(); + if (list.count() == 1) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } + } else realkey = theKey; + QStringList ret; + if ( subkeycount == 1 ) { + QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); + while ( it != d->headings.end() ) { + if ( it.key() != "General" && ! ret.contains( it.key() ) ) + ret << it.key(); + ++it; + } + + return ret; + } + QSettingsGroup grp = d->readGroup(); QSettingsGroup::Iterator it = grp.begin(); - QStringList ret; QString itkey; while (it != grp.end()) { itkey = it.key(); - it++; + ++it; if ( realkey.length() > 0 ) { if ( itkey.left( realkey.length() ) != realkey ) continue; else itkey.remove( 0, realkey.length() + 1 ); } int slash = itkey.find( '/' ); if ( slash == -1 ) continue; itkey.truncate( slash ); if ( ! ret.contains( itkey ) ) ret << itkey; } return ret; } /*! \internal This function returns the time of last modification for \a key. */ QDateTime QSettings::lastModficationTime(const QString &key) { - if ( !verifyKey( key ) ) { + if ( !qt_verify_key( key ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); #endif return QDateTime(); } QString theKey = groupKey( group(), key ); -#if defined(Q_WS_WIN) || defined(Q_OS_MAC) +#if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return QDateTime(); #endif if (theKey[0] == '/') { // parse our key QStringList list(QStringList::split('/', theKey)); if (list.count() < 2) { #ifdef QT_CHECK_STATE qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1()); #endif // QT_CHECK_STATE return QDateTime(); } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; } } return d->modificationTime(); } /*! \overload Writes the string list entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. The list is stored as a sequence of strings separated - by \a separator, so none of the strings in the list should contain - the separator. If the list is empty or null the key's value will - be an empty string. + by \a separator (using QStringList::join()), so none of the + strings in the list should contain the separator. If the list is + empty or null the key's value will be an empty string. + + \warning The list should not contain empty or null strings, as + readListEntry() will use QStringList::split() to recreate the + list. As the documentation states, QStringList::split() will omit + empty strings from the list. Because of this, it is impossible to + retrieve identical list data that is stored with this function. + We recommend using the writeEntry() and readListEntry() overloads + that do not take a \a separator argument. If an error occurs the settings are left unchanged and FALSE is returned; otherwise returns TRUE. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const QStringList &value, const QChar &separator) { QString s(value.join(separator)); return writeEntry(key, s); } /*! \overload Writes the string list entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise returns TRUE. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const QStringList &value) { QString s; for (QStringList::ConstIterator it=value.begin(); it!=value.end(); ++it) { QString el = *it; if ( el.isNull() ) { el = "^0"; } else { el.replace("^", "^^"); } s+=el; s+="^e"; // end of element } return writeEntry(key, s); } /*! \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const Reads the entry specified by \a key as a string. The \a separator is used to create a QStringList by calling QStringList::split(\a separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the key was read, otherwise \a *ok is set to FALSE. + \warning As the documentation states, QStringList::split() will + omit empty strings from the list. Because of this, it is + impossible to retrieve identical list data with this function. We + recommend using the readListEntry() and writeEntry() overloads + that do not take a \a separator argument. + + Note that if you want to iterate over the list, you should iterate over a copy, e.g. \code QStringList list = mySettings.readListEntry( "size", " " ); QStringList::Iterator it = list.begin(); while( it != list.end() ) { myProcessing( *it ); ++it; } \endcode \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() */ /*! \internal */ QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) { QString value = readEntry( key, QString::null, ok ); if ( ok && !*ok ) return QStringList(); return QStringList::split(separator, value); } /*! \fn QStringList QSettings::readListEntry(const QString &key, bool *ok ) const Reads the entry specified by \a key as a string. If \a ok is not 0, \a *ok is set to TRUE if the key was read, otherwise \a *ok is set to FALSE. Note that if you want to iterate over the list, you should iterate over a copy, e.g. \code QStringList list = mySettings.readListEntry( "recentfiles" ); QStringList::Iterator it = list.begin(); while( it != list.end() ) { myProcessing( *it ); ++it; } \endcode \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() */ /*! \internal */ QStringList QSettings::readListEntry(const QString &key, bool *ok ) { QString value = readEntry( key, QString::null, ok ); if ( ok && !*ok ) return QStringList(); QStringList l; QString s; bool esc=FALSE; for (int i=0; i<(int)value.length(); i++) { if ( esc ) { if ( value[i] == 'e' ) { // end-of-string l.append(s); s=""; } else if ( value[i] == '0' ) { // null string s=QString::null; } else { s.append(value[i]); } esc=FALSE; } else if ( value[i] == '^' ) { esc = TRUE; } else { s.append(value[i]); if ( i == (int)value.length()-1 ) l.append(s); } } return l; } +#ifdef Q_OS_MAC +void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp +#endif + /*! Insert platform-dependent paths from platform-independent information. The \a domain should be an Internet domain name controlled by the producer of the software, eg. Trolltech products use "trolltech.com". The \a product should be the official name of the product. The \a scope should be QSettings::User for user-specific settings, or QSettings::Global for system-wide settings (generally these will be read-only to many users). + + Not all information is relevant on all systems (e.g. scoping is + currently used only if QSettings accesses the Windows registry). */ void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) { // On Windows, any trailing ".com(\..*)" is stripped from the domain. The // Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to // HKEY_CURRENT_USER. Note that on some installations, not all users can // write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped // from the domain. The Global scope corresponds to "/opt" (this would be // configurable at library build time - eg. to "/usr/local" or "/usr"), // while the User scope corresponds to $HOME/.*rc. // Note that on most installations, not all users can write to the System // scope. // // On MacOS X, if there is no "." in domain, append ".com", then reverse the // order of the elements (Mac OS uses "com.apple.finder" as domain+product). // The Global scope corresponds to /Library/Preferences/*.plist, while the // User scope corresponds to ~/Library/Preferences/*.plist. // Note that on most installations, not all users can write to the System // scope. + d->globalScope = scope == Global; + QString actualSearchPath; int lastDot = domain.findRev( '.' ); #if defined(Q_WS_WIN) actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; insertSearchPath( Windows, actualSearchPath ); -#elif defined(Q_WS_MAC) +#elif !defined(QWS) && defined(Q_OS_MAC) QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; - if ( topLevelDomain.isEmpty() ) - topLevelDomain = "com."; - actualSearchPath = "/" + topLevelDomain + domain.left( lastDot ) + product; + if ( !topLevelDomain.isEmpty() ) + qt_setSettingsBasePath( topLevelDomain ); + actualSearchPath = "/" + domain.left( lastDot ) + product; insertSearchPath( Mac, actualSearchPath ); #else actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; insertSearchPath( Unix, actualSearchPath ); #endif - - d->globalScope = scope == Global; } /*! Appends \a group to the current key prefix. + + \code + QSettings settings; + settings.beginGroup( "/MainWindow" ); + // read values + settings.endGroup(); + \endcode */ void QSettings::beginGroup( const QString &group ) { d->groupStack.push( group ); d->groupDirty = TRUE; } /*! Undo previous calls to beginGroup(). Note that a single beginGroup("a/b/c") is undone by a single call to endGroup(). + + \code + QSettings settings; + settings.beginGroup( "/MainWindow/Geometry" ); + // read values + settings.endGroup(); + \endcode */ void QSettings::endGroup() { d->groupStack.pop(); d->groupDirty = TRUE; } /*! Set the current key prefix to the empty string. */ void QSettings::resetGroup() { d->groupStack.clear(); d->groupDirty = FALSE; d->groupPrefix = QString::null; } /*! Returns the current key prefix, or a null string if there is no key prefix set. \sa beginGroup(); */ QString QSettings::group() const { if ( d->groupDirty ) { d->groupDirty = FALSE; d->groupPrefix = QString::null; QValueStack<QString>::Iterator it = d->groupStack.begin(); while ( it != d->groupStack.end() ) { QString group = *it; ++it; if ( group[0] != '/' ) - group = "/" + group; + group.prepend( "/" ); d->groupPrefix += group; } } return d->groupPrefix; } #endif diff --git a/qmake/tools/qstring.cpp b/qmake/tools/qstring.cpp index 56df62b..7f1fac3 100644 --- a/qmake/tools/qstring.cpp +++ b/qmake/tools/qstring.cpp @@ -1,445 +1,449 @@ /**************************************************************************** ** $Id$ ** ** Implementation of the QString class and related Unicode functions ** ** Created : 920722 ** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ // Don't define it while compiling this module, or USERS of Qt will // not be able to link. #ifdef QT_NO_CAST_ASCII #undef QT_NO_CAST_ASCII #endif #include "qstring.h" #include "qregexp.h" #include "qdatastream.h" #ifndef QT_NO_TEXTCODEC #include "qtextcodec.h" #endif -#include <ctype.h> #include <limits.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #if defined(Q_WS_WIN) #include "qt_windows.h" #endif #if !defined( QT_NO_COMPONENT ) && !defined( QT_LITE_COMPONENT ) #include "qcleanuphandler.h" #endif +#ifdef QT_NO_UNICODETABLES +# include <ctype.h> +#endif + /* ------------------------------------------------------------------------- * unicode information * these tables are generated from the unicode reference file * ftp://ftp.unicode.org/Public/3.2-Update/UnicodeData.txt * * Lars * ------------------------------------------------------------------------- */ /* Perl script to generate (run perl -x tools/qstring.cpp) #!perl sub numberize { my(%r, $n, $id); for $id ( @_ ) { $i = $id; $i="" if $i eq "EMPTY"; $r{$i}=$n++; } return %r; } sub readUnicodeDataLine { $code = shift @_; for $n (qw{ name category combining_class bidi_category character_decomposition decimal_digit_value digit_value numeric_value mirrored oldname comment uppercase lowercase titlecase}) { $id = shift @_; $codes = "${n}_code"; if ( defined %$codes && defined $$codes{$id} ) { $id = $$codes{$id}; } ${$n}{$code}=$id; } $decomp = $character_decomposition{$code}; if ( length $decomp == 0 ) { $decomp = "<single>"; } if (substr($decomp, 0, 1) ne '<') { $decomp = "<canonical> " . $decomp; } @_ = split(" ", $decomp); $tag = shift @_; $tag = $character_decomposition_tag{$tag}; $decomp = join( ", 0x", @_ ); $decomp = "0x".$decomp; $decomposition{$code} = $decomp; $decomposition_tag{$code} = $tag; $decomposition_pos{$code} = $position; $len = scalar(@_); $decomposition_len{$code} = $len; # we use canonical decompositions longer than 1 char # we exlude Arabic ligatures from the table if($len > 1 and $tag == 1) { # ligature to add... $start = shift @_; $ligature{$start} = $ligature{$start}." ".$code; } # adjust position if($len != 0) { $position += $len + 3; } } # Code to integer mappings... # %category_code = numberize(qw{ EMPTY Mn Mc Me Nd Nl No Zs Zl Zp Cc Cf Cs Co Cn Lu Ll Lt Lm Lo Pc Pd Ps Pe Pi Pf Po Sm Sc Sk So }); %bidi_category_code = numberize(qw{ L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN}); %character_decomposition_tag = numberize(qw{ <single> <canonical> <font> <noBreak> <initial> <medial> <final> <isolated> <circle> <super> <sub> <vertical> <wide> <narrow> <small> <square> <compat> <fraction> }); %mirrored_code = numberize(qw{N Y}); %joining_code = numberize(qw{U D R C}); # Read data into hashes... # open IN, "UnicodeData.txt"; $position = 1; while (<IN>) { @fields = split /;/; if ( length($fields[0]) < 5 ) { if ( $fields[1] =~ /, First>/ ) { $codeRangeBegin = $fields[0]; } elsif ( $fields[1] =~ /, Last>/ ) { for ( $i=hex($codeRangeBegin); $i<=hex($fields[0]); $i+=1 ) { @fields2 = @fields; $fields2[0] = sprintf "%lX", $i; readUnicodeDataLine @fields2; } } else { readUnicodeDataLine @fields; } } } open IN2, "ArabicShaping.txt"; $position = 1; while (<IN2>) { @fields = split /;/; $code = shift @fields; $dummy = shift @fields; $join = shift @fields; $join =~ s/ //g; $join = $joining_code{$join}; $joining{$code}=$join; } # Build pages... # $rowtable_txt = "static const Q_UINT8 * const unicode_info[256] = {"; for $row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$row,$cell); $info = $category{$code}; $info = 0 if !defined $info; $txt .= "\n " if $cell%8 == 0; $txt .= "$info, "; } $therow = $row{$txt}; if ( !defined $therow ) { $size+=256; $therow = "ui_".sprintf("%02X",$row); $rowtext{$therow} = "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; $row{$txt}=$therow; } $rowtable_txt .= "\n " if $row%8 == 0; $rowtable_txt .= "$therow, "; } print "// START OF GENERATED DATA\n\n"; print "#ifndef QT_NO_UNICODETABLES\n\n"; # Print pages... # for $r ( sort keys %rowtext ) { print $rowtext{$r}; } print "$rowtable_txt\n};\n"; $size += 256*4; print "// $size bytes\n\n"; # Build decomposition tables # $rowtable_txt = "static const Q_UINT16 * const decomposition_info[256] = {"; $table_txt = "static const Q_UINT16 decomposition_map[] = {\n 0,\n"; for $row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$row,$cell); $txt .= "\n " if $cell%8 == 0; if( $decomposition_tag{$code} != 0 ) { $txt .= " $decomposition_pos{$code},"; $table_txt .= " $decomposition_tag{$code},"; $table_txt .= " 0x$code,"; $table_txt .= " $decomposition{$code}, 0,\n"; $size += 2 * $decomposition_len{$code} + 6; } else { $txt .= " 0,"; } } $therow = $row{$txt}; if ( !defined $therow ) { $size+=512; $therow = "di_".sprintf("%02X",$row); $dec_rowtext{$therow} = "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; $row{$txt}=$therow; } $rowtable_txt .= "\n " if $row%8 == 0; $rowtable_txt .= "$therow, "; } # Print decomposition tables # print "$table_txt\n};\n\n"; for $r ( sort keys %dec_rowtext ) { print $dec_rowtext{$r}; } print "$rowtable_txt\n};\n"; $size += 256*4; print "// $size bytes\n\n"; # build ligature tables # $size = 0; $position = 1; $rowtable_txt = "static const Q_UINT16 * const ligature_info[256] = {"; $table_txt = "static const Q_UINT16 ligature_map[] = {\n 0,\n"; for $lig_row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$lig_row,$cell); $txt .= "\n " if $cell%8 == 0; if( defined $ligature{$code} ) { $txt .= " $position,"; @ligature = split(" ", $ligature{$code}); # we need to sort ligatures according to their length. # long ones have to come first! @ligature_sort = sort { $decomposition_len{$b} <=> $decomposition_len{$a} } @ligature; # now replace each code by its position in # the decomposition map. undef(@lig_pos); for $n (@ligature_sort) { push(@lig_pos, $decomposition_pos{$n}); } # debug info if( 0 ) { print "ligatures: $ligature{$code}\n"; $sort = join(" ", @ligature_sort); print "sorted : $sort\n"; } $lig = join(", ", @lig_pos); $table_txt .= " $lig, 0,\n"; $size += 2 * scalar(@ligature) + 2; $position += scalar(@ligature) + 1; } else { $txt .= " 0,"; } } $therow = $lig_row{$txt}; if ( !defined $therow ) { $size+=512; $therow = "li_".sprintf("%02X",$lig_row); $lig_rowtext{$therow} = "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; $lig_row{$txt}=$therow; } $rowtable_txt .= "\n " if $lig_row%8 == 0; $rowtable_txt .= "$therow, "; } # Print ligature tables # print "$table_txt\n};\n\n"; for $r ( sort keys %lig_rowtext ) { print $lig_rowtext{$r}; } print "$rowtable_txt\n};\n"; $size += 256*4; print "// $size bytes\n\n"; # Build direction/joining/mirrored pages... # $rowtable_txt = "static const Q_UINT8 * const direction_info[256] = {"; for $dir_row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$dir_row,$cell); $dir = $bidi_category{$code}; $dir = 0 if !defined $dir; $join = $joining{$code}; $join = 0 if !defined $join; $mirr = $mirrored{$code}; $mirr = 0 if !defined $mirr; $info = $dir + 32*$join + 128*$mirr; $txt .= "\n " if $cell%8 == 0; $txt .= "$info, "; } $therow = $dir_row{$txt}; if ( !defined $therow ) { $size+=256; $therow = "dir_".sprintf("%02X",$dir_row); $dir_rowtext{$therow} = "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; $dir_row{$txt}=$therow; } $rowtable_txt .= "\n " if $dir_row%8 == 0; $rowtable_txt .= "$therow, "; } # Print pages... # for $r ( sort keys %dir_rowtext ) { print $dir_rowtext{$r}; } print "$rowtable_txt\n};\n"; $size += 256*4; print "// $size bytes\n\n"; # Build table of combining classes # $rowtable_txt = "static const Q_UINT8 * const combining_info[256] = {"; for $combining_row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$combining_row,$cell); $info = $combining_class{$code}; $info = 0 if !defined $info; $txt .= "\n " if $cell%8 == 0; $txt .= "$info, "; } $therow = $combining_row{$txt}; if ( !defined $therow ) { $size+=256; $therow = "cmb_".sprintf("%02X",$combining_row); $combining_rowtext{$therow} = "static const Q_UINT8 ${therow}[] = {$txt\n};\n\n"; $combining_row{$txt}=$therow; } $rowtable_txt .= "\n " if $combining_row%8 == 0; $rowtable_txt .= "$therow, "; } # Print pages... # for $r ( sort keys %combining_rowtext ) { print $combining_rowtext{$r}; } print "$rowtable_txt\n};\n"; $size += 256*4; print "// $size bytes\n\n"; # Build case info # $rowtable_txt = "static const Q_UINT16 * const case_info[256] = {"; for $row ( 0..255 ) { $nonzero=0; $txt = ""; for $cell ( 0..255 ) { $code = sprintf("%02X%02X",$row,$cell); $info = $uppercase{$code}; if ( length( $info ) eq 0 ) { $info = $lowercase{$code}; } $info =~ s/^0+//; if ( length( $info ) eq 0 ) { $info = "0"; } else { $info = "0x".lc($info); } if ( length( $info ) ne 1 ) { $nonzero = 1; } $txt .= "\n " if $cell%8 == 0; $txt .= "$info, "; } $therow = $case_row{$txt}; if ( !defined $therow && $nonzero ne 0 ) { $size+=512; $therow = "case_".sprintf("%02X",$row); $case_rowtext{$therow} = "static const Q_UINT16 ${therow}[] = {$txt\n};\n\n"; @@ -11406,882 +11410,884 @@ static const Q_INT8 num_0E[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_0F[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_10[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_13[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_17[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_18[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_20[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 num_24[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, }; static const Q_INT8 num_27[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; static const Q_INT8 * const decimal_info[256] = { num_00, 0, 0, 0, 0, 0, num_06, 0, 0, num_09, num_09, num_0B, num_09, num_0D, num_0E, num_0F, num_10, 0, 0, num_13, 0, 0, 0, num_17, num_18, 0, 0, 0, 0, 0, 0, 0, num_20, 0, 0, 0, num_24, 0, 0, num_27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, num_18, }; // 47354 bytes // END OF GENERATED DATA #endif static inline QChar::Category category( const QChar &c ) { #ifndef QT_NO_UNICODETABLES return (QChar::Category)(unicode_info[c.row()][c.cell()]); #else // ### just ASCII if ( c.unicode() < 0x100 ) { return (QChar::Category)(ui_00[c.unicode()]); } return QChar::Letter_Uppercase; //####### #endif } static inline QChar lower( const QChar &c ) { #ifndef QT_NO_UNICODETABLES uchar row = c.row(); uchar cell = c.cell(); if ( unicode_info[row][cell] != QChar::Letter_Uppercase ) return c; Q_UINT16 lower = *( case_info[row] + cell ); if ( lower == 0 ) return c; return lower; #else if ( c.row() ) return c; else return QChar( tolower((uchar) c.latin1()) ); #endif } static inline QChar upper( const QChar &c ) { #ifndef QT_NO_UNICODETABLES uchar row = c.row(); uchar cell = c.cell(); if ( unicode_info[row][cell] != QChar::Letter_Lowercase ) return c; Q_UINT16 upper = *(case_info[row]+cell); if ( upper == 0 ) return c; return upper; #else if ( c.row() ) return c; else return QChar( toupper((uchar) c.latin1()) ); #endif } static inline QChar::Direction direction( const QChar &c ) { #ifndef QT_NO_UNICODETABLES const Q_UINT8 *rowp = direction_info[c.row()]; if(!rowp) return QChar::DirL; return (QChar::Direction) ( *(rowp+c.cell()) & 0x1f ); #else + Q_UNUSED(c); return QChar::DirL; #endif } static inline bool mirrored( const QChar &c ) { #ifndef QT_NO_UNICODETABLES const Q_UINT8 *rowp = direction_info[c.row()]; if ( !rowp ) return FALSE; return *(rowp+c.cell())>128; #else + Q_UNUSED(c); return FALSE; #endif } #ifndef QT_NO_UNICODETABLES static const Q_UINT16 symmetricPairs[] = { 0x0028, 0x0029, 0x003C, 0x003E, 0x005B, 0x005D, 0x007B, 0x007D, 0x00AB, 0x00BB, 0x2039, 0x203A, 0x2045, 0x2046, 0x207D, 0x207E, 0x208D, 0x208E, 0x2208, 0x220B, 0x2209, 0x220C, 0x220A, 0x220D, 0x2215, 0x29F5, 0x223C, 0x223D, 0x2243, 0x22CD, 0x2252, 0x2253, 0x2254, 0x2255, 0x2264, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, 0x226A, 0x226B, 0x226E, 0x226F, 0x2270, 0x2271, 0x2272, 0x2273, 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, 0x227A, 0x227B, 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, 0x2281, 0x2282, 0x2283, 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, 0x228A, 0x228B, 0x228F, 0x2290, 0x2291, 0x2292, 0x2298, 0x29B8, 0x22A2, 0x22A3, 0x22A6, 0x2ADE, 0x22A8, 0x2AE4, 0x22A9, 0x2AE3, 0x22AB, 0x2AE5, 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0x22B6, 0x22B7, 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22D0, 0x22D1, 0x22D6, 0x22D7, 0x22D8, 0x22D9, 0x22DA, 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, 0x22E0, 0x22E1, 0x22E2, 0x22E3, 0x22E4, 0x22E5, 0x22E6, 0x22E7, 0x22E8, 0x22E9, 0x22EA, 0x22EB, 0x22EC, 0x22ED, 0x22F0, 0x22F1, 0x22F2, 0x22FA, 0x22F3, 0x22FB, 0x22F4, 0x22FC, 0x22F6, 0x22FD, 0x22F7, 0x22FE, 0x2308, 0x2309, 0x230A, 0x230B, 0x2329, 0x232A, 0x2768, 0x2769, 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27D5, 0x27D6, 0x27DD, 0x27DE, 0x27E2, 0x27E3, 0x27E4, 0x27E5, 0x27E6, 0x27E7, 0x27E8, 0x27E9, 0x27EA, 0x27EB, 0x2983, 0x2984, 0x2985, 0x2986, 0x2987, 0x2988, 0x2989, 0x298A, 0x298B, 0x298C, 0x298D, 0x2990, 0x298E, 0x298F, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, 0x2997, 0x2998, 0x29C0, 0x29C1, 0x29C4, 0x29C5, 0x29CF, 0x29D0, 0x29D1, 0x29D2, 0x29D4, 0x29D5, 0x29D8, 0x29D9, 0x29DA, 0x29DB, 0x29F8, 0x29F9, 0x29FC, 0x29FD, 0x2A2B, 0x2A2C, 0x2A34, 0x2A35, 0x2A3C, 0x2A3D, 0x2A64, 0x2A65, 0x2A79, 0x2A7A, 0x2A7D, 0x2A7E, 0x2A7F, 0x2A80, 0x2A81, 0x2A82, 0x2A83, 0x2A84, 0x2A8B, 0x2A8C, 0x2A91, 0x2A92, 0x2A93, 0x2A94, 0x2A95, 0x2A96, 0x2A97, 0x2A98, 0x2A99, 0x2A9A, 0x2A9B, 0x2A9C, 0x2AA1, 0x2AA2, 0x2AA6, 0x2AA7, 0x2AA8, 0x2AA9, 0x2AAA, 0x2AAB, 0x2AAC, 0x2AAD, 0x2AAF, 0x2AB0, 0x2AB3, 0x2AB4, 0x2ABB, 0x2ABC, 0x2ABD, 0x2ABE, 0x2ABF, 0x2AC0, 0x2AC1, 0x2AC2, 0x2AC3, 0x2AC4, 0x2AC5, 0x2AC6, 0x2ACD, 0x2ACE, 0x2ACF, 0x2AD0, 0x2AD1, 0x2AD2, 0x2AD3, 0x2AD4, 0x2AD5, 0x2AD6, 0x2AEC, 0x2AED, 0x2AF7, 0x2AF8, 0x2AF9, 0x2AFA, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3010, 0x3011, 0x3014, 0x3015, 0x3016, 0x3017, 0x3018, 0x3019, 0x301A, 0x301B, 0xFF08, 0xFF09, 0xFF1C, 0xFF1E, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, 0xFF5F, 0xFF60, 0xFF62, 0xFF63, }; // ### shouldn't this be const? static const int symmetricPairsSize = sizeof(symmetricPairs)/sizeof(symmetricPairs[0]); /* * ---------------------------------------------------------------------- * End of unicode tables * ---------------------------------------------------------------------- */ #endif static int ucstrcmp( const QString &as, const QString &bs ) { const QChar *a = as.unicode(); const QChar *b = bs.unicode(); if ( a == b ) return 0; if ( a == 0 ) return 1; if ( b == 0 ) return -1; int l=QMIN(as.length(),bs.length()); while ( l-- && *a == *b ) a++,b++; if ( l==-1 ) return ( as.length()-bs.length() ); return a->unicode() - b->unicode(); } static int ucstrncmp( const QChar *a, const QChar *b, int l ) { while ( l-- && *a == *b ) a++,b++; if ( l==-1 ) return 0; return a->unicode() - b->unicode(); } static int ucstrnicmp( const QChar *a, const QChar *b, int l ) { while ( l-- && ::lower( *a ) == ::lower( *b ) ) a++,b++; if ( l==-1 ) return 0; return ::lower( *a ).unicode() - ::lower( *b ).unicode(); } static uint computeNewMax( uint len ) { uint newMax = 4; while ( newMax < len ) newMax *= 2; - // try to spare some memory + // try to save some memory if ( newMax >= 1024 * 1024 && len <= newMax - (newMax >> 2) ) newMax -= newMax >> 2; return newMax; } /*! \class QCharRef qstring.h \reentrant \brief The QCharRef class is a helper class for QString. \ingroup text When you get an object of type QCharRef, if you can assign to it, the assignment will apply to the character in the string from which you got the reference. That is its whole purpose in life. The QCharRef becomes invalid once modifications are made to the string: if you want to keep the character, copy it into a QChar. Most of the QChar member functions also exist in QCharRef. However, they are not explicitly documented here. \sa QString::operator[]() QString::at() QChar */ /*! \class QChar qstring.h \reentrant \brief The QChar class provides a lightweight Unicode character. \ingroup text Unicode characters are (so far) 16-bit entities without any markup or structure. This class represents such an entity. It is lightweight, so it can be used everywhere. Most compilers treat it like a "short int". (In a few years it may be necessary to make QChar 32-bit when more than 65536 Unicode code points have been defined and come into use.) QChar provides a full complement of testing/classification functions, converting to and from other formats, converting from composed to decomposed Unicode, and trying to compare and case-convert if you ask it to. The classification functions include functions like those in ctype.h, but operating on the full range of Unicode characters. They all return TRUE if the character is a certain type of character; otherwise they return FALSE. These classification functions are isNull() (returns TRUE if the character is U+0000), isPrint() (TRUE if the character is any sort of printable character, including whitespace), isPunct() (any sort of punctation), isMark() (Unicode Mark), isLetter (a letter), isNumber() (any sort of numeric character), isLetterOrNumber(), and isDigit() (decimal digits). All of these are wrappers around category() which return the Unicode-defined category of each character. QChar further provides direction(), which indicates the "natural" writing direction of this character. The joining() function indicates how the character joins with its neighbors (needed mostly for Arabic) and finally mirrored(), which indicates whether the character needs to be mirrored when it is printed in its "unnatural" writing direction. Composed Unicode characters (like å) can be converted to decomposed Unicode ("a" followed by "ring above") by using decomposition(). In Unicode, comparison is not necessarily possible and case conversion is very difficult at best. Unicode, covering the "entire" world, also includes most of the world's case and sorting problems. Qt tries, but not very hard: operator==() and friends will do comparison based purely on the numeric Unicode value (code point) of the characters, and upper() and lower() will do case changes when the character has a well-defined upper/lower-case equivalent. There is no provision for locale-dependent case folding rules or comparison; these functions are meant to be fast so they can be used unambiguously in data structures. (See QString::localeAwareCompare() though.) The conversion functions include unicode() (to a scalar), latin1() (to scalar, but converts all non-Latin1 characters to 0), row() (gives the Unicode row), cell() (gives the Unicode cell), digitValue() (gives the integer value of any of the numerous digit characters), and a host of constructors. More information can be found in the document \link unicode.html About Unicode. \endlink \sa QString QCharRef */ /*! \enum QChar::Category This enum maps the Unicode character categories. The following characters are normative in Unicode: \value Mark_NonSpacing Unicode class name Mn \value Mark_SpacingCombining Unicode class name Mc \value Mark_Enclosing Unicode class name Me \value Number_DecimalDigit Unicode class name Nd \value Number_Letter Unicode class name Nl \value Number_Other Unicode class name No \value Separator_Space Unicode class name Zs \value Separator_Line Unicode class name Zl \value Separator_Paragraph Unicode class name Zp \value Other_Control Unicode class name Cc \value Other_Format Unicode class name Cf \value Other_Surrogate Unicode class name Cs \value Other_PrivateUse Unicode class name Co \value Other_NotAssigned Unicode class name Cn The following categories are informative in Unicode: \value Letter_Uppercase Unicode class name Lu \value Letter_Lowercase Unicode class name Ll \value Letter_Titlecase Unicode class name Lt \value Letter_Modifier Unicode class name Lm \value Letter_Other Unicode class name Lo \value Punctuation_Connector Unicode class name Pc \value Punctuation_Dash Unicode class name Pd \value Punctuation_Open Unicode class name Ps \value Punctuation_Close Unicode class name Pe \value Punctuation_InitialQuote Unicode class name Pi \value Punctuation_FinalQuote Unicode class name Pf \value Punctuation_Other Unicode class name Po \value Symbol_Math Unicode class name Sm \value Symbol_Currency Unicode class name Sc \value Symbol_Modifier Unicode class name Sk \value Symbol_Other Unicode class name So There are two categories that are specific to Qt: \value NoCategory used when Qt is dazed and confused and cannot make sense of anything. \value Punctuation_Dask old typo alias for Punctuation_Dash */ /*! \enum QChar::Direction This enum type defines the Unicode direction attributes. See \link http://www.unicode.org/ the Unicode Standard\endlink for a description of the values. In order to conform to C/C++ naming conventions "Dir" is prepended to the codes used in the Unicode Standard. */ /*! \enum QChar::Decomposition This enum type defines the Unicode decomposition attributes. See \link http://www.unicode.org/ the Unicode Standard\endlink for a description of the values. */ /*! \enum QChar::Joining This enum type defines the Unicode joining attributes. See \link http://www.unicode.org/ the Unicode Standard\endlink for a description of the values. */ /*! \enum QChar::CombiningClass This enum type defines names for some of the Unicode combining classes. See \link http://www.unicode.org/ the Unicode Standard\endlink for a description of the values. */ /*! \fn void QChar::setCell( uchar cell ) \internal */ /*! \fn void QChar::setRow( uchar row ) \internal */ /*! \fn QChar::QChar() Constructs a null QChar (one that isNull()). */ /*! \fn QChar::QChar( char c ) Constructs a QChar corresponding to ASCII/Latin1 character \a c. */ /*! \fn QChar::QChar( uchar c ) Constructs a QChar corresponding to ASCII/Latin1 character \a c. */ /*! \fn QChar::QChar( uchar c, uchar r ) Constructs a QChar for Unicode cell \a c in row \a r. */ /*! \fn QChar::QChar( const QChar& c ) Constructs a copy of \a c. This is a deep copy, if such a lightweight object can be said to have deep copies. */ /*! \fn QChar::QChar( ushort rc ) Constructs a QChar for the character with Unicode code point \a rc. */ /*! \fn QChar::QChar( short rc ) Constructs a QChar for the character with Unicode code point \a rc. */ /*! \fn QChar::QChar( uint rc ) Constructs a QChar for the character with Unicode code point \a rc. */ /*! \fn QChar::QChar( int rc ) Constructs a QChar for the character with Unicode code point \a rc. */ /*! \fn bool QChar::networkOrdered () \obsolete Returns TRUE if this character is in network byte order (MSB first); otherwise returns FALSE. This is platform dependent. */ /*! \fn bool QChar::isNull() const Returns TRUE if the character is the Unicode character 0x0000, i.e. ASCII NUL; otherwise returns FALSE. */ /*! \fn uchar QChar::cell () const Returns the cell (least significant byte) of the Unicode character. */ /*! \fn uchar QChar::row () const Returns the row (most significant byte) of the Unicode character. */ /*! Returns TRUE if the character is a printable character; otherwise returns FALSE. This is any character not of category Cc or Cn. Note that this gives no indication of whether the character is available in a particular \link QFont font\endlink. */ bool QChar::isPrint() const { Category c = ::category( *this ); return !(c == Other_Control || c == Other_NotAssigned); } /*! Returns TRUE if the character is a separator character (Separator_* categories); otherwise returns FALSE. */ bool QChar::isSpace() const { if( ucs >= 9 && ucs <=13 ) return TRUE; Category c = ::category( *this ); return c >= Separator_Space && c <= Separator_Paragraph; } /*! Returns TRUE if the character is a mark (Mark_* categories); otherwise returns FALSE. */ bool QChar::isMark() const { Category c = ::category( *this ); return c >= Mark_NonSpacing && c <= Mark_Enclosing; } /*! Returns TRUE if the character is a punctuation mark (Punctuation_* categories); otherwise returns FALSE. */ bool QChar::isPunct() const { Category c = ::category( *this ); return (c >= Punctuation_Connector && c <= Punctuation_Other); } /*! Returns TRUE if the character is a letter (Letter_* categories); otherwise returns FALSE. */ bool QChar::isLetter() const { Category c = ::category( *this ); return (c >= Letter_Uppercase && c <= Letter_Other); } /*! Returns TRUE if the character is a number (of any sort - Number_* categories); otherwise returns FALSE. \sa isDigit() */ bool QChar::isNumber() const { Category c = ::category( *this ); return c >= Number_DecimalDigit && c <= Number_Other; } /*! Returns TRUE if the character is a letter or number (Letter_* or Number_* categories); otherwise returns FALSE. */ bool QChar::isLetterOrNumber() const { Category c = ::category( *this ); @@ -12510,4938 +12516,5078 @@ QChar QChar::upper() const /*! \fn ushort & QChar::unicode() \overload Returns a reference to the numeric Unicode value equal to the QChar. */ /***************************************************************************** Documentation of QChar related functions *****************************************************************************/ /*! \fn bool operator==( QChar c1, QChar c2 ) \relates QChar Returns TRUE if \a c1 and \a c2 are the same Unicode character; otherwise returns FALSE. */ /*! \fn bool operator==( char ch, QChar c ) \overload \relates QChar Returns TRUE if \a c is the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn bool operator==( QChar c, char ch ) \overload \relates QChar Returns TRUE if \a c is the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator!=( QChar c1, QChar c2 ) \relates QChar Returns TRUE if \a c1 and \a c2 are not the same Unicode character; otherwise returns FALSE. */ /*! \fn int operator!=( char ch, QChar c ) \overload \relates QChar Returns TRUE if \a c is not the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator!=( QChar c, char ch ) \overload \relates QChar Returns TRUE if \a c is not the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator<=( QChar c1, QChar c2 ) \relates QChar Returns TRUE if the numeric Unicode value of \a c1 is less than that of \a c2, or they are the same Unicode character; otherwise returns FALSE. */ /*! \fn int operator<=( QChar c, char ch ) \overload \relates QChar Returns TRUE if the numeric Unicode value of \a c is less than or equal to that of the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator<=( char ch, QChar c ) \overload \relates QChar Returns TRUE if the numeric Unicode value of the ASCII/Latin1 character \a ch is less than or equal to that of \a c; otherwise returns FALSE. */ /*! \fn int operator>=( QChar c1, QChar c2 ) \relates QChar Returns TRUE if the numeric Unicode value of \a c1 is greater than that of \a c2, or they are the same Unicode character; otherwise returns FALSE. */ /*! \fn int operator>=( QChar c, char ch ) \overload \relates QChar Returns TRUE if the numeric Unicode value of \a c is greater than or equal to that of the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator>=( char ch, QChar c ) \overload \relates QChar Returns TRUE if the numeric Unicode value of the ASCII/Latin1 character \a ch is greater than or equal to that of \a c; otherwise returns FALSE. */ /*! \fn int operator<( QChar c1, QChar c2 ) \relates QChar Returns TRUE if the numeric Unicode value of \a c1 is less than that of \a c2; otherwise returns FALSE. */ /*! \fn int operator<( QChar c, char ch ) \overload \relates QChar Returns TRUE if the numeric Unicode value of \a c is less than that of the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator<( char ch, QChar c ) \overload \relates QChar Returns TRUE if the numeric Unicode value of the ASCII/Latin1 character \a ch is less than that of \a c; otherwise returns FALSE. */ /*! \fn int operator>( QChar c1, QChar c2 ) \relates QChar Returns TRUE if the numeric Unicode value of \a c1 is greater than that of \a c2; otherwise returns FALSE. */ /*! \fn int operator>( QChar c, char ch ) \overload \relates QChar Returns TRUE if the numeric Unicode value of \a c is greater than that of the ASCII/Latin1 character \a ch; otherwise returns FALSE. */ /*! \fn int operator>( char ch, QChar c ) \overload \relates QChar Returns TRUE if the numeric Unicode value of the ASCII/Latin1 character \a ch is greater than that of \a c; otherwise returns FALSE. */ #ifndef QT_NO_UNICODETABLES // small class used internally in QString::Compose() class QLigature { public: QLigature( QChar c ); Q_UINT16 first() { cur = ligatures; return cur ? *cur : 0; } Q_UINT16 next() { return cur && *cur ? *(cur++) : 0; } Q_UINT16 current() { return cur ? *cur : 0; } int match(QString & str, unsigned int index); QChar head(); QChar::Decomposition tag(); private: Q_UINT16 *ligatures; Q_UINT16 *cur; }; QLigature::QLigature( QChar c ) { const Q_UINT16 *r = ligature_info[c.row()]; if( !r ) ligatures = 0; else { const Q_UINT16 pos = r[c.cell()]; ligatures = (Q_UINT16 *)&(ligature_map[pos]); } cur = ligatures; } QChar QLigature::head() { if(current()) return QChar(decomposition_map[current()+1]); return QChar::null; } QChar::Decomposition QLigature::tag() { if(current()) return (QChar::Decomposition) decomposition_map[current()]; return QChar::Canonical; } int QLigature::match(QString & str, unsigned int index) { unsigned int i=index; if(!current()) return 0; Q_UINT16 lig = current() + 2; Q_UINT16 ch; while ((i < str.length()) && (ch = decomposition_map[lig])) { if (str[(int)i] != QChar(ch)) return 0; i++; lig++; } if (!decomposition_map[lig]) { return i-index; } return 0; } // this function is just used in QString::compose() static inline bool format(QChar::Decomposition tag, QString & str, int index, int len) { unsigned int l = index + len; unsigned int r = index; bool left = FALSE, right = FALSE; left = ((l < str.length()) && ((str[(int)l].joining() == QChar::Dual) || (str[(int)l].joining() == QChar::Right))); if (r > 0) { r--; //printf("joining(right) = %d\n", str[(int)r].joining()); right = (str[(int)r].joining() == QChar::Dual); } switch (tag) { case QChar::Medial: return (left & right); case QChar::Initial: return (left && !right); case QChar::Final: return (right);// && !left); case QChar::Isolated: default: return (!right && !left); } } // format() #endif /* QString::compose() and visual() were developed by Gordon Tisher <tisher@uniserve.ca>, with input from Lars Knoll <knoll@mpi-hd.mpg.de>, who developed the unicode data tables. */ /*! \warning This function is not supported in Qt 3.x. It is provided for experimental and illustrative purposes only. It is mainly of interest to those experimenting with Arabic and other composition-rich texts. Applies possible ligatures to a QString. Useful when composition-rich text requires rendering with glyph-poor fonts, but it also makes compositions such as QChar(0x0041) ('A') and QChar(0x0308) (Unicode accent diaresis), giving QChar(0x00c4) (German A Umlaut). */ void QString::compose() { #ifndef QT_NO_UNICODETABLES unsigned int index=0, len; unsigned int cindex = 0; QChar code, head; QMemArray<QChar> dia; QString composed = *this; while (index < length()) { code = at(index); //printf("\n\nligature for 0x%x:\n", code.unicode()); QLigature ligature(code); ligature.first(); while(ligature.current()) { if ((len = ligature.match(*this, index)) != 0) { head = ligature.head(); unsigned short code = head.unicode(); // we exclude Arabic presentation forms A and a few // other ligatures, which are undefined in most fonts if(!(code > 0xfb50 && code < 0xfe80) && !(code > 0xfb00 && code < 0xfb2a)) { // joining info is only needed for Arabic if (format(ligature.tag(), *this, index, len)) { //printf("using ligature 0x%x, len=%d\n",code,len); // replace letter composed.replace(cindex, len, QChar(head)); index += len-1; // we continue searching in case we have a final // form because medial ones are preferred. if ( len != 1 || ligature.tag() !=QChar::Final ) break; } } } ligature.next(); } cindex++; index++; } *this = composed; #endif } // These macros are used for efficient allocation of QChar strings. // IMPORTANT! If you change these, make sure you also change the // "delete unicode" statement in ~QStringData() in qstring.h correspondingly! #define QT_ALLOC_QCHAR_VEC( N ) (QChar*) new char[ sizeof(QChar)*( N ) ] #define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P )) /*! This utility function converts the 8-bit string \a ba to Unicode, returning the result. The caller is responsible for deleting the return value with delete[]. */ -QChar* QString::asciiToUnicode( const QByteArray& ba, uint* len ) +QChar* QString::latin1ToUnicode( const QByteArray& ba, uint* len ) { if ( ba.isNull() ) { *len = 0; return 0; } int l = 0; while ( l < (int)ba.size() && ba[l] ) l++; char* str = ba.data(); QChar *uc = new QChar[ l ]; // Can't use macro, since function is public QChar *result = uc; if ( len ) *len = l; while (l--) *uc++ = *str++; return result; } -static QChar* internalAsciiToUnicode( const QByteArray& ba, uint* len ) +static QChar* internalLatin1ToUnicode( const QByteArray& ba, uint* len ) { if ( ba.isNull() ) { *len = 0; return 0; } int l = 0; while ( l < (int)ba.size() && ba[l] ) l++; char* str = ba.data(); QChar *uc = QT_ALLOC_QCHAR_VEC( l ); QChar *result = uc; if ( len ) *len = l; while (l--) *uc++ = *str++; return result; } /*! \overload This utility function converts the '\0'-terminated 8-bit string \a str to Unicode, returning the result and setting \a *len to the length of the Unicode string. The caller is responsible for deleting the return value with delete[]. */ -QChar* QString::asciiToUnicode( const char *str, uint* len, uint maxlen ) +QChar* QString::latin1ToUnicode( const char *str, uint* len, uint maxlen ) { QChar* result = 0; uint l = 0; if ( str ) { if ( maxlen != (uint)-1 ) { while ( l < maxlen && str[l] ) l++; } else { // Faster? - l = qstrlen(str); + l = strlen( str ); } QChar *uc = new QChar[ l ]; // Can't use macro since function is public result = uc; uint i = l; while ( i-- ) *uc++ = *str++; } if ( len ) *len = l; return result; } -static QChar* internalAsciiToUnicode( const char *str, uint* len, +static QChar* internalLatin1ToUnicode( const char *str, uint* len, uint maxlen = (uint)-1 ) { QChar* result = 0; uint l = 0; if ( str ) { if ( maxlen != (uint)-1 ) { while ( l < maxlen && str[l] ) l++; } else { // Faster? - l = qstrlen(str); + l = strlen( str ); } QChar *uc = QT_ALLOC_QCHAR_VEC( l ); result = uc; uint i = l; while ( i-- ) *uc++ = *str++; } if ( len ) *len = l; return result; } /*! This utility function converts \a l 16-bit characters from \a uc to ASCII, returning a '\0'-terminated string. The caller is responsible for deleting the resultant string with delete[]. */ -char* QString::unicodeToAscii(const QChar *uc, uint l) +char* QString::unicodeToLatin1(const QChar *uc, uint l) { if (!uc) { return 0; } char *a = new char[l+1]; char *result = a; while (l--) { *a++ = (uc->unicode() > 0xff) ? '?' : (char)uc->unicode(); uc++; } *a = '\0'; return result; } /***************************************************************************** QString member functions *****************************************************************************/ /*! \class QString qstring.h \reentrant \brief The QString class provides an abstraction of Unicode text and the classic C '\0'-terminated char array. \ingroup tools \ingroup shared \ingroup text \mainclass QString uses \link shclass.html implicit sharing\endlink, which makes it very efficient and easy to use. In all of the QString methods that take \c {const char *} parameters, the \c {const char *} is interpreted as a classic C-style '\0'-terminated ASCII string. It is legal for the \c {const char *} parameter to be 0. If the \c {const char *} is not '\0'-terminated, the results are undefined. Functions that copy classic C strings into a QString will not copy the terminating '\0' character. The QChar array of the QString (as returned by unicode()) is generally not terminated by a '\0'. If you need to pass a QString to a function that requires a C '\0'-terminated string use latin1(). \keyword QString::null A QString that has not been assigned to anything is \e null, i.e. both the length and data pointer is 0. A QString that references the empty string ("", a single '\0' char) is \e empty. Both null and empty QStrings are legal parameters to the methods. Assigning \c{(const char *) 0} to QString gives a null QString. For convenience, \c QString::null is a null QString. When sorting, empty strings come first, followed by non-empty strings, followed by null strings. We recommend using \c{if ( !str.isNull() )} to check for a non-null string rather than \c{if ( !str )}; see \l operator!() for an explanation. Note that if you find that you are mixing usage of \l QCString, QString, and \l QByteArray, this causes lots of unnecessary copying and might indicate that the true nature of the data you are dealing with is uncertain. If the data is '\0'-terminated 8-bit data, use \l QCString; if it is unterminated (i.e. contains '\0's) 8-bit data, use \l QByteArray; if it is text, use QString. Lists of strings are handled by the QStringList class. You can split a string into a list of strings using QStringList::split(), and join a list of strings into a single string with an optional separator using QStringList::join(). You can obtain a list of strings from a string list that contain a particular substring or that match a particular \link qregexp.html regex\endlink using QStringList::grep(). <b>Note for C programmers</b> Due to C++'s type system and the fact that QString is implicitly shared, QStrings may be treated like ints or other simple base types. For example: \code QString boolToString( bool b ) { QString result; if ( b ) result = "True"; else result = "False"; return result; } \endcode The variable, result, is an auto variable allocated on the stack. When return is called, because we're returning by value, The copy constructor is called and a copy of the string is returned. (No actual copying takes place thanks to the implicit sharing, see below.) Throughout Qt's source code you will encounter QString usages like this: \code QString func( const QString& input ) { QString output = input; // process output return output; } \endcode The 'copying' of input to output is almost as fast as copying a pointer because behind the scenes copying is achieved by incrementing a reference count. QString (like all Qt's implicitly shared classes) operates on a copy-on-write basis, only copying if an instance is actually changed. If you wish to create a deep copy of a QString without losing any Unicode information then you should use QDeepCopy. \sa QChar QCString QByteArray QConstString */ /*! \enum Qt::ComparisonFlags \internal */ /*! \enum Qt::StringComparisonMode This enum type is used to set the string comparison mode when searching for an item. It is used by QListBox, QListView and QIconView, for example. We'll refer to the string being searched as the 'target' string. \value CaseSensitive The strings must match case sensitively. \value ExactMatch The target and search strings must match exactly. \value BeginsWith The target string begins with the search string. \value EndsWith The target string ends with the search string. \value Contains The target string contains the search string. If you OR these flags together (excluding \c CaseSensitive), the search criteria be applied in the following order: \c ExactMatch, \c BeginsWith, \c EndsWith, \c Contains. Matching is case-insensitive unless \c CaseSensitive is set. \c CaseSensitive may be OR-ed with any combination of the other flags. */ Q_EXPORT QStringData *QString::shared_null = 0; QT_STATIC_CONST_IMPL QString QString::null; QT_STATIC_CONST_IMPL QChar QChar::null; QT_STATIC_CONST_IMPL QChar QChar::replacement((ushort)0xfffd); QT_STATIC_CONST_IMPL QChar QChar::byteOrderMark((ushort)0xfeff); QT_STATIC_CONST_IMPL QChar QChar::byteOrderSwapped((ushort)0xfffe); QT_STATIC_CONST_IMPL QChar QChar::nbsp((ushort)0x00a0); QStringData* QString::makeSharedNull() { QString::shared_null = new QStringData; #if defined( Q_OS_MAC ) QString *that = const_cast<QString *>(&QString::null); that->d = QString::shared_null; #endif return QString::shared_null; } -// Uncomment this to get some useful statistics. -// #define Q2HELPER(x) x - -#ifdef Q2HELPER -static int stat_construct_charstar=0; -static int stat_construct_charstar_size=0; -static int stat_construct_null=0; -static int stat_construct_int=0; -static int stat_construct_int_size=0; -static int stat_construct_ba=0; -static int stat_get_ascii=0; -static int stat_get_ascii_size=0; -static int stat_copy_on_write=0; -static int stat_copy_on_write_size=0; -static int stat_fast_copy=0; -Q_EXPORT void qt_qstring_stats() -{ - qDebug("construct_charstar = %d (%d chars)", stat_construct_charstar, stat_construct_charstar_size); - qDebug("construct_null = %d", stat_construct_null); - qDebug("construct_int = %d (%d chars)", stat_construct_int, stat_construct_int_size); - qDebug("construct_ba = %d", stat_construct_ba); - qDebug("get_ascii = %d (%d chars)", stat_get_ascii, stat_get_ascii_size); - qDebug("copy_on_write = %d (%d chars)", stat_copy_on_write, stat_copy_on_write_size); - qDebug("fast_copy = %d", stat_fast_copy); -} -#else -#define Q2HELPER(x) -#endif - /*! \fn QString::QString() Constructs a null string, i.e. both the length and data pointer are 0. \sa isNull() */ /*! Constructs a string of length one, containing the character \a ch. */ QString::QString( QChar ch ) { d = new QStringData( QT_ALLOC_QCHAR_VEC( 1 ), 1, 1 ); d->unicode[0] = ch; } /*! Constructs an implicitly shared copy of \a s. This is very fast since it only involves incrementing a reference count. */ QString::QString( const QString &s ) : d(s.d) { - Q2HELPER(stat_fast_copy++) d->ref(); } /*! \internal Private function. Constructs a string with preallocated space for \a size characters. The string is empty. \sa isNull() */ QString::QString( int size, bool /*dummy*/ ) { if ( size ) { - Q2HELPER(stat_construct_int++) int l = size; - Q2HELPER(stat_construct_int_size+=l) QChar* uc = QT_ALLOC_QCHAR_VEC( l ); d = new QStringData( uc, 0, l ); } else { - Q2HELPER(stat_construct_null++) d = shared_null ? shared_null : (shared_null=new QStringData); d->ref(); } } /*! Constructs a string that is a deep copy of \a ba interpreted as a classic C string. */ QString::QString( const QByteArray& ba ) { - Q2HELPER(stat_construct_ba++) +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( ba.data(), ba.size() ); + return; + } +#endif uint l; - QChar *uc = internalAsciiToUnicode(ba,&l); + QChar *uc = internalLatin1ToUnicode(ba,&l); d = new QStringData(uc,l,l); } /*! Constructs a string that is a deep copy of the first \a length characters in the QChar array. If \a unicode and \a length are 0, then a null string is created. If only \a unicode is 0, the string is empty but has \a length characters of space preallocated: QString expands automatically anyway, but this may speed up some cases a little. We recommend using the plain constructor and setLength() for this purpose since it will result in more readable code. \sa isNull() setLength() */ QString::QString( const QChar* unicode, uint length ) { if ( !unicode && !length ) { d = shared_null ? shared_null : makeSharedNull(); d->ref(); } else { QChar* uc = QT_ALLOC_QCHAR_VEC( length ); if ( unicode ) memcpy(uc, unicode, length*sizeof(QChar)); d = new QStringData(uc,unicode ? length : 0,length); } } /*! Constructs a string that is a deep copy of \a str, interpreted as a classic C string. If \a str is 0, then a null string is created. This is a cast constructor, but it is perfectly safe: converting a Latin1 const char* to QString preserves all the information. You can disable this constructor by defining \c QT_NO_CAST_ASCII when you compile your applications. You can also make QString objects by using setLatin1(), fromLatin1(), fromLocal8Bit(), and fromUtf8(). Or whatever encoding is appropriate for the 8-bit data you have. \sa isNull() */ QString::QString( const char *str ) { - Q2HELPER(stat_construct_charstar++) +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( str ); + return; + } +#endif uint l; - QChar *uc = internalAsciiToUnicode(str,&l); - Q2HELPER(stat_construct_charstar_size+=l) + QChar *uc = internalLatin1ToUnicode(str,&l); d = new QStringData(uc,l,l); } +#ifndef QT_NO_STL +/*! + Constructs a string that is a deep copy of \a str. + + This is the same as fromAscii(\a str). +*/ + +QString::QString( const std::string &str ) +{ +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( str.c_str() ); + return; + } +#endif + uint l; + QChar *uc = internalLatin1ToUnicode(str.c_str(),&l); + d = new QStringData(uc,l,l); +} +#endif + /*! \fn QString::~QString() Destroys the string and frees the string's data if this is the last reference to the string. */ /*! Deallocates any space reserved solely by this QString. If the string does not share its data with another QString instance, nothing happens; otherwise the function creates a new, unique copy of this string. This function is called whenever the string is modified. */ void QString::real_detach() { setLength( length() ); } void QString::deref() { - if ( d->deref() ) { + if ( d && d->deref() ) { if ( d != shared_null ) delete d; - d = 0; // helps debugging + d = 0; } } void QStringData::deleteSelf() { delete this; } /*! \fn QString& QString::operator=( QChar c ) Sets the string to contain just the single character \a c. */ /*! + \fn QString& QString::operator=( const std::string& s ) + + \overload + + Makes a deep copy of \a s and returns a reference to the deep + copy. +*/ + +/*! \fn QString& QString::operator=( char c ) \overload Sets the string to contain just the single character \a c. */ /*! \overload Assigns a shallow copy of \a s to this string and returns a reference to this string. This is very fast because the string isn't actually copied. */ QString &QString::operator=( const QString &s ) { - Q2HELPER(stat_fast_copy++) s.d->ref(); deref(); d = s.d; return *this; } /*! \overload Assigns a deep copy of \a cs, interpreted as a classic C string, to this string and returns a reference to this string. */ QString &QString::operator=( const QCString& cs ) { - return setLatin1(cs); + return setAscii(cs); } /*! \overload Assigns a deep copy of \a str, interpreted as a classic C string to this string and returns a reference to this string. If \a str is 0, then a null string is created. \sa isNull() */ QString &QString::operator=( const char *str ) { - return setLatin1(str); + return setAscii(str); } /*! \fn bool QString::isNull() const Returns TRUE if the string is null; otherwise returns FALSE. A null string is always empty. \code QString a; // a.unicode() == 0, a.length() == 0 a.isNull(); // TRUE, because a.unicode() == 0 a.isEmpty(); // TRUE \endcode \sa isEmpty(), length() */ /*! \fn bool QString::isEmpty() const Returns TRUE if the string is empty, i.e. if length() == 0; otherwise returns FALSE. Null strings are also empty. \code QString a( "" ); a.isEmpty(); // TRUE a.isNull(); // FALSE QString b; b.isEmpty(); // TRUE b.isNull(); // TRUE \endcode \sa isNull(), length() */ /*! \fn uint QString::length() const Returns the length of the string. Null strings and empty strings have zero length. \sa isNull(), isEmpty() */ /*! If \a newLen is less than the length of the string, then the string is truncated at position \a newLen. Otherwise nothing happens. \code QString s = "truncate me"; s.truncate( 5 ); // s == "trunc" \endcode \sa setLength() */ void QString::truncate( uint newLen ) { if ( newLen < d->len ) setLength( newLen ); } /*! Ensures that at least \a newLen characters are allocated to the string, and sets the length of the string to \a newLen. Any new space allocated contains arbitrary data. - If \a newLen is 0, then the string becomes empty, unless the - string is null, in which case it remains null. + If \a newLen is 0, then the string becomes empty (non-null). If it is not possible to allocate enough memory, the string remains unchanged. This function always detaches the string from other references to the same data. This function is useful for code that needs to build up a long string and wants to avoid repeated reallocation. In this example, we want to add to the string until some condition is true, and we're fairly sure that size is big enough: \code QString result; - int resultLength = 0; - result.setLength( newLen ) // allocate some space + int len = 0; + result.setLength( maxLen ); // allocate some space while ( ... ) { - result[resultLength++] = ... // fill (part of) the space with data + result[len++] = ... // fill part of the space } - result.truncate[resultLength]; // and get rid of the undefined junk + result.truncate( len ); // and get rid of the rest \endcode If \a newLen is an underestimate, the worst that will happen is that the loop will slow down. \sa truncate(), isNull(), isEmpty(), length() */ void QString::setLength( uint newLen ) { if ( d->count != 1 || newLen > d->maxl || ( newLen * 4 < d->maxl && d->maxl > 4 ) ) { // detach, grow or shrink - Q2HELPER(stat_copy_on_write++) - Q2HELPER(stat_copy_on_write_size+=d->len) uint newMax = computeNewMax( newLen ); QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); if ( nd ) { uint len = QMIN( d->len, newLen ); if ( d->unicode ) memcpy( nd, d->unicode, sizeof(QChar)*len ); deref(); d = new QStringData( nd, newLen, newMax ); } } else { d->len = newLen; d->setDirty(); } } /*! This function will return a string that replaces the lowest numbered occurrence of \c %1, \c %2, ..., \c %9 with \a a. The \a fieldwidth value specifies the minimum amount of space that \a a is padded to. A positive value will produce right-aligned text, whereas a negative value will produce left-aligned text. + The following example shows how we could create a 'status' string + when processing a list of files: \code - QString firstName( "Joe" ); - QString lastName( "Bloggs" ); - QString fullName; - fullName = QString( "First name is '%1', last name is '%2'" ) - .arg( firstName ) - .arg( lastName ); - - // fullName == First name is 'Joe', last name is 'Bloggs' + QString status = QString( "Processing file %1 of %2: %3" ) + .arg( i ) // current file's number + .arg( total ) // number of files to process + .arg( fileName ); // current file's name \endcode - Note that using arg() to construct sentences as we've done in the - example above does not usually translate well into other languages - because sentence structure and word order often differ between - languages. + It is generally fine to use filenames and numbers as we have done + in the example above. But note that using arg() to construct + natural language sentences does not usually translate well into + other languages because sentence structure and word order often + differ between languages. If there is no place marker (\c %1 or \c %2, etc.), a warning message (qWarning()) is output and the text is appended at the end of the string. We recommend that the correct number of place markers is always used in production code. */ QString QString::arg( const QString& a, int fieldwidth ) const { int pos, len; QString r = *this; if ( !findArg( pos, len ) ) { qWarning( "QString::arg(): Argument missing: %s, %s", latin1(), a.latin1() ); // Make sure the text at least appears SOMEWHERE r += ' '; pos = r.length(); len = 0; } r.replace( pos, len, a ); if ( fieldwidth < 0 ) { QString s; while ( (uint)-fieldwidth > a.length() ) { s += ' '; fieldwidth++; } r.insert( pos + a.length(), s ); } else if ( fieldwidth ) { QString s; while ( (uint)fieldwidth > a.length() ) { s += ' '; fieldwidth--; } r.insert( pos, s ); } return r; } /*! \overload The \a fieldwidth value specifies the minimum amount of space that \a a is padded to. A positive value will produce a right-aligned number, whereas a negative value will produce a left-aligned number. \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. \code QString str; str = QString( "Decimal 63 is %1 in hexadecimal" ) .arg( 63, 0, 16 ); // str == "Decimal 63 is 3f in hexadecimal" \endcode */ QString QString::arg( long a, int fieldwidth, int base ) const { return arg( QString::number(a, base), fieldwidth ); } /*! \overload \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. */ QString QString::arg( ulong a, int fieldwidth, int base ) const { return arg( QString::number(a, base), fieldwidth ); } /*! \fn QString QString::arg( int a, int fieldwidth, int base ) const \overload \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. */ /*! \fn QString QString::arg( uint a, int fieldwidth, int base ) const \overload \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. */ /*! \fn QString QString::arg( short a, int fieldwidth, int base ) const \overload \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. */ /*! \fn QString QString::arg( ushort a, int fieldwidth, int base ) const \overload \a a is expressed in base \a base, which is 10 by default and must be between 2 and 36. */ /*! \overload \a a is assumed to be in the Latin1 character set. */ QString QString::arg( char a, int fieldwidth ) const { QString c; c += a; return arg( c, fieldwidth ); } /*! \overload */ QString QString::arg( QChar a, int fieldwidth ) const { QString c; c += a; return arg( c, fieldwidth ); } /*! \overload \target arg-formats Argument \a a is formatted according to the \a fmt format specified, which is 'g' by default and can be any of the following: \table \header \i Format \i Meaning \row \i \c e \i format as [-]9.9e[+|-]999 \row \i \c E \i format as [-]9.9E[+|-]999 \row \i \c f \i format as [-]9.9 \row \i \c g \i use \c e or \c f format, whichever is the most concise \row \i \c G \i use \c E or \c f format, whichever is the most concise \endtable With 'e', 'E', and 'f', \a prec is the number of digits after the decimal point. With 'g' and 'G', \a prec is the maximum number of significant digits (trailing zeroes are omitted). \code double d = 12.34; QString ds = QString( "'E' format, precision 3, gives %1" ) .arg( d, 0, 'E', 3 ); // ds == "1.234E+001" \endcode */ QString QString::arg( double a, int fieldwidth, char fmt, int prec ) const { return arg( QString::number( a, fmt, prec ), fieldwidth ); } /* Just 1-digit arguments. */ bool QString::findArg( int& pos, int& len ) const { char lowest=0; register const QChar *uc = d->unicode; const uint l = length(); for (uint i = 0; i < l; i++) { if ( uc[i] == '%' && i+1<l ) { QChar dig = uc[i+1]; if ( dig >= '0' && dig <= '9' ) { if ( !lowest || dig < lowest ) { lowest = dig; pos = i; len = 2; } } } } return lowest != 0; } /*! Safely builds a formatted string from the format string \a cformat and an arbitrary list of arguments. The format string supports all the escape sequences of printf() in the standard C library. The %s escape sequence expects a utf8() encoded string. The format string \e cformat is expected to be in latin1. If you need a Unicode format string, use arg() instead. For typesafe string building, with full Unicode support, you can use QTextOStream like this: \code QString str; QString s = ...; int x = ...; QTextOStream( &str ) << s << " : " << x; \endcode For \link QObject::tr() translations,\endlink especially if the strings contains more than one escape sequence, you should consider using the arg() function instead. This allows the order of the replacements to be controlled by the translator, and has Unicode support. \sa arg() */ #ifndef QT_NO_SPRINTF QString &QString::sprintf( const char* cformat, ... ) { va_list ap; va_start( ap, cformat ); if ( !cformat || !*cformat ) { // Qt 1.x compat *this = fromLatin1( "" ); return *this; } - QString format = fromLatin1( cformat ); + QString format = fromAscii( cformat ); QRegExp escape( "%#?0?-? ?\\+?'?[0-9*]*\\.?[0-9*]*h?l?L?q?Z?" ); QString result; uint last = 0; int pos; int len = 0; for (;;) { pos = escape.search( format, last ); len = escape.matchedLength(); // Non-escaped text if ( pos > (int)last ) result += format.mid( last, pos - last ); if ( pos < 0 ) { // The rest if ( last < format.length() ) result += format.mid( last ); break; } last = pos + len + 1; // Escape QString f = format.mid( pos, len ); uint width, decimals; int params = 0; int wpos = f.find('*'); if ( wpos >= 0 ) { params++; width = va_arg( ap, int ); if ( f.find('*', wpos + 1) >= 0 ) { decimals = va_arg( ap, int ); params++; } else { decimals = 0; } } else { decimals = width = 0; } QString replacement; if ( format[pos + len] == 's' || format[pos + len] == 'S' || format[pos + len] == 'c' ) { bool rightjust = ( f.find('-') < 0 ); // %-5s really means left adjust in sprintf if ( wpos < 0 ) { QRegExp num( fromLatin1("[0-9]+") ); int p = num.search( f ); int nlen = num.matchedLength(); int q = f.find( '.' ); if ( q < 0 || (p < q && p >= 0) ) width = f.mid( p, nlen ).toInt(); if ( q >= 0 ) { p = num.search( f, q ); // "decimals" is used to specify string truncation if ( p >= 0 ) decimals = f.mid( p, nlen ).toInt(); } } if ( format[pos + len] == 's' ) { QString s = QString::fromUtf8( va_arg(ap, char*) ); replacement = ( decimals <= 0 ) ? s : s.left( decimals ); } else { int ch = va_arg(ap, int); replacement = QChar((ushort)ch); } if ( replacement.length() < width ) { replacement = rightjust ? replacement.rightJustify(width) : replacement.leftJustify(width); } } else if ( format[pos+len] == '%' ) { replacement = '%'; } else if ( format[pos+len] == 'n' ) { int* n = va_arg(ap, int*); *n = result.length(); } else { char in[64], out[330]; strncpy(in,f.latin1(),63); out[0] = '\0'; char fch = format[pos+len].latin1(); in[f.length()] = fch; switch ( fch ) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { int value = va_arg( ap, int ); switch ( params ) { case 0: ::sprintf( out, in, value ); break; case 1: ::sprintf( out, in, width, value ); break; case 2: ::sprintf( out, in, width, decimals, value ); } } break; case 'e': case 'E': case 'f': case 'g': case 'G': { double value = va_arg( ap, double ); switch ( params ) { case 0: ::sprintf( out, in, value ); break; case 1: ::sprintf( out, in, width, value ); break; case 2: ::sprintf( out, in, width, decimals, value ); } } break; case 'p': { void* value = va_arg( ap, void * ); switch ( params ) { case 0: ::sprintf( out, in, value ); break; case 1: ::sprintf( out, in, width, value ); break; case 2: ::sprintf( out, in, width, decimals, value ); } } } - replacement = fromLatin1( out ); + replacement = fromAscii( out ); } result += replacement; } *this = result; va_end( ap ); return *this; } #endif /*! Fills the string with \a len characters of value \a c, and returns a reference to the string. If \a len is negative (the default), the current string length is used. \code QString str; str.fill( 'g', 5 ); // string == "ggggg" \endcode */ QString& QString::fill( QChar c, int len ) { if ( len < 0 ) len = length(); if ( len == 0 ) { *this = ""; } else { deref(); QChar * nd = QT_ALLOC_QCHAR_VEC( len ); d = new QStringData(nd,len,len); while (len--) *nd++ = c; } return *this; } /*! \fn QString QString::copy() const \obsolete In Qt 2.0 and later, all calls to this function are needless. Just remove them. */ /*! \overload Finds the first occurrence of the character \a c, starting at position \a index. If \a index is -1, the search starts at the last character; if -2, at the next to last character and so on. (See findRev() for searching backwards.) If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. Returns the position of \a c or -1 if \a c could not be found. */ int QString::find( QChar c, int index, bool cs ) const { const uint l = length(); if ( index < 0 ) index += l; if ( (uint)index >= l ) return -1; register const QChar *uc = unicode()+index; const QChar *end = unicode() + l; if ( cs ) { while ( uc < end && *uc != c ) uc++; } else { c = ::lower( c ); while ( uc < end && ::lower( *uc ) != c ) uc++; } if ( uint(uc - unicode()) >= l ) return -1; return (int)(uc - unicode()); } /* an implementation of the Boyer-Moore search algorithm */ /* initializes the skiptable to know haw far ahead we can skip on a wrong match */ static void bm_init_skiptable( const QString &pattern, uint *skiptable, bool cs ) { int i = 0; register uint *st = skiptable; int l = pattern.length(); while ( i++ < 0x100/8 ) { *(st++) = l; *(st++) = l; *(st++) = l; *(st++) = l; *(st++) = l; *(st++) = l; *(st++) = l; *(st++) = l; } const QChar *uc = pattern.unicode(); if ( cs ) { while( l-- ) { skiptable[ uc->cell() ] = l; uc++; } } else { while( l-- ) { skiptable[ ::lower( *uc ).cell() ] = l; uc++; } } } static int bm_find( const QString &str, int index, const QString &pattern, uint *skiptable, bool cs ) { const uint l = str.length(); if ( pattern.isEmpty() ) return index > (int)l ? -1 : index; const QChar *uc = str.unicode(); const QChar *puc = pattern.unicode(); const uint pl = pattern.length(); const uint pl_minus_one = pl - 1; register const QChar *current = uc + index + pl_minus_one; const QChar *end = uc + l; if ( cs ) { while( current < end ) { uint skip = skiptable[ current->cell() ]; if ( !skip ) { // possible match while( skip < pl ) { if ( *(current - skip ) != puc[pl_minus_one-skip] ) break; skip++; } if ( skip > pl_minus_one ) { // we have a match return (current - uc) - skip + 1; } // in case we don't have a match we are a bit inefficient as we only skip by one // when we have the non matching char in the string. if ( skiptable[ (current-skip)->cell() ] == pl ) skip = pl - skip; else skip = 1; } current += skip; } } else { while( current < end ) { uint skip = skiptable[ ::lower( *current ).cell() ]; if ( !skip ) { // possible match while( skip < pl ) { if ( ::lower( *(current - skip) ) != ::lower( puc[pl_minus_one-skip] ) ) break; skip++; } if ( skip > pl_minus_one ) // we have a match return (current - uc) - skip + 1; // in case we don't have a match we are a bit inefficient as we only skip by one // when we have the non matching char in the string. if ( skiptable[ ::lower( (current - skip)->cell() ) ] == pl ) skip = pl - skip; else skip = 1; } current += skip; } } // not found return -1; } #define REHASH( a ) \ if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \ hashHaystack -= (a) << sl_minus_1; \ hashHaystack <<= 1 /*! \overload Finds the first occurrence of the string \a str, starting at position \a index. If \a index is -1, the search starts at the last character, if it is -2, at the next to last character and so on. (See findRev() for searching backwards.) If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. Returns the position of \a str or -1 if \a str could not be found. */ int QString::find( const QString& str, int index, bool cs ) const { const uint l = length(); const uint sl = str.length(); if ( index < 0 ) index += l; if ( sl + index > l ) return -1; if ( !sl ) return index; +#ifndef MACOSX_101 if ( sl == 1 ) return find( *str.unicode(), index, cs ); +#endif // we use the Boyer-Moore algorithm in cases where the overhead // for the hash table should pay off, otherwise we use a simple // hash function if ( l > 500 && sl > 5 ) { uint skiptable[0x100]; bm_init_skiptable( str, skiptable, cs ); return bm_find( *this, index, str, skiptable, cs ); } /* We use some hashing for efficiency's sake. Instead of comparing strings, we compare the hash value of str with that of a part of this QString. Only if that matches, we call ucstrncmp or ucstrnicmp. */ const QChar* needle = str.unicode(); const QChar* haystack = unicode() + index; const QChar* end = unicode() + (l-sl); const uint sl_minus_1 = sl-1; uint hashNeedle = 0, hashHaystack = 0, i; if ( cs ) { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + needle[i].unicode() ); hashHaystack = ((hashHaystack<<1) + haystack[i].unicode() ); } hashHaystack -= (haystack+sl_minus_1)->unicode(); while ( haystack <= end ) { hashHaystack += (haystack+sl_minus_1)->unicode(); if ( hashHaystack == hashNeedle && ucstrncmp( needle, haystack, sl ) == 0 ) return haystack-unicode(); REHASH( haystack->unicode() ); ++haystack; } } else { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + ::lower( needle[i].unicode() ).unicode() ); hashHaystack = ((hashHaystack<<1) + ::lower( haystack[i].unicode() ).unicode() ); } hashHaystack -= ::lower(*(haystack+sl_minus_1)).unicode(); while ( haystack <= end ) { hashHaystack += ::lower(*(haystack+sl_minus_1)).unicode(); if ( hashHaystack == hashNeedle && ucstrnicmp( needle, haystack, sl ) == 0 ) return haystack-unicode(); REHASH( ::lower(*haystack).unicode() ); ++haystack; } } return -1; } /*! \fn int QString::findRev( const char* str, int index ) const Equivalent to findRev(QString(\a str), \a index). */ /*! \fn int QString::find( const char* str, int index ) const \overload Equivalent to find(QString(\a str), \a index). */ /*! \overload Finds the first occurrence of the character \a c, starting at position \a index and searching backwards. If the index is -1, the search starts at the last character, if it is -2, at the next to last character and so on. Returns the position of \a c or -1 if \a c could not be found. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. \code QString string( "bananas" ); int i = string.findRev( 'a' ); // i == 5 \endcode */ int QString::findRev( QChar c, int index, bool cs ) const { +#ifdef MACOSX_101 + return findRev( QString( c ), index, cs ); +#else const uint l = length(); if ( index < 0 ) index += l; if ( (uint)index >= l ) return -1; const QChar *end = unicode(); register const QChar *uc = end + index; if ( cs ) { while ( uc >= end && *uc != c ) uc--; } else { c = ::lower( c ); while ( uc >= end && ::lower( *uc ) != c ) uc--; } return uc - end; +#endif } /*! \overload Finds the first occurrence of the string \a str, starting at position \a index and searching backwards. If the index is -1, the search starts at the last character, if it is -2, at the next to last character and so on. Returns the position of \a str or -1 if \a str could not be found. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. \code QString string("bananas"); int i = string.findRev( "ana" ); // i == 3 \endcode */ int QString::findRev( const QString& str, int index, bool cs ) const { /* See QString::find() for explanations. */ const uint l = length(); if ( index < 0 ) index += l; const uint sl = str.length(); int delta = l-sl; if ( index < 0 || index > (int)l || delta < 0 ) return -1; if ( index > delta ) index = delta; +#ifndef MACOSX_101 if ( sl == 1 ) return findRev( *str.unicode(), index, cs ); +#endif const QChar* needle = str.unicode(); const QChar* haystack = unicode() + index; const QChar* end = unicode(); const uint sl_minus_1 = sl-1; const QChar* n = needle+sl_minus_1; const QChar* h = haystack+sl_minus_1; uint hashNeedle = 0, hashHaystack = 0, i; if ( cs ) { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + (n-i)->unicode() ); hashHaystack = ((hashHaystack<<1) + (h-i)->unicode() ); } hashHaystack -= haystack->unicode(); while ( haystack >= end ) { hashHaystack += haystack->unicode(); if ( hashHaystack == hashNeedle && ucstrncmp( needle, haystack, sl ) == 0 ) return haystack-unicode(); --haystack; REHASH( (haystack+sl)->unicode() ); } } else { for ( i = 0; i < sl; ++i ) { hashNeedle = ((hashNeedle<<1) + ::lower( (n-i)->unicode() ).unicode() ); hashHaystack = ((hashHaystack<<1) + ::lower( (h-i)->unicode() ).unicode() ); } hashHaystack -= ::lower(*haystack).unicode(); while ( haystack >= end ) { hashHaystack += ::lower(*haystack).unicode(); if ( hashHaystack == hashNeedle && ucstrnicmp( needle, haystack, sl ) == 0 ) return haystack-unicode(); --haystack; REHASH( ::lower(*(haystack+sl)).unicode() ); } } return -1; } #undef REHASH /*! \enum QString::SectionFlags \value SectionDefault Empty fields are counted, leading and trailing separators are not included, and the separator is compared case sensitively. \value SectionSkipEmpty Treat empty fields as if they don't exist, i.e. they are not considered as far as \e start and \e end are concerned. \value SectionIncludeLeadingSep Include the leading separator (if any) in the result string. \value SectionIncludeTrailingSep Include the trailing separator (if any) in the result string. \value SectionCaseInsensitiveSeps Compare the separator case-insensitively. Any of the last four values can be OR-ed together to form a flag. \sa section() */ /*! \fn QString QString::section( QChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const This function returns a section of the string. This string is treated as a sequence of fields separated by the character, \a sep. The returned string consists of the fields from position \a start to position \a end inclusive. If \a end is not specified, all fields from position \a start to the end of the string are included. Fields are numbered 0, 1, 2, etc., counting from the left, and -1, -2, etc., counting from right to left. The \a flags argument can be used to affect some aspects of the function's behaviour, e.g. whether to be case sensitive, whether to skip empty fields and how to deal with leading and trailing separators; see \l{SectionFlags}. \code QString csv( "forename,middlename,surname,phone" ); QString s = csv.section( ',', 2, 2 ); // s == "surname" QString path( "/usr/local/bin/myapp" ); // First field is empty QString s = path.section( '/', 3, 4 ); // s == "bin/myapp" QString s = path.section( '/', 3, 3, SectionSkipEmpty ); // s == "myapp" \endcode If \a start or \a end is negative, we count fields from the right of the string, the right-most field being -1, the one from right-most field being -2, and so on. \code QString csv( "forename,middlename,surname,phone" ); QString s = csv.section( ',', -3, -2 ); // s == "middlename,surname" QString path( "/usr/local/bin/myapp" ); // First field is empty QString s = path.section( '/', -1 ); // s == "myapp" \endcode \sa QStringList::split() */ /*! \overload This function returns a section of the string. This string is treated as a sequence of fields separated by the string, \a sep. The returned string consists of the fields from position \a start to position \a end inclusive. If \a end is not specified, all fields from position \a start to the end of the string are included. Fields are numbered 0, 1, 2, etc., counting from the left, and -1, -2, etc., counting from right to left. The \a flags argument can be used to affect some aspects of the function's behaviour, e.g. whether to be case sensitive, whether to skip empty fields and how to deal with leading and trailing separators; see \l{SectionFlags}. \code QString data( "forename**middlename**surname**phone" ); QString s = data.section( "**", 2, 2 ); // s == "surname" \endcode If \a start or \a end is negative, we count fields from the right of the string, the right-most field being -1, the one from right-most field being -2, and so on. \code QString data( "forename**middlename**surname**phone" ); QString s = data.section( "**", -3, -2 ); // s == "middlename**surname" \endcode \sa QStringList::split() */ QString QString::section( const QString &sep, int start, int end, int flags ) const { const QChar *uc = unicode(); if ( !uc ) return QString(); QString _sep = (flags & SectionCaseInsensitiveSeps) ? sep.lower() : sep; const QChar *uc_sep = _sep.unicode(); if(!uc_sep) return QString(); bool match = FALSE, last_match = TRUE; //find start int n = length(), sep_len = _sep.length(); const QChar *begin = start < 0 ? uc + n : uc; while(start) { match = FALSE; int c = 0; for(const QChar *tmp = start < 0 ? begin - sep_len : begin; c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { if(flags & SectionCaseInsensitiveSeps) { if( ::lower( *tmp ) != *(uc_sep + c)) break; } else { if( *tmp != *(uc_sep + c) ) break; } if(c == sep_len - 1) { match = TRUE; break; } } if(start > 0 && (flags & SectionSkipEmpty) && match && last_match) match = FALSE; last_match = match; if(start < 0) { if(match) { begin -= sep_len; if(!++start) break; } else { if(start == -1 && begin == uc) break; begin--; } } else { if(match) { if(!--start) break; begin += sep_len; } else { if(start == 1 && begin == uc + n) break; begin++; } } if(begin > uc + n || begin < uc) return QString(); } if(match && !(flags & SectionIncludeLeadingSep)) begin+=sep_len; if(begin > uc + n || begin < uc) return QString(); //now find last match = FALSE; const QChar *last = end < 0 ? uc + n : uc; if(end == -1) { int c = 0; for(const QChar *tmp = end < 0 ? last - sep_len : last; c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { if(flags & SectionCaseInsensitiveSeps) { if( ::lower( *tmp ) != *(uc_sep + c)) break; } else { if( *tmp != *(uc_sep + c) ) break; } if(c == sep_len - 1) { match = TRUE; break; } } } else { end++; last_match = TRUE; while(end) { match = FALSE; int c = 0; for(const QChar *tmp = end < 0 ? last - sep_len : last; c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { if(flags & SectionCaseInsensitiveSeps) { if( ::lower( *tmp ) != *(uc_sep + c)) break; } else { if( *tmp != *(uc_sep + c) ) break; } if(c == sep_len - 1) { match = TRUE; break; } } if(end > 0 && (flags & SectionSkipEmpty) && match && last_match) match = FALSE; last_match = match; if(end < 0) { if(match) { if(!++end) break; last -= sep_len; } else { last--; } } else { if(match) { last += sep_len; if(!--end) break; } else { last++; } } if(last >= uc + n) { last = uc + n; break; } else if(last < uc) { return QString(); } } } if(match && !(flags & SectionIncludeTrailingSep)) last -= sep_len; if(last < uc || last > uc + n || begin >= last) return QString(); //done return QString(begin, last - begin); } #ifndef QT_NO_REGEXP class section_chunk { public: section_chunk(int l, QString s) { length = l; string = s; } int length; QString string; }; /*! \overload This function returns a section of the string. This string is treated as a sequence of fields separated by the regular expression, \a reg. The returned string consists of the fields from position \a start to position \a end inclusive. If \a end is not specified, all fields from position \a start to the end of the string are included. Fields are numbered 0, 1, 2, etc., counting from the left, and -1, -2, etc., counting from right to left. The \a flags argument can be used to affect some aspects of the function's behaviour, e.g. whether to be case sensitive, whether to skip empty fields and how to deal with leading and trailing separators; see \l{SectionFlags}. \code QString line( "forename\tmiddlename surname \t \t phone" ); QRegExp sep( "\s+" ); QString s = line.section( sep, 2, 2 ); // s == "surname" \endcode If \a start or \a end is negative, we count fields from the right of the string, the right-most field being -1, the one from right-most field being -2, and so on. \code QString line( "forename\tmiddlename surname \t \t phone" ); QRegExp sep( "\\s+" ); QString s = line.section( sep, -3, -2 ); // s == "middlename surname" \endcode \warning Using this QRegExp version is much more expensive than the overloaded string and character versions. \sa QStringList::split() simplifyWhiteSpace() */ QString QString::section( const QRegExp ®, int start, int end, int flags ) const { const QChar *uc = unicode(); if(!uc) return QString(); QRegExp sep(reg); sep.setCaseSensitive(!(flags & SectionCaseInsensitiveSeps)); QPtrList<section_chunk> l; l.setAutoDelete(TRUE); int n = length(), m = 0, last_m = 0, last = 0, last_len = 0; while( ( m = sep.search( *this, m ) ) != -1 ) { l.append(new section_chunk(last_len, QString(uc + last_m, m - last_m))); last_m = m; last_len = sep.matchedLength(); if((m += sep.matchedLength()) >= n) { last = 1; break; } } if(!last) l.append(new section_chunk(last_len, QString(uc + last_m, n - last_m))); if(start < 0) start = l.count() + start; if(end == -1) end = l.count(); else if(end < 0) end = l.count() + end; int i = 0; QString ret; for ( section_chunk *chk=l.first(); chk; chk=l.next(), i++ ) { if((flags & SectionSkipEmpty) && chk->length == (int)chk->string.length()) { if(i <= start) start++; end++; } if(i == start) { ret = (flags & SectionIncludeLeadingSep) ? chk->string : chk->string.mid(chk->length); } else if(i > start) { ret += chk->string; } if(i == end) { if((chk=l.next()) && flags & SectionIncludeTrailingSep) ret += chk->string.left(chk->length); break; } } return ret; } #endif /*! \fn QString QString::section( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const \overload */ /*! \fn QString QString::section( const char *sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const \overload */ /*! Returns the number of times the character \a c occurs in the string. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. \code QString string( "Trolltech and Qt" ); int i = string.contains( 't', FALSE ); // i == 3 \endcode */ int QString::contains( QChar c, bool cs ) const { int count = 0; const QChar *uc = unicode(); if ( !uc ) return 0; int n = length(); if ( cs ) { while ( n-- ) if ( *uc++ == c ) count++; } else { c = ::lower( c ); while ( n-- ) { if ( ::lower( *uc ) == c ) count++; uc++; } } return count; } /*! \overload Returns the number of times the string \a str occurs in the string. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. */ int QString::contains( const char* str, bool cs ) const { return contains( QString(str), cs ); } /*! \fn int QString::contains( char c, bool cs ) const \overload */ /*! \fn int QString::find( char c, int index, bool cs ) const \overload Find character \a c starting from position \a index. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. */ /*! \fn int QString::findRev( char c, int index, bool cs ) const \overload Find character \a c starting from position \a index and working backwards. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. */ /*! \overload Returns the number of times \a str occurs in the string. If \a cs is TRUE, the search is case sensitive; otherwise the search is case insensitive. This function counts overlapping strings, so in the example below, there are two instances of "ana" in "bananas". \code QString str( "bananas" ); int i = str.contains( "ana" ); // i == 2 \endcode \sa findRev() */ int QString::contains( const QString &str, bool cs ) const { if ( isNull() ) return 0; int count = 0; uint skiptable[0x100]; bm_init_skiptable( str, skiptable, cs ); int i = -1; // use boyer-moore for the ultimate speed experience while ( ( i = bm_find( *this, i+1, str, skiptable, cs ) ) != -1 ) count++; return count; } /*! Returns a substring that contains the \a len leftmost characters of the string. The whole string is returned if \a len exceeds the length of the string. \code QString s = "Pineapple"; QString t = s.left( 4 ); // t == "Pine" \endcode \sa right(), mid(), isEmpty() */ QString QString::left( uint len ) const { if ( isEmpty() ) { return QString(); } else if ( len == 0 ) { // ## just for 1.x compat: return fromLatin1( "" ); } else if ( len >= length() ) { return *this; } else { QString s( len, TRUE ); memcpy( s.d->unicode, d->unicode, len * sizeof(QChar) ); s.d->len = len; return s; } } /*! Returns a string that contains the \a len rightmost characters of the string. If \a len is greater than the length of the string then the whole string is returned. \code QString string( "Pineapple" ); QString t = string.right( 5 ); // t == "apple" \endcode \sa left(), mid(), isEmpty() */ QString QString::right( uint len ) const { if ( isEmpty() ) { return QString(); } else if ( len == 0 ) { // ## just for 1.x compat: return fromLatin1( "" ); } else { uint l = length(); if ( len >= l ) return *this; QString s( len, TRUE ); memcpy( s.d->unicode, d->unicode+(l-len), len*sizeof(QChar) ); s.d->len = len; return s; } } /*! Returns a string that contains the \a len characters of this string, starting at position \a index. Returns a null string if the string is empty or \a index is out of range. Returns the whole string from \a index if \a index + \a len exceeds the length of the string. \code QString s( "Five pineapples" ); QString t = s.mid( 5, 4 ); // t == "pine" \endcode \sa left(), right() */ QString QString::mid( uint index, uint len ) const { uint slen = length(); if ( isEmpty() || index >= slen ) { return QString(); } else if ( len == 0 ) { // ## just for 1.x compat: return fromLatin1( "" ); } else { if ( len > slen-index ) len = slen - index; if ( index == 0 && len == slen ) return *this; register const QChar *p = unicode()+index; QString s( len, TRUE ); memcpy( s.d->unicode, p, len * sizeof(QChar) ); s.d->len = len; return s; } } /*! Returns a string of length \a width that contains this string padded by the \a fill character. If \a truncate is FALSE and the length of the string is more than \a width, then the returned string is a copy of the string. If \a truncate is TRUE and the length of the string is more than \a width, then any characters in a copy of the string after length \a width are removed, and the copy is returned. \code QString s( "apple" ); QString t = s.leftJustify( 8, '.' ); // t == "apple..." \endcode \sa rightJustify() */ QString QString::leftJustify( uint width, QChar fill, bool truncate ) const { QString result; int len = length(); int padlen = width - len; if ( padlen > 0 ) { result.setLength(len+padlen); if ( len ) memcpy( result.d->unicode, unicode(), sizeof(QChar)*len ); QChar* uc = result.d->unicode + len; while (padlen--) *uc++ = fill; } else { if ( truncate ) result = left( width ); else result = *this; } return result; } /*! Returns a string of length \a width that contains the \a fill character followed by the string. If \a truncate is FALSE and the length of the string is more than \a width, then the returned string is a copy of the string. If \a truncate is TRUE and the length of the string is more than \a width, then the resulting string is truncated at position \a width. \code QString string( "apple" ); QString t = string.rightJustify( 8, '.' ); // t == "...apple" \endcode \sa leftJustify() */ QString QString::rightJustify( uint width, QChar fill, bool truncate ) const { QString result; int len = length(); int padlen = width - len; if ( padlen > 0 ) { result.setLength( len+padlen ); QChar* uc = result.d->unicode; while (padlen--) *uc++ = fill; if ( len ) memcpy( uc, unicode(), sizeof(QChar)*len ); } else { if ( truncate ) result = left( width ); else result = *this; } return result; } /*! Returns a lowercase copy of the string. \code QString string( "TROlltECH" ); str = string.lower(); // str == "trolltech" \endcode \sa upper() */ QString QString::lower() const { - QString s(*this); int l=length(); - if ( l ) { - s.real_detach(); // could do this only when we find a change - register QChar *p=s.d->unicode; - if ( p ) { - while ( l-- ) { + register QChar *p = d->unicode; + while ( l ) { + if ( *p != ::lower(*p) ) { + QString s( *this ); + s.real_detach(); + p = s.d->unicode + ( p - d->unicode ); + while ( l ) { *p = ::lower( *p ); + l--; p++; } + return s; } + l--; + p++; } - return s; + return *this; } /*! Returns an uppercase copy of the string. \code QString string( "TeXt" ); str = string.upper(); // t == "TEXT" \endcode \sa lower() */ QString QString::upper() const { - QString s(*this); int l=length(); - if ( l ) { - s.real_detach(); // could do this only when we find a change - register QChar *p=s.d->unicode; - if ( p ) { - while ( l-- ) { + register QChar *p = d->unicode; + while ( l ) { + if ( *p != ::upper(*p) ) { + QString s( *this ); + s.real_detach(); + p = s.d->unicode + ( p - d->unicode ); + while ( l ) { *p = ::upper( *p ); + l--; p++; } + return s; } + l--; + p++; } - return s; + return *this; } /*! Returns a string that has whitespace removed from the start and the end. Whitespace means any character for which QChar::isSpace() returns TRUE. This includes Unicode characters with decimal values 9 (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR) and 32 (Space), and may also include other Unicode characters. \code QString string = " white space "; QString s = string.stripWhiteSpace(); // s == "white space" \endcode \sa simplifyWhiteSpace() */ QString QString::stripWhiteSpace() const { if ( isEmpty() ) // nothing to do return *this; register const QChar *s = unicode(); if ( !s->isSpace() && !s[length()-1].isSpace() ) return *this; int start = 0; int end = length() - 1; while ( start<=end && s[start].isSpace() ) // skip white space from start start++; if ( start <= end ) { // only white space while ( end && s[end].isSpace() ) // skip white space from end end--; } int l = end - start + 1; if ( l <= 0 ) return QString::fromLatin1(""); QString result( l, TRUE ); memcpy( result.d->unicode, &s[start], sizeof(QChar)*l ); result.d->len = l; return result; } /*! Returns a string that has whitespace removed from the start and the end, and which has each sequence of internal whitespace replaced with a single space. Whitespace means any character for which QChar::isSpace() returns TRUE. This includes Unicode characters with decimal values 9 (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR), and 32 (Space). \code QString string = " lots\t of\nwhite space "; QString t = string.simplifyWhiteSpace(); // t == "lots of white space" \endcode \sa stripWhiteSpace() */ QString QString::simplifyWhiteSpace() const { if ( isEmpty() ) return *this; QString result; result.setLength( length() ); const QChar *from = unicode(); const QChar *fromend = from+length(); int outc=0; QChar *to = result.d->unicode; for (;;) { while ( from!=fromend && from->isSpace() ) from++; while ( from!=fromend && !from->isSpace() ) to[outc++] = *from++; if ( from!=fromend ) to[outc++] = ' '; else break; } if ( outc > 0 && to[outc-1] == ' ' ) outc--; result.truncate( outc ); return result; } /*! Inserts \a s into the string at position \a index. If \a index is beyond the end of the string, the string is extended with spaces to length \a index and \a s is then appended and returns a reference to the string. \code QString string( "I like fish" ); str = string.insert( 2, "don't " ); // str == "I don't like fish" \endcode \sa remove(), replace() */ QString &QString::insert( uint index, const QString &s ) { // the sub function takes care of &s == this case. return insert( index, s.unicode(), s.length() ); } /*! \overload - Inserts the character in \a s into the string at position \a index - \a len number of times and returns a reference to the string. + Inserts the first \a len characters in \a s into the string at + position \a index and returns a reference to the string. */ QString &QString::insert( uint index, const QChar* s, uint len ) { if ( len == 0 ) return *this; uint olen = length(); int nlen = olen + len; if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { // Part of me - take a copy. QChar *tmp = QT_ALLOC_QCHAR_VEC( len ); memcpy(tmp,s,len*sizeof(QChar)); insert(index,tmp,len); QT_DELETE_QCHAR_VEC( tmp ); return *this; } if ( index >= olen ) { // insert after end of string setLength( len + index ); int n = index - olen; QChar* uc = d->unicode+olen; while (n--) *uc++ = ' '; memcpy( d->unicode+index, s, sizeof(QChar)*len ); } else { // normal insert setLength( nlen ); memmove( d->unicode + index + len, unicode() + index, sizeof(QChar) * (olen - index) ); memcpy( d->unicode + index, s, sizeof(QChar) * len ); } return *this; } /*! \overload Insert \a c into the string at position \a index and returns a reference to the string. If \a index is beyond the end of the string, the string is extended with spaces (ASCII 32) to length \a index and \a c is then appended. */ QString &QString::insert( uint index, QChar c ) // insert char { QString s( c ); return insert( index, s ); } /*! \fn QString& QString::insert( uint index, char c ) \overload Insert character \a c at position \a index. */ /*! \fn QString &QString::prepend( const QString &s ) Inserts \a s at the beginning of the string and returns a reference to the string. Equivalent to insert(0, \a s). \code QString string = "42"; string.prepend( "The answer is " ); // string == "The answer is 42" \endcode \sa insert() */ /*! \fn QString& QString::prepend( char ch ) \overload Inserts \a ch at the beginning of the string and returns a reference to the string. Equivalent to insert(0, \a ch). \sa insert() */ /*! \fn QString& QString::prepend( QChar ch ) \overload Inserts \a ch at the beginning of the string and returns a reference to the string. Equivalent to insert(0, \a ch). \sa insert() */ /*! \fn QString& QString::prepend( const QByteArray &s ) \overload Inserts \a s at the beginning of the string and returns a reference to the string. Equivalent to insert(0, \a s). \sa insert() */ +/*! \fn QString& QString::prepend( const std::string &s ) + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() + */ + /*! \overload Inserts \a s at the beginning of the string and returns a reference to the string. Equivalent to insert(0, \a s). \sa insert() */ QString &QString::prepend( const char *s ) { return insert( 0, QString(s) ); } /*! Removes \a len characters from the string starting at position \a index, and returns a reference to the string. If \a index is beyond the length of the string, nothing happens. If \a index is within the string, but \a index + \a len is beyond the end of the string, the string is truncated at position \a index. \code QString string( "Montreal" ); string.remove( 1, 4 ); // string == "Meal" \endcode \sa insert(), replace() */ QString &QString::remove( uint index, uint len ) { uint olen = length(); if ( index >= olen ) { // range problems } else if ( index + len >= olen ) { // index ok setLength( index ); } else if ( len != 0 ) { real_detach(); memmove( d->unicode+index, d->unicode+index+len, sizeof(QChar)*(olen-index-len) ); setLength( olen-len ); } return *this; } /*! \overload Removes every occurrence of the character \a c in the string. Returns a reference to the string. This is the same as replace(\a c, ""). */ QString &QString::remove( QChar c ) { int i = 0; while ( i < (int) length() ) { if ( constref(i) == c ) { remove( i, 1 ); } else { i++; } } return *this; } /*! \overload \fn QString &QString::remove( char c ) Removes every occurrence of the character \a c in the string. Returns a reference to the string. This is the same as replace(\a c, ""). */ /*! \overload Removes every occurrence of \a str in the string. Returns a reference to the string. This is the same as replace(\a str, ""). */ QString &QString::remove( const QString & str ) { int index = 0; if ( !str.isEmpty() ) { while ( (index = find(str, index)) != -1 ) remove( index, str.length() ); } return *this; } /*! \overload Replaces every occurrence of \a c1 with the char \a c2. Returns a reference to the string. */ QString &QString::replace( QChar c1, QChar c2 ) { real_detach(); uint i = 0; while ( i < d->len ) { if ( d->unicode[i] == c1 ) d->unicode[i] = c2; i++; } return *this; } #ifndef QT_NO_REGEXP_CAPTURE /*! \overload Removes every occurrence of the regular expression \a rx in the string. Returns a reference to the string. This is the same as replace(\a rx, ""). */ QString &QString::remove( const QRegExp & rx ) { return replace( rx, QString::null ); } #endif /*! \overload Removes every occurrence of \a str in the string. Returns a reference to the string. */ QString &QString::remove( const char *str ) { return remove( QString::fromLatin1(str) ); } /*! Replaces \a len characters from the string with \a s, starting at position \a index, and returns a reference to the string. If \a index is beyond the length of the string, nothing is deleted and \a s is appended at the end of the string. If \a index is valid, but \a index + \a len is beyond the end of the string, the string is truncated at position \a index, then \a s is appended at the end. \code QString string( "Say yes!" ); string = string.replace( 4, 3, "NO" ); // string == "Say NO!" \endcode \sa insert(), remove() */ QString &QString::replace( uint index, uint len, const QString &s ) { return replace( index, len, s.unicode(), s.length() ); } /*! \overload This is the same as replace(\a index, \a len, QString(\a c)). */ QString &QString::replace( uint index, uint len, QChar c ) { return replace( index, len, &c, 1 ); } /*! \overload \fn QString &QString::replace( uint index, uint len, char c ) This is the same as replace(\a index, \a len, QChar(\a c)). */ /*! \overload Replaces \a len characters with \a slen characters of QChar data from \a s, starting at position \a index, and returns a reference to the string. \sa insert(), remove() */ QString &QString::replace( uint index, uint len, const QChar* s, uint slen ) { real_detach(); if ( len == slen && index + len <= length() ) { // Optimized common case: replace without size change memcpy( d->unicode+index, s, len * sizeof(QChar) ); } else if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { // Part of me - take a copy. QChar *tmp = QT_ALLOC_QCHAR_VEC( slen ); memcpy( tmp, s, slen * sizeof(QChar) ); replace( index, len, tmp, slen ); QT_DELETE_QCHAR_VEC( tmp ); } else { remove( index, len ); insert( index, s, slen ); } return *this; } /*! \overload Replaces every occurrence of the character \a c in the string with \a after. Returns a reference to the string. Example: \code QString s = "a,b,c"; s.replace( QChar(','), " or " ); // s == "a or b or c" \endcode */ QString &QString::replace( QChar c, const QString & after ) { return replace( QString( c ), after ); } /*! \overload \fn QString &QString::replace( char c, const QString & after ) Replaces every occurrence of the character \a c in the string with \a after. Returns a reference to the string. */ /*! \overload Replaces every occurrence of the string \a before in the string with the string \a after. Returns a reference to the string. Example: \code QString s = "Greek is Greek"; s.replace( "Greek", "English" ); // s == "English is English" \endcode */ QString &QString::replace( const QString & before, const QString & after ) { if ( before == after || isNull() ) return *this; real_detach(); int index = 0; uint skiptable[256]; bm_init_skiptable( before, skiptable, TRUE ); const int bl = before.length(); const int al = after.length(); if ( bl == al ) { if ( bl ) { const QChar *auc = after.unicode(); while( (index = bm_find(*this, index, before, skiptable, TRUE) ) != -1 ) { memcpy( d->unicode+index, auc, al*sizeof(QChar) ); index += bl; } } } else if ( al < bl ) { const QChar *auc = after.unicode(); uint to = 0; uint movestart = 0; uint num = 0; while( (index = bm_find(*this, index, before, skiptable, TRUE) ) != -1 ) { if ( num ) { int msize = index - movestart; if ( msize > 0 ) { memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(QChar) ); to += msize; } } else { to = index; } if ( al ) { memcpy( d->unicode+to, auc, al*sizeof(QChar) ); to += al; } index += bl; movestart = index; num++; } if ( num ) { int msize = d->len - movestart; if ( msize > 0 ) memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(QChar) ); setLength( d->len - num*(bl-al) ); } } else { // the most complex case. We don't want to loose performance by doing repeated // copies and reallocs of the string. while( index != -1 ) { uint indices[4096]; uint pos = 0; while( pos < 4095 ) { index = bm_find(*this, index, before, skiptable, TRUE); if ( index == -1 ) break; indices[pos++] = index; index += bl; // avoid infinite loop if ( !bl ) index++; } if ( !pos ) break; // we have a table of replacement positions, use them for fast replacing int adjust = pos*(al-bl); // index has to be adjusted in case we get back into the loop above. if ( index != -1 ) index += adjust; uint newlen = d->len + adjust; int moveend = d->len; if ( newlen > d->len ) setLength( newlen ); while( pos ) { pos--; int movestart = indices[pos] + bl; int insertstart = indices[pos] + pos*(al-bl); int moveto = insertstart + al; memmove( d->unicode + moveto, d->unicode + movestart, (moveend - movestart)*sizeof(QChar) ); memcpy( d->unicode + insertstart, after.unicode(), al*sizeof(QChar) ); moveend = movestart-bl; } } } return *this; } #ifndef QT_NO_REGEXP_CAPTURE /*! \overload Replaces every occurrence of the regexp \a rx in the string with \a str. Returns a reference to the string. For example: \code QString s = "banana"; s.replace( QRegExp("an"), "" ); // s == "ba" \endcode For regexps containing \link qregexp.html#capturing-text capturing parentheses \endlink, occurrences of <b>\\1</b>, <b>\\2</b>, ..., in \a str are replaced with \a{rx}.cap(1), cap(2), ... \code QString t = "A <i>bon mot</i>."; t.replace( QRegExp("<i>([^<]*)</i>"), "\\emph{\\1}" ); // t == "A \\emph{bon mot}." \endcode \sa find(), findRev(), QRegExp::cap() */ QString &QString::replace( const QRegExp &rx, const QString &str ) { if ( isNull() ) return *this; real_detach(); QRegExp rx2 = rx; int index = 0; int numCaptures = rx2.numCaptures(); int al = str.length(); QRegExp::CaretMode caretMode = QRegExp::CaretAtZero; if ( numCaptures > 0 ) { if ( numCaptures > 9 ) numCaptures = 9; const QChar *uc = str.unicode(); int numBackRefs = 0; for ( int i = 0; i < al - 1; i++ ) { if ( uc[i] == '\\' ) { int no = uc[i + 1].digitValue(); if ( no > 0 && no <= numCaptures ) numBackRefs++; } } /* This is the harder case where we have back-references. We don't try to optimize it. */ if ( numBackRefs > 0 ) { int *capturePositions = new int[numBackRefs]; int *captureNumbers = new int[numBackRefs]; int j = 0; for ( int i = 0; i < al - 1; i++ ) { if ( uc[i] == '\\' ) { int no = uc[i + 1].digitValue(); if ( no > 0 && no <= numCaptures ) { capturePositions[j] = i; captureNumbers[j] = no; j++; } } } while ( index <= (int)length() ) { index = rx2.search( *this, index, caretMode ); if ( index == -1 ) break; QString str2 = str; for ( j = numBackRefs - 1; j >= 0; j-- ) str2.replace( capturePositions[j], 2, rx2.cap(captureNumbers[j]) ); replace( index, rx2.matchedLength(), str2 ); index += str2.length(); if ( rx2.matchedLength() == 0 ) { // avoid infinite loop on 0-length matches (e.g., [a-z]*) index++; } else if ( index == 0 ) { caretMode = QRegExp::CaretWontMatch; } } delete[] capturePositions; delete[] captureNumbers; return *this; } } /* This is the simple and optimized case where we don't have back-references. */ while ( index != -1 ) { struct { int pos; int length; } replacements[2048]; uint pos = 0; int adjust = 0; while( pos < 2047 ) { index = rx2.search( *this, index, caretMode ); if ( index == -1 ) break; int ml = rx2.matchedLength(); replacements[pos].pos = index; replacements[pos++].length = ml; index += ml; adjust += al - ml; // avoid infinite loop if ( !ml ) index++; } if ( !pos ) break; replacements[pos].pos = d->len; uint newlen = d->len + adjust; // to continue searching at the right position after we did // the first round of replacements if ( index != -1 ) index += adjust; QChar *newuc = QT_ALLOC_QCHAR_VEC( newlen + 1 ); QChar *uc = newuc; int copystart = 0; uint i = 0; while( i < pos ) { int copyend = replacements[i].pos; int size = copyend - copystart; memcpy( uc, d->unicode + copystart, size*sizeof(QChar) ); uc += size; memcpy( uc, str.unicode(), al*sizeof( QChar ) ); uc += al; copystart = copyend + replacements[i].length; i++; } memcpy( uc, d->unicode + copystart, (d->len - copystart) * sizeof(QChar) ); QT_DELETE_QCHAR_VEC( d->unicode ); d->unicode = newuc; d->len = newlen; d->maxl = newlen + 1; d->setDirty(); caretMode = QRegExp::CaretWontMatch; } return *this; } #endif #ifndef QT_NO_REGEXP /*! Finds the first match of the regular expression \a rx, starting from position \a index. If \a index is -1, the search starts at the last character; if -2, at the next to last character and so on. (See findRev() for searching backwards.) Returns the position of the first match of \a rx or -1 if no match was found. \code QString string( "bananas" ); int i = string.find( QRegExp("an"), 0 ); // i == 1 \endcode \sa findRev() replace() contains() */ int QString::find( const QRegExp &rx, int index ) const { return rx.search( *this, index ); } /*! \overload Finds the first match of the regexp \a rx, starting at position \a index and searching backwards. If the index is -1, the search starts at the last character, if it is -2, at the next to last character and so on. (See findRev() for searching backwards.) Returns the position of the match or -1 if no match was found. \code QString string( "bananas" ); int i = string.findRev( QRegExp("an") ); // i == 3 \endcode \sa find() */ int QString::findRev( const QRegExp &rx, int index ) const { return rx.searchRev( *this, index ); } /*! \overload Returns the number of times the regexp, \a rx, matches in the string. This function counts overlapping matches, so in the example below, there are four instances of "ana" or "ama". \code QString str = "banana and panama"; QRegExp rxp = QRegExp( "a[nm]a", TRUE, FALSE ); int i = str.contains( rxp ); // i == 4 \endcode \sa find() findRev() */ int QString::contains( const QRegExp &rx ) const { int count = 0; int index = -1; int len = length(); while ( index < len - 1 ) { // count overlapping matches index = rx.search( *this, index + 1 ); if ( index == -1 ) break; count++; } return count; } #endif //QT_NO_REGEXP static bool ok_in_base( QChar c, int base ) { if ( base <= 10 ) return c.isDigit() && c.digitValue() < base; else return c.isDigit() || (c >= 'a' && c < char('a'+base-10)) || (c >= 'A' && c < char('A'+base-10)); } /*! Returns the string converted to a \c long value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \sa number() */ long QString::toLong( bool *ok, int base ) const { const QChar *p = unicode(); - long val = 0; + ulong val = 0; int l = length(); - const long max_mult = INT_MAX / base; + const ulong max_mult = LONG_MAX / base; bool is_ok = FALSE; int neg = 0; if ( !p ) goto bye; while ( l && p->isSpace() ) // skip leading space l--,p++; if ( !l ) goto bye; if ( *p == '-' ) { l--; p++; neg = 1; } else if ( *p == '+' ) { l--; p++; } // NOTE: toULong() code is similar if ( !l || !ok_in_base(*p,base) ) goto bye; while ( l && ok_in_base(*p,base) ) { l--; int dv; if ( p->isDigit() ) { dv = p->digitValue(); } else { if ( *p >= 'a' && *p <= 'z' ) dv = *p - 'a' + 10; else dv = *p - 'A' + 10; } if ( val > max_mult || - (val == max_mult && dv > (INT_MAX % base) + neg) ) + (val == max_mult && dv > (LONG_MAX % base) + neg) ) goto bye; val = base * val + dv; p++; } - if ( neg ) - val = -val; while ( l && p->isSpace() ) // skip trailing space l--,p++; if ( !l ) is_ok = TRUE; bye: if ( ok ) *ok = is_ok; - return is_ok ? val : 0; + return is_ok ? ( neg ? -( (long) val ) : (long) val ) : 0L; } /*! Returns the string converted to an \c {unsigned long} value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \sa number() */ ulong QString::toULong( bool *ok, int base ) const { const QChar *p = unicode(); ulong val = 0; int l = length(); - const ulong max_mult = UINT_MAX / base; + const ulong max_mult = ULONG_MAX / base; bool is_ok = FALSE; if ( !p ) goto bye; while ( l && p->isSpace() ) // skip leading space l--,p++; if ( !l ) goto bye; if ( *p == '+' ) l--,p++; // NOTE: toLong() code is similar if ( !l || !ok_in_base(*p,base) ) goto bye; while ( l && ok_in_base(*p,base) ) { l--; uint dv; if ( p->isDigit() ) { dv = p->digitValue(); } else { if ( *p >= 'a' && *p <= 'z' ) dv = *p - 'a' + 10; else dv = *p - 'A' + 10; } - if ( val > max_mult || (val == max_mult && dv > UINT_MAX % base) ) + if ( val > max_mult || (val == max_mult && dv > ULONG_MAX % base) ) goto bye; val = base * val + dv; p++; } while ( l && p->isSpace() ) // skip trailing space l--,p++; if ( !l ) is_ok = TRUE; bye: if ( ok ) *ok = is_ok; return is_ok ? val : 0; } /*! Returns the string converted to a \c short value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. */ short QString::toShort( bool *ok, int base ) const { long v = toLong( ok, base ); - if ( ok && *ok && (v < -32768 || v > 32767) ) { + if ( ok && *ok && (v < SHRT_MIN || v > SHRT_MAX) ) { *ok = FALSE; v = 0; } return (short)v; } /*! Returns the string converted to an \c {unsigned short} value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. */ ushort QString::toUShort( bool *ok, int base ) const { ulong v = toULong( ok, base ); - if ( ok && *ok && (v > 65535) ) { + if ( ok && *ok && (v > USHRT_MAX) ) { *ok = FALSE; v = 0; } return (ushort)v; } /*! Returns the string converted to an \c int value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \code QString str( "FF" ); bool ok; int hex = str.toInt( &ok, 16 ); // hex == 255, ok == TRUE int dec = str.toInt( &ok, 10 ); // dec == 0, ok == FALSE \endcode \sa number() */ int QString::toInt( bool *ok, int base ) const { - return (int)toLong( ok, base ); + long v = toLong( ok, base ); + if ( ok && *ok && (v < INT_MIN || v > INT_MAX) ) { + *ok = FALSE; + v = 0; + } + return (int)v; } /*! Returns the string converted to an \c{unsigned int} value to the base \a base, which is 10 by default and must be between 2 and 36. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \sa number() */ uint QString::toUInt( bool *ok, int base ) const { - return (uint)toULong( ok, base ); + ulong v = toULong( ok, base ); + if ( ok && *ok && (v > UINT_MAX) ) { + *ok = FALSE; + v = 0; + } + return (uint)v; } /*! Returns the string converted to a \c double value. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \code QString string( "1234.56" ); double a = string.toDouble(); // a == 1234.56 \endcode \sa number() */ double QString::toDouble( bool *ok ) const { char *end; const char *a = latin1(); double val = strtod( a ? a : "", &end ); if ( ok ) - *ok = ( a && *a && (end == 0 || (end - a) == (int)length()) ); + *ok = ( a && *a && (end == 0 || *end == '\0') ); return val; } /*! Returns the string converted to a \c float value. If \a ok is not 0: if a conversion error occurs, \a *ok is set to FALSE; otherwise \a *ok is set to TRUE. \sa number() */ float QString::toFloat( bool *ok ) const { return (float)toDouble( ok ); } /*! Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. \code QString string; string = string.setNum( 1234 ); // string == "1234" \endcode */ QString &QString::setNum( long n, int base ) { #if defined(QT_CHECK_RANGE) if ( base < 2 || base > 36 ) { qWarning( "QString::setNum: Invalid base %d", base ); base = 10; } #endif char charbuf[65*sizeof(QChar)]; QChar *buf = (QChar*)charbuf; QChar *p = &buf[64]; int len = 0; bool neg; if ( n < 0 ) { neg = TRUE; - if ( n == INT_MIN ) { + if ( n == LONG_MIN ) { // Cannot always negate this special case QString s1, s2; - s1.setNum(n/base); - s2.setNum((-(n+base))%base); + s1.setNum(n/base, base ); + s2.setNum((-(n+base))%base, base ); *this = s1 + s2; return *this; } n = -n; } else { neg = FALSE; } do { *--p = "0123456789abcdefghijklmnopqrstuvwxyz"[((int)(n%base))]; n /= base; ++len; } while ( n ); if ( neg ) { *--p = '-'; ++len; } return setUnicode( p, len ); } /*! \overload Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. */ QString &QString::setNum( ulong n, int base ) { #if defined(QT_CHECK_RANGE) if ( base < 2 || base > 36 ) { qWarning( "QString::setNum: Invalid base %d", base ); base = 10; } #endif char charbuf[65*sizeof(QChar)]; QChar *buf = (QChar*)charbuf; QChar *p = &buf[64]; int len = 0; do { *--p = "0123456789abcdefghijklmnopqrstuvwxyz"[((int)(n%base))]; n /= base; len++; } while ( n ); return setUnicode(p,len); } /*! \fn QString &QString::setNum( int n, int base ) \overload Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. */ /*! \fn QString &QString::setNum( uint n, int base ) \overload Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. */ /*! \fn QString &QString::setNum( short n, int base ) \overload Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. */ /*! \fn QString &QString::setNum( ushort n, int base ) \overload Sets the string to the printed value of \a n in base \a base and returns a reference to the string. The base is 10 by default and must be between 2 and 36. */ /*! \overload Sets the string to the printed value of \a n, formatted in format \a f with precision \a prec, and returns a reference to the string. The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link #arg-formats arg \endlink() for an explanation of the formats. */ QString &QString::setNum( double n, char f, int prec ) { #if defined(QT_CHECK_RANGE) if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) { qWarning( "QString::setNum: Invalid format char '%c'", f ); f = 'f'; } #endif char format[20]; char *fs = format; // generate format string: %.<prec>l<f> *fs++ = '%'; if ( prec >= 0 ) { if ( prec > 99 ) // rather than crash in sprintf() prec = 99; *fs++ = '.'; if ( prec >= 10 ) { *fs++ = prec / 10 + '0'; *fs++ = prec % 10 + '0'; } else { *fs++ = prec + '0'; } } *fs++ = 'l'; *fs++ = f; *fs = '\0'; #ifndef QT_NO_SPRINTF sprintf( format, n ); return *this; #else char buf[512]; ::sprintf( buf, format, n ); // snprintf is unfortunately not portable return setLatin1(buf); #endif } /*! \fn QString &QString::setNum( float n, char f, int prec ) \overload Sets the string to the printed value of \a n, formatted in format \a f with precision \a prec, and returns a reference to the string. The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link #arg-formats arg \endlink() for an explanation of the formats. */ /*! A convenience function that returns a string equivalent of the number \a n to base \a base, which is 10 by default and must be between 2 and 36. \code long a = 63; QString str = QString::number( a, 16 ); // str == "3f" QString str = QString::number( a, 16 ).upper(); // str == "3F" \endcode \sa setNum() */ QString QString::number( long n, int base ) { QString s; s.setNum( n, base ); return s; } /*! \overload \sa setNum() */ QString QString::number( ulong n, int base ) { QString s; s.setNum( n, base ); return s; } /*! \overload \sa setNum() */ QString QString::number( int n, int base ) { QString s; s.setNum( n, base ); return s; } /*! \overload A convenience factory function that returns a string representation of the number \a n to the base \a base, which is 10 by default and must be between 2 and 36. \sa setNum() */ QString QString::number( uint n, int base ) { QString s; s.setNum( n, base ); return s; } /*! \overload Argument \a n is formatted according to the \a f format specified, which is \c g by default, and can be any of the following: \table \header \i Format \i Meaning \row \i \c e \i format as [-]9.9e[+|-]999 \row \i \c E \i format as [-]9.9E[+|-]999 \row \i \c f \i format as [-]9.9 \row \i \c g \i use \c e or \c f format, whichever is the most concise \row \i \c G \i use \c E or \c f format, whichever is the most concise \endtable With 'e', 'E', and 'f', \a prec is the number of digits after the decimal point. With 'g' and 'G', \a prec is the maximum number of significant digits (trailing zeroes are omitted). \code double d = 12.34; QString ds = QString( "'E' format, precision 3, gives %1" ) .arg( d, 0, 'E', 3 ); // ds == "1.234E+001" \endcode \sa setNum() */ QString QString::number( double n, char f, int prec ) { QString s; s.setNum( n, f, prec ); return s; } /*! \obsolete Sets the character at position \a index to \a c and expands the string if necessary, filling with spaces. This method is redundant in Qt 3.x, because operator[] will expand the string as necessary. */ void QString::setExpand( uint index, QChar c ) { int spaces = index - d->len; at(index) = c; while (spaces-->0) d->unicode[--index]=' '; } /*! \fn const char* QString::data() const \obsolete Returns a pointer to a '\0'-terminated classic C string. In Qt 1.x, this returned a char* allowing direct manipulation of the string as a sequence of bytes. In Qt 2.x where QString is a Unicode string, char* conversion constructs a temporary string, and hence direct character operations are meaningless. */ /*! \fn bool QString::operator!() const Returns TRUE if this is a null string; otherwise returns FALSE. \code QString name = getName(); if ( !name ) name = "Rodney"; \endcode Note that if you say \code QString name = getName(); if ( name ) doSomethingWith(name); \endcode It will call "operator const char*()", which is inefficent; you may wish to define the macro \c QT_NO_ASCII_CAST when writing code which you wish to remain Unicode-clean. When you want the above semantics, use: \code QString name = getName(); if ( !name.isNull() ) doSomethingWith(name); \endcode \sa isEmpty() */ /*! \fn QString& QString::append( const QString& str ) Appends \a str to the string and returns a reference to the result. \code string = "Test"; string.append( "ing" ); // string == "Testing" \endcode Equivalent to operator+=(). */ /*! \fn QString& QString::append( char ch ) \overload Appends character \a ch to the string and returns a reference to the result. Equivalent to operator+=(). */ /*! \fn QString& QString::append( QChar ch ) \overload Appends character \a ch to the string and returns a reference to the result. Equivalent to operator+=(). */ /*! \fn QString& QString::append( const QByteArray &str ) \overload Appends \a str to the string and returns a reference to the result. Equivalent to operator+=(). */ +/*! \fn QString& QString::append( const std::string &str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). + */ + + /*! \fn QString& QString::append( const char *str ) \overload Appends \a str to the string and returns a reference to the result. Equivalent to operator+=(). */ /*! Appends \a str to the string and returns a reference to the string. */ QString& QString::operator+=( const QString &str ) { uint len1 = length(); uint len2 = str.length(); if ( len2 ) { setLength(len1+len2); memcpy( d->unicode+len1, str.unicode(), sizeof(QChar)*len2 ); } else if ( isNull() && !str.isNull() ) { // ## just for 1.x compat: *this = fromLatin1( "" ); } return *this; } /*! \overload Appends \a str to the string and returns a reference to the string. */ +#ifndef QT_NO_CAST_ASCII QString& QString::operator+=( const char *str ) { if ( str ) { +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) + return operator+=( fromAscii( str ) ); +#endif + uint len1 = length(); uint len2 = strlen( str ); if ( len2 ) { setLength(len1+len2); uint i = 0; while( i < len2 ) { d->unicode[len1+i] = str[i]; i++; } } else if ( isNull() ) { // ## just for 1.x compat: *this = fromLatin1( "" ); } } return *this; } +#endif /*! \overload Appends \a c to the string and returns a reference to the string. */ QString &QString::operator+=( QChar c ) { setLength(length()+1); d->unicode[length()-1] = c; return *this; } /*! \overload Appends \a c to the string and returns a reference to the string. */ QString &QString::operator+=( char c ) { +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) + return operator+=( fromAscii( &c, 1 ) ); +#endif setLength(length()+1); d->unicode[length()-1] = c; return *this; } /*! \fn QString &QString::operator+=( const QByteArray &str ) \overload Appends \a str to the string and returns a reference to the string. */ +/*! + \fn QString &QString::operator+=( const std::string &str ) + \overload + + Appends \a str to the string and returns a reference to the string. +*/ + /*! \fn char QChar::latin1() const - Returns a latin-1 copy of this character, if this character is in - the latin-1 character set. If not, this function returns 0. + Returns the Latin-1 value of this character, or 0 if it + cannot be represented in Latin-1. */ /*! - Returns a Latin-1 representation of the string. Note that the + Returns a Latin-1 representation of the string. The returned value is undefined if the string contains non-Latin-1 characters. If you want to convert strings into formats other than Unicode, see the QTextCodec classes. This function is mainly useful for boot-strapping legacy code to use Unicode. The result remains valid so long as one unmodified copy of the source string exists. - \sa utf8(), local8Bit() + \sa fromLatin1(), ascii(), utf8(), local8Bit() */ const char* QString::latin1() const { - if ( !d->ascii ) { - Q2HELPER(stat_get_ascii++) - Q2HELPER(stat_get_ascii_size+=d->len) - d->ascii = unicodeToAscii( d->unicode, d->len ); + if ( !d->ascii || !d->islatin1 ) { + d->ascii = unicodeToLatin1( d->unicode, d->len ); + d->islatin1 = TRUE; } return d->ascii; } /*! - \fn const char* QString::ascii() const - \obsolete + Returns an 8-bit ASCII representation of the string. + + If a codec has been set using QTextCodec::codecForCStrings(), + it is used to convert Unicode to 8-bit char. Otherwise, this function + does the same as latin1(). - This function simply calls latin1() and returns the result. + \sa fromAscii(), latin1(), utf8(), local8Bit() */ +const char* QString::ascii() const +{ +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + if ( !d->ascii || d->islatin1 ) { + QCString s = QTextCodec::codecForCStrings()->fromUnicode( *this ); + s.detach(); + d->ascii = s.data(); + d->islatin1 = FALSE; + s.resetRawData( s.data(), s.size() ); // we have stolen the data + } + return d->ascii; + } +#endif // QT_NO_TEXTCODEC + return latin1(); +} /*! - Returns the string encoded in UTF8 format. + Returns the string encoded in UTF-8 format. See QTextCodec for more diverse coding/decoding of Unicode strings. - \sa QString::fromUtf8(), local8Bit(), latin1() + \sa fromUtf8(), ascii(), latin1(), local8Bit() */ QCString QString::utf8() const { int l = length(); int rlen = l*3+1; QCString rstr(rlen); uchar* cursor = (uchar*)rstr.data(); const QChar *ch = d->unicode; for (int i=0; i<l; i++) { ushort u = ch->unicode(); if ( u < 0x80 ) { *cursor++ = (uchar)u; } else { if ( u < 0x0800 ) { *cursor++ = 0xc0 | ((uchar) (u >> 6)); } else { *cursor++ = 0xe0 | ((uchar) (u >> 12)); *cursor++ = 0x80 | ( ((uchar) (u >> 6)) & 0x3f); } *cursor++ = 0x80 | ((uchar) (u&0x3f)); } ch++; } rstr.truncate( cursor - (uchar*)rstr.data() ); return rstr; } /*! Returns the Unicode string decoded from the first \a len characters of \a utf8, ignoring the rest of \a utf8. If \a len is -1 then the length of \a utf8 is used. If \a len is bigger than the length of \a utf8 then it will use the length of \a utf8. \code QString str = QString::fromUtf8( "123456789", 5 ); // str == "12345" \endcode See QTextCodec for more diverse coding/decoding of Unicode strings. */ QString QString::fromUtf8( const char* utf8, int len ) { if ( !utf8 ) return QString::null; - if ( len < 0 ) len = qstrlen( utf8 ); + if ( len < 0 ) + len = strlen( utf8 ); QString result; result.setLength( len ); // worst case QChar *qch = (QChar *)result.unicode(); ushort uc = 0; int need = 0; for (int i=0; i<len; i++) { uchar ch = utf8[i]; if (need) { if ( (ch&0xc0) == 0x80 ) { uc = (uc << 6) | (ch & 0x3f); need--; if ( !need ) { *qch = uc; qch++; } } else { // error *qch = QChar::replacement; qch++; need = 0; } } else { if ( ch < 128 ) { *qch = ch; qch++; } else if ( (ch&0xe0) == 0xc0 ) { uc = ch &0x1f; need = 1; } else if ( (ch&0xf0) == 0xe0 ) { uc = ch &0x0f; need = 2; } } } result.truncate( qch - result.unicode() ); return result; } /*! Returns the Unicode string decoded from the first \a len - characters of \a chars, ignoring the rest of \a chars. If \a len - is -1 then the length of \a chars is used. If \a len is bigger - than the length of \a chars then it will use the length of \a - chars. + characters of \a ascii, ignoring the rest of \a ascii. If \a len + is -1 then the length of \a ascii is used. If \a len is bigger + than the length of \a ascii then it will use the length of \a + ascii. + + If a codec has been set using QTextCodec::codecForCStrings(), + it is used to convert Unicode to 8-bit char. Otherwise, this function + does the same as fromLatin1(). This is the same as the QString(const char*) constructor, but you can make that constructor invisible if you compile with the define \c QT_NO_CAST_ASCII, in which case you can explicitly create a - QString from Latin-1 text using this function. + QString from 8-bit ASCII text using this function. \code - QString str = QString::fromLatin1( "123456789", 5 ); + QString str = QString::fromAscii( "123456789", 5 ); // str == "12345" \endcode */ +QString QString::fromAscii( const char* ascii, int len ) +{ +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + if ( !ascii ) + return QString::null; + if ( len < 0 ) + len = strlen( ascii ); + if ( len == 0 || *ascii == '\0' ) + return QString::fromLatin1( "" ); + return QTextCodec::codecForCStrings()->toUnicode( ascii, len ); + } +#endif + return fromLatin1( ascii, len ); +} + + +/*! + Returns the Unicode string decoded from the first \a len + characters of \a chars, ignoring the rest of \a chars. If \a len + is -1 then the length of \a chars is used. If \a len is bigger + than the length of \a chars then it will use the length of \a + chars. + + \sa fromAscii() +*/ QString QString::fromLatin1( const char* chars, int len ) { uint l; QChar *uc; if ( len < 0 ) len = -1; - uc = internalAsciiToUnicode( chars, &l, len ); + uc = internalLatin1ToUnicode( chars, &l, len ); return QString( new QStringData(uc, l, l), TRUE ); } /*! \fn const QChar* QString::unicode() const Returns the Unicode representation of the string. The result remains valid until the string is modified. */ /*! Returns the string encoded in a locale-specific format. On X11, this is the QTextCodec::codecForLocale(). On Windows, it is a - system-defined encoding. On Mac OS X, this always uses utf8 as the - encoding. + system-defined encoding. On Mac OS X, this always uses UTF-8 as + the encoding. See QTextCodec for more diverse coding/decoding of Unicode strings. - \sa QString::fromLocal8Bit(), latin1(), utf8() + \sa fromLocal8Bit(), ascii(), latin1(), utf8() */ - QCString QString::local8Bit() const { #ifdef QT_NO_TEXTCODEC return latin1(); #else #ifdef Q_WS_X11 QTextCodec* codec = QTextCodec::codecForLocale(); return codec ? codec->fromUnicode(*this) : QCString(latin1()); #endif #if defined( Q_WS_MACX ) return utf8(); #endif #if defined( Q_WS_MAC9 ) return QCString(latin1()); //I'm evil.. #endif #ifdef Q_WS_WIN return qt_winQString2MB( *this ); #endif #ifdef Q_WS_QWS - return utf8(); // ##### if there is ANY 8 bit format supported? + return utf8(); // ### if there is any 8 bit format supported? #endif #endif } /*! Returns the Unicode string decoded from the first \a len characters of \a local8Bit, ignoring the rest of \a local8Bit. If \a len is -1 then the length of \a local8Bit is used. If \a len is bigger than the length of \a local8Bit then it will use the length of \a local8Bit. \code QString str = QString::fromLocal8Bit( "123456789", 5 ); // str == "12345" \endcode \a local8Bit is assumed to be encoded in a locale-specific format. See QTextCodec for more diverse coding/decoding of Unicode strings. */ QString QString::fromLocal8Bit( const char* local8Bit, int len ) { #ifdef QT_NO_TEXTCODEC return fromLatin1( local8Bit, len ); #else if ( !local8Bit ) return QString::null; #ifdef Q_WS_X11 QTextCodec* codec = QTextCodec::codecForLocale(); - if ( len < 0 ) len = qstrlen(local8Bit); + if ( len < 0 ) + len = strlen( local8Bit ); return codec ? codec->toUnicode( local8Bit, len ) : fromLatin1( local8Bit, len ); #endif #if defined( Q_WS_MAC ) return fromUtf8(local8Bit,len); #endif // Should this be OS_WIN32? #ifdef Q_WS_WIN if ( len >= 0 ) { QCString s(local8Bit,len+1); return qt_winMB2QString(s); } return qt_winMB2QString( local8Bit ); #endif #ifdef Q_WS_QWS return fromUtf8(local8Bit,len); #endif #endif // QT_NO_TEXTCODEC } /*! \fn QString::operator const char *() const Returns latin1(). Be sure to see the warnings documented in the latin1() function. Note that for new code which you wish to be strictly Unicode-clean, you can define the macro \c QT_NO_ASCII_CAST when compiling your code to hide this function so that automatic casts are not done. This has the added advantage that you catch the programming error described in operator!(). */ +/*! + \fn QString::operator std::string() const + + Returns ascii(). +*/ + /*! Returns the QString as a zero terminated array of unsigned shorts if the string is not null; otherwise returns zero. The result remains valid so long as one unmodified copy of the source string exists. */ const unsigned short *QString::ucs2() const { if ( ! d->unicode ) return 0; unsigned int len = d->len; if ( d->maxl < len + 1 ) { // detach, grow or shrink - Q2HELPER(stat_copy_on_write++) - Q2HELPER(stat_copy_on_write_size += len) uint newMax = computeNewMax( len + 1 ); QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); if ( nd ) { if ( d->unicode ) memcpy( nd, d->unicode, sizeof(QChar)*len ); ((QString *)this)->deref(); ((QString *)this)->d = new QStringData( nd, len, newMax ); } } d->unicode[len] = 0; return (unsigned short *) d->unicode; } /*! Constructs a string that is a deep copy of \a str, interpreted as a UCS2 encoded, zero terminated, Unicode string. If \a str is 0, then a null string is created. \sa isNull() */ QString QString::fromUcs2( const unsigned short *str ) { if ( !str ) { return QString::null; } else { int length = 0; while( str[length] != 0 ) length++; QChar* uc = QT_ALLOC_QCHAR_VEC( length ); memcpy( uc, str, length*sizeof(QChar) ); return QString( new QStringData( uc, length, length ), TRUE ); } } /*! \fn QChar QString::at( uint ) const Returns the character at index \a i, or 0 if \a i is beyond the length of the string. \code const QString string( "abcdefgh" ); QChar ch = string.at( 4 ); // ch == 'e' \endcode If the QString is not const (i.e. const QString) or const& (i.e. const QString &), then the non-const overload of at() will be used instead. */ /*! \fn QChar QString::constref(uint i) const Returns the QChar at index \a i by value. Equivalent to at(\a i). \sa ref() */ /*! \fn QChar& QString::ref(uint i) Returns the QChar at index \a i by reference, expanding the string with QChar::null if necessary. The resulting reference can be assigned to, or otherwise used immediately, but becomes invalid once furher modifications are made to the string. \code QString string("ABCDEF"); QChar ch = string.ref( 3 ); // ch == 'D' \endcode \sa constref() */ /*! \fn QChar QString::operator[]( int ) const Returns the character at index \a i, or QChar::null if \a i is beyond the length of the string. If the QString is not const (i.e., const QString) or const\& (i.e., const QString\&), then the non-const overload of operator[] will be used instead. */ /*! \fn QCharRef QString::operator[]( int ) \overload The function returns a reference to the character at index \a i. The resulting reference can then be assigned to, or used immediately, but it will become invalid once further modifications are made to the original string. If \a i is beyond the length of the string then the string is expanded with QChar::nulls, so that the QCharRef references a valid (null) character in the string. The QCharRef internal class can be used much like a constant QChar, but if you assign to it, you change the original string (which will detach itself because of QString's copy-on-write semantics). You will get compilation errors if you try to use the result as anything but a QChar. */ /*! \fn QCharRef QString::at( uint i ) \overload The function returns a reference to the character at index \a i. The resulting reference can then be assigned to, or used immediately, but it will become invalid once further modifications are made to the original string. If \a i is beyond the length of the string then the string is expanded with QChar::null. */ /* Internal chunk of code to handle the uncommon cases of at() above. */ void QString::subat( uint i ) { uint olen = d->len; if ( i >= olen ) { setLength( i+1 ); // i is index; i+1 is needed length for ( uint j=olen; j<=i; j++ ) d->unicode[j] = QChar::null; } else { // Just be sure to detach real_detach(); } } /*! Resizes the string to \a len characters and copies \a unicode into the string. If \a unicode is 0, nothing is copied, but the string is still resized to \a len. If \a len is zero, then the string becomes a \link isNull() null\endlink string. \sa setLatin1(), isNull() */ QString& QString::setUnicode( const QChar *unicode, uint len ) { if ( len == 0 ) { // set to null string if ( d != shared_null ) { // beware of nullstring being set to nullstring deref(); d = shared_null ? shared_null : makeSharedNull(); d->ref(); } } else if ( d->count != 1 || len > d->maxl || ( len * 4 < d->maxl && d->maxl > 4 ) ) { // detach, grown or shrink - Q2HELPER(stat_copy_on_write++) - Q2HELPER(stat_copy_on_write_size+=d->len) uint newMax = computeNewMax( len ); QChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); if ( unicode ) memcpy( nd, unicode, sizeof(QChar)*len ); deref(); d = new QStringData( nd, len, newMax ); } else { d->len = len; d->setDirty(); if ( unicode ) memcpy( d->unicode, unicode, sizeof(QChar)*len ); } return *this; } /*! Resizes the string to \a len characters and copies \a unicode_as_ushorts into the string (on some X11 client platforms this will involve a byte-swapping pass). If \a unicode_as_ushorts is 0, nothing is copied, but the string is still resized to \a len. If \a len is zero, the string becomes a \link isNull() null\endlink string. \sa setLatin1(), isNull() */ QString& QString::setUnicodeCodes( const ushort* unicode_as_ushorts, uint len ) { return setUnicode((const QChar*)unicode_as_ushorts, len); } /*! + Sets this string to \a str, interpreted as a classic 8-bit ASCII C + string. If \a len is -1 (the default), then it is set to + strlen(str). + + If \a str is 0 a null string is created. If \a str is "", an empty + string is created. + + \sa isNull(), isEmpty() +*/ + +QString &QString::setAscii( const char *str, int len ) +{ +#ifndef QT_NO_TEXTCODEC + if ( QTextCodec::codecForCStrings() ) { + *this = QString::fromAscii( str, len ); + return *this; + } +#endif // QT_NO_TEXTCODEC + return setLatin1( str, len ); +} + +/*! Sets this string to \a str, interpreted as a classic Latin1 C string. If \a len is -1 (the default), then it is set to strlen(str). If \a str is 0 a null string is created. If \a str is "", an empty string is created. \sa isNull(), isEmpty() */ QString &QString::setLatin1( const char *str, int len ) { if ( str == 0 ) return setUnicode(0,0); if ( len < 0 ) - len = qstrlen(str); + len = strlen( str ); if ( len == 0 ) { // won't make a null string *this = QString::fromLatin1( "" ); } else { setUnicode( 0, len ); // resize but not copy QChar *p = d->unicode; while ( len-- ) *p++ = *str++; } return *this; } /*! \internal */ void QString::checkSimpleText() const { QChar *p = d->unicode; QChar *end = p + d->len; - d->simpletext = 1; while( p < end ) { ushort uc = p->unicode(); // sort out regions of complex text formatting if ( uc > 0x058f && ( uc < 0x1100 || uc > 0xfb0f ) ) { - d->simpletext = 0; + d->issimpletext = FALSE; return; } p++; } + d->issimpletext = TRUE; } /*! \fn bool QString::simpleText() const \internal */ /*! \internal */ bool QString::isRightToLeft() const { int len = length(); QChar *p = d->unicode; while( len-- ) { switch( ::direction( *p ) ) { case QChar::DirL: case QChar::DirLRO: case QChar::DirLRE: return FALSE; case QChar::DirR: case QChar::DirAL: case QChar::DirRLO: case QChar::DirRLE: return TRUE; default: break; } ++p; } return FALSE; } /*! \fn int QString::compare( const QString & s1, const QString & s2 ) Lexically compares \a s1 with \a s2 and returns an integer less than, equal to, or greater than zero if \a s1 is less than, equal to, or greater than \a s2. The comparison is based exclusively on the numeric Unicode values of the characters and is very fast, but is not what a human would expect. Consider sorting user-interface strings with QString::localeAwareCompare(). \code int a = QString::compare( "def", "abc" ); // a > 0 int b = QString::compare( "abc", "def" ); // b < 0 int c = QString::compare(" abc", "abc" ); // c == 0 \endcode */ /*! \overload Lexically compares this string with \a s and returns an integer less than, equal to, or greater than zero if it is less than, equal to, or greater than \a s. */ int QString::compare( const QString& s ) const { return ucstrcmp( *this, s ); } /*! \fn int QString::localeAwareCompare( const QString & s1, const QString & s2 ) Compares \a s1 with \a s2 and returns an integer less than, equal to, or greater than zero if \a s1 is less than, equal to, or greater than \a s2. The comparison is performed in a locale- and also platform-dependent manner. Use this function to present sorted lists of strings to the user. \sa QString::compare() QTextCodec::locale() */ /*! \overload Compares this string with \a s. */ #if !defined(CSTR_LESS_THAN) #define CSTR_LESS_THAN 1 #define CSTR_EQUAL 2 #define CSTR_GREATER_THAN 3 #endif int QString::localeAwareCompare( const QString& s ) const { // do the right thing for null and empty if ( isEmpty() || s.isEmpty() ) return compare( s ); #if defined(Q_WS_WIN) int res; QT_WA( { const TCHAR* s1 = (TCHAR*)ucs2(); const TCHAR* s2 = (TCHAR*)s.ucs2(); res = CompareStringW( LOCALE_USER_DEFAULT, 0, s1, length(), s2, s.length() ); } , { QCString s1 = local8Bit(); QCString s2 = s.local8Bit(); res = CompareStringA( LOCALE_USER_DEFAULT, 0, s1.data(), s1.length(), s2.data(), s2.length() ); } ); switch ( res ) { case CSTR_LESS_THAN: return -1; case CSTR_GREATER_THAN: return 1; default: return 0; } #elif defined(Q_WS_X11) // declared in <string.h> int delta = strcoll( local8Bit(), s.local8Bit() ); if ( delta == 0 ) delta = ucstrcmp( *this, s ); return delta; #else return ucstrcmp( *this, s ); #endif } bool operator==( const QString &s1, const QString &s2 ) { if ( s1.unicode() == s2.unicode() ) return TRUE; return (s1.length() == s2.length()) && s1.isNull() == s2.isNull() && (memcmp((char*)s1.unicode(),(char*)s2.unicode(), s1.length()*sizeof(QChar)) == 0 ); } bool operator!=( const QString &s1, const QString &s2 ) { return !(s1==s2); } bool operator<( const QString &s1, const QString &s2 ) { return ucstrcmp(s1,s2) < 0; } bool operator<=( const QString &s1, const QString &s2 ) { return ucstrcmp(s1,s2) <= 0; } bool operator>( const QString &s1, const QString &s2 ) { return ucstrcmp(s1,s2) > 0; } bool operator>=( const QString &s1, const QString &s2 ) { return ucstrcmp(s1,s2) >= 0; } bool operator==( const QString &s1, const char *s2 ) { if ( !s2 ) return s1.isNull(); int len = s1.length(); const QChar *uc = s1.unicode(); while ( len ) { if ( !(*s2) || uc->unicode() != (uchar) *s2 ) return FALSE; ++uc; ++s2; --len; } return !*s2; } bool operator==( const char *s1, const QString &s2 ) { return (s2 == s1); } bool operator!=( const QString &s1, const char *s2 ) { return !(s1==s2); } bool operator!=( const char *s1, const QString &s2 ) { return !(s1==s2); } bool operator<( const QString &s1, const char *s2 ) { return ucstrcmp(s1,s2) < 0; } bool operator<( const char *s1, const QString &s2 ) { return ucstrcmp(s1,s2) < 0; } bool operator<=( const QString &s1, const char *s2 ) { return ucstrcmp(s1,s2) <= 0; } bool operator<=( const char *s1, const QString &s2 ) { return ucstrcmp(s1,s2) <= 0; } bool operator>( const QString &s1, const char *s2 ) { return ucstrcmp(s1,s2) > 0; } bool operator>( const char *s1, const QString &s2 ) { return ucstrcmp(s1,s2) > 0; } bool operator>=( const QString &s1, const char *s2 ) { return ucstrcmp(s1,s2) >= 0; } bool operator>=( const char *s1, const QString &s2 ) { return ucstrcmp(s1,s2) >= 0; } /***************************************************************************** Documentation for QString related functions *****************************************************************************/ /*! \fn bool operator==( const QString &s1, const QString &s2 ) \relates QString Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) != 0. \sa isNull(), isEmpty() */ /*! \fn bool operator==( const QString &s1, const char *s2 ) \overload \relates QString Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) == 0. \sa isNull(), isEmpty() */ /*! \fn bool operator==( const char *s1, const QString &s2 ) \overload \relates QString Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) == 0. \sa isNull(), isEmpty() */ /*! \fn bool operator!=( const QString &s1, const QString &s2 ) \relates QString Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) != 0. \sa isNull(), isEmpty() */ /*! \fn bool operator!=( const QString &s1, const char *s2 ) \overload \relates QString Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) != 0. \sa isNull(), isEmpty() */ /*! \fn bool operator!=( const char *s1, const QString &s2 ) \overload \relates QString Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) != 0. \sa isNull(), isEmpty() */ /*! \fn bool operator<( const QString &s1, const char *s2 ) \relates QString Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. The comparison is case sensitive. Equivalent to compare(\a s1, \a s2) \< 0. */ /*! \fn bool operator<( const char *s1, const QString &s2 ) \overload \relates QString Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. The comparison is case sensitive. Equivalent to compare(\a s1, \a s2) \< 0. */ /*! \fn bool operator<=( const QString &s1, const char *s2 ) \relates QString Returns TRUE if \a s1 is lexically less than or equal to \a s2; otherwise returns FALSE. The comparison is case sensitive. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1,\a s2) \<= 0. \sa isNull(), isEmpty() */ /*! \fn bool operator<=( const char *s1, const QString &s2 ) \overload \relates QString Returns TRUE if \a s1 is lexically less than or equal to \a s2; otherwise returns FALSE. The comparison is case sensitive. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) \<= 0. \sa isNull(), isEmpty() */ /*! \fn bool operator>( const QString &s1, const char *s2 ) \relates QString Returns TRUE if \a s1 is lexically greater than \a s2; otherwise returns FALSE. The comparison is case sensitive. Equivalent to compare(\a s1, \a s2) \> 0. */ /*! \fn bool operator>( const char *s1, const QString &s2 ) \overload \relates QString Returns TRUE if \a s1 is lexically greater than \a s2; otherwise returns FALSE. The comparison is case sensitive. Equivalent to compare(\a s1, \a s2) \> 0. */ /*! \fn bool operator>=( const QString &s1, const char *s2 ) \relates QString Returns TRUE if \a s1 is lexically greater than or equal to \a s2; otherwise returns FALSE. The comparison is case sensitive. Note that a null string is not equal to a not-null empty string. Equivalent to compare(\a s1, \a s2) \>= 0. \sa isNull(), isEmpty() */ /*! diff --git a/qmake/tools/qtextstream.cpp b/qmake/tools/qtextstream.cpp index 75c6531..ddca5bd 100644 --- a/qmake/tools/qtextstream.cpp +++ b/qmake/tools/qtextstream.cpp @@ -708,769 +708,769 @@ uint QTextStream::ts_getbuf( QChar* buf, uint len ) bool readBlock = !( len == 1+rnum ); for (;;) { // for efficiency: normally read a whole block if ( readBlock ) { // guess buffersize; this may be wrong (too small or too // big). But we can handle this (either iterate reading // or use ungetcBuf). // Note that this might cause problems for codecs where // one byte can result in >1 Unicode Characters if bytes // are written to the stream in the meantime (loss of // synchronicity). uint rlen = len - rnum; char *cbuf = new char[ rlen ]; if ( ungetHack != EOF ) { rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); cbuf[0] = (char)ungetHack; ungetHack = EOF; } else { rlen = dev->readBlock( cbuf, rlen ); } s += d->decoder->toUnicode( cbuf, rlen ); delete[] cbuf; // use buffered reading only for the first time, because we // have to get the stream synchronous again (this is easier // with single character reading) readBlock = FALSE; } // get stream (and codec) in sync int c; if ( ungetHack == EOF ) { c = dev->getch(); } else { c = ungetHack; ungetHack = EOF; } if ( c == EOF ) { shortRead = TRUE; break; } char b = c; uint lengthBefore = s.length(); s += d->decoder->toUnicode( &b, 1 ); if ( s.length() > lengthBefore ) break; // it seems we are in sync now } uint i = 0; uint end = QMIN( len-rnum, s.length() ); while( i < end ) { *buf = s.constref(i++); buf++; } rnum += end; if ( s.length() > i ) // could be = but append is clearer d->ungetcBuf.append( s.mid( i ) ); if ( shortRead ) return rnum; } } else #endif if ( latin1 ) { if ( len == 1+rnum ) { // use this method for one character because it is more efficient // (arnt doubts whether it makes a difference, but lets it stand) int c = (ungetHack == EOF) ? dev->getch() : ungetHack; if ( c != EOF ) { *buf = (char)c; buf++; rnum++; } } else { if ( ungetHack != EOF ) { *buf = (char)ungetHack; buf++; rnum++; ungetHack = EOF; } char *cbuf = new char[len - rnum]; while ( !dev->atEnd() && rnum < len ) { uint rlen = len - rnum; rlen = dev->readBlock( cbuf, rlen ); char *it = cbuf; char *end = cbuf + rlen; while ( it < end ) { *buf = *it; buf++; it++; } rnum += rlen; } delete[] cbuf; } } else { // UCS-2 or UTF-16 if ( len == 1+rnum ) { int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack; if ( c1 == EOF ) return rnum; int c2 = dev->getch(); if ( c2 == EOF ) return rnum; if ( networkOrder ) { *buf = QChar( c2, c1 ); } else { *buf = QChar( c1, c2 ); } buf++; rnum++; } else { char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible while ( !dev->atEnd() && rnum < len ) { uint rlen = 2 * ( len-rnum ); if ( ungetHack != EOF ) { rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); cbuf[0] = (char)ungetHack; ungetHack = EOF; } else { rlen = dev->readBlock( cbuf, rlen ); } // We can't use an odd number of bytes, so put it back. But // do it only if we are capable of reading more -- normally // there should not be an odd number, but the file might be // truncated or not in UTF-16... if ( (rlen & 1) == 1 ) if ( !dev->atEnd() ) dev->ungetch( cbuf[--rlen] ); uint i = 0; if ( networkOrder ) { while( i < rlen ) { *buf = QChar( cbuf[i+1], cbuf[i] ); buf++; i+=2; } } else { while( i < rlen ) { *buf = QChar( cbuf[i], cbuf[i+1] ); buf++; i+=2; } } rnum += i/2; } delete[] cbuf; } } return rnum; } /*! Tries to read one line, but at most len characters from the stream and stores them in \a buf. Returns the number of characters really read. Newlines are not stripped. There will be a QEOF appended if the read reaches the end of file; this is different to ts_getbuf(). This function works only if a newline (as byte) is also a newline (as resulting character) since it uses QIODevice::readLine(). So use it only for such codecs where this is true! This function is (almost) a no-op for UTF 16. Don't use it if doUnicodeHeader is TRUE! */ uint QTextStream::ts_getline( QChar* buf ) { uint rnum=0; // the number of QChars really read char cbuf[ getline_buf_size+1 ]; if ( d && d->ungetcBuf.length() ) { while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) { buf[rnum] = d->ungetcBuf.constref(rnum); rnum++; } d->ungetcBuf = d->ungetcBuf.mid( rnum ); if ( rnum >= getline_buf_size ) return rnum; } #ifndef QT_NO_TEXTCODEC if ( mapper ) { if ( !d->decoder ) d->decoder = mapper->makeDecoder(); QString s; bool readBlock = TRUE; for (;;) { // for efficiency: try to read a line if ( readBlock ) { int rlen = getline_buf_size - rnum; rlen = dev->readLine( cbuf, rlen+1 ); if ( rlen == -1 ) rlen = 0; s += d->decoder->toUnicode( cbuf, rlen ); readBlock = FALSE; } if ( dev->atEnd() || s.at( s.length()-1 ) == '\n' || s.at( s.length()-1 ) == '\r' ) { break; } else { // get stream (and codec) in sync int c; c = dev->getch(); if ( c == EOF ) { break; } char b = c; uint lengthBefore = s.length(); s += d->decoder->toUnicode( &b, 1 ); if ( s.length() > lengthBefore ) break; // it seems we are in sync now } } uint i = 0; while( rnum < getline_buf_size && i < s.length() ) buf[rnum++] = s.constref(i++); if ( s.length() > i ) // could be = but append is clearer d->ungetcBuf.append( s.mid( i ) ); if ( rnum < getline_buf_size && dev->atEnd() ) buf[rnum++] = QEOF; } else #endif if ( latin1 ) { int rlen = getline_buf_size - rnum; rlen = dev->readLine( cbuf, rlen+1 ); if ( rlen == -1 ) rlen = 0; char *end = cbuf+rlen; char *it = cbuf; buf +=rnum; while ( it != end ) { buf->setCell( *(it++) ); buf->setRow( 0 ); buf++; } rnum += rlen; if ( rnum < getline_buf_size && dev->atEnd() ) buf[1] = QEOF; } return rnum; } /*! Puts one character into the stream. */ void QTextStream::ts_putc( QChar c ) { #ifndef QT_NO_TEXTCODEC if ( mapper ) { if ( !d->encoder ) d->encoder = mapper->makeEncoder(); int len = 1; QString s = c; QCString block = d->encoder->fromUnicode( s, len ); dev->writeBlock( block, len ); } else #endif if ( latin1 ) { if ( c.row() ) dev->putch( '?' ); // unknown character else dev->putch( c.cell() ); } else { if ( doUnicodeHeader ) { doUnicodeHeader = FALSE; ts_putc( QChar::byteOrderMark ); } if ( internalOrder ) { // this case is needed by QStringBuffer dev->writeBlock( (char*)&c, sizeof(QChar) ); } else if ( networkOrder ) { dev->putch( c.row() ); dev->putch( c.cell() ); } else { dev->putch( c.cell() ); dev->putch( c.row() ); } } } /*! Puts one character into the stream. */ void QTextStream::ts_putc( int ch ) { ts_putc( QChar((ushort)ch) ); } bool QTextStream::ts_isdigit( QChar c ) { return c.isDigit(); } bool QTextStream::ts_isspace( QChar c ) { return c.isSpace(); } void QTextStream::ts_ungetc( QChar c ) { if ( c.unicode() == 0xffff ) return; d->ungetcBuf.prepend( c ); } /*! Reads \a len bytes from the stream into \a s and returns a reference to the stream. The buffer \a s must be preallocated. Note that no encoding is done by this function. \warning The behavior of this function is undefined unless the stream's encoding is set to Unicode or Latin1. \sa QIODevice::readBlock() */ QTextStream &QTextStream::readRawBytes( char *s, uint len ) { dev->readBlock( s, len ); return *this; } /*! Writes the \a len bytes from \a s to the stream and returns a reference to the stream. Note that no encoding is done by this function. \sa QIODevice::writeBlock() */ QTextStream &QTextStream::writeRawBytes( const char* s, uint len ) { dev->writeBlock( s, len ); return *this; } QTextStream &QTextStream::writeBlock( const char* p, uint len ) { if ( doUnicodeHeader ) { doUnicodeHeader = FALSE; if ( !mapper && !latin1 ) ts_putc( QChar::byteOrderMark ); } // QCString and const char * are treated as Latin-1 if ( !mapper && latin1 ) { dev->writeBlock( p, len ); } else if ( !mapper && internalOrder ) { QChar *u = new QChar[len]; for ( uint i = 0; i < len; i++ ) u[i] = p[i]; dev->writeBlock( (char*)u, len * sizeof(QChar) ); delete [] u; } else { for ( uint i = 0; i < len; i++ ) ts_putc( (uchar)p[i] ); } return *this; } QTextStream &QTextStream::writeBlock( const QChar* p, uint len ) { #ifndef QT_NO_TEXTCODEC if ( mapper ) { if ( !d->encoder ) d->encoder = mapper->makeEncoder(); QConstString s( p, len ); int l = len; QCString block = d->encoder->fromUnicode( s.string(), l ); dev->writeBlock( block, l ); } else #endif if ( latin1 ) { - char *str = QString::unicodeToAscii( p, len ); + char *str = QString::unicodeToLatin1( p, len ); dev->writeBlock( str, len ); delete [] str; } else if ( internalOrder ) { if ( doUnicodeHeader ) { doUnicodeHeader = FALSE; ts_putc( QChar::byteOrderMark ); } dev->writeBlock( (char*)p, sizeof(QChar)*len ); } else { for (uint i=0; i<len; i++) ts_putc( p[i] ); } return *this; } /*! Resets the text stream. \list \i All flags are set to 0. \i The field width is set to 0. \i The fill character is set to ' ' (Space). \i The precision is set to 6. \endlist \sa setf(), width(), fill(), precision() */ void QTextStream::reset() { fflags = 0; fwidth = 0; fillchar = ' '; fprec = 6; } /*! \fn QIODevice *QTextStream::device() const Returns the IO device currently set. \sa setDevice(), unsetDevice() */ /*! Sets the IO device to \a iod. \sa device(), unsetDevice() */ void QTextStream::setDevice( QIODevice *iod ) { if ( owndev ) { delete dev; owndev = FALSE; } dev = iod; d->sourceType = QTextStreamPrivate::IODevice; } /*! Unsets the IO device. Equivalent to setDevice( 0 ). \sa device(), setDevice() */ void QTextStream::unsetDevice() { setDevice( 0 ); d->sourceType = QTextStreamPrivate::NotSet; } /*! \fn bool QTextStream::atEnd() const Returns TRUE if the IO device has reached the end position (end of the stream or file) or if there is no IO device set; otherwise returns FALSE. \sa QIODevice::atEnd() */ /*!\fn bool QTextStream::eof() const \obsolete This function has been renamed to atEnd(). \sa QIODevice::atEnd() */ /***************************************************************************** QTextStream read functions *****************************************************************************/ /*! \overload Reads a char \a c from the stream and returns a reference to the stream. Note that whitespace is skipped. */ QTextStream &QTextStream::operator>>( char &c ) { CHECK_STREAM_PRECOND c = eat_ws(); return *this; } /*! Reads a char \a c from the stream and returns a reference to the stream. Note that whitespace is \e not skipped. */ QTextStream &QTextStream::operator>>( QChar &c ) { CHECK_STREAM_PRECOND c = ts_getc(); return *this; } ulong QTextStream::input_bin() { ulong val = 0; QChar ch = eat_ws(); int dv = ch.digitValue(); while ( dv == 0 || dv == 1 ) { val = ( val << 1 ) + dv; ch = ts_getc(); dv = ch.digitValue(); } if ( ch != QEOF ) ts_ungetc( ch ); return val; } ulong QTextStream::input_oct() { ulong val = 0; QChar ch = eat_ws(); int dv = ch.digitValue(); while ( dv >= 0 && dv <= 7 ) { val = ( val << 3 ) + dv; ch = ts_getc(); dv = ch.digitValue(); } if ( dv == 8 || dv == 9 ) { while ( ts_isdigit(ch) ) ch = ts_getc(); } if ( ch != QEOF ) ts_ungetc( ch ); return val; } ulong QTextStream::input_dec() { ulong val = 0; QChar ch = eat_ws(); int dv = ch.digitValue(); while ( ts_isdigit(ch) ) { val = val * 10 + dv; ch = ts_getc(); dv = ch.digitValue(); } if ( ch != QEOF ) ts_ungetc( ch ); return val; } ulong QTextStream::input_hex() { ulong val = 0; QChar ch = eat_ws(); char c = ch; while ( isxdigit((uchar) c) ) { val <<= 4; if ( ts_isdigit(c) ) val += c - '0'; else val += 10 + tolower( (uchar) c ) - 'a'; c = ch = ts_getc(); } if ( ch != QEOF ) ts_ungetc( ch ); return val; } long QTextStream::input_int() { long val; QChar ch; char c; switch ( flags() & basefield ) { case bin: val = (long)input_bin(); break; case oct: val = (long)input_oct(); break; case dec: c = ch = eat_ws(); if ( ch == QEOF ) { val = 0; } else { if ( !(c == '-' || c == '+') ) ts_ungetc( ch ); if ( c == '-' ) { ulong v = input_dec(); if ( v ) { // ensure that LONG_MIN can be read v--; val = -((long)v) - 1; } else { val = 0; } } else { val = (long)input_dec(); } } break; case hex: val = (long)input_hex(); break; default: val = 0; c = ch = eat_ws(); if ( c == '0' ) { // bin, oct or hex c = ch = ts_getc(); if ( tolower((uchar) c) == 'x' ) val = (long)input_hex(); else if ( tolower((uchar) c) == 'b' ) val = (long)input_bin(); else { // octal ts_ungetc( ch ); if ( c >= '0' && c <= '7' ) { val = (long)input_oct(); } else { val = 0; } } } else if ( ts_isdigit(ch) ) { ts_ungetc( ch ); val = (long)input_dec(); } else if ( c == '-' || c == '+' ) { ulong v = input_dec(); if ( c == '-' ) { if ( v ) { // ensure that LONG_MIN can be read v--; val = -((long)v) - 1; } else { val = 0; } } else { val = (long)v; } } } return val; } // // We use a table-driven FSM to parse floating point numbers // strtod() cannot be used directly since we're reading from a QIODevice // double QTextStream::input_double() { const int Init = 0; // states const int Sign = 1; const int Mantissa = 2; const int Dot = 3; const int Abscissa = 4; const int ExpMark = 5; const int ExpSign = 6; const int Exponent = 7; const int Done = 8; const int InputSign = 1; // input tokens const int InputDigit = 2; const int InputDot = 3; const int InputExp = 4; static const uchar table[8][5] = { /* None InputSign InputDigit InputDot InputExp */ { 0, Sign, Mantissa, Dot, 0, }, // Init { 0, 0, Mantissa, Dot, 0, }, // Sign { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa { 0, 0, Abscissa, 0, 0, }, // Dot { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa { 0, ExpSign, Exponent, 0, 0, }, // ExpMark { 0, 0, Exponent, 0, 0, }, // ExpSign { Done, Done, Exponent, Done, Done } // Exponent }; int state = Init; // parse state int input; // input token char buf[256]; int i = 0; QChar c = eat_ws(); for (;;) { switch ( c ) { case '+': case '-': input = InputSign; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': input = InputDigit; break; case '.': input = InputDot; break; case 'e': case 'E': input = InputExp; break; default: input = 0; break; } state = table[state][input]; if ( state == 0 || state == Done || i > 250 ) { if ( i > 250 ) { // ignore rest of digits do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) ); } if ( c != QEOF ) ts_ungetc( c ); buf[i] = '\0'; char *end; return strtod( buf, &end ); } buf[i++] = c; c = ts_getc(); } #if !defined(Q_CC_EDG) return 0.0; #endif } /*! \overload Reads a signed \c short integer \a i from the stream and returns a reference to the stream. See flags() for an explanation of the expected input format. */ QTextStream &QTextStream::operator>>( signed short &i ) { CHECK_STREAM_PRECOND i = (signed short)input_int(); return *this; } /*! \overload Reads an unsigned \c short integer \a i from the stream and returns a reference to the stream. See flags() for an explanation of the expected input format. */ QTextStream &QTextStream::operator>>( unsigned short &i ) { CHECK_STREAM_PRECOND i = (unsigned short)input_int(); return *this; } /*! \overload diff --git a/qmake/tools/qucom.cpp b/qmake/tools/qucom.cpp index 6086a79..658da97 100644 --- a/qmake/tools/qucom.cpp +++ b/qmake/tools/qucom.cpp @@ -1,668 +1,544 @@ /**************************************************************************** ** $Id$ ** ** Implementation of the QUcom classes ** ** Created : 990101 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qucom_p.h" // Standard types // {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} const QUuid TID_QUType_Null( 0xde56510e, 0x4e9f, 0x4b76, 0xa3, 0xc2, 0xd1, 0xe2, 0xef, 0x42, 0xf1, 0xac ); const QUuid *QUType_Null::uuid() const { return &TID_QUType_Null; } const char *QUType_Null::desc() const { return "null"; } bool QUType_Null::canConvertFrom( QUObject *, QUType * ) { return FALSE; } bool QUType_Null::canConvertTo( QUObject *, QUType * ) { return FALSE; } bool QUType_Null::convertFrom( QUObject *, QUType * ) { return FALSE; } bool QUType_Null::convertTo( QUObject *, QUType * ) { return FALSE; } void QUType_Null::clear( QUObject *) {}; int QUType_Null::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_Null::serializeFrom( QUObject *, QUBuffer * ) { return 0; }; QUType_Null static_QUType_Null; // {7EE17B08-5419-47e2-9776-8EEA112DCAEC} const QUuid TID_QUType_enum( 0x7ee17b08, 0x5419, 0x47e2, 0x97, 0x76, 0x8e, 0xea, 0x11, 0x2d, 0xca, 0xec ); QUType_enum static_QUType_enum; const QUuid *QUType_enum::uuid() const { return &TID_QUType_enum; } const char *QUType_enum::desc() const { return "enum"; } void QUType_enum::set( QUObject *o, int v ) { o->payload.i = v; o->type = this; } bool QUType_enum::canConvertFrom( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? return TRUE; return t->canConvertTo( o, this ); } bool QUType_enum::canConvertTo( QUObject * /*o*/, QUType *t ) { return isEqual( t, &static_QUType_int ); } bool QUType_enum::convertFrom( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? ; else return t->convertTo( o, this ); o->type = this; return TRUE; } bool QUType_enum::convertTo( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_int ) ) { o->type = &static_QUType_int; return TRUE; } return FALSE; } int QUType_enum::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_enum::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // {8AC26448-5AB4-49eb-968C-8F30AB13D732} const QUuid TID_QUType_ptr( 0x8ac26448, 0x5ab4, 0x49eb, 0x96, 0x8c, 0x8f, 0x30, 0xab, 0x13, 0xd7, 0x32 ); QUType_ptr static_QUType_ptr; const QUuid *QUType_ptr::uuid() const { return &TID_QUType_ptr; } const char *QUType_ptr::desc() const { return "ptr"; } void QUType_ptr::set( QUObject *o, const void* v ) { o->payload.ptr = (void*) v; o->type = this; } bool QUType_ptr::canConvertFrom( QUObject *o, QUType *t ) { return t->canConvertTo( o, this ); } bool QUType_ptr::canConvertTo( QUObject *, QUType * ) { return FALSE; } bool QUType_ptr::convertFrom( QUObject *o, QUType *t ) { return t->convertTo( o, this ); } bool QUType_ptr::convertTo( QUObject *, QUType * ) { return FALSE; } int QUType_ptr::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_ptr::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // {97A2594D-6496-4402-A11E-55AEF2D4D25C} const QUuid TID_QUType_iface( 0x97a2594d, 0x6496, 0x4402, 0xa1, 0x1e, 0x55, 0xae, 0xf2, 0xd4, 0xd2, 0x5c ); QUType_iface static_QUType_iface; const QUuid *QUType_iface::uuid() const { return &TID_QUType_iface; } const char *QUType_iface::desc() const { return "UnknownInterface"; } void QUType_iface::set( QUObject *o, QUnknownInterface* iface ) { o->payload.iface = iface; o->type = this; } bool QUType_iface::canConvertFrom( QUObject *o, QUType *t ) { return t->canConvertTo( o, this ); } bool QUType_iface::canConvertTo( QUObject *, QUType * ) { return FALSE; } bool QUType_iface::convertFrom( QUObject *o, QUType *t ) { return t->convertTo( o, this ); } bool QUType_iface::convertTo( QUObject *, QUType * ) { return FALSE; } int QUType_iface::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_iface::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} const QUuid TID_QUType_idisp( 0x2f358164, 0xe28f, 0x4bf4, 0x9f, 0xa9, 0x4e, 0xc, 0xdc, 0xab, 0xa5, 0xb ); QUType_idisp static_QUType_idisp; const QUuid *QUType_idisp::uuid() const { return &TID_QUType_idisp; } const char *QUType_idisp::desc() const { return "DispatchInterface"; } void QUType_idisp::set( QUObject *o, QDispatchInterface* idisp ) { o->payload.idisp = idisp; o->type = this; } bool QUType_idisp::canConvertFrom( QUObject *o, QUType *t ) { return t->canConvertTo( o, this ); } bool QUType_idisp::canConvertTo( QUObject * /*o*/, QUType *t ) { return isEqual( t, &static_QUType_iface ); } bool QUType_idisp::convertFrom( QUObject *o, QUType *t ) { return t->convertTo( o, this ); } bool QUType_idisp::convertTo( QUObject *o, QUType *t ) { #ifndef QT_NO_COMPONENT if ( isEqual( t, &static_QUType_iface ) ) { o->payload.iface = (QUnknownInterface*)o->payload.idisp; o->type = &static_QUType_iface; return TRUE; } #endif return FALSE; } int QUType_idisp::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_idisp::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // {CA42115D-13D0-456c-82B5-FC10187F313E} const QUuid TID_QUType_bool( 0xca42115d, 0x13d0, 0x456c, 0x82, 0xb5, 0xfc, 0x10, 0x18, 0x7f, 0x31, 0x3e ); QUType_bool static_QUType_bool; const QUuid *QUType_bool::uuid() const { return &TID_QUType_bool; } const char *QUType_bool::desc() const { return "bool"; } void QUType_bool::set( QUObject *o, bool v ) { o->payload.b = v; o->type = this; } bool QUType_bool::canConvertFrom( QUObject *o, QUType *t ) { return t->canConvertTo( o, this ); } bool QUType_bool::canConvertTo( QUObject *, QUType * ) { return FALSE; } bool QUType_bool::convertFrom( QUObject *o, QUType *t ) { return t->convertTo( o, this ); } bool QUType_bool::convertTo( QUObject *, QUType * ) { return FALSE; } int QUType_bool::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_bool::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} const QUuid TID_QUType_int( 0x53c1f3be, 0x73c3, 0x4c7d, 0x9e, 0x5, 0xcc, 0xf0, 0x9e, 0xb6, 0x76, 0xb5 ); QUType_int static_QUType_int; const QUuid *QUType_int::uuid() const { return &TID_QUType_int; } const char *QUType_int::desc() const { return "int"; } void QUType_int::set( QUObject *o, int v ) { o->payload.i = v; o->type = this; } bool QUType_int::canConvertFrom( QUObject *o, QUType *t ) { - if ( isEqual( t, &static_QUType_double ) || - isEqual( t, &static_QUType_float ) ) + if ( isEqual( t, &static_QUType_double ) ) return TRUE; return t->canConvertTo( o, this ); } bool QUType_int::canConvertTo( QUObject * /*o*/, QUType *t ) { - return isEqual( t, &static_QUType_double ) || - isEqual( t, &static_QUType_float ); + return isEqual( t, &static_QUType_double ); } bool QUType_int::convertFrom( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_double ) ) o->payload.i = (long)o->payload.d; - else if ( isEqual( t, &static_QUType_float ) ) - o->payload.i = (long)o->payload.f; else return t->convertTo( o, this ); o->type = this; return TRUE; } bool QUType_int::convertTo( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_double ) ) { o->payload.d = (double)o->payload.i; o->type = &static_QUType_double; - } else if ( isEqual( t, &static_QUType_float ) ) { - o->payload.f = (float)o->payload.i; - o->type = &static_QUType_float; } else return FALSE; return TRUE; } int QUType_int::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_int::serializeFrom( QUObject *, QUBuffer * ) { return 0; } -// {5938712A-C496-11D5-8CB2-00C0F03BC0F3} -const QUuid TID_QUType_uint( 0x5938712a, 0xc496, 0x11d5, 0x8c, 0xb2, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3); -QUType_uint static_QUType_uint; -const QUuid *QUType_uint::uuid() const { return &TID_QUType_uint; } -const char *QUType_uint::desc() const { return "uint"; } - -void QUType_uint::set( QUObject *o, uint v ) -{ - o->payload.ui = v; - o->type = this; -} - -bool QUType_uint::canConvertFrom( QUObject *o, QUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool QUType_uint::canConvertTo( QUObject * /*o*/, QUType * /*t*/ ) -{ - return FALSE; -} - -bool QUType_uint::convertFrom( QUObject *o, QUType *t ) -{ - return t->convertTo( o, this ); -} - -bool QUType_uint::convertTo( QUObject * /*o*/, QUType * /*t*/ ) -{ - return FALSE; -} - -int QUType_uint::serializeTo( QUObject *, QUBuffer * ) -{ - return 0; -} - -int QUType_uint::serializeFrom( QUObject *, QUBuffer * ) -{ - return 0; -} - // {2D0974E5-0BA6-4ec2-8837-C198972CB48C} const QUuid TID_QUType_double( 0x2d0974e5, 0xba6, 0x4ec2, 0x88, 0x37, 0xc1, 0x98, 0x97, 0x2c, 0xb4, 0x8c ); QUType_double static_QUType_double; const QUuid *QUType_double::uuid() const { return &TID_QUType_double; } const char *QUType_double::desc() const {return "double"; } void QUType_double::set( QUObject *o, double v ) { o->payload.d = v; o->type = this; } bool QUType_double::canConvertFrom( QUObject *o, QUType *t ) { - if ( isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_float) ) + if ( isEqual( t, &static_QUType_int ) ) return TRUE; return t->canConvertTo( o, this ); } bool QUType_double::canConvertTo( QUObject * /*o*/, QUType *t ) { - return isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_float ); + return isEqual( t, &static_QUType_int ); } bool QUType_double::convertFrom( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_int ) ) o->payload.d = (double)o->payload.i; - else if ( isEqual( t, &static_QUType_float ) ) - o->payload.d = (double)o->payload.f; else return t->convertTo( o, this ); o->type = this; return TRUE; } bool QUType_double::convertTo( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_int ) ) { o->payload.i = (int) o->payload.d; o->type = &static_QUType_int; } else if ( isEqual( t, &static_QUType_double ) ) { o->payload.d = (double) o->payload.f; o->type = &static_QUType_double; } else return FALSE; return TRUE; } int QUType_double::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_double::serializeFrom( QUObject *, QUBuffer * ) { return 0; } - -// {544C5175-6993-4486-B04D-CEC4D21BF4B9 } -const QUuid TID_QUType_float( 0x544c5175, 0x6993, 0x4486, 0xb0, 0x4d, 0xce, 0xc4, 0xd2, 0x1b, 0xf4, 0xb9 ); -QUType_float static_QUType_float; -const QUuid *QUType_float::uuid() const { return &TID_QUType_float; } -const char *QUType_float::desc() const {return "float"; } - -void QUType_float::set( QUObject *o, float v ) -{ - o->payload.f = v; - o->type = this; -} - -bool QUType_float::canConvertFrom( QUObject *o, QUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_double ) ) - return TRUE; - - return t->canConvertTo( o, this ); -} - -bool QUType_float::canConvertTo( QUObject * /*o*/, QUType *t ) -{ - return isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_double ); -} - -bool QUType_float::convertFrom( QUObject *o, QUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) - o->payload.f = (float)o->payload.i; - else if ( isEqual( t, &static_QUType_double ) ) - o->payload.f = (float)o->payload.d; - else - return t->convertTo( o, this ); - - o->type = this; - return TRUE; -} - -bool QUType_float::convertTo( QUObject *o, QUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) { - o->payload.i = (int) o->payload.f; - o->type = &static_QUType_int; - } else if ( isEqual( t, &static_QUType_double ) ) { - o->payload.d = (double) o->payload.f; - o->type = &static_QUType_double; - } else - return FALSE; - return TRUE; -} - -int QUType_float::serializeTo( QUObject *, QUBuffer * ) -{ - return 0; -} - -int QUType_float::serializeFrom( QUObject *, QUBuffer * ) -{ - return 0; -} - // {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} const QUuid TID_QUType_charstar( 0xefcdd1d4, 0x77a3, 0x4b8e, 0x8d, 0x46, 0xdc, 0x14, 0xb8, 0xd3, 0x93, 0xe9 ); QUType_charstar static_QUType_charstar; const QUuid *QUType_charstar::uuid() const { return &TID_QUType_charstar; } const char *QUType_charstar::desc() const { return "char*"; } void QUType_charstar::set( QUObject *o, const char* v, bool take ) { if ( take ) { if ( v ) { o->payload.charstar.ptr = new char[ strlen(v) + 1 ]; strcpy( o->payload.charstar.ptr, v ); } else { o->payload.charstar.ptr = 0; } o->payload.charstar.owner = TRUE; } else { o->payload.charstar.ptr = (char*) v; o->payload.charstar.owner = FALSE; } o->type = this; } bool QUType_charstar::canConvertFrom( QUObject *o, QUType *t ) { return t->canConvertTo( o, this ); } bool QUType_charstar::canConvertTo( QUObject *, QUType * ) { return FALSE; } bool QUType_charstar::convertFrom( QUObject *o, QUType *t ) { return t->convertTo( o, this ); } bool QUType_charstar::convertTo( QUObject *, QUType * ) { return FALSE; } void QUType_charstar::clear( QUObject *o ) { if ( o->payload.charstar.owner ) delete [] o->payload.charstar.ptr; o->payload.charstar.ptr = 0; } int QUType_charstar::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_charstar::serializeFrom( QUObject *, QUBuffer * ) { return 0; } // Qt specific types // {44C2A547-01E7-4e56-8559-35AF9D2F42B7} const QUuid TID_QUType_QString( 0x44c2a547, 0x1e7, 0x4e56, 0x85, 0x59, 0x35, 0xaf, 0x9d, 0x2f, 0x42, 0xb7 ); QUType_QString static_QUType_QString; const QUuid *QUType_QString::uuid() const { return &TID_QUType_QString; } const char *QUType_QString::desc() const { return "QString"; } void QUType_QString::set( QUObject *o, const QString& v ) { o->payload.ptr = new QString( v ); o->type = this; } bool QUType_QString::canConvertFrom( QUObject *o, QUType *t ) { if ( isEqual( t, &static_QUType_charstar ) || isEqual( t, &static_QUType_double ) || - isEqual( t, &static_QUType_float ) || isEqual( t, &static_QUType_int ) ) return TRUE; return t->canConvertTo( o, this ); } bool QUType_QString::canConvertTo( QUObject * /*o*/, QUType *t ) { return isEqual( t, &static_QUType_charstar ) || isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_double ) || - isEqual( t, &static_QUType_float ); + isEqual( t, &static_QUType_double ); } bool QUType_QString::convertFrom( QUObject *o, QUType *t ) { QString *str = 0; if ( isEqual( t, &static_QUType_charstar ) ) str = new QString( o->payload.charstar.ptr ); else if ( isEqual( t, &static_QUType_double ) ) str = new QString( QString::number( o->payload.d ) ); - else if ( isEqual( t, &static_QUType_float ) ) - str = new QString( QString::number( o->payload.f ) ); else if ( isEqual( t, &static_QUType_int ) ) str = new QString( QString::number( o->payload.i ) ); else return t->convertTo( o, this ); o->type->clear( o ); o->payload.ptr = str; o->type = this; return TRUE; } bool QUType_QString::convertTo( QUObject *o, QUType *t ) { QString *str = (QString *)o->payload.ptr; if ( isEqual( t, &static_QUType_charstar ) ) { o->payload.charstar.ptr = qstrdup( str->local8Bit().data() ); o->payload.charstar.owner = TRUE; o->type = &static_QUType_charstar; } else if ( isEqual( t, &static_QUType_int ) ) { o->payload.l = str->toLong(); o->type = &static_QUType_int; } else if ( isEqual( t, &static_QUType_double ) ) { o->payload.d = str->toDouble(); o->type = &static_QUType_double; - } else if ( isEqual( t, &static_QUType_float ) ) { - o->payload.d = str->toFloat(); - o->type = &static_QUType_float; } else { return FALSE; } delete str; return TRUE; } int QUType_QString::serializeTo( QUObject *, QUBuffer * ) { return 0; } int QUType_QString::serializeFrom( QUObject *, QUBuffer * ) { return 0; } void QUType_QString::clear( QUObject *o ) { delete (QString*)o->payload.ptr; o->payload.ptr = 0; } diff --git a/qmake/tools/qwaitcondition_unix.cpp b/qmake/tools/qwaitcondition_unix.cpp index 99c1014..6684617 100644 --- a/qmake/tools/qwaitcondition_unix.cpp +++ b/qmake/tools/qwaitcondition_unix.cpp @@ -1,310 +1,315 @@ /**************************************************************************** ** $Id$ ** ** QWaitCondition class for Unix ** ** Created : 20010725 ** ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition ** licenses may use this file in accordance with the Qt Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about Qt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for QPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #if defined(QT_THREAD_SUPPORT) #include "qplatformdefs.h" typedef pthread_mutex_t Q_MUTEX_T; #include "qwaitcondition.h" #include "qmutex.h" #include "qmutex_p.h" #include <errno.h> #include <string.h> struct QWaitConditionPrivate { pthread_cond_t cond; }; /*! \class QWaitCondition qwaitcondition.h \threadsafe \brief The QWaitCondition class allows waiting/waking for conditions between threads. \ingroup thread \ingroup environment QWaitConditions allow a thread to tell other threads that some sort of condition has been met; one or many threads can block waiting for a QWaitCondition to set a condition with wakeOne() or wakeAll(). Use wakeOne() to wake one randomly selected event or wakeAll() to wake them all. For example, say we have three tasks that should be performed every time the user presses a key; each task could be split into a thread, each of which would have a run() body like this: \code QWaitCondition key_pressed; for (;;) { key_pressed.wait(); // This is a QWaitCondition global variable // Key was pressed, do something interesting do_something(); } \endcode A fourth thread would read key presses and wake the other three threads up every time it receives one, like this: \code QWaitCondition key_pressed; for (;;) { getchar(); // Causes any thread in key_pressed.wait() to return from // that method and continue processing key_pressed.wakeAll(); } \endcode Note that the order the three threads are woken up in is undefined, and that if some or all of the threads are still in do_something() when the key is pressed, they won't be woken up (since they're not waiting on the condition variable) and so the task will not be performed for that key press. This can be avoided by, for example, doing something like this: \code QMutex mymutex; QWaitCondition key_pressed; int mycount=0; // Worker thread code for (;;) { key_pressed.wait(); // This is a QWaitCondition global variable mymutex.lock(); mycount++; mymutex.unlock(); do_something(); mymutex.lock(); mycount--; mymutex.unlock(); } // Key reading thread code for (;;) { getchar(); mymutex.lock(); // Sleep until there are no busy worker threads - while( count > 0 ) { + while( mycount > 0 ) { mymutex.unlock(); sleep( 1 ); mymutex.lock(); } mymutex.unlock(); key_pressed.wakeAll(); } \endcode The mutexes are necessary because the results of two threads attempting to change the value of the same variable simultaneously are unpredictable. */ /*! Constructs a new event signalling, i.e. wait condition, object. */ QWaitCondition::QWaitCondition() { d = new QWaitConditionPrivate; int ret = pthread_cond_init(&d->cond, NULL); #ifdef QT_CHECK_RANGE if (ret) qWarning( "Wait condition init failure: %s", strerror( ret ) ); #endif } /*! Deletes the event signalling, i.e. wait condition, object. */ QWaitCondition::~QWaitCondition() { int ret = pthread_cond_destroy(&d->cond); if (ret) { #ifdef QT_CHECK_RANGE qWarning( "Wait condition destroy failure: %s", strerror( ret ) ); #endif // seems we have threads waiting on us, lets wake them up pthread_cond_broadcast(&d->cond); } delete d; } /*! This wakes one thread waiting on the QWaitCondition. The thread that is woken up depends on the operating system's scheduling policies, and cannot be controlled or predicted. \sa wakeAll() */ void QWaitCondition::wakeOne() { int ret = pthread_cond_signal(&d->cond); #ifdef QT_CHECK_RANGE if (ret) qWarning("Wait condition wakeOne failure: %s", strerror(ret)); #endif } /*! This wakes all threads waiting on the QWaitCondition. The order in which the threads are woken up depends on the operating system's scheduling policies, and cannot be controlled or predicted. \sa wakeOne() */ void QWaitCondition::wakeAll() { int ret = pthread_cond_broadcast(&d->cond); #ifdef QT_CHECK_RANGE if (ret) qWarning("Wait condition wakeAll failure: %s", strerror(ret)); #endif } /*! Wait on the thread event object. The thread calling this will block until either of these conditions is met: \list \i Another thread signals it using wakeOne() or wakeAll(). This function will return TRUE in this case. \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return FALSE if the wait timed out. \endlist \sa wakeOne(), wakeAll() */ bool QWaitCondition::wait(unsigned long time) { - pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t mutex; + pthread_mutex_init( &mutex, 0 ); + pthread_mutex_lock( &mutex ); int ret; if (time != ULONG_MAX) { struct timeval tv; gettimeofday(&tv, 0); timespec ti; - ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000; + ti.tv_nsec = ( tv.tv_usec + ( time % 1000 ) * 1000 ) * 1000; ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 ); ti.tv_nsec %= 1000000000; ret = pthread_cond_timedwait(&d->cond, &mutex, &ti); } else ret = pthread_cond_wait(&d->cond, &mutex); #ifdef QT_CHECK_RANGE if (ret && ret != ETIMEDOUT) qWarning("Wait condition wait failure: %s",strerror(ret)); #endif + pthread_mutex_unlock( &mutex ); + pthread_mutex_destroy( &mutex ); + return (ret == 0); } /*! \overload Release the locked \a mutex and wait on the thread event object. The \a mutex must be initially locked by the calling thread. If \a mutex is not in a locked state, this function returns immediately. If \a mutex is a recursive mutex, this function returns immediately. The \a mutex will be unlocked, and the calling thread will block until either of these conditions is met: \list \i Another thread signals it using wakeOne() or wakeAll(). This function will return TRUE in this case. \i \a time milliseconds has elapsed. If \a time is ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return FALSE if the wait timed out. \endlist The mutex will be returned to the same locked state. This function is provided to allow the atomic transition from the locked state to the wait state. \sa wakeOne(), wakeAll() */ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) { if (! mutex) return FALSE; if (mutex->d->type() == Q_MUTEX_RECURSIVE) { #ifdef QT_CHECK_RANGE qWarning("Wait condition warning: using recursive mutexes with\n" " wait conditions is undefined!"); #endif return FALSE; } int ret; if (time != ULONG_MAX) { struct timeval tv; gettimeofday(&tv, 0); timespec ti; - ti.tv_nsec = (tv.tv_usec * 1000) + (time % 1000) * 1000; + ti.tv_nsec = ( tv.tv_usec + ( time % 1000 ) * 1000 ) * 1000; ti.tv_sec = tv.tv_sec + (time / 1000) + ( ti.tv_nsec / 1000000000 ); ti.tv_nsec %= 1000000000; ret = pthread_cond_timedwait(&d->cond, &mutex->d->handle, &ti); } else ret = pthread_cond_wait(&d->cond, &mutex->d->handle); #ifdef QT_CHECK_RANGE if (ret && ret != ETIMEDOUT) qWarning("Wait condition wait failure: %s",strerror(ret)); #endif return (ret == 0); } #endif // QT_THREAD_SUPPORT |