tools/linguist/lupdate/cpp.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   133     // Class definitions may appear multiple times - but only because we are trying to
   133     // Class definitions may appear multiple times - but only because we are trying to
   134     // "compile" all sources irrespective of build configuration.
   134     // "compile" all sources irrespective of build configuration.
   135     // Nested classes may be forward-declared inside a definition, and defined in another file.
   135     // Nested classes may be forward-declared inside a definition, and defined in another file.
   136     // The latter will detach the class' child list, so clones need a backlink to the original
   136     // The latter will detach the class' child list, so clones need a backlink to the original
   137     // definition (either one in case of multiple definitions).
   137     // definition (either one in case of multiple definitions).
       
   138     // Namespaces can have tr() functions as well, so we need to track parent definitions for
       
   139     // them as well. The complication is that we may have to deal with a forrest instead of
       
   140     // a tree - in that case the parent will be arbitrary. However, it seem likely that
       
   141     // Q_DECLARE_TR_FUNCTIONS would be used either in "class-like" namespaces with a central
       
   142     // header or only locally in a file.
   138     Namespace *classDef;
   143     Namespace *classDef;
   139 
   144 
   140     QString trQualification;
   145     QString trQualification;
   141 
   146 
   142     bool hasTrFunctions;
   147     bool hasTrFunctions;
   254     static QStringList stringListifySegments(const QList<HashString> &namespaces);
   259     static QStringList stringListifySegments(const QList<HashString> &namespaces);
   255     bool qualifyOneCallbackOwn(const Namespace *ns, void *context) const;
   260     bool qualifyOneCallbackOwn(const Namespace *ns, void *context) const;
   256     bool qualifyOneCallbackUsing(const Namespace *ns, void *context) const;
   261     bool qualifyOneCallbackUsing(const Namespace *ns, void *context) const;
   257     bool qualifyOne(const NamespaceList &namespaces, int nsCnt, const HashString &segment,
   262     bool qualifyOne(const NamespaceList &namespaces, int nsCnt, const HashString &segment,
   258                     NamespaceList *resolved) const;
   263                     NamespaceList *resolved) const;
   259     bool fullyQualify(const NamespaceList &namespaces, const QList<HashString> &segments,
   264     bool fullyQualify(const NamespaceList &namespaces, int nsCnt,
   260                       bool isDeclaration,
   265                       const QList<HashString> &segments, bool isDeclaration,
   261                       NamespaceList *resolved, QStringList *unresolved) const;
   266                       NamespaceList *resolved, QStringList *unresolved) const;
   262     bool fullyQualify(const NamespaceList &namespaces, const QString &segments,
   267     bool fullyQualify(const NamespaceList &namespaces,
   263                       bool isDeclaration,
   268                       const QList<HashString> &segments, bool isDeclaration,
       
   269                       NamespaceList *resolved, QStringList *unresolved) const;
       
   270     bool fullyQualify(const NamespaceList &namespaces,
       
   271                       const QString &segments, bool isDeclaration,
   264                       NamespaceList *resolved, QStringList *unresolved) const;
   272                       NamespaceList *resolved, QStringList *unresolved) const;
   265     bool findNamespaceCallback(const Namespace *ns, void *context) const;
   273     bool findNamespaceCallback(const Namespace *ns, void *context) const;
   266     const Namespace *findNamespace(const NamespaceList &namespaces, int nsCount = -1) const;
   274     const Namespace *findNamespace(const NamespaceList &namespaces, int nsCount = -1) const;
   267     void enterNamespace(NamespaceList *namespaces, const HashString &name);
   275     void enterNamespace(NamespaceList *namespaces, const HashString &name);
   268     void truncateNamespaces(NamespaceList *namespaces, int lenght);
   276     void truncateNamespaces(NamespaceList *namespaces, int lenght);
   269     Namespace *modifyNamespace(NamespaceList *namespaces, bool tryOrigin = true);
   277     Namespace *modifyNamespace(NamespaceList *namespaces, bool haveLast = true);
   270 
   278 
   271     enum {
   279     enum {
   272         Tok_Eof, Tok_class, Tok_friend, Tok_namespace, Tok_using, Tok_return,
   280         Tok_Eof, Tok_class, Tok_friend, Tok_namespace, Tok_using, Tok_return,
   273         Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8, Tok_trid,
   281         Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8, Tok_trid,
   274         Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS,
   282         Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS,
   296     int yyBraceLineNo;
   304     int yyBraceLineNo;
   297     int yyParenLineNo;
   305     int yyParenLineNo;
   298 
   306 
   299     // the string to read from and current position in the string
   307     // the string to read from and current position in the string
   300     QTextCodec *yySourceCodec;
   308     QTextCodec *yySourceCodec;
   301     bool yySourceIsUnicode;
       
   302     QString yyInStr;
   309     QString yyInStr;
   303     const ushort *yyInPtr;
   310     const ushort *yyInPtr;
   304 
   311 
   305     // Parser state
   312     // Parser state
   306     uint yyTok;
   313     uint yyTok;
   343 void CppParser::setInput(const QString &in)
   350 void CppParser::setInput(const QString &in)
   344 {
   351 {
   345     yyInStr = in;
   352     yyInStr = in;
   346     yyFileName = QString();
   353     yyFileName = QString();
   347     yySourceCodec = 0;
   354     yySourceCodec = 0;
   348     yySourceIsUnicode = true;
       
   349     yyForceUtf8 = true;
   355     yyForceUtf8 = true;
   350 }
   356 }
   351 
   357 
   352 void CppParser::setInput(QTextStream &ts, const QString &fileName)
   358 void CppParser::setInput(QTextStream &ts, const QString &fileName)
   353 {
   359 {
   354     yyInStr = ts.readAll();
   360     yyInStr = ts.readAll();
   355     yyFileName = fileName;
   361     yyFileName = fileName;
   356     yySourceCodec = ts.codec();
   362     yySourceCodec = ts.codec();
   357     yySourceIsUnicode = yySourceCodec->name().startsWith("UTF-");
       
   358     yyForceUtf8 = false;
   363     yyForceUtf8 = false;
   359 }
   364 }
   360 
   365 
   361 /*
   366 /*
   362   The first part of this source file is the C++ tokenizer.  We skip
   367   The first part of this source file is the C++ tokenizer.  We skip
   778                     forever {
   783                     forever {
   779                         yyCh = getChar();
   784                         yyCh = getChar();
   780                         if (yyCh == EOF) {
   785                         if (yyCh == EOF) {
   781                             qWarning("%s:%d: Unterminated C++ comment\n",
   786                             qWarning("%s:%d: Unterminated C++ comment\n",
   782                                      qPrintable(yyFileName), yyLineNo);
   787                                      qPrintable(yyFileName), yyLineNo);
   783                             return Tok_Comment;
   788                             break;
   784                         }
   789                         }
   785                         *ptr++ = yyCh;
   790                         *ptr++ = yyCh;
   786 
   791 
   787                         if (yyCh == '*')
   792                         if (yyCh == '*')
   788                             metAster = true;
   793                             metAster = true;
   956     functionContext = state->functionContext;
   961     functionContext = state->functionContext;
   957     functionContextUnresolved = state->functionContextUnresolved;
   962     functionContextUnresolved = state->functionContextUnresolved;
   958     pendingContext = state->pendingContext;
   963     pendingContext = state->pendingContext;
   959 }
   964 }
   960 
   965 
   961 Namespace *CppParser::modifyNamespace(NamespaceList *namespaces, bool tryOrigin)
   966 Namespace *CppParser::modifyNamespace(NamespaceList *namespaces, bool haveLast)
   962 {
   967 {
   963     Namespace *pns, *ns = &results->rootNamespace;
   968     Namespace *pns, *ns = &results->rootNamespace;
   964     for (int i = 1; i < namespaces->count(); ++i) {
   969     for (int i = 1; i < namespaces->count(); ++i) {
   965         pns = ns;
   970         pns = ns;
   966         if (!(ns = pns->children.value(namespaces->at(i)))) {
   971         if (!(ns = pns->children.value(namespaces->at(i)))) {
   967             do {
   972             do {
   968                 ns = new Namespace;
   973                 ns = new Namespace;
   969                 if (tryOrigin)
   974                 if (haveLast || i < namespaces->count() - 1)
   970                     if (const Namespace *ons = findNamespace(*namespaces, i + 1))
   975                     if (const Namespace *ons = findNamespace(*namespaces, i + 1))
   971                         ns->classDef = ons->classDef;
   976                         ns->classDef = ons->classDef;
   972                 pns->children.insert(namespaces->at(i), ns);
   977                 pns->children.insert(namespaces->at(i), ns);
   973                 pns = ns;
   978                 pns = ns;
   974             } while (++i < namespaces->count());
   979             } while (++i < namespaces->count());
  1050         *data->resolved << data->segment;
  1055         *data->resolved << data->segment;
  1051         return true;
  1056         return true;
  1052     }
  1057     }
  1053     QHash<HashString, NamespaceList>::ConstIterator nsai = ns->aliases.constFind(data->segment);
  1058     QHash<HashString, NamespaceList>::ConstIterator nsai = ns->aliases.constFind(data->segment);
  1054     if (nsai != ns->aliases.constEnd()) {
  1059     if (nsai != ns->aliases.constEnd()) {
  1055         *data->resolved = *nsai;
  1060         const NamespaceList &nsl = *nsai;
       
  1061         if (nsl.last().value().isEmpty()) { // Delayed alias resolution
       
  1062             NamespaceList &nslIn = *const_cast<NamespaceList *>(&nsl);
       
  1063             nslIn.removeLast();
       
  1064             NamespaceList nslOut;
       
  1065             if (!fullyQualify(data->namespaces, data->nsCount, nslIn, false, &nslOut, 0)) {
       
  1066                 const_cast<Namespace *>(ns)->aliases.remove(data->segment);
       
  1067                 return false;
       
  1068             }
       
  1069             nslIn = nslOut;
       
  1070         }
       
  1071         *data->resolved = nsl;
  1056         return true;
  1072         return true;
  1057     }
  1073     }
  1058     return false;
  1074     return false;
  1059 }
  1075 }
  1060 
  1076 
  1079         return true;
  1095         return true;
  1080 
  1096 
  1081     return visitNamespace(namespaces, nsCnt, &CppParser::qualifyOneCallbackUsing, &data);
  1097     return visitNamespace(namespaces, nsCnt, &CppParser::qualifyOneCallbackUsing, &data);
  1082 }
  1098 }
  1083 
  1099 
  1084 bool CppParser::fullyQualify(const NamespaceList &namespaces, const QList<HashString> &segments,
  1100 bool CppParser::fullyQualify(const NamespaceList &namespaces, int nsCnt,
  1085                              bool isDeclaration,
  1101                              const QList<HashString> &segments, bool isDeclaration,
  1086                              NamespaceList *resolved, QStringList *unresolved) const
  1102                              NamespaceList *resolved, QStringList *unresolved) const
  1087 {
  1103 {
  1088     int nsIdx;
  1104     int nsIdx;
  1089     int initSegIdx;
  1105     int initSegIdx;
  1090 
  1106 
  1097         }
  1113         }
  1098         initSegIdx = 1;
  1114         initSegIdx = 1;
  1099         nsIdx = 0;
  1115         nsIdx = 0;
  1100     } else {
  1116     } else {
  1101         initSegIdx = 0;
  1117         initSegIdx = 0;
  1102         nsIdx = namespaces.count() - 1;
  1118         nsIdx = nsCnt - 1;
  1103     }
  1119     }
  1104 
  1120 
  1105     do {
  1121     do {
  1106         if (qualifyOne(namespaces, nsIdx + 1, segments[initSegIdx], resolved)) {
  1122         if (qualifyOne(namespaces, nsIdx + 1, segments[initSegIdx], resolved)) {
  1107             int segIdx = initSegIdx;
  1123             int segIdx = initSegIdx;
  1120     if (unresolved)
  1136     if (unresolved)
  1121         *unresolved = stringListifySegments(segments.mid(initSegIdx));
  1137         *unresolved = stringListifySegments(segments.mid(initSegIdx));
  1122     return false;
  1138     return false;
  1123 }
  1139 }
  1124 
  1140 
  1125 bool CppParser::fullyQualify(const NamespaceList &namespaces, const QString &quali,
  1141 bool CppParser::fullyQualify(const NamespaceList &namespaces,
  1126                              bool isDeclaration,
  1142                              const QList<HashString> &segments, bool isDeclaration,
       
  1143                              NamespaceList *resolved, QStringList *unresolved) const
       
  1144 {
       
  1145     return fullyQualify(namespaces, namespaces.count(),
       
  1146                         segments, isDeclaration, resolved, unresolved);
       
  1147 }
       
  1148 
       
  1149 bool CppParser::fullyQualify(const NamespaceList &namespaces,
       
  1150                              const QString &quali, bool isDeclaration,
  1127                              NamespaceList *resolved, QStringList *unresolved) const
  1151                              NamespaceList *resolved, QStringList *unresolved) const
  1128 {
  1152 {
  1129     static QString strColons(QLatin1String("::"));
  1153     static QString strColons(QLatin1String("::"));
  1130 
  1154 
  1131     QList<HashString> segments;
  1155     QList<HashString> segments;
  1401 
  1425 
  1402 QString CppParser::transcode(const QString &str, bool utf8)
  1426 QString CppParser::transcode(const QString &str, bool utf8)
  1403 {
  1427 {
  1404     static const char tab[] = "abfnrtv";
  1428     static const char tab[] = "abfnrtv";
  1405     static const char backTab[] = "\a\b\f\n\r\t\v";
  1429     static const char backTab[] = "\a\b\f\n\r\t\v";
  1406     const QString in = (!utf8 || yySourceIsUnicode)
  1430     // This function has to convert back to bytes, as C's \0* sequences work at that level.
  1407         ? str : QString::fromUtf8(yySourceCodec->fromUnicode(str).data());
  1431     const QByteArray in = yyForceUtf8 ? str.toUtf8() : tor->codec()->fromUnicode(str);
  1408     QString out;
  1432     QByteArray out;
  1409 
  1433 
  1410     out.reserve(in.length());
  1434     out.reserve(in.length());
  1411     for (int i = 0; i < in.length();) {
  1435     for (int i = 0; i < in.length();) {
  1412         ushort c = in[i++].unicode();
  1436         uchar c = in[i++];
  1413         if (c == '\\') {
  1437         if (c == '\\') {
  1414             if (i >= in.length())
  1438             if (i >= in.length())
  1415                 break;
  1439                 break;
  1416             c = in[i++].unicode();
  1440             c = in[i++];
  1417 
  1441 
  1418             if (c == '\n')
  1442             if (c == '\n')
  1419                 continue;
  1443                 continue;
  1420 
  1444 
  1421             if (c == 'x') {
  1445             if (c == 'x') {
  1422                 QByteArray hex;
  1446                 QByteArray hex;
  1423                 while (i < in.length() && isxdigit((c = in[i].unicode()))) {
  1447                 while (i < in.length() && isxdigit((c = in[i]))) {
  1424                     hex += c;
  1448                     hex += c;
  1425                     i++;
  1449                     i++;
  1426                 }
  1450                 }
  1427                 out += hex.toUInt(0, 16);
  1451                 out += hex.toUInt(0, 16);
  1428             } else if (c >= '0' && c < '8') {
  1452             } else if (c >= '0' && c < '8') {
  1429                 QByteArray oct;
  1453                 QByteArray oct;
  1430                 int n = 0;
  1454                 int n = 0;
  1431                 oct += c;
  1455                 oct += c;
  1432                 while (n < 2 && i < in.length() && (c = in[i].unicode()) >= '0' && c < '8') {
  1456                 while (n < 2 && i < in.length() && (c = in[i]) >= '0' && c < '8') {
  1433                     i++;
  1457                     i++;
  1434                     n++;
  1458                     n++;
  1435                     oct += c;
  1459                     oct += c;
  1436                 }
  1460                 }
  1437                 out += oct.toUInt(0, 8);
  1461                 out += oct.toUInt(0, 8);
  1438             } else {
  1462             } else {
  1439                 const char *p = strchr(tab, c);
  1463                 const char *p = strchr(tab, c);
  1440                 out += QChar(QLatin1Char(!p ? c : backTab[p - tab]));
  1464                 out += !p ? c : backTab[p - tab];
  1441             }
  1465             }
  1442         } else {
  1466         } else {
  1443             out += c;
  1467             out += c;
  1444         }
  1468         }
  1445     }
  1469     }
  1446     return out;
  1470     return (utf8 || yyForceUtf8) ? QString::fromUtf8(out.constData(), out.length())
       
  1471                                  : tor->codec()->toUnicode(out);
  1447 }
  1472 }
  1448 
  1473 
  1449 void CppParser::recordMessage(
  1474 void CppParser::recordMessage(
  1450     int line, const QString &context, const QString &text, const QString &comment,
  1475     int line, const QString &context, const QString &text, const QString &comment,
  1451     const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
  1476     const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra,
  1631                         }
  1656                         }
  1632                         yyTok = getToken();
  1657                         yyTok = getToken();
  1633                     }
  1658                     }
  1634                     if (fullName.isEmpty())
  1659                     if (fullName.isEmpty())
  1635                         break;
  1660                         break;
  1636                     NamespaceList nsl;
  1661                     fullName.append(HashString(QString())); // Mark as unresolved
  1637                     if (fullyQualify(namespaces, fullName, false, &nsl, 0))
  1662                     modifyNamespace(&namespaces)->aliases[ns] = fullName;
  1638                         modifyNamespace(&namespaces, false)->aliases[ns] = nsl;
       
  1639                 }
  1663                 }
  1640             } else if (yyTok == Tok_LeftBrace) {
  1664             } else if (yyTok == Tok_LeftBrace) {
  1641                 // Anonymous namespace
  1665                 // Anonymous namespace
  1642                 namespaceDepths.push(namespaces.count());
  1666                 namespaceDepths.push(namespaces.count());
  1643                 yyTok = getToken();
  1667                 yyTok = getToken();
  1659                     }
  1683                     }
  1660                     yyTok = getToken();
  1684                     yyTok = getToken();
  1661                 }
  1685                 }
  1662                 NamespaceList nsl;
  1686                 NamespaceList nsl;
  1663                 if (fullyQualify(namespaces, fullName, false, &nsl, 0))
  1687                 if (fullyQualify(namespaces, fullName, false, &nsl, 0))
  1664                     modifyNamespace(&namespaces, false)->usings << HashStringList(nsl);
  1688                     modifyNamespace(&namespaces)->usings << HashStringList(nsl);
  1665             } else {
  1689             } else {
  1666                 QList<HashString> fullName;
  1690                 QList<HashString> fullName;
  1667                 if (yyTok == Tok_ColonColon)
  1691                 if (yyTok == Tok_ColonColon)
  1668                     fullName.append(HashString(QString()));
  1692                     fullName.append(HashString(QString()));
  1669                 while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
  1693                 while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
  1674                     }
  1698                     }
  1675                     yyTok = getToken();
  1699                     yyTok = getToken();
  1676                 }
  1700                 }
  1677                 if (fullName.isEmpty())
  1701                 if (fullName.isEmpty())
  1678                     break;
  1702                     break;
  1679                 NamespaceList nsl;
  1703                 // using-declarations cannot rename classes, so the last element of
  1680                 if (fullyQualify(namespaces, fullName, false, &nsl, 0))
  1704                 // fullName is already the resolved name we actually want.
  1681                     modifyNamespace(&namespaces, true)->aliases[nsl.last()] = nsl;
  1705                 // As we do no resolution here, we'll collect useless usings of data
       
  1706                 // members and methods as well. This is no big deal.
       
  1707                 HashString &ns = fullName.last();
       
  1708                 fullName.append(HashString(QString())); // Mark as unresolved
       
  1709                 modifyNamespace(&namespaces)->aliases[ns] = fullName;
  1682             }
  1710             }
  1683             break;
  1711             break;
  1684         case Tok_tr:
  1712         case Tok_tr:
  1685         case Tok_trUtf8:
  1713         case Tok_trUtf8:
  1686             if (!tor)
  1714             if (!tor)
  1851             extra.clear();
  1879             extra.clear();
  1852             break;
  1880             break;
  1853         case Tok_trid:
  1881         case Tok_trid:
  1854             if (!tor)
  1882             if (!tor)
  1855                 goto case_default;
  1883                 goto case_default;
  1856             if (sourcetext.isEmpty()) {
  1884             if (!msgid.isEmpty())
  1857                 yyTok = getToken();
  1885                 qWarning("%s:%d: //= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n",
  1858             } else {
  1886                          qPrintable(yyFileName), yyLineNo);
  1859                 if (!msgid.isEmpty())
  1887             //utf8 = false; // Maybe use //%% or something like that
  1860                     qWarning("%s:%d: //= cannot be used with qtTrId() / QT_TRID_NOOP(). Ignoring\n",
  1888             line = yyLineNo;
  1861                              qPrintable(yyFileName), yyLineNo);
  1889             yyTok = getToken();
  1862                 //utf8 = false; // Maybe use //%% or something like that
  1890             if (match(Tok_LeftParen) && matchString(&msgid) && !msgid.isEmpty()) {
  1863                 line = yyLineNo;
  1891                 bool plural = match(Tok_Comma);
  1864                 yyTok = getToken();
  1892                 recordMessage(line, QString(), sourcetext, QString(), extracomment,
  1865                 if (match(Tok_LeftParen) && matchString(&msgid) && !msgid.isEmpty()) {
  1893                               msgid, extra, false, plural);
  1866                     bool plural = match(Tok_Comma);
  1894             }
  1867                     recordMessage(line, QString(), sourcetext, QString(), extracomment,
  1895             sourcetext.clear();
  1868                                   msgid, extra, false, plural);
       
  1869                 }
       
  1870                 sourcetext.clear();
       
  1871             }
       
  1872             extracomment.clear();
  1896             extracomment.clear();
  1873             msgid.clear();
  1897             msgid.clear();
  1874             extra.clear();
  1898             extra.clear();
  1875             break;
  1899             break;
  1876         case Tok_Q_DECLARE_TR_FUNCTIONS:
  1900         case Tok_Q_DECLARE_TR_FUNCTIONS:
  1877             if (getMacroArgs()) {
  1901             if (getMacroArgs()) {
  1878                 Namespace *ns = modifyNamespace(&namespaces, true);
  1902                 Namespace *ns = modifyNamespace(&namespaces);
  1879                 ns->hasTrFunctions = true;
  1903                 ns->hasTrFunctions = true;
  1880                 ns->trQualification = yyWord;
  1904                 ns->trQualification = yyWord;
  1881                 ns->trQualification.detach();
  1905                 ns->trQualification.detach();
  1882             }
  1906             }
  1883             yyTok = getToken();
  1907             yyTok = getToken();
  1884             break;
  1908             break;
  1885         case Tok_Q_OBJECT:
  1909         case Tok_Q_OBJECT:
  1886             modifyNamespace(&namespaces, true)->hasTrFunctions = true;
  1910             modifyNamespace(&namespaces)->hasTrFunctions = true;
  1887             yyTok = getToken();
  1911             yyTok = getToken();
  1888             break;
  1912             break;
  1889         case Tok_Ident:
  1913         case Tok_Ident:
  1890             prefix += yyWord;
  1914             prefix += yyWord;
  1891             prefix.detach();
  1915             prefix.detach();
  1894                 prefix.clear();
  1918                 prefix.clear();
  1895                 if (yyTok == Tok_Ident && !yyParenDepth)
  1919                 if (yyTok == Tok_Ident && !yyParenDepth)
  1896                     prospectiveContext.clear();
  1920                     prospectiveContext.clear();
  1897             }
  1921             }
  1898             break;
  1922             break;
  1899         case Tok_Comment:
  1923         case Tok_Comment: {
  1900             if (!tor)
  1924             if (!tor)
  1901                 goto case_default;
  1925                 goto case_default;
  1902             if (yyWord.startsWith(QLatin1Char(':'))) {
  1926             const QChar *ptr = yyWord.unicode();
  1903                 yyWord.remove(0, 1);
  1927             if (*ptr == QLatin1Char(':') && ptr[1].isSpace()) {
       
  1928                 yyWord.remove(0, 2);
  1904                 extracomment += yyWord;
  1929                 extracomment += yyWord;
  1905                 extracomment.detach();
  1930                 extracomment.detach();
  1906             } else if (yyWord.startsWith(QLatin1Char('='))) {
  1931             } else if (*ptr == QLatin1Char('=') && ptr[1].isSpace()) {
  1907                 yyWord.remove(0, 1);
  1932                 yyWord.remove(0, 2);
  1908                 msgid = yyWord.simplified();
  1933                 msgid = yyWord.simplified();
  1909                 msgid.detach();
  1934                 msgid.detach();
  1910             } else if (yyWord.startsWith(QLatin1Char('~'))) {
  1935             } else if (*ptr == QLatin1Char('~') && ptr[1].isSpace()) {
  1911                 yyWord.remove(0, 1);
  1936                 yyWord.remove(0, 2);
  1912                 text = yyWord.trimmed();
  1937                 text = yyWord.trimmed();
  1913                 int k = text.indexOf(QLatin1Char(' '));
  1938                 int k = text.indexOf(QLatin1Char(' '));
  1914                 if (k > -1)
  1939                 if (k > -1)
  1915                     extra.insert(text.left(k), text.mid(k + 1).trimmed());
  1940                     extra.insert(text.left(k), text.mid(k + 1).trimmed());
  1916                 text.clear();
  1941                 text.clear();
  1917             } else if (yyWord.startsWith(QLatin1Char('%'))) {
  1942             } else if (*ptr == QLatin1Char('%') && ptr[1].isSpace()) {
  1918                 sourcetext.reserve(sourcetext.length() + yyWord.length());
  1943                 sourcetext.reserve(sourcetext.length() + yyWord.length() - 2);
  1919                 ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
  1944                 ushort *ptr = (ushort *)sourcetext.data() + sourcetext.length();
  1920                 int p = 1, c;
  1945                 int p = 2, c;
  1921                 forever {
  1946                 forever {
  1922                     if (p >= yyWord.length())
  1947                     if (p >= yyWord.length())
  1923                         break;
  1948                         break;
  1924                     c = yyWord.unicode()[p++].unicode();
  1949                     c = yyWord.unicode()[p++].unicode();
  1925                     if (isspace(c))
  1950                     if (isspace(c))
  1975                     }
  2000                     }
  1976                 }
  2001                 }
  1977             }
  2002             }
  1978             yyTok = getToken();
  2003             yyTok = getToken();
  1979             break;
  2004             break;
       
  2005         }
  1980         case Tok_Arrow:
  2006         case Tok_Arrow:
  1981             yyTok = getToken();
  2007             yyTok = getToken();
  1982             if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
  2008             if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
  1983                 qWarning("%s:%d: Cannot invoke tr() like this\n",
  2009                 qWarning("%s:%d: Cannot invoke tr() like this\n",
  1984                           qPrintable(yyFileName), yyLineNo);
  2010                           qPrintable(yyFileName), yyLineNo);
  2120 
  2146 
  2121         CppParser parser;
  2147         CppParser parser;
  2122         QTextStream ts(&file);
  2148         QTextStream ts(&file);
  2123         ts.setCodec(codec);
  2149         ts.setCodec(codec);
  2124         ts.setAutoDetectUnicode(true);
  2150         ts.setAutoDetectUnicode(true);
  2125         if (ts.codec()->name() == "UTF-16")
  2151         parser.setInput(ts, filename);
       
  2152         if (cd.m_outputCodec.isEmpty() && ts.codec()->name() == "UTF-16")
  2126             translator.setCodecName("System");
  2153             translator.setCodecName("System");
  2127         parser.setInput(ts, filename);
       
  2128         Translator *tor = new Translator;
  2154         Translator *tor = new Translator;
  2129         tor->setCodecName(translator.codecName());
  2155         tor->setCodecName(translator.codecName());
  2130         parser.setTranslator(tor);
  2156         parser.setTranslator(tor);
  2131         QSet<QString> inclusions;
  2157         QSet<QString> inclusions;
  2132         parser.parse(cd.m_defaultContext, cd, inclusions);
  2158         parser.parse(cd.m_defaultContext, cd, inclusions);