profileevaluator.cpp 126 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11
12
13
14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
con's avatar
con committed
25
26
27
28
29
30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
con's avatar
con committed
31
**
32
**************************************************************************/
33

con's avatar
con committed
34
#include "profileevaluator.h"
35
36

#include "profileparser.h"
37
#include "ioutils.h"
con's avatar
con committed
38
39

#include <QtCore/QByteArray>
40
#include <QtCore/QDateTime>
con's avatar
con committed
41
42
43
44
45
46
47
48
49
50
51
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QList>
#include <QtCore/QRegExp>
#include <QtCore/QSet>
#include <QtCore/QStack>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
52
#ifdef PROEVALUATOR_THREAD_SAFE
53
54
# include <QtCore/QThreadPool>
#endif
con's avatar
con committed
55

56
57
58
#ifdef Q_OS_UNIX
#include <unistd.h>
#include <sys/utsname.h>
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
59
#else
60
61
62
63
64
#include <Windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>

con's avatar
con committed
65
66
#ifdef Q_OS_WIN32
#define QT_POPEN _popen
67
#define QT_PCLOSE _pclose
con's avatar
con committed
68
69
#else
#define QT_POPEN popen
70
#define QT_PCLOSE pclose
con's avatar
con committed
71
72
#endif

73
74
using namespace ProFileEvaluatorInternal;

con's avatar
con committed
75
76
QT_BEGIN_NAMESPACE

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
77
78
79
using namespace ProStringConstants;


80
81
#define fL1S(s) QString::fromLatin1(s)

82
83
///////////////////////////////////////////////////////////////////////
//
84
// ProFileOption
85
86
87
//
///////////////////////////////////////////////////////////////////////

88
ProFileOption::ProFileOption()
89
90
91
92
93
94
95
96
{
#ifdef Q_OS_WIN
    dirlist_sep = QLatin1Char(';');
    dir_sep = QLatin1Char('\\');
#else
    dirlist_sep = QLatin1Char(':');
    dir_sep = QLatin1Char('/');
#endif
97
    qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").data());
98

99
100
101
    host_mode = HOST_UNKNOWN_MODE;
    target_mode = TARG_UNKNOWN_MODE;

102
103
104
105
106
107
108
109
110
#ifdef PROEVALUATOR_THREAD_SAFE
    base_inProgress = false;
#endif
}

ProFileOption::~ProFileOption()
{
}

111
112
void ProFileOption::setCommandLineArguments(const QStringList &args)
{
113
114
    QStringList _precmds, _preconfigs, _postcmds, _postconfigs;
    bool after = false;
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
    bool isConf = false;
    foreach (const QString &arg, args) {
        if (isConf) {
            isConf = false;
            if (after)
                _postconfigs << arg;
            else
                _preconfigs << arg;
        } else if (arg.startsWith(QLatin1Char('-'))) {
            if (arg == QLatin1String("-after")) {
                after = true;
            } else if (arg == QLatin1String("-config")) {
                isConf = true;
            } else if (arg == QLatin1String("-win32")) {
130
                host_mode = HOST_WIN_MODE;
131
132
                target_mode = TARG_WIN_MODE;
            } else if (arg == QLatin1String("-unix")) {
133
                host_mode = HOST_UNIX_MODE;
134
135
                target_mode = TARG_UNIX_MODE;
            } else if (arg == QLatin1String("-macx")) {
136
                host_mode = HOST_MACX_MODE;
137
                target_mode = TARG_MACX_MODE;
138
            }
139
140
141
142
143
        } else if (arg.contains(QLatin1Char('='))) {
            if (after)
                _postcmds << arg;
            else
                _precmds << arg;
144
145
        }
    }
146
147
148
149
150
151
152

    if (!_preconfigs.isEmpty())
        _precmds << (fL1S("CONFIG += ") + _preconfigs.join(fL1S(" ")));
    precmds = _precmds.join(fL1S("\n"));
    if (!_postconfigs.isEmpty())
        _postcmds << (fL1S("CONFIG += ") + _postconfigs.join(fL1S(" ")));
    postcmds = _postcmds.join(fL1S("\n"));
153
154
155

    if (host_mode != HOST_UNKNOWN_MODE)
        applyHostMode();
156
157
}

158
void ProFileOption::applyHostMode()
159
{
160
161
162
163
164
   if (host_mode == HOST_WIN_MODE) {
       dir_sep = fL1S("\\");
   } else {
       dir_sep = fL1S("/");
   }
165
166
}

con's avatar
con committed
167
168
169
170
171
172
///////////////////////////////////////////////////////////////////////
//
// ProFileEvaluator::Private
//
///////////////////////////////////////////////////////////////////////

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
173
class ProFileEvaluator::Private
con's avatar
con committed
174
175
{
public:
176
    static void initStatics();
177
    Private(ProFileEvaluator *q_, ProFileOption *option, ProFileParser *parser,
178
            ProFileEvaluatorHandler *handler);
179
    ~Private();
con's avatar
con committed
180

181
182
    ProFileEvaluator *q;

183
184
185
186
187
188
189
190
    enum VisitReturn {
        ReturnFalse,
        ReturnTrue,
        ReturnBreak,
        ReturnNext,
        ReturnReturn
    };

191
192
193
    static ALWAYS_INLINE uint getBlockLen(const ushort *&tokPtr);
    ProString getStr(const ushort *&tokPtr);
    ProString getHashStr(const ushort *&tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
194
    void evaluateExpression(const ushort *&tokPtr, ProStringList *ret, bool joined);
195
196
    static ALWAYS_INLINE void skipStr(const ushort *&tokPtr);
    static ALWAYS_INLINE void skipHashStr(const ushort *&tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
197
    void skipExpression(const ushort *&tokPtr);
198

199
    void visitCmdLine(const QString &cmds);
200
201
    VisitReturn visitProFile(ProFile *pro, ProFileEvaluatorHandler::EvalFileType type,
                             ProFileEvaluator::LoadFlags flags);
202
    VisitReturn visitProBlock(ProFile *pro, const ushort *tokPtr);
203
    VisitReturn visitProBlock(const ushort *tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
204
    VisitReturn visitProLoop(const ProString &variable, const ushort *exprPtr,
205
206
                             const ushort *tokPtr);
    void visitProFunctionDef(ushort tok, const ProString &name, const ushort *tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
207
    void visitProVariable(ushort tok, const ProStringList &curr, const ushort *&tokPtr);
con's avatar
con committed
208

209
    static inline const ProString &map(const ProString &var);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
210
211
212
213
214
    QHash<ProString, ProStringList> *findValues(const ProString &variableName,
                                                QHash<ProString, ProStringList>::Iterator *it);
    ProStringList &valuesRef(const ProString &variableName);
    ProStringList valuesDirect(const ProString &variableName) const;
    ProStringList values(const ProString &variableName) const;
215
    QString propertyValue(const QString &val, bool complain) const;
con's avatar
con committed
216

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
217
    static ProStringList split_value_list(const QString &vals);
con's avatar
con committed
218
    bool isActiveConfig(const QString &config, bool regex = false);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
219
    ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
220
    ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
221
    ProStringList evaluateExpandFunction(const ProString &function, const ProString &arguments);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
222
223
    ProStringList evaluateExpandFunction(const ProString &function, const ushort *&tokPtr);
    ProStringList evaluateExpandFunction(const ProString &function, const ProStringList &args);
224
    void evalError(const QString &msg) const;
con's avatar
con committed
225
226

    QString currentFileName() const;
227
    QString currentDirectory() const;
con's avatar
con committed
228
    ProFile *currentProFile() const;
229
230
    QString resolvePath(const QString &fileName) const
        { return IoUtils::resolvePath(currentDirectory(), fileName); }
con's avatar
con committed
231

232
    VisitReturn evaluateConditionalFunction(const ProString &function, const ProString &arguments);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
233
234
    VisitReturn evaluateConditionalFunction(const ProString &function, const ushort *&tokPtr);
    VisitReturn evaluateConditionalFunction(const ProString &function, const ProStringList &args);
235
236
237
238
    bool evaluateFileDirect(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type,
                            ProFileEvaluator::LoadFlags flags);
    bool evaluateFile(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type,
                      ProFileEvaluator::LoadFlags flags);
239
    bool evaluateFeatureFile(const QString &fileName);
240
    enum EvalIntoMode { EvalProOnly, EvalWithDefaults, EvalWithSetup };
241
    bool evaluateFileInto(const QString &fileName, ProFileEvaluatorHandler::EvalFileType type,
242
243
                          QHash<ProString, ProStringList> *values, FunctionDefs *defs,
                          EvalIntoMode mode); // values are output-only, defs are input-only
con's avatar
con committed
244

245
    static ALWAYS_INLINE VisitReturn returnBool(bool b)
246
        { return b ? ReturnTrue : ReturnFalse; }
247

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
248
    QList<ProStringList> prepareFunctionArgs(const ushort *&tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
249
    QList<ProStringList> prepareFunctionArgs(const ProString &arguments);
250
    ProStringList evaluateFunction(const FunctionDef &func, const QList<ProStringList> &argumentsList, bool *ok);
251
252
    VisitReturn evaluateBoolFunction(const FunctionDef &func, const QList<ProStringList> &argumentsList,
                                     const ProString &function);
253

254
255
256
    bool modesForGenerator(const QString &gen,
            ProFileOption::HOST_MODE *host_mode, ProFileOption::TARG_MODE *target_mode) const;
    void validateModes() const;
257
258
    QStringList qmakeMkspecPaths() const;
    QStringList qmakeFeaturePaths() const;
con's avatar
con committed
259

260
261
    QString sysrootify(const QString &path, const QString &baseDir) const;

262
    int m_skipLevel;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
263
    int m_loopLevel; // To report unexpected break() and next()s
264
    bool m_cumulative;
265
266
267
268
269
270
271
272
273
274
275

    struct Location {
        Location() : pro(0), line(0) {}
        Location(ProFile *_pro, int _line) : pro(_pro), line(_line) {}
        ProFile *pro;
        int line;
    };

    Location m_current; // Currently evaluated location
    QStack<Location> m_locationStack; // All execution location changes
    QStack<ProFile *> m_profileStack; // Includes only
con's avatar
con committed
276

277
    QString m_outputDir;
con's avatar
con committed
278

279
    int m_listCount;
280
    FunctionDefs m_functionDefs;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
281
282
283
284
    ProStringList m_returnValue;
    QStack<QHash<ProString, ProStringList> > m_valuemapStack;         // VariableName must be us-ascii, the content however can be non-us-ascii.
    QHash<const ProFile*, QHash<ProString, ProStringList> > m_filevaluemap; // Variables per include file
    QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
285

286
    ProFileOption *m_option;
287
    ProFileParser *m_parser;
288
    ProFileEvaluatorHandler *m_handler;
289
290

    enum ExpandFunc {
291
        E_INVALID = 0, E_MEMBER, E_FIRST, E_LAST, E_SIZE, E_CAT, E_FROMFILE, E_EVAL, E_LIST,
292
293
294
295
296
297
298
        E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
        E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND,
        E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE,
        E_REPLACE
    };

    enum TestFunc {
299
        T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
300
301
        T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
        T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
302
        T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF
303
304
305
306
307
308
309
310
311
312
313
    };

    enum VarName {
        V_LITERAL_DOLLAR, V_LITERAL_HASH, V_LITERAL_WHITESPACE,
        V_DIRLIST_SEPARATOR, V_DIR_SEPARATOR,
        V_OUT_PWD, V_PWD, V_IN_PWD,
        V__FILE_, V__LINE_, V__PRO_FILE_, V__PRO_FILE_PWD_,
        V_QMAKE_HOST_arch, V_QMAKE_HOST_name, V_QMAKE_HOST_os,
        V_QMAKE_HOST_version, V_QMAKE_HOST_version_string,
        V__DATE_, V__QMAKE_CACHE_
    };
con's avatar
con committed
314
315
};

316
317
static struct {
    QString field_sep;
318
319
320
321
322
323
    QString strtrue;
    QString strfalse;
    QString strunix;
    QString strmacx;
    QString strmac;
    QString strwin32;
324
    QString strsymbian;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
325
326
    ProString strCONFIG;
    ProString strARGS;
327
328
329
330
    QString strDot;
    QString strDotDot;
    QString strever;
    QString strforever;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
331
332
    ProString strTEMPLATE;
    ProString strQMAKE_DIR_SEP;
333
    QHash<ProString, int> expands;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
334
335
336
    QHash<ProString, int> functions;
    QHash<ProString, int> varList;
    QHash<ProString, ProString> varMap;
337
    QRegExp reg_variableName;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
338
    ProStringList fakeValue;
339
340
341
342
343
344
345
346
} statics;

void ProFileEvaluator::Private::initStatics()
{
    if (!statics.field_sep.isNull())
        return;

    statics.field_sep = QLatin1String(" ");
347
348
349
350
351
352
    statics.strtrue = QLatin1String("true");
    statics.strfalse = QLatin1String("false");
    statics.strunix = QLatin1String("unix");
    statics.strmacx = QLatin1String("macx");
    statics.strmac = QLatin1String("mac");
    statics.strwin32 = QLatin1String("win32");
353
    statics.strsymbian = QLatin1String("symbian");
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
354
355
    statics.strCONFIG = ProString("CONFIG");
    statics.strARGS = ProString("ARGS");
356
357
358
359
    statics.strDot = QLatin1String(".");
    statics.strDotDot = QLatin1String("..");
    statics.strever = QLatin1String("ever");
    statics.strforever = QLatin1String("forever");
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
360
361
    statics.strTEMPLATE = ProString("TEMPLATE");
    statics.strQMAKE_DIR_SEP = ProString("QMAKE_DIR_SEP");
362
363
364

    statics.reg_variableName.setPattern(QLatin1String("\\$\\(.*\\)"));
    statics.reg_variableName.setMinimal(true);
365

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
366
367
    statics.fakeValue.detach(); // It has to have a unique begin() value

368
369
370
371
372
373
374
    static const struct {
        const char * const name;
        const ExpandFunc func;
    } expandInits[] = {
        { "member", E_MEMBER },
        { "first", E_FIRST },
        { "last", E_LAST },
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
375
        { "size", E_SIZE },
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
        { "cat", E_CAT },
        { "fromfile", E_FROMFILE },
        { "eval", E_EVAL },
        { "list", E_LIST },
        { "sprintf", E_SPRINTF },
        { "join", E_JOIN },
        { "split", E_SPLIT },
        { "basename", E_BASENAME },
        { "dirname", E_DIRNAME },
        { "section", E_SECTION },
        { "find", E_FIND },
        { "system", E_SYSTEM },
        { "unique", E_UNIQUE },
        { "quote", E_QUOTE },
        { "escape_expand", E_ESCAPE_EXPAND },
        { "upper", E_UPPER },
        { "lower", E_LOWER },
        { "re_escape", E_RE_ESCAPE },
        { "files", E_FILES },
        { "prompt", E_PROMPT }, // interactive, so cannot be implemented
        { "replace", E_REPLACE }
    };
    for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
399
        statics.expands.insert(ProString(expandInits[i].name), expandInits[i].func);
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

    static const struct {
        const char * const name;
        const TestFunc func;
    } testInits[] = {
        { "requires", T_REQUIRES },
        { "greaterThan", T_GREATERTHAN },
        { "lessThan", T_LESSTHAN },
        { "equals", T_EQUALS },
        { "isEqual", T_EQUALS },
        { "exists", T_EXISTS },
        { "export", T_EXPORT },
        { "clear", T_CLEAR },
        { "unset", T_UNSET },
        { "eval", T_EVAL },
        { "CONFIG", T_CONFIG },
        { "if", T_IF },
        { "isActiveConfig", T_CONFIG },
        { "system", T_SYSTEM },
        { "return", T_RETURN },
        { "break", T_BREAK },
        { "next", T_NEXT },
        { "defined", T_DEFINED },
        { "contains", T_CONTAINS },
        { "infile", T_INFILE },
        { "count", T_COUNT },
        { "isEmpty", T_ISEMPTY },
        { "load", T_LOAD },
        { "include", T_INCLUDE },
        { "debug", T_DEBUG },
        { "message", T_MESSAGE },
        { "warning", T_MESSAGE },
        { "error", T_MESSAGE },
    };
    for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
435
        statics.functions.insert(ProString(testInits[i].name), testInits[i].func);
436
437
438
439
440
441
442
443
444
445
446

    static const char * const names[] = {
        "LITERAL_DOLLAR", "LITERAL_HASH", "LITERAL_WHITESPACE",
        "DIRLIST_SEPARATOR", "DIR_SEPARATOR",
        "OUT_PWD", "PWD", "IN_PWD",
        "_FILE_", "_LINE_", "_PRO_FILE_", "_PRO_FILE_PWD_",
        "QMAKE_HOST.arch", "QMAKE_HOST.name", "QMAKE_HOST.os",
        "QMAKE_HOST.version", "QMAKE_HOST.version_string",
        "_DATE_", "_QMAKE_CACHE_"
    };
    for (unsigned i = 0; i < sizeof(names)/sizeof(names[0]); ++i)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
447
        statics.varList.insert(ProString(names[i]), i);
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472

    static const struct {
        const char * const oldname, * const newname;
    } mapInits[] = {
        { "INTERFACES", "FORMS" },
        { "QMAKE_POST_BUILD", "QMAKE_POST_LINK" },
        { "TARGETDEPS", "POST_TARGETDEPS" },
        { "LIBPATH", "QMAKE_LIBDIR" },
        { "QMAKE_EXT_MOC", "QMAKE_EXT_CPP_MOC" },
        { "QMAKE_MOD_MOC", "QMAKE_H_MOD_MOC" },
        { "QMAKE_LFLAGS_SHAPP", "QMAKE_LFLAGS_APP" },
        { "PRECOMPH", "PRECOMPILED_HEADER" },
        { "PRECOMPCPP", "PRECOMPILED_SOURCE" },
        { "INCPATH", "INCLUDEPATH" },
        { "QMAKE_EXTRA_WIN_COMPILERS", "QMAKE_EXTRA_COMPILERS" },
        { "QMAKE_EXTRA_UNIX_COMPILERS", "QMAKE_EXTRA_COMPILERS" },
        { "QMAKE_EXTRA_WIN_TARGETS", "QMAKE_EXTRA_TARGETS" },
        { "QMAKE_EXTRA_UNIX_TARGETS", "QMAKE_EXTRA_TARGETS" },
        { "QMAKE_EXTRA_UNIX_INCLUDES", "QMAKE_EXTRA_INCLUDES" },
        { "QMAKE_EXTRA_UNIX_VARIABLES", "QMAKE_EXTRA_VARIABLES" },
        { "QMAKE_RPATH", "QMAKE_LFLAGS_RPATH" },
        { "QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH" },
        { "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" }
    };
    for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
473
474
        statics.varMap.insert(ProString(mapInits[i].oldname),
                              ProString(mapInits[i].newname));
475
476
}

477
const ProString &ProFileEvaluator::Private::map(const ProString &var)
478
{
479
480
    QHash<ProString, ProString>::ConstIterator it = statics.varMap.constFind(var);
    return (it != statics.varMap.constEnd()) ? it.value() : var;
481
482
483
}


484
ProFileEvaluator::Private::Private(ProFileEvaluator *q_, ProFileOption *option,
485
486
                                   ProFileParser *parser, ProFileEvaluatorHandler *handler)
  : q(q_), m_option(option), m_parser(parser), m_handler(handler)
con's avatar
con committed
487
{
488
489
490
    // So that single-threaded apps don't have to call initialize() for now.
    initStatics();

491
    // Configuration, more or less
492
    m_cumulative = true;
493
494

    // Evaluator state
495
    m_skipLevel = 0;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
496
    m_loopLevel = 0;
497
    m_listCount = 0;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
498
    m_valuemapStack.push(QHash<ProString, ProStringList>());
con's avatar
con committed
499
500
}

501
502
503
504
ProFileEvaluator::Private::~Private()
{
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
505
506
//////// Evaluator tools /////////

507
508
509
510
511
512
513
514
515
516
uint ProFileEvaluator::Private::getBlockLen(const ushort *&tokPtr)
{
    uint len = *tokPtr++;
    len |= (uint)*tokPtr++ << 16;
    return len;
}

ProString ProFileEvaluator::Private::getStr(const ushort *&tokPtr)
{
    uint len = *tokPtr++;
517
    ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, NoHash);
518
519
520
521
522
523
524
525
    tokPtr += len;
    return ret;
}

ProString ProFileEvaluator::Private::getHashStr(const ushort *&tokPtr)
{
    uint hash = getBlockLen(tokPtr);
    uint len = *tokPtr++;
526
    ProString ret(m_current.pro->items(), tokPtr - m_current.pro->tokPtr(), len, hash);
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
    tokPtr += len;
    return ret;
}

void ProFileEvaluator::Private::skipStr(const ushort *&tokPtr)
{
    uint len = *tokPtr++;
    tokPtr += len;
}

void ProFileEvaluator::Private::skipHashStr(const ushort *&tokPtr)
{
    tokPtr += 2;
    uint len = *tokPtr++;
    tokPtr += len;
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
544
545
546
// FIXME: this should not build new strings for direct sections.
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
547
548
{
    QString build;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
549
    ProStringList ret;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
550
551
    QStack<char> quote;

552
    const ushort SPACE = ' ';
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
    const ushort LPAREN = '(';
    const ushort RPAREN = ')';
    const ushort SINGLEQUOTE = '\'';
    const ushort DOUBLEQUOTE = '"';
    const ushort BACKSLASH = '\\';

    ushort unicode;
    const QChar *vals_data = vals.data();
    const int vals_len = vals.length();
    for (int x = 0, parens = 0; x < vals_len; x++) {
        unicode = vals_data[x].unicode();
        if (x != (int)vals_len-1 && unicode == BACKSLASH &&
            (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) {
            build += vals_data[x++]; //get that 'escape'
        } else if (!quote.isEmpty() && unicode == quote.top()) {
            quote.pop();
        } else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) {
            quote.push(unicode);
        } else if (unicode == RPAREN) {
            --parens;
        } else if (unicode == LPAREN) {
            ++parens;
        }

577
        if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
578
            ret << ProString(build, NoHash);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
579
580
581
582
583
584
            build.clear();
        } else {
            build += vals_data[x];
        }
    }
    if (!build.isEmpty())
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
585
        ret << ProString(build, NoHash);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
586
587
588
    return ret;
}

589
590
591
592
593
594
595
static void zipEmpty(ProStringList *value)
{
    for (int i = value->size(); --i >= 0;)
        if (value->at(i).isEmpty())
            value->remove(i);
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
596
static void insertUnique(ProStringList *varlist, const ProStringList &value)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
597
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
598
    foreach (const ProString &str, value)
599
        if (!str.isEmpty() && !varlist->contains(str))
600
            varlist->append(str);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
601
602
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
603
static void removeAll(ProStringList *varlist, const ProString &value)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
604
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
605
606
607
    for (int i = varlist->size(); --i >= 0; )
        if (varlist->at(i) == value)
            varlist->remove(i);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
608
609
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
610
static void removeEach(ProStringList *varlist, const ProStringList &value)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
611
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
612
    foreach (const ProString &str, value)
613
614
        if (!str.isEmpty())
            removeAll(varlist, str);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
615
616
617
618
619
620
621
622
623
624
625
}

static void replaceInList(ProStringList *varlist,
        const QRegExp &regexp, const QString &replace, bool global, QString &tmp)
{
    for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) {
        QString val = varit->toQString(tmp);
        QString copy = val; // Force detach and have a reference value
        val.replace(regexp, replace);
        if (!val.isSharedWith(copy)) {
            if (val.isEmpty()) {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
626
                varit = varlist->erase(varit);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
627
628
            } else {
                *varit = ProString(val);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
629
                ++varit;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
630
            }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
631
632
633
634
635
636
637
638
            if (!global)
                break;
        } else {
            ++varit;
        }
    }
}

639
640
641
642
static QString expandEnvVars(const QString &str)
{
    QString string = str;
    int rep;
643
    QRegExp reg_variableName = statics.reg_variableName; // Copy for thread safety
644
645
646
647
648
649
650
651
652
    while ((rep = reg_variableName.indexIn(string)) != -1)
        string.replace(rep, reg_variableName.matchedLength(),
                       QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_variableName.matchedLength() - 3).toLatin1().constData()).constData()));
    return string;
}

// This is braindead, but we want qmake compat
static QString fixPathToLocalOS(const QString &str)
{
653
    QString string = expandEnvVars(str);
654

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
655
    if (string.length() > 2 && string.at(0).isLetter() && string.at(1) == QLatin1Char(':'))
656
657
658
659
660
661
662
663
664
665
        string[0] = string[0].toLower();

#if defined(Q_OS_WIN32)
    string.replace(QLatin1Char('/'), QLatin1Char('\\'));
#else
    string.replace(QLatin1Char('\\'), QLatin1Char('/'));
#endif
    return string;
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
666
static bool isTrue(const ProString &_str, QString &tmp)
667
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
668
    const QString &str = _str.toQString(tmp);
669
670
671
    return !str.compare(statics.strtrue, Qt::CaseInsensitive) || str.toInt();
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
672
//////// Evaluator /////////
con's avatar
con committed
673

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
static ALWAYS_INLINE void addStr(
        const ProString &str, ProStringList *ret, bool &pending, bool joined)
{
    if (joined) {
        ret->last().append(str, &pending);
    } else {
        if (!pending) {
            pending = true;
            *ret << str;
        } else {
            ret->last().append(str);
        }
    }
}

static ALWAYS_INLINE void addStrList(
        const ProStringList &list, ushort tok, ProStringList *ret, bool &pending, bool joined)
{
    if (!list.isEmpty()) {
        if (joined) {
            ret->last().append(list, &pending, !(tok & TokQuoted));
        } else {
            if (tok & TokQuoted) {
                if (!pending) {
                    pending = true;
                    *ret << ProString();
                }
                ret->last().append(list);
            } else {
                if (!pending) {
                    // Another qmake bizzarity: if nothing is pending and the
                    // first element is empty, it will be eaten
                    if (!list.at(0).isEmpty()) {
                        // The common case
708
                        pending = true;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
709
710
711
712
713
714
715
                        *ret += list;
                        return;
                    }
                } else {
                    ret->last().append(list.at(0));
                }
                // This is somewhat slow, but a corner case
716
717
                for (int j = 1; j < list.size(); ++j) {
                    pending = true;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
718
                    *ret << list.at(j);
719
                }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
            }
        }
    }
}

void ProFileEvaluator::Private::evaluateExpression(
        const ushort *&tokPtr, ProStringList *ret, bool joined)
{
    if (joined)
        *ret << ProString();
    bool pending = false;
    forever {
        ushort tok = *tokPtr++;
        if (tok & TokNewStr)
            pending = false;
        ushort maskedTok = tok & TokMask;
        switch (maskedTok) {
        case TokLine:
738
            m_current.line = *tokPtr++;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
739
740
741
742
743
744
745
746
747
748
749
750
            break;
        case TokLiteral:
            addStr(getStr(tokPtr), ret, pending, joined);
            break;
        case TokHashLiteral:
            addStr(getHashStr(tokPtr), ret, pending, joined);
            break;
        case TokVariable:
            addStrList(values(map(getHashStr(tokPtr))), tok, ret, pending, joined);
            break;
        case TokProperty:
            addStr(ProString(propertyValue(
751
                    getStr(tokPtr).toQString(m_tmp1), true), NoHash), ret, pending, joined);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
            break;
        case TokEnvVar:
            addStrList(split_value_list(QString::fromLocal8Bit(qgetenv(
                    getStr(tokPtr).toQString(m_tmp1).toLatin1().constData()))), tok, ret, pending, joined);
            break;
        case TokFuncName: {
            ProString func = getHashStr(tokPtr);
            addStrList(evaluateExpandFunction(func, tokPtr), tok, ret, pending, joined);
            break; }
        default:
            tokPtr--;
            return;
        }
    }
}

void ProFileEvaluator::Private::skipExpression(const ushort *&pTokPtr)
{
    const ushort *tokPtr = pTokPtr;
    forever {
        ushort tok = *tokPtr++;
        switch (tok) {
        case TokLine:
775
            m_current.line = *tokPtr++;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
            break;
        case TokValueTerminator:
        case TokFuncTerminator:
            pTokPtr = tokPtr;
            return;
        case TokArgSeparator:
            break;
        default:
            switch (tok & TokMask) {
            case TokLiteral:
            case TokProperty:
            case TokEnvVar:
                skipStr(tokPtr);
                break;
            case TokHashLiteral:
            case TokVariable:
                skipHashStr(tokPtr);
                break;
            case TokFuncName:
                skipHashStr(tokPtr);
                pTokPtr = tokPtr;
                skipExpression(pTokPtr);
                tokPtr = pTokPtr;
                break;
            default:
                Q_ASSERT_X(false, "skipExpression", "Unrecognized token");
                break;
            }
        }
    }
}

808
809
810
811
812
813
814
815
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
        ProFile *pro, const ushort *tokPtr)
{
    m_current.pro = pro;
    m_current.line = 0;
    return visitProBlock(tokPtr);
}

816
817
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProBlock(
        const ushort *tokPtr)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
818
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
819
    ProStringList curr;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
820
    bool okey = true, or_op = false, invert = false;
821
    uint blockLen;
822
    VisitReturn ret = ReturnTrue;
823
824
825
    while (ushort tok = *tokPtr++) {
        switch (tok) {
        case TokLine:
826
            m_current.line = *tokPtr++;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
827
            continue;
828
829
830
831
        case TokAssign:
        case TokAppend:
        case TokAppendUnique:
        case TokRemove:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
832
833
834
835
        case TokReplace:
            visitProVariable(tok, curr, tokPtr);
            curr.clear();
            continue;
836
837
        case TokBranch:
            blockLen = getBlockLen(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
838
839
840
            if (m_cumulative) {
                if (!okey)
                    m_skipLevel++;
841
842
843
                ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue;
                tokPtr += blockLen;
                blockLen = getBlockLen(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
844
845
846
847
                if (!okey)
                    m_skipLevel--;
                else
                    m_skipLevel++;
848
849
                if ((ret == ReturnTrue || ret == ReturnFalse) && blockLen)
                    ret = visitProBlock(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
850
851
852
                if (okey)
                    m_skipLevel--;
            } else {
853
854
855
856
857
858
                if (okey)
                    ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue;
                tokPtr += blockLen;
                blockLen = getBlockLen(tokPtr);
                if (!okey)
                    ret = blockLen ? visitProBlock(tokPtr) : ReturnTrue;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
859
            }
860
            tokPtr += blockLen;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
861
862
            okey = true, or_op = false; // force next evaluation
            break;
863
864
865
        case TokForLoop:
            if (m_cumulative) { // This is a no-win situation, so just pretend it's no loop
                skipHashStr(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
866
867
                uint exprLen = getBlockLen(tokPtr);
                tokPtr += exprLen;
868
869
870
871
                blockLen = getBlockLen(tokPtr);
                ret = visitProBlock(tokPtr);
            } else if (okey != or_op) {
                const ProString &variable = getHashStr(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
872
873
874
                uint exprLen = getBlockLen(tokPtr);
                const ushort *exprPtr = tokPtr;
                tokPtr += exprLen;
875
                blockLen = getBlockLen(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
876
                ret = visitProLoop(variable, exprPtr, tokPtr);
877
878
            } else {
                skipHashStr(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
879
880
                uint exprLen = getBlockLen(tokPtr);
                tokPtr += exprLen;
881
882
883
884
                blockLen = getBlockLen(tokPtr);
                ret = ReturnTrue;
            }
            tokPtr += blockLen;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
885
886
            okey = true, or_op = false; // force next evaluation
            break;
887
888
889
890
891
892
893
894
895
896
897
        case TokTestDef:
        case TokReplaceDef:
            if (m_cumulative || okey != or_op) {
                const ProString &name = getHashStr(tokPtr);
                blockLen = getBlockLen(tokPtr);
                visitProFunctionDef(tok, name, tokPtr);
            } else {
                skipHashStr(tokPtr);
                blockLen = getBlockLen(tokPtr);
            }
            tokPtr += blockLen;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
898
899
            okey = true, or_op = false; // force next evaluation
            continue;
900
        case TokNot:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
901
            invert ^= true;
902
903
            continue;
        case TokAnd:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
904
            or_op = false;
905
906
            continue;
        case TokOr:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
907
            or_op = true;
908
909
            continue;
        case TokCondition:
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
910
            if (!m_skipLevel && okey != or_op) {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
911
                if (curr.size() != 1) {
912
                    evalError(fL1S("Conditional must expand to exactly one word."));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
913
914
915
916
917
918
919
920
921
922
923
924
                    okey = false;
                } else {
                    okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true) ^ invert;
                }
            }
            or_op = !okey; // tentatively force next evaluation
            invert = false;
            curr.clear();
            continue;
        case TokTestCall:
            if (!m_skipLevel && okey != or_op) {
                if (curr.size() != 1) {
925
                    evalError(fL1S("Test name must expand to exactly one word."));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
926
927
928
929
930
931
932
933
934
935
                    skipExpression(tokPtr);
                    okey = false;
                } else {
                    ret = evaluateConditionalFunction(curr.at(0), tokPtr);
                    switch (ret) {
                    case ReturnTrue: okey = true; break;
                    case ReturnFalse: okey = false; break;
                    default: return ret;
                    }
                    okey ^= invert;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
936
937
938
                }
            } else if (m_cumulative) {
                m_skipLevel++;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
939
940
941
942
                if (curr.size() != 1)
                    skipExpression(tokPtr);
                else
                    evaluateConditionalFunction(curr.at(0), tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
943
                m_skipLevel--;
944
            } else {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
945
                skipExpression(tokPtr);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
946
947
948
            }
            or_op = !okey; // tentatively force next evaluation
            invert = false;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
949
            curr.clear();
950
            continue;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
951
952
953
954
955
956
957
        default: {
                const ushort *oTokPtr = --tokPtr;
                evaluateExpression(tokPtr, &curr, false);
                if (tokPtr != oTokPtr)
                    continue;
            }
            Q_ASSERT_X(false, "visitProBlock", "unexpected item type");
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
958
        }
959
        if (ret != ReturnTrue && ret != ReturnFalse)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
960
            break;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
961
    }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
962
    return ret;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
963
964
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
965

966
967
void ProFileEvaluator::Private::visitProFunctionDef(
        ushort tok, const ProString &name, const ushort *tokPtr)
con's avatar
con committed
968
{
969
970
    QHash<ProString, FunctionDef> *hash =
            (tok == TokTestDef
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
971
972
             ? &m_functionDefs.testFunctions
             : &m_functionDefs.replaceFunctions);
973
    hash->insert(name, FunctionDef(m_current.pro, tokPtr - m_current.pro->tokPtr()));
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
974
975
}

976
ProFileEvaluator::Private::VisitReturn ProFileEvaluator::Private::visitProLoop(
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
977
        const ProString &_variable, const ushort *exprPtr, const ushort *tokPtr)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
978
{
979
    VisitReturn ret = ReturnTrue;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
980
981
    bool infinite = false;
    int index = 0;
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
982
983
    ProString variable;
    ProStringList oldVarVal;
984
    ProString it_list = expandVariableReferences(exprPtr, 0, true).at(0);
985
    if (_variable.isEmpty()) {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
986
        if (it_list != statics.strever) {
987
            evalError(fL1S("Invalid loop expression."));
988
            return ReturnFalse;
989
        }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
990
        it_list = ProString(statics.strforever);
991
    } else {
992
        variable = map(_variable);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
993
        oldVarVal = valuesDirect(variable);
con's avatar
con committed
994
    }
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
995
    ProStringList list = valuesDirect(it_list);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
996
997
998
999
    if (list.isEmpty()) {
        if (it_list == statics.strforever) {
            infinite = true;
        } else {
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
1000
            const QString &itl = it_list.toQString(m_tmp1);