summaryrefslogtreecommitdiffstats
path: root/tools/linguist/shared/cpp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/linguist/shared/cpp.cpp')
-rw-r--r--tools/linguist/shared/cpp.cpp1098
1 files changed, 0 insertions, 1098 deletions
diff --git a/tools/linguist/shared/cpp.cpp b/tools/linguist/shared/cpp.cpp
deleted file mode 100644
index ac6bd33..0000000
--- a/tools/linguist/shared/cpp.cpp
+++ /dev/null
@@ -1,1098 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Linguist of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** 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 either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://www.qtsoftware.com/contact.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "translator.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QStack>
-#include <QtCore/QString>
-#include <QtCore/QTextCodec>
-#include <QtCore/QTextStream>
-
-#include <ctype.h> // for isXXX()
-
-QT_BEGIN_NAMESPACE
-
-/* qmake ignore Q_OBJECT */
-
-static const char MagicComment[] = "TRANSLATOR ";
-
-static QSet<QString> needs_Q_OBJECT;
-static QSet<QString> lacks_Q_OBJECT;
-
-static const int yyIdentMaxLen = 128;
-static const int yyCommentMaxLen = 65536;
-static const int yyStringMaxLen = 65536;
-
-#define STRINGIFY_INTERNAL(x) #x
-#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
-#define STRING(s) static QString str##s(QLatin1String(STRINGIFY(s)))
-
-//#define DIAGNOSE_RETRANSLATABILITY
-/*
- The first part of this source file is the C++ tokenizer. We skip
- most of C++; the only tokens that interest us are defined here.
- Thus, the code fragment
-
- int main()
- {
- printf("Hello, world!\n");
- return 0;
- }
-
- is broken down into the following tokens (Tok_ omitted):
-
- Ident Ident LeftParen RightParen
- LeftBrace
- Ident LeftParen String RightParen Semicolon
- return Semicolon
- RightBrace.
-
- The 0 doesn't produce any token.
-*/
-
-enum {
- Tok_Eof, Tok_class, Tok_namespace, Tok_return,
- Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8,
- Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS,
- Tok_Ident, Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, Tok_ColonColon,
- Tok_Equals,
- Tok_LeftBrace = 30, Tok_RightBrace, Tok_LeftParen, Tok_RightParen, Tok_Comma, Tok_Semicolon,
- Tok_Integer = 40,
- Tok_Other
-};
-
-/*
- The tokenizer maintains the following global variables. The names
- should be self-explanatory.
-*/
-static QString yyFileName;
-static int yyCh;
-static bool yyCodecIsUtf8;
-static bool yyForceUtf8;
-static QString yyIdent;
-static QString yyComment;
-static QString yyString;
-static qlonglong yyInteger;
-static QStack<int> yySavedBraceDepth;
-static QStack<int> yySavedParenDepth;
-static int yyBraceDepth;
-static int yyParenDepth;
-static int yyLineNo;
-static int yyCurLineNo;
-static int yyBraceLineNo;
-static int yyParenLineNo;
-static bool yyTokColonSeen = false;
-
-// the string to read from and current position in the string
-static QTextCodec *yySourceCodec;
-static bool yySourceIsUnicode;
-static QString yyInStr;
-static int yyInPos;
-
-static uint getChar()
-{
- forever {
- if (yyInPos >= yyInStr.size())
- return EOF;
- uint c = yyInStr[yyInPos++].unicode();
- if (c == '\\' && yyInPos < yyInStr.size()) {
- if (yyInStr[yyInPos].unicode() == '\n') {
- ++yyCurLineNo;
- ++yyInPos;
- continue;
- }
- if (yyInStr[yyInPos].unicode() == '\r') {
- ++yyCurLineNo;
- ++yyInPos;
- if (yyInPos < yyInStr.size() && yyInStr[yyInPos].unicode() == '\n')
- ++yyInPos;
- continue;
- }
- }
- if (c == '\r') {
- if (yyInPos < yyInStr.size() && yyInStr[yyInPos].unicode() == '\n')
- ++yyInPos;
- c = '\n';
- ++yyCurLineNo;
- } else if (c == '\n') {
- ++yyCurLineNo;
- }
- return c;
- }
-}
-
-static uint getToken()
-{
- yyIdent.clear();
- yyComment.clear();
- yyString.clear();
-
- while (yyCh != EOF) {
- yyLineNo = yyCurLineNo;
-
- if (isalpha(yyCh) || yyCh == '_') {
- do {
- yyIdent += yyCh;
- yyCh = getChar();
- } while (isalnum(yyCh) || yyCh == '_');
-
- //qDebug() << "IDENT: " << yyIdent;
-
- switch (yyIdent.at(0).unicode()) {
- case 'Q':
- if (yyIdent == QLatin1String("Q_OBJECT"))
- return Tok_Q_OBJECT;
- if (yyIdent == QLatin1String("Q_DECLARE_TR_FUNCTIONS"))
- return Tok_Q_DECLARE_TR_FUNCTIONS;
- if (yyIdent == QLatin1String("QT_TR_NOOP"))
- return Tok_tr;
- if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP"))
- return Tok_translate;
- if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP3"))
- return Tok_translate;
- if (yyIdent == QLatin1String("QT_TR_NOOP_UTF8"))
- return Tok_trUtf8;
- if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP_UTF8"))
- return Tok_translateUtf8;
- if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP3_UTF8"))
- return Tok_translateUtf8;
- break;
- case 'T':
- // TR() for when all else fails
- if (yyIdent.compare(QLatin1String("TR"), Qt::CaseInsensitive) == 0) {
- return Tok_tr;
- }
- break;
- case 'c':
- if (yyIdent == QLatin1String("class"))
- return Tok_class;
- break;
- case 'f':
- /*
- QTranslator::findMessage() has the same parameters as
- QApplication::translate().
- */
- if (yyIdent == QLatin1String("findMessage"))
- return Tok_translate;
- break;
- case 'n':
- if (yyIdent == QLatin1String("namespace"))
- return Tok_namespace;
- break;
- case 'r':
- if (yyIdent == QLatin1String("return"))
- return Tok_return;
- break;
- case 's':
- if (yyIdent == QLatin1String("struct"))
- return Tok_class;
- break;
- case 't':
- if (yyIdent == QLatin1String("tr")) {
- return Tok_tr;
- }
- if (yyIdent == QLatin1String("trUtf8")) {
- return Tok_trUtf8;
- }
- if (yyIdent == QLatin1String("translate")) {
- return Tok_translate;
- }
- }
- return Tok_Ident;
- } else {
- switch (yyCh) {
- case '#':
- /*
- Early versions of lupdate complained about
- unbalanced braces in the following code:
-
- #ifdef ALPHA
- while (beta) {
- #else
- while (gamma) {
- #endif
- delta;
- }
-
- The code contains, indeed, two opening braces for
- one closing brace; yet there's no reason to panic.
-
- The solution is to remember yyBraceDepth as it was
- when #if, #ifdef or #ifndef was met, and to set
- yyBraceDepth to that value when meeting #elif or
- #else.
- */
- do {
- yyCh = getChar();
- } while (isspace(yyCh) && yyCh != '\n');
-
- switch (yyCh) {
- case 'i':
- yyCh = getChar();
- if (yyCh == 'f') {
- // if, ifdef, ifndef
- yySavedBraceDepth.push(yyBraceDepth);
- yySavedParenDepth.push(yyParenDepth);
- }
- break;
- case 'e':
- yyCh = getChar();
- if (yyCh == 'l') {
- // elif, else
- if (!yySavedBraceDepth.isEmpty()) {
- yyBraceDepth = yySavedBraceDepth.top();
- yyParenDepth = yySavedParenDepth.top();
- }
- } else if (yyCh == 'n') {
- // endif
- if (!yySavedBraceDepth.isEmpty()) {
- yySavedBraceDepth.pop();
- yySavedParenDepth.pop();
- }
- }
- }
- while (isalnum(yyCh) || yyCh == '_')
- yyCh = getChar();
- break;
- case '/':
- yyCh = getChar();
- if (yyCh == '/') {
- do {
- yyCh = getChar();
- if (yyCh == EOF)
- break;
- yyComment.append(yyCh);
- } while (yyCh != '\n');
- } else if (yyCh == '*') {
- bool metAster = false;
- bool metAsterSlash = false;
-
- while (!metAsterSlash) {
- yyCh = getChar();
- if (yyCh == EOF) {
- qWarning("%s: Unterminated C++ comment starting at"
- " line %d\n",
- qPrintable(yyFileName), yyLineNo);
- return Tok_Comment;
- }
- yyComment.append(yyCh);
-
- if (yyCh == '*')
- metAster = true;
- else if (metAster && yyCh == '/')
- metAsterSlash = true;
- else
- metAster = false;
- }
- yyCh = getChar();
- yyComment.chop(2);
- }
- return Tok_Comment;
- case '"':
- yyCh = getChar();
- while (yyCh != EOF && yyCh != '\n' && yyCh != '"') {
- if (yyCh == '\\') {
- yyCh = getChar();
- if (yyString.size() < yyStringMaxLen) {
- yyString.append(QLatin1Char('\\'));
- yyString.append(yyCh);
- }
- } else {
- if (yyString.size() < yyStringMaxLen)
- yyString.append(yyCh);
- }
- yyCh = getChar();
- }
-
- if (yyCh != '"')
- qWarning("%s:%d: Unterminated C++ string",
- qPrintable(yyFileName), yyLineNo);
-
- if (yyCh == EOF)
- return Tok_Eof;
- yyCh = getChar();
- return Tok_String;
- case '-':
- yyCh = getChar();
- if (yyCh == '>') {
- yyCh = getChar();
- return Tok_Arrow;
- }
- break;
- case ':':
- yyCh = getChar();
- if (yyCh == ':') {
- yyCh = getChar();
- return Tok_ColonColon;
- }
- return Tok_Colon;
- // Incomplete: '<' might be part of '<=' or of template syntax.
- // The main intent of not completely ignoring it is to break
- // parsing of things like std::cout << QObject::tr() as
- // context std::cout::QObject (see Task 161106)
- case '=':
- yyCh = getChar();
- return Tok_Equals;
- case '>':
- case '<':
- yyCh = getChar();
- return Tok_Other;
- case '\'':
- yyCh = getChar();
- if (yyCh == '\\')
- yyCh = getChar();
-
- do {
- yyCh = getChar();
- } while (yyCh != EOF && yyCh != '\'');
- yyCh = getChar();
- break;
- case '{':
- if (yyBraceDepth == 0)
- yyBraceLineNo = yyCurLineNo;
- yyBraceDepth++;
- yyCh = getChar();
- return Tok_LeftBrace;
- case '}':
- if (yyBraceDepth == 0)
- yyBraceLineNo = yyCurLineNo;
- yyBraceDepth--;
- yyCh = getChar();
- return Tok_RightBrace;
- case '(':
- if (yyParenDepth == 0)
- yyParenLineNo = yyCurLineNo;
- yyParenDepth++;
- yyCh = getChar();
- return Tok_LeftParen;
- case ')':
- if (yyParenDepth == 0)
- yyParenLineNo = yyCurLineNo;
- yyParenDepth--;
- yyCh = getChar();
- return Tok_RightParen;
- case ',':
- yyCh = getChar();
- return Tok_Comma;
- case ';':
- yyCh = getChar();
- return Tok_Semicolon;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- QByteArray ba;
- ba += yyCh;
- yyCh = getChar();
- bool hex = yyCh == 'x';
- if (hex) {
- ba += yyCh;
- yyCh = getChar();
- }
- while (hex ? isxdigit(yyCh) : isdigit(yyCh)) {
- ba += yyCh;
- yyCh = getChar();
- }
- bool ok;
- yyInteger = ba.toLongLong(&ok);
- if (ok)
- return Tok_Integer;
- break;
- }
- default:
- yyCh = getChar();
- break;
- }
- }
- }
- return Tok_Eof;
-}
-
-/*
- The second part of this source file is the parser. It accomplishes
- a very easy task: It finds all strings inside a tr() or translate()
- call, and possibly finds out the context of the call. It supports
- three cases: (1) the context is specified, as in
- FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello");
- (2) the call appears within an inlined function; (3) the call
- appears within a function defined outside the class definition.
-*/
-
-static uint yyTok;
-
-static bool match(uint t)
-{
- bool matches = (yyTok == t);
- if (matches)
- yyTok = getToken();
- return matches;
-}
-
-static bool matchString(QString *s)
-{
- bool matches = (yyTok == Tok_String);
- s->clear();
- while (yyTok == Tok_String) {
- *s += yyString;
- do {
- yyTok = getToken();
- } while (yyTok == Tok_Comment);
- }
- return matches;
-}
-
-static bool matchEncoding(bool *utf8)
-{
- STRING(QApplication);
- STRING(QCoreApplication);
- STRING(UnicodeUTF8);
- STRING(DefaultCodec);
- STRING(CodecForTr);
-
- if (yyTok != Tok_Ident)
- return false;
- if (yyIdent == strQApplication || yyIdent == strQCoreApplication) {
- yyTok = getToken();
- if (yyTok == Tok_ColonColon)
- yyTok = getToken();
- }
- if (yyIdent == strUnicodeUTF8) {
- *utf8 = true;
- yyTok = getToken();
- return true;
- }
- if (yyIdent == strDefaultCodec || yyIdent == strCodecForTr) {
- *utf8 = false;
- yyTok = getToken();
- return true;
- }
- return false;
-}
-
-static bool matchInteger(qlonglong *number)
-{
- bool matches = (yyTok == Tok_Integer);
- if (matches) {
- yyTok = getToken();
- *number = yyInteger;
- }
- return matches;
-}
-
-static bool matchStringOrNull(QString *s)
-{
- bool matches = matchString(s);
- qlonglong num = 0;
- if (!matches)
- matches = matchInteger(&num);
- return matches && num == 0;
-}
-
-/*
- * match any expression that can return a number, which can be
- * 1. Literal number (e.g. '11')
- * 2. simple identifier (e.g. 'm_count')
- * 3. simple function call (e.g. 'size()' )
- * 4. function call on an object (e.g. 'list.size()')
- * 5. function call on an object (e.g. 'list->size()')
- *
- * Other cases:
- * size(2,4)
- * list().size()
- * list(a,b).size(2,4)
- * etc...
- */
-static bool matchExpression()
-{
- if (match(Tok_Integer))
- return true;
-
- int parenlevel = 0;
- while (match(Tok_Ident) || parenlevel > 0) {
- if (yyTok == Tok_RightParen) {
- if (parenlevel == 0) break;
- --parenlevel;
- yyTok = getToken();
- } else if (yyTok == Tok_LeftParen) {
- yyTok = getToken();
- if (yyTok == Tok_RightParen) {
- yyTok = getToken();
- } else {
- ++parenlevel;
- }
- } else if (yyTok == Tok_Ident) {
- continue;
- } else if (yyTok == Tok_Arrow) {
- yyTok = getToken();
- } else if (parenlevel == 0) {
- return false;
- }
- }
- return true;
-}
-
-static QStringList resolveNamespaces(
- const QStringList &namespaces, const QHash<QString, QStringList> &namespaceAliases)
-{
- static QString strColons(QLatin1String("::"));
-
- QStringList ns;
- foreach (const QString &cns, namespaces) {
- ns << cns;
- ns = namespaceAliases.value(ns.join(strColons), ns);
- }
- return ns;
-}
-
-static QStringList getFullyQualifiedNamespaceName(
- const QSet<QString> &allNamespaces, const QStringList &namespaces,
- const QHash<QString, QStringList> &namespaceAliases,
- const QStringList &segments)
-{
- static QString strColons(QLatin1String("::"));
-
- if (segments.first().isEmpty()) {
- // fully qualified
- QStringList segs = segments;
- segs.removeFirst();
- return resolveNamespaces(segs, namespaceAliases);
- } else {
- for (int n = namespaces.count(); --n >= -1; ) {
- QStringList ns;
- for (int i = 0; i <= n; ++i) // Note: n == -1 possible
- ns << namespaces[i];
- foreach (const QString &cns, segments) {
- ns << cns;
- ns = namespaceAliases.value(ns.join(strColons), ns);
- }
- if (allNamespaces.contains(ns.join(strColons)))
- return ns;
- }
-
- // Fallback when the namespace was declared in a header, etc.
- QStringList ns = namespaces;
- ns += segments;
- return ns;
- }
-}
-
-static QString getFullyQualifiedClassName(
- const QSet<QString> &allClasses, const QStringList &namespaces,
- const QHash<QString, QStringList> &namespaceAliases,
- const QString &ident, bool hasPrefix)
-{
- static QString strColons(QLatin1String("::"));
-
- QString context = ident;
- QStringList segments = context.split(strColons);
- if (segments.first().isEmpty()) {
- // fully qualified
- segments.removeFirst();
- context = resolveNamespaces(segments, namespaceAliases).join(strColons);
- } else {
- for (int n = namespaces.count(); --n >= -1; ) {
- QStringList ns;
- for (int i = 0; i <= n; ++i) // Note: n == -1 possible
- ns.append(namespaces[i]);
- foreach (const QString &cns, segments) {
- ns.append(cns);
- ns = namespaceAliases.value(ns.join(strColons), ns);
- }
- QString nctx = ns.join(strColons);
- if (allClasses.contains(nctx)) {
- context = nctx;
- goto gotit;
- }
- }
-
- if (!hasPrefix && namespaces.count())
- context = namespaces.join(strColons) + strColons + context;
- }
-gotit:
- //qDebug() << "CLASSES:" << allClasses << "NAMEPACES:" << namespaces
- // << "IDENT:" << ident << "CONTEXT:" << context;
- return context;
-}
-
-
-static QString transcode(const QString &str, bool utf8)
-{
- static const char tab[] = "abfnrtv";
- static const char backTab[] = "\a\b\f\n\r\t\v";
- const QString in = (!utf8 || yySourceIsUnicode)
- ? str : QString::fromUtf8(yySourceCodec->fromUnicode(str).data());
- QString out;
-
- out.reserve(in.length());
- for (int i = 0; i < in.length();) {
- ushort c = in[i++].unicode();
- if (c == '\\') {
- if (i >= in.length())
- break;
- c = in[i++].unicode();
-
- if (c == '\n')
- continue;
-
- if (c == 'x') {
- QByteArray hex;
- while (i < in.length() && isxdigit((c = in[i].unicode()))) {
- hex += c;
- i++;
- }
- out += hex.toUInt(0, 16);
- } else if (c >= '0' && c < '8') {
- QByteArray oct;
- int n = 0;
- oct += c;
- while (n < 2 && i < in.length() && (c = in[i].unicode()) >= '0' && c < '8') {
- i++;
- n++;
- oct += c;
- }
- out += oct.toUInt(0, 8);
- } else {
- const char *p = strchr(tab, c);
- out += QChar(QLatin1Char(!p ? c : backTab[p - tab]));
- }
- } else {
- out += c;
- }
- }
- return out;
-}
-
-static void recordMessage(
- Translator *tor, int line, const QString &context, const QString &text, const QString &comment,
- const QString &extracomment, bool utf8, bool plural)
-{
- TranslatorMessage msg(
- transcode(context, utf8), transcode(text, utf8), transcode(comment, utf8), QString(),
- yyFileName, line, QStringList(),
- TranslatorMessage::Unfinished, plural);
- msg.setExtraComment(transcode(extracomment.simplified(), utf8));
- if ((utf8 || yyForceUtf8) && !yyCodecIsUtf8 && msg.needs8Bit())
- msg.setUtf8(true);
- tor->extend(msg);
-}
-
-static void parse(Translator *tor, const QString &initialContext, const QString &defaultContext)
-{
- static QString strColons(QLatin1String("::"));
-
- QMap<QString, QString> qualifiedContexts;
- QSet<QString> allClasses;
- QSet<QString> allNamespaces;
- QHash<QString, QStringList> namespaceAliases;
- QStringList namespaces;
- QString context;
- QString text;
- QString comment;
- QString extracomment;
- QString functionContext = initialContext;
- QString prefix;
-#ifdef DIAGNOSE_RETRANSLATABILITY
- QString functionName;
-#endif
- int line;
- bool utf8 = false;
- bool missing_Q_OBJECT = false;
-
- yyTok = getToken();
- while (yyTok != Tok_Eof) {
- //qDebug() << "TOKEN: " << yyTok;
- switch (yyTok) {
- case Tok_class:
- yyTokColonSeen = false;
- /*
- Partial support for inlined functions.
- */
- yyTok = getToken();
- if (yyBraceDepth == namespaces.count() && yyParenDepth == 0) {
- QStringList fct;
- do {
- /*
- This code should execute only once, but we play
- safe with impure definitions such as
- 'class Q_EXPORT QMessageBox', in which case
- 'QMessageBox' is the class name, not 'Q_EXPORT'.
- */
- fct = QStringList(yyIdent);
- yyTok = getToken();
- } while (yyTok == Tok_Ident);
- while (yyTok == Tok_ColonColon) {
- yyTok = getToken();
- if (yyTok != Tok_Ident)
- break; // Oops ...
- fct += yyIdent;
- yyTok = getToken();
- }
- functionContext = resolveNamespaces(namespaces + fct, namespaceAliases).join(strColons);
- allClasses.insert(functionContext);
-
- if (yyTok == Tok_Colon) {
- missing_Q_OBJECT = true;
- // Skip any token until '{' since lupdate might do things wrong if it finds
- // a '::' token here.
- do {
- yyTok = getToken();
- } while (yyTok != Tok_LeftBrace && yyTok != Tok_Eof);
- } else {
- //functionContext = defaultContext;
- }
- }
- break;
- case Tok_namespace:
- yyTokColonSeen = false;
- yyTok = getToken();
- if (yyTok == Tok_Ident) {
- QString ns = yyIdent;
- yyTok = getToken();
- if (yyTok == Tok_LeftBrace) {
- if (yyBraceDepth == namespaces.count() + 1) {
- namespaces.append(ns);
- allNamespaces.insert(namespaces.join(strColons));
- }
- } else if (yyTok == Tok_Equals) {
- // e.g. namespace Is = OuterSpace::InnerSpace;
- QStringList alias = namespaces;
- alias.append(ns);
- QStringList fullName;
- yyTok = getToken();
- if (yyTok == Tok_ColonColon)
- fullName.append(QString());
- while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
- if (yyTok == Tok_Ident)
- fullName.append(yyIdent);
- yyTok = getToken();
- }
- namespaceAliases[alias.join(strColons)] =
- getFullyQualifiedNamespaceName(allNamespaces, namespaces, namespaceAliases, fullName);
- }
- }
- break;
- case Tok_tr:
- case Tok_trUtf8:
- utf8 = (yyTok == Tok_trUtf8);
- line = yyLineNo;
- yyTok = getToken();
- if (match(Tok_LeftParen) && matchString(&text) && !text.isEmpty()) {
- comment.clear();
- bool plural = false;
-
- if (match(Tok_RightParen)) {
- // no comment
- } else if (match(Tok_Comma) && matchStringOrNull(&comment)) { //comment
- if (match(Tok_RightParen)) {
- // ok,
- } else if (match(Tok_Comma)) {
- plural = true;
- }
- }
- if (prefix.isEmpty()) {
- context = functionContext;
- } else {
-#ifdef DIAGNOSE_RETRANSLATABILITY
- int last = prefix.lastIndexOf(strColons);
- QString className = prefix.mid(last == -1 ? 0 : last + 2);
- if (!className.isEmpty() && className == functionName) {
- qWarning("%s::%d: It is not recommended to call tr() from within a constructor '%s::%s' ",
- qPrintable(yyFileName), yyLineNo,
- className.constData(), functionName.constData());
- }
-#endif
- prefix.chop(2);
- context = getFullyQualifiedClassName(allClasses, namespaces, namespaceAliases, prefix, true);
- }
- prefix.clear();
- if (qualifiedContexts.contains(context))
- context = qualifiedContexts[context];
-
- if (!text.isEmpty())
- recordMessage(tor, line, context, text, comment, extracomment, utf8, plural);
-
- if (lacks_Q_OBJECT.contains(context)) {
- qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro",
- qPrintable(yyFileName), yyLineNo,
- qPrintable(context));
- lacks_Q_OBJECT.remove(context);
- } else {
- needs_Q_OBJECT.insert(context);
- }
- }
- extracomment.clear();
- break;
- case Tok_translateUtf8:
- case Tok_translate:
- utf8 = (yyTok == Tok_translateUtf8);
- line = yyLineNo;
- yyTok = getToken();
- if (match(Tok_LeftParen)
- && matchString(&context)
- && match(Tok_Comma)
- && matchString(&text))
- {
- comment.clear();
- bool plural = false;
- if (!match(Tok_RightParen)) {
- // look for comment
- if (match(Tok_Comma) && matchStringOrNull(&comment)) {
- if (!match(Tok_RightParen)) {
- // look for encoding
- if (match(Tok_Comma)) {
- if (matchEncoding(&utf8)) {
- if (!match(Tok_RightParen)) {
- // look for the plural quantifier,
- // this can be a number, an identifier or
- // a function call,
- // so for simplicity we mark it as plural if
- // we know we have a comma instead of an
- // right parentheses.
- plural = match(Tok_Comma);
- }
- } else {
- // This can be a QTranslator::translate("context",
- // "source", "comment", n) plural translation
- if (matchExpression() && match(Tok_RightParen)) {
- plural = true;
- } else {
- break;
- }
- }
- } else {
- break;
- }
- }
- } else {
- break;
- }
- }
- if (!text.isEmpty())
- recordMessage(tor, line, context, text, comment, extracomment, utf8, plural);
- }
- extracomment.clear();
- break;
- case Tok_Q_DECLARE_TR_FUNCTIONS:
- case Tok_Q_OBJECT:
- missing_Q_OBJECT = false;
- yyTok = getToken();
- break;
- case Tok_Ident:
- prefix += yyIdent;
- yyTok = getToken();
- if (yyTok != Tok_ColonColon)
- prefix.clear();
- break;
- case Tok_Comment:
- if (yyComment.startsWith(QLatin1Char(':'))) {
- yyComment.remove(0, 1);
- extracomment.append(yyComment);
- } else {
- comment = yyComment.simplified();
- if (comment.startsWith(QLatin1String(MagicComment))) {
- comment.remove(0, sizeof(MagicComment) - 1);
- int k = comment.indexOf(QLatin1Char(' '));
- if (k == -1) {
- context = comment;
- } else {
- context = comment.left(k);
- comment.remove(0, k + 1);
- recordMessage(tor, yyLineNo, context, QString(), comment, extracomment, false, false);
- }
-
- /*
- Provide a backdoor for people using "using
- namespace". See the manual for details.
- */
- k = 0;
- while ((k = context.indexOf(strColons, k)) != -1) {
- qualifiedContexts.insert(context.mid(k + 2), context);
- k++;
- }
- }
- }
- yyTok = getToken();
- break;
- case Tok_Arrow:
- yyTok = getToken();
- if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
- qWarning("%s:%d: Cannot invoke tr() like this",
- qPrintable(yyFileName), yyLineNo);
- break;
- case Tok_ColonColon:
- if (yyBraceDepth == namespaces.count() && yyParenDepth == 0 && !yyTokColonSeen)
- functionContext = getFullyQualifiedClassName(allClasses, namespaces, namespaceAliases, prefix, false);
- prefix += strColons;
- yyTok = getToken();
-#ifdef DIAGNOSE_RETRANSLATABILITY
- if (yyTok == Tok_Ident && yyBraceDepth == namespaces.count() && yyParenDepth == 0)
- functionName = yyIdent;
-#endif
- break;
- case Tok_RightBrace:
- case Tok_Semicolon:
- prefix.clear();
- extracomment.clear();
- yyTokColonSeen = false;
- if (yyBraceDepth >= 0 && yyBraceDepth + 1 == namespaces.count())
- namespaces.removeLast();
- if (yyBraceDepth == namespaces.count()) {
- if (missing_Q_OBJECT) {
- if (needs_Q_OBJECT.contains(functionContext)) {
- qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro",
- qPrintable(yyFileName), yyLineNo,
- qPrintable(functionContext));
- } else {
- lacks_Q_OBJECT.insert(functionContext);
- }
- }
- functionContext = defaultContext;
- missing_Q_OBJECT = false;
- }
- yyTok = getToken();
- break;
- case Tok_Colon:
- yyTokColonSeen = true;
- yyTok = getToken();
- break;
- case Tok_LeftParen:
- case Tok_RightParen:
- case Tok_LeftBrace:
- yyTokColonSeen = false;
- yyTok = getToken();
- break;
- default:
- yyTok = getToken();
- break;
- }
- }
-
- if (yyBraceDepth != 0)
- qWarning("%s:%d: Unbalanced braces in C++ code (or abuse of the C++"
- " preprocessor)\n",
- qPrintable(yyFileName), yyBraceLineNo);
- else if (yyParenDepth != 0)
- qWarning("%s:%d: Unbalanced parentheses in C++ code (or abuse of the C++"
- " preprocessor)\n",
- qPrintable(yyFileName), yyParenLineNo);
-}
-
-/*
- Fetches tr() calls in C++ code in UI files (inside "<function>"
- tag). This mechanism is obsolete.
-*/
-void fetchtrInlinedCpp(const QString &in, Translator &translator, const QString &context)
-{
- yyInStr = in;
- yyInPos = 0;
- yyFileName = QString();
- yyCodecIsUtf8 = (translator.codecName() == "UTF-8");
- yyForceUtf8 = true;
- yySourceIsUnicode = true;
- yySavedBraceDepth.clear();
- yySavedParenDepth.clear();
- yyBraceDepth = 0;
- yyParenDepth = 0;
- yyCurLineNo = 1;
- yyBraceLineNo = 1;
- yyParenLineNo = 1;
- yyCh = getChar();
-
- parse(&translator, context, QString());
-}
-
-
-bool loadCPP(Translator &translator, QIODevice &dev, ConversionData &cd)
-{
- QString defaultContext = cd.m_defaultContext;
-
- yyCodecIsUtf8 = (translator.codecName() == "UTF-8");
- yyForceUtf8 = false;
- QTextStream ts(&dev);
- QByteArray codecName = cd.m_codecForSource.isEmpty()
- ? translator.codecName() : cd.m_codecForSource;
- ts.setCodec(QTextCodec::codecForName(codecName));
- ts.setAutoDetectUnicode(true);
- yySourceCodec = ts.codec();
- if (yySourceCodec->name() == "UTF-16")
- translator.setCodecName("System");
- yySourceIsUnicode = yySourceCodec->name().startsWith("UTF-");
- yyInStr = ts.readAll();
- yyInPos = 0;
- yyFileName = cd.m_sourceFileName;
- yySavedBraceDepth.clear();
- yySavedParenDepth.clear();
- yyBraceDepth = 0;
- yyParenDepth = 0;
- yyCurLineNo = 1;
- yyBraceLineNo = 1;
- yyParenLineNo = 1;
- yyCh = getChar();
-
- parse(&translator, defaultContext, defaultContext);
-
- return true;
-}
-
-int initCPP()
-{
- Translator::FileFormat format;
- format.extension = QLatin1String("cpp");
- format.fileType = Translator::FileFormat::SourceCode;
- format.priority = 0;
- format.description = QObject::tr("C++ source files");
- format.loader = &loadCPP;
- format.saver = 0;
- Translator::registerFileFormat(format);
- return 1;
-}
-
-Q_CONSTRUCTOR_FUNCTION(initCPP)
-
-QT_END_NAMESPACE