| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the qmake application of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 | #ifndef PROITEMS_H | 
| 30 | #define PROITEMS_H | 
| 31 |  | 
| 32 | #include "qmake_global.h" | 
| 33 |  | 
| 34 | #include <qdebug.h> | 
| 35 | #include <qhash.h> | 
| 36 | #include <qlist.h> | 
| 37 | #include <qmap.h> | 
| 38 | #include <qstring.h> | 
| 39 |  | 
| 40 | QT_BEGIN_NAMESPACE | 
| 41 |  | 
| 42 | class QTextStream; | 
| 43 |  | 
| 44 | #ifdef PROPARSER_THREAD_SAFE | 
| 45 | typedef QAtomicInt ProItemRefCount; | 
| 46 | #else | 
| 47 | class ProItemRefCount { | 
| 48 | public: | 
| 49 |     ProItemRefCount(int cnt = 0) : m_cnt(cnt) {} | 
| 50 |     bool ref() { return ++m_cnt != 0; } | 
| 51 |     bool deref() { return --m_cnt != 0; } | 
| 52 |     ProItemRefCount &operator=(int value) { m_cnt = value; return *this; } | 
| 53 | private: | 
| 54 |     int m_cnt; | 
| 55 | }; | 
| 56 | #endif | 
| 57 |  | 
| 58 | #ifndef QT_BUILD_QMAKE | 
| 59 | #  define PROITEM_EXPLICIT explicit | 
| 60 | #else | 
| 61 | #  define PROITEM_EXPLICIT | 
| 62 | #endif | 
| 63 |  | 
| 64 | class ProKey; | 
| 65 | class ProStringList; | 
| 66 | class ProFile; | 
| 67 |  | 
| 68 | class ProString { | 
| 69 | public: | 
| 70 |     ProString(); | 
| 71 |     ProString(const ProString &other); | 
| 72 |     ProString &operator=(const ProString &) = default; | 
| 73 |     template<typename A, typename B> | 
| 74 |     ProString &operator=(const QStringBuilder<A, B> &str) | 
| 75 |     { return *this = QString(str); } | 
| 76 |     ProString(const QString &str); | 
| 77 |     PROITEM_EXPLICIT ProString(QStringView str); | 
| 78 |     PROITEM_EXPLICIT ProString(const char *str); | 
| 79 |     template<typename A, typename B> | 
| 80 |     ProString(const QStringBuilder<A, B> &str) | 
| 81 |         : ProString(QString(str)) | 
| 82 |     {} | 
| 83 |     ProString(const QString &str, int offset, int length); | 
| 84 |     void setValue(const QString &str); | 
| 85 |     void clear() { m_string.clear(); m_length = 0; } | 
| 86 |     ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; } | 
| 87 |     ProString &setSource(int id) { m_file = id; return *this; } | 
| 88 |     int sourceFile() const { return m_file; } | 
| 89 |  | 
| 90 |     ProString &prepend(const ProString &other); | 
| 91 |     ProString &append(const ProString &other, bool *pending = nullptr); | 
| 92 |     ProString &append(const QString &other) { return append(ProString(other)); } | 
| 93 |     template<typename A, typename B> | 
| 94 |     ProString &append(const QStringBuilder<A, B> &other) { return append(QString(other)); } | 
| 95 |     ProString &append(const QLatin1String other); | 
| 96 |     ProString &append(const char *other) { return append(QLatin1String(other)); } | 
| 97 |     ProString &append(QChar other); | 
| 98 |     ProString &append(const ProStringList &other, bool *pending = nullptr, bool skipEmpty1st = false); | 
| 99 |     ProString &operator+=(const ProString &other) { return append(other); } | 
| 100 |     ProString &operator+=(const QString &other) { return append(other); } | 
| 101 |     template<typename A, typename B> | 
| 102 |     ProString &operator+=(const QStringBuilder<A, B> &other) { return append(QString(other)); } | 
| 103 |     ProString &operator+=(const QLatin1String other) { return append(other); } | 
| 104 |     ProString &operator+=(const char *other) { return append(other); } | 
| 105 |     ProString &operator+=(QChar other) { return append(other); } | 
| 106 |  | 
| 107 |     void chop(int n) { Q_ASSERT(n <= m_length); m_length -= n; } | 
| 108 |     void chopFront(int n) { Q_ASSERT(n <= m_length); m_offset += n; m_length -= n; } | 
| 109 |  | 
| 110 |     bool operator==(const ProString &other) const { return toQStringView() == other.toQStringView(); } | 
| 111 |     bool operator==(const QString &other) const { return toQStringView() == other; } | 
| 112 |     bool operator==(QStringView other) const { return toQStringView() == other; } | 
| 113 |     bool operator==(QLatin1String other) const  { return toQStringView() == other; } | 
| 114 |     bool operator==(const char *other) const { return toQStringView() == QLatin1String(other); } | 
| 115 |     bool operator!=(const ProString &other) const { return !(*this == other); } | 
| 116 |     bool operator!=(const QString &other) const { return !(*this == other); } | 
| 117 |     bool operator!=(QLatin1String other) const { return !(*this == other); } | 
| 118 |     bool operator!=(const char *other) const { return !(*this == other); } | 
| 119 |     bool operator<(const ProString &other) const { return toQStringView() < other.toQStringView(); } | 
| 120 |     bool isNull() const { return m_string.isNull(); } | 
| 121 |     bool isEmpty() const { return !m_length; } | 
| 122 |     int length() const { return m_length; } | 
| 123 |     int size() const { return m_length; } | 
| 124 |     QChar at(int i) const { Q_ASSERT((uint)i < (uint)m_length); return constData()[i]; } | 
| 125 |     const QChar *constData() const { return m_string.constData() + m_offset; } | 
| 126 |     ProString mid(int off, int len = -1) const; | 
| 127 |     ProString left(int len) const { return mid(0, len); } | 
| 128 |     ProString right(int len) const { return mid(qMax(0, size() - len)); } | 
| 129 |     ProString trimmed() const; | 
| 130 |     int compare(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().compare(sub.toQStringView(), cs); } | 
| 131 |     int compare(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().compare(sub, cs); } | 
| 132 |     int compare(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().compare(QLatin1String(sub), cs); } | 
| 133 |     bool startsWith(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().startsWith(sub.toQStringView(), cs); } | 
| 134 |     bool startsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().startsWith(sub, cs); } | 
| 135 |     bool startsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().startsWith(QLatin1String(sub), cs); } | 
| 136 |     bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().startsWith(c, cs); } | 
| 137 |     template<typename A, typename B> | 
| 138 |     bool startsWith(const QStringBuilder<A, B> &str) { return startsWith(QString(str)); } | 
| 139 |     bool endsWith(const ProString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().endsWith(sub.toQStringView(), cs); } | 
| 140 |     bool endsWith(const QString &sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().endsWith(sub, cs); } | 
| 141 |     bool endsWith(const char *sub, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().endsWith(QLatin1String(sub), cs); } | 
| 142 |     template<typename A, typename B> | 
| 143 |     bool endsWith(const QStringBuilder<A, B> &str) { return endsWith(QString(str)); } | 
| 144 |     bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().endsWith(c, cs); } | 
| 145 |     int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().indexOf(s, from, cs); } | 
| 146 |     int indexOf(const char *s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().indexOf(QLatin1String(s), from, cs); } | 
| 147 |     int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().indexOf(c, from, cs); } | 
| 148 |     int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().lastIndexOf(s, from, cs); } | 
| 149 |     int lastIndexOf(const char *s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().lastIndexOf(QLatin1String(s), from, cs); } | 
| 150 |     int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return toQStringView().lastIndexOf(c, from, cs); } | 
| 151 |     bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; } | 
| 152 |     bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; } | 
| 153 |     bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; } | 
| 154 |     qlonglong toLongLong(bool *ok = nullptr, int base = 10) const { return toQStringView().toLongLong(ok, base); } | 
| 155 |     int toInt(bool *ok = nullptr, int base = 10) const { return toQStringView().toInt(ok, base); } | 
| 156 |     short toShort(bool *ok = nullptr, int base = 10) const { return toQStringView().toShort(ok, base); } | 
| 157 |  | 
| 158 |     size_t hash() const { return m_hash; } | 
| 159 |     static size_t hash(const QChar *p, int n); | 
| 160 |  | 
| 161 |     ALWAYS_INLINE QStringView toQStringView() const { return QStringView(m_string).mid(m_offset, m_length); } | 
| 162 |  | 
| 163 |     ALWAYS_INLINE ProKey &toKey() { return *(ProKey *)this; } | 
| 164 |     ALWAYS_INLINE const ProKey &toKey() const { return *(const ProKey *)this; } | 
| 165 |  | 
| 166 |     QString toQString() const; | 
| 167 |     QString &toQString(QString &tmp) const; | 
| 168 |  | 
| 169 |     QByteArray toLatin1() const { return toQStringView().toLatin1(); } | 
| 170 |  | 
| 171 | private: | 
| 172 |     ProString(const ProKey &other); | 
| 173 |     ProString &operator=(const ProKey &other); | 
| 174 |  | 
| 175 |     enum OmitPreHashing { NoHash }; | 
| 176 |     ProString(const ProString &other, OmitPreHashing); | 
| 177 |  | 
| 178 |     enum DoPreHashing { DoHash }; | 
| 179 |     ALWAYS_INLINE ProString(const QString &str, DoPreHashing); | 
| 180 |     ALWAYS_INLINE ProString(const char *str, DoPreHashing); | 
| 181 |     ALWAYS_INLINE ProString(const QString &str, int offset, int length, DoPreHashing); | 
| 182 |     ALWAYS_INLINE ProString(const QString &str, int offset, int length, uint hash); | 
| 183 |  | 
| 184 |     QString m_string; | 
| 185 |     int m_offset, m_length; | 
| 186 |     int m_file; | 
| 187 |     mutable size_t m_hash; | 
| 188 |     size_t updatedHash() const; | 
| 189 |     friend size_t qHash(const ProString &str); | 
| 190 |     friend QString operator+(const ProString &one, const ProString &two); | 
| 191 |     friend class ProKey; | 
| 192 | }; | 
| 193 | Q_DECLARE_TYPEINFO(ProString, Q_MOVABLE_TYPE); | 
| 194 |  | 
| 195 |  | 
| 196 | class ProKey : public ProString { | 
| 197 | public: | 
| 198 |     ALWAYS_INLINE ProKey() : ProString() {} | 
| 199 |     explicit ProKey(const QString &str); | 
| 200 |     template<typename A, typename B> | 
| 201 |     ProKey(const QStringBuilder<A, B> &str) | 
| 202 |         : ProString(str) | 
| 203 |     {} | 
| 204 |     PROITEM_EXPLICIT ProKey(const char *str); | 
| 205 |     ProKey(const QString &str, int off, int len); | 
| 206 |     ProKey(const QString &str, int off, int len, uint hash); | 
| 207 |     void setValue(const QString &str); | 
| 208 |  | 
| 209 | #ifdef Q_CC_MSVC | 
| 210 |     // Workaround strange MSVC behaviour when exporting classes with ProKey members. | 
| 211 |     ALWAYS_INLINE ProKey(const ProKey &other) : ProString(other.toString()) {} | 
| 212 |     ALWAYS_INLINE ProKey &operator=(const ProKey &other) | 
| 213 |     { | 
| 214 |         toString() = other.toString(); | 
| 215 |         return *this; | 
| 216 |     } | 
| 217 | #endif | 
| 218 |  | 
| 219 |     ALWAYS_INLINE ProString &toString() { return *(ProString *)this; } | 
| 220 |     ALWAYS_INLINE const ProString &toString() const { return *(const ProString *)this; } | 
| 221 |  | 
| 222 | private: | 
| 223 |     ProKey(const ProString &other); | 
| 224 | }; | 
| 225 | Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE); | 
| 226 |  | 
| 227 | template <> struct QConcatenable<ProString> : private QAbstractConcatenable | 
| 228 | { | 
| 229 |     typedef ProString type; | 
| 230 |     typedef QString ConvertTo; | 
| 231 |     enum { ExactSize = true }; | 
| 232 |     static int size(const ProString &a) { return a.length(); } | 
| 233 |     static inline void appendTo(const ProString &a, QChar *&out) | 
| 234 |     { | 
| 235 |         const auto n = a.size(); | 
| 236 |         memcpy(out, a.toQStringView().data(), sizeof(QChar) * n); | 
| 237 |         out += n; | 
| 238 |     } | 
| 239 | }; | 
| 240 |  | 
| 241 | template <> struct QConcatenable<ProKey> : private QAbstractConcatenable | 
| 242 | { | 
| 243 |     typedef ProKey type; | 
| 244 |     typedef QString ConvertTo; | 
| 245 |     enum { ExactSize = true }; | 
| 246 |     static int size(const ProKey &a) { return a.length(); } | 
| 247 |     static inline void appendTo(const ProKey &a, QChar *&out) | 
| 248 |     { | 
| 249 |         const auto n = a.size(); | 
| 250 |         memcpy(out, a.toQStringView().data(), sizeof(QChar) * n); | 
| 251 |         out += n; | 
| 252 |     } | 
| 253 | }; | 
| 254 |  | 
| 255 |  | 
| 256 | size_t qHash(const ProString &str); | 
| 257 |  | 
| 258 | inline QString &operator+=(QString &that, const ProString &other) | 
| 259 |     { return that += other.toQStringView(); } | 
| 260 |  | 
| 261 | QTextStream &operator<<(QTextStream &t, const ProString &str); | 
| 262 | template<typename A, typename B> | 
| 263 | QTextStream &operator<<(QTextStream &t, const QStringBuilder<A, B> &str) { return t << QString(str); } | 
| 264 |  | 
| 265 | // This class manages read-only access to a ProString via a raw data QString | 
| 266 | // temporary, ensuring that the latter is accessed exclusively. | 
| 267 | class ProStringRoUser | 
| 268 | { | 
| 269 | public: | 
| 270 |     ProStringRoUser(QString &rs) | 
| 271 |     { | 
| 272 |         m_rs = &rs; | 
| 273 |     } | 
| 274 |     ProStringRoUser(const ProString &ps, QString &rs) | 
| 275 |         : ProStringRoUser(rs) | 
| 276 |     { | 
| 277 |         ps.toQString(rs); | 
| 278 |     } | 
| 279 |     // No destructor, as a RAII pattern cannot be used: references to the | 
| 280 |     // temporary string can legitimately outlive instances of this class | 
| 281 |     // (if they are held by Qt, e.g. in QRegExp). | 
| 282 |     QString &set(const ProString &ps) { return ps.toQString(*m_rs); } | 
| 283 |     QString &str() { return *m_rs; } | 
| 284 |  | 
| 285 | protected: | 
| 286 |     QString *m_rs; | 
| 287 | }; | 
| 288 |  | 
| 289 | // This class manages read-write access to a ProString via a raw data QString | 
| 290 | // temporary, ensuring that the latter is accessed exclusively, and that raw | 
| 291 | // data does not leak outside its source's refcounting. | 
| 292 | class ProStringRwUser : public ProStringRoUser | 
| 293 | { | 
| 294 | public: | 
| 295 |     ProStringRwUser(QString &rs) | 
| 296 |         : ProStringRoUser(rs), m_ps(nullptr) {} | 
| 297 |     ProStringRwUser(const ProString &ps, QString &rs) | 
| 298 |         : ProStringRoUser(ps, rs), m_ps(&ps) {} | 
| 299 |     QString &set(const ProString &ps) { m_ps = &ps; return ProStringRoUser::set(ps); } | 
| 300 |     ProString (const QString &s) const | 
| 301 |         { return s.isSharedWith(*m_rs) ? *m_ps : ProString(s).setSource(*m_ps); } | 
| 302 |     ProString (const QString &s, const ProStringRwUser &other) const | 
| 303 |     { | 
| 304 |         if (other.m_ps && s.isSharedWith(*other.m_rs)) | 
| 305 |             return *other.m_ps; | 
| 306 |         return extract(s); | 
| 307 |     } | 
| 308 |  | 
| 309 | private: | 
| 310 |     const ProString *m_ps; | 
| 311 | }; | 
| 312 |  | 
| 313 | class ProStringList : public QList<ProString> { | 
| 314 | public: | 
| 315 |     ProStringList() {} | 
| 316 |     ProStringList(const ProString &str) { *this << str; } | 
| 317 |     explicit ProStringList(const QStringList &list); | 
| 318 |     QStringList toQStringList() const; | 
| 319 |  | 
| 320 |     ProStringList &operator<<(const ProString &str) | 
| 321 |         { QList<ProString>::operator<<(str); return *this; } | 
| 322 |  | 
| 323 |     int length() const { return size(); } | 
| 324 |  | 
| 325 |     QString join(const ProString &sep) const; | 
| 326 |     QString join(const QString &sep) const; | 
| 327 |     QString join(QChar sep) const; | 
| 328 |     template<typename A, typename B> | 
| 329 |     QString join(const QStringBuilder<A, B> &str) { return join(QString(str)); } | 
| 330 |  | 
| 331 |     void insertUnique(const ProStringList &value); | 
| 332 |  | 
| 333 |     void removeAll(const ProString &str); | 
| 334 |     void removeAll(const char *str); | 
| 335 |     void removeEach(const ProStringList &value); | 
| 336 |     void removeAt(int idx) { remove(idx); } | 
| 337 |     void removeEmpty(); | 
| 338 |     void removeDuplicates(); | 
| 339 |  | 
| 340 |     bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; | 
| 341 |     bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; | 
| 342 |     bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const | 
| 343 |         { return contains(ProString(str), cs); } | 
| 344 |     bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; | 
| 345 | }; | 
| 346 | Q_DECLARE_TYPEINFO(ProStringList, Q_MOVABLE_TYPE); | 
| 347 |  | 
| 348 | inline ProStringList operator+(const ProStringList &one, const ProStringList &two) | 
| 349 |     { ProStringList ret = one; ret += two; return ret; } | 
| 350 |  | 
| 351 | typedef QMap<ProKey, ProStringList> ProValueMap; | 
| 352 |  | 
| 353 | // These token definitions affect both ProFileEvaluator and ProWriter | 
| 354 | enum ProToken { | 
| 355 |     TokTerminator = 0,  // end of stream (possibly not included in length; must be zero) | 
| 356 |     TokLine,            // line marker: | 
| 357 |                         // - line (1) | 
| 358 |     TokAssign,          // variable = | 
| 359 |     TokAppend,          // variable += | 
| 360 |     TokAppendUnique,    // variable *= | 
| 361 |     TokRemove,          // variable -= | 
| 362 |     TokReplace,         // variable ~= | 
| 363 |                         // previous literal/expansion is a variable manipulation | 
| 364 |                         // - lower bound for expected output length (1) | 
| 365 |                         // - value expression + TokValueTerminator | 
| 366 |     TokValueTerminator, // assignment value terminator | 
| 367 |     TokLiteral,         // literal string (fully dequoted) | 
| 368 |                         // - length (1) | 
| 369 |                         // - string data (length; unterminated) | 
| 370 |     TokHashLiteral,     // literal string with hash (fully dequoted) | 
| 371 |                         // - hash (2) | 
| 372 |                         // - length (1) | 
| 373 |                         // - string data (length; unterminated) | 
| 374 |     TokVariable,        // qmake variable expansion | 
| 375 |                         // - hash (2) | 
| 376 |                         // - name length (1) | 
| 377 |                         // - name (name length; unterminated) | 
| 378 |     TokProperty,        // qmake property expansion | 
| 379 |                         // - hash (2) | 
| 380 |                         // - name length (1) | 
| 381 |                         // - name (name length; unterminated) | 
| 382 |     TokEnvVar,          // environment variable expansion | 
| 383 |                         // - name length (1) | 
| 384 |                         // - name (name length; unterminated) | 
| 385 |     TokFuncName,        // replace function expansion | 
| 386 |                         // - hash (2) | 
| 387 |                         // - name length (1) | 
| 388 |                         // - name (name length; unterminated) | 
| 389 |                         // - ((nested expansion + TokArgSeparator)* + nested expansion)? | 
| 390 |                         // - TokFuncTerminator | 
| 391 |     TokArgSeparator,    // function argument separator | 
| 392 |     TokFuncTerminator,  // function argument list terminator | 
| 393 |     TokCondition,       // previous literal/expansion is a conditional | 
| 394 |     TokTestCall,        // previous literal/expansion is a test function call | 
| 395 |                         // - ((nested expansion + TokArgSeparator)* + nested expansion)? | 
| 396 |                         // - TokFuncTerminator | 
| 397 |     TokReturn,          // previous literal/expansion is a return value | 
| 398 |     TokBreak,           // break loop | 
| 399 |     TokNext,            // shortcut to next loop iteration | 
| 400 |     TokNot,             // '!' operator | 
| 401 |     TokAnd,             // ':' operator | 
| 402 |     TokOr,              // '|' operator | 
| 403 |     TokBranch,          // branch point: | 
| 404 |                         // - then block length (2) | 
| 405 |                         // - then block + TokTerminator (then block length) | 
| 406 |                         // - else block length (2) | 
| 407 |                         // - else block + TokTerminator (else block length) | 
| 408 |     TokForLoop,         // for loop: | 
| 409 |                         // - variable name: hash (2), length (1), chars (length) | 
| 410 |                         // - expression: length (2), bytes + TokValueTerminator (length) | 
| 411 |                         // - body length (2) | 
| 412 |                         // - body + TokTerminator (body length) | 
| 413 |     TokTestDef,         // test function definition: | 
| 414 |     TokReplaceDef,      // replace function definition: | 
| 415 |                         // - function name: hash (2), length (1), chars (length) | 
| 416 |                         // - body length (2) | 
| 417 |                         // - body + TokTerminator (body length) | 
| 418 |     TokBypassNesting,   // escape from function local variable scopes: | 
| 419 |                         // - block length (2) | 
| 420 |                         // - block + TokTerminator (block length) | 
| 421 |     TokMask = 0xff, | 
| 422 |     TokQuoted = 0x100,  // The expression is quoted => join expanded stringlist | 
| 423 |     TokNewStr = 0x200   // Next stringlist element | 
| 424 | }; | 
| 425 |  | 
| 426 | class QMAKE_EXPORT ProFile | 
| 427 | { | 
| 428 | public: | 
| 429 |     ProFile(int id, const QString &fileName); | 
| 430 |     ~ProFile(); | 
| 431 |  | 
| 432 |     int id() const { return m_id; } | 
| 433 |     QString fileName() const { return m_fileName; } | 
| 434 |     QString directoryName() const { return m_directoryName; } | 
| 435 |     const QString &items() const { return m_proitems; } | 
| 436 |     QString *itemsRef() { return &m_proitems; } | 
| 437 |     const ushort *tokPtr() const { return (const ushort *)m_proitems.constData(); } | 
| 438 |     const ushort *tokPtrEnd() const { return (const ushort *)m_proitems.constData() + m_proitems.size(); } | 
| 439 |  | 
| 440 |     void ref() { m_refCount.ref(); } | 
| 441 |     void deref() { if (!m_refCount.deref()) delete this; } | 
| 442 |  | 
| 443 |     bool isOk() const { return m_ok; } | 
| 444 |     void setOk(bool ok) { m_ok = ok; } | 
| 445 |  | 
| 446 |     bool isHostBuild() const { return m_hostBuild; } | 
| 447 |     void setHostBuild(bool host_build) { m_hostBuild = host_build; } | 
| 448 |  | 
| 449 |     ProString getStr(const ushort *&tPtr); | 
| 450 |     ProKey getHashStr(const ushort *&tPtr); | 
| 451 |  | 
| 452 | private: | 
| 453 |     ProItemRefCount m_refCount; | 
| 454 |     QString m_proitems; | 
| 455 |     QString m_fileName; | 
| 456 |     QString m_directoryName; | 
| 457 |     int m_id; | 
| 458 |     bool m_ok; | 
| 459 |     bool m_hostBuild; | 
| 460 | }; | 
| 461 |  | 
| 462 | class ProFunctionDef { | 
| 463 | public: | 
| 464 |     ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); } | 
| 465 |     ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } | 
| 466 |     ProFunctionDef(ProFunctionDef &&other) noexcept | 
| 467 |         : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; } | 
| 468 |     ~ProFunctionDef() { if (m_pro) m_pro->deref(); } | 
| 469 |     ProFunctionDef &operator=(const ProFunctionDef &o) | 
| 470 |     { | 
| 471 |         if (this != &o) { | 
| 472 |             if (m_pro) | 
| 473 |                 m_pro->deref(); | 
| 474 |             m_pro = o.m_pro; | 
| 475 |             m_pro->ref(); | 
| 476 |             m_offset = o.m_offset; | 
| 477 |         } | 
| 478 |         return *this; | 
| 479 |     } | 
| 480 |     ProFunctionDef &operator=(ProFunctionDef &&other) noexcept | 
| 481 |     { | 
| 482 |         ProFunctionDef moved(std::move(other)); | 
| 483 |         swap(moved); | 
| 484 |         return *this; | 
| 485 |     } | 
| 486 |     void swap(ProFunctionDef &other) noexcept | 
| 487 |     { | 
| 488 |         qSwap(m_pro, other.m_pro); | 
| 489 |         qSwap(m_offset, other.m_offset); | 
| 490 |     } | 
| 491 |  | 
| 492 |     ProFile *pro() const { return m_pro; } | 
| 493 |     const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; } | 
| 494 | private: | 
| 495 |     ProFile *m_pro; | 
| 496 |     int m_offset; | 
| 497 | }; | 
| 498 |  | 
| 499 | Q_DECLARE_TYPEINFO(ProFunctionDef, Q_MOVABLE_TYPE); | 
| 500 |  | 
| 501 | struct ProFunctionDefs { | 
| 502 |     QHash<ProKey, ProFunctionDef> testFunctions; | 
| 503 |     QHash<ProKey, ProFunctionDef> replaceFunctions; | 
| 504 | }; | 
| 505 |  | 
| 506 | QDebug operator<<(QDebug debug, const ProString &str); | 
| 507 |  | 
| 508 | QT_END_NAMESPACE | 
| 509 |  | 
| 510 | #endif // PROITEMS_H | 
| 511 |  |