Ignore:
Timestamp:
Mar 8, 2010, 12:52:58 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.2 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/tools/linguist/lupdate/main.cpp

    r561 r651  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include <translator.h>
    4545#include <profileevaluator.h>
    46 #include <proreader.h>
    4746
    4847#include <QtCore/QCoreApplication>
     
    119118        "           Disable the named merge heuristic. Can be specified multiple times.\n"
    120119        "    -pro <filename>\n"
    121         "           Name of a .pro file. Useful for files with .pro\n"
    122         "           file syntax but different file suffix\n"
     120        "           Name of a .pro file. Useful for files with .pro file syntax but\n"
     121        "           different file suffix. Projects are recursed into and merged.\n"
    123122        "    -source-language <language>[_<region>]\n"
    124123        "           Specify the language of the source strings for new files.\n"
     
    127126        "           Specify the language of the translations for new files.\n"
    128127        "           Guessed from the file name if not specified.\n"
     128        "    -ts <ts-file>...\n"
     129        "           Specify the output file(s). This will override the TRANSLATIONS\n"
     130        "           and nullify the CODECFORTR from possibly specified project files.\n"
     131        "    -codecfortr <codec>\n"
     132        "           Specify the codec assumed for tr() calls. Effective only with -ts.\n"
    129133        "    -version\n"
    130134        "           Display the version of lupdate and exit.\n"
     
    215219}
    216220
     221static QStringList getSources(const char *var, const char *vvar, const QStringList &baseVPaths,
     222                              const QString &projectDir, const ProFileEvaluator &visitor)
     223{
     224    QStringList vPaths = visitor.absolutePathValues(QLatin1String(vvar), projectDir);
     225    vPaths += baseVPaths;
     226    vPaths.removeDuplicates();
     227    return visitor.absoluteFileValues(QLatin1String(var), projectDir, vPaths, 0);
     228}
     229
     230static QStringList getSources(const ProFileEvaluator &visitor, const QString &projectDir)
     231{
     232    QStringList baseVPaths;
     233    baseVPaths += visitor.absolutePathValues(QLatin1String("VPATH"), projectDir);
     234    baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
     235    baseVPaths += visitor.absolutePathValues(QLatin1String("DEPENDPATH"), projectDir);
     236    baseVPaths.removeDuplicates();
     237
     238    QStringList sourceFiles;
     239
     240    // app/lib template
     241    sourceFiles += getSources("SOURCES", "VPATH_SOURCES", baseVPaths, projectDir, visitor);
     242
     243    sourceFiles += getSources("FORMS", "VPATH_FORMS", baseVPaths, projectDir, visitor);
     244    sourceFiles += getSources("FORMS3", "VPATH_FORMS3", baseVPaths, projectDir, visitor);
     245
     246    QStringList vPathsInc = baseVPaths;
     247    vPathsInc += visitor.absolutePathValues(QLatin1String("INCLUDEPATH"), projectDir);
     248    vPathsInc.removeDuplicates();
     249    sourceFiles += visitor.absoluteFileValues(QLatin1String("HEADERS"), projectDir, vPathsInc, 0);
     250
     251    sourceFiles.removeDuplicates();
     252    sourceFiles.sort();
     253
     254    return sourceFiles;
     255}
     256
     257static void processSources(Translator &fetchedTor,
     258                           const QStringList &sourceFiles, ConversionData &cd)
     259{
     260    QStringList sourceFilesCpp;
     261    for (QStringList::const_iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) {
     262        if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive))
     263            loadJava(fetchedTor, *it, cd);
     264        else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)
     265                 || it->endsWith(QLatin1String(".jui"), Qt::CaseInsensitive))
     266            loadUI(fetchedTor, *it, cd);
     267        else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
     268                 || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
     269            loadQScript(fetchedTor, *it, cd);
     270        else
     271            sourceFilesCpp << *it;
     272    }
     273    loadCPP(fetchedTor, sourceFilesCpp, cd);
     274    if (!cd.error().isEmpty())
     275        printOut(cd.error());
     276}
     277
     278static void processProjects(
     279        bool topLevel, bool nestComplain, const QStringList &proFiles,
     280        UpdateOptions options, const QByteArray &codecForSource,
     281        const QString &targetLanguage, const QString &sourceLanguage,
     282        Translator *parentTor, bool *fail);
     283
     284static void processProject(
     285        bool nestComplain, const QFileInfo &pfi, ProFileEvaluator &visitor,
     286        UpdateOptions options, const QByteArray &_codecForSource,
     287        const QString &targetLanguage, const QString &sourceLanguage,
     288        Translator *fetchedTor, bool *fail)
     289{
     290    QByteArray codecForSource = _codecForSource;
     291    QStringList tmp = visitor.values(QLatin1String("CODECFORSRC"));
     292    if (!tmp.isEmpty()) {
     293        codecForSource = tmp.last().toLatin1();
     294        if (!QTextCodec::codecForName(codecForSource)) {
     295            qWarning("lupdate warning: Codec for source '%s' is invalid. "
     296                     "Falling back to codec for tr().", codecForSource.constData());
     297            codecForSource.clear();
     298        }
     299    }
     300    if (visitor.templateType() == ProFileEvaluator::TT_Subdirs) {
     301        QStringList subProFiles;
     302        QDir proDir(pfi.absoluteDir());
     303        foreach (const QString &subdir, visitor.values(QLatin1String("SUBDIRS"))) {
     304            QString subPro = QDir::cleanPath(proDir.absoluteFilePath(subdir));
     305            QFileInfo subInfo(subPro);
     306            if (subInfo.isDir())
     307                subProFiles << (subPro + QLatin1Char('/')
     308                                + subInfo.fileName() + QLatin1String(".pro"));
     309            else
     310                subProFiles << subPro;
     311        }
     312        processProjects(false, nestComplain, subProFiles, options, codecForSource,
     313                        targetLanguage, sourceLanguage, fetchedTor, fail);
     314    } else {
     315        ConversionData cd;
     316        cd.m_noUiLines = options & NoUiLines;
     317        cd.m_codecForSource = codecForSource;
     318        cd.m_includePath = visitor.values(QLatin1String("INCLUDEPATH"));
     319        QStringList sourceFiles = getSources(visitor, pfi.absolutePath());
     320        QSet<QString> sourceDirs;
     321        sourceDirs.insert(QDir::cleanPath(pfi.absolutePath()) + QLatin1Char('/'));
     322        foreach (const QString &sf, sourceFiles)
     323            sourceDirs.insert(sf.left(sf.lastIndexOf(QLatin1Char('/')) + 1));
     324        QStringList rootList = sourceDirs.toList();
     325        rootList.sort();
     326        for (int prev = 0, curr = 1; curr < rootList.length(); )
     327            if (rootList.at(curr).startsWith(rootList.at(prev)))
     328                rootList.removeAt(curr);
     329            else
     330                prev = curr++;
     331        cd.m_projectRoots = QSet<QString>::fromList(rootList);
     332        processSources(*fetchedTor, sourceFiles, cd);
     333    }
     334}
     335
     336static void processProjects(
     337        bool topLevel, bool nestComplain, const QStringList &proFiles,
     338        UpdateOptions options, const QByteArray &codecForSource,
     339        const QString &targetLanguage, const QString &sourceLanguage,
     340        Translator *parentTor, bool *fail)
     341{
     342    foreach (const QString &proFile, proFiles) {
     343        ProFileEvaluator visitor;
     344        visitor.setVerbose(options & Verbose);
     345
     346        QFileInfo pfi(proFile);
     347        ProFile pro(pfi.absoluteFilePath());
     348        if (!visitor.queryProFile(&pro) || !visitor.accept(&pro)) {
     349            if (topLevel)
     350                *fail = true;
     351            continue;
     352        }
     353
     354        if (visitor.contains(QLatin1String("TRANSLATIONS"))) {
     355            if (parentTor) {
     356                if (topLevel) {
     357                    std::cerr << "lupdate warning: TS files from command line "
     358                            "will override TRANSLATIONS in " << qPrintable(proFile) << ".\n";
     359                    goto noTrans;
     360                } else if (nestComplain) {
     361                    std::cerr << "lupdate warning: TS files from command line "
     362                            "prevent recursing into " << qPrintable(proFile) << ".\n";
     363                    continue;
     364                }
     365            }
     366            QStringList tsFiles;
     367            QDir proDir(pfi.absolutePath());
     368            foreach (const QString &tsFile, visitor.values(QLatin1String("TRANSLATIONS")))
     369                tsFiles << QFileInfo(proDir, tsFile).filePath();
     370            if (tsFiles.isEmpty()) {
     371                // This might mean either a buggy PRO file or an intentional detach -
     372                // we can't know without seeing the actual RHS of the assignment ...
     373                // Just assume correctness and be silent.
     374                continue;
     375            }
     376            Translator tor;
     377            QByteArray codecForTr;
     378            QStringList tmp = visitor.values(QLatin1String("CODEC"))
     379                              + visitor.values(QLatin1String("DEFAULTCODEC"))
     380                              + visitor.values(QLatin1String("CODECFORTR"));
     381            if (!tmp.isEmpty()) {
     382                codecForTr = tmp.last().toLatin1();
     383                tor.setCodecName(codecForTr);
     384            }
     385            processProject(false, pfi, visitor, options, codecForSource,
     386                           targetLanguage, sourceLanguage, &tor, fail);
     387            updateTsFiles(tor, tsFiles, codecForTr, sourceLanguage, targetLanguage, options, fail);
     388            continue;
     389        }
     390      noTrans:
     391        if (!parentTor) {
     392            if (topLevel)
     393                std::cerr << "lupdate warning: no TS files specified. Only diagnostics "
     394                        "will be produced for '" << qPrintable(proFile) << "'.\n";
     395            Translator tor;
     396            processProject(nestComplain, pfi, visitor, options, codecForSource,
     397                           targetLanguage, sourceLanguage, &tor, fail);
     398        } else {
     399            processProject(nestComplain, pfi, visitor, options, codecForSource,
     400                           targetLanguage, sourceLanguage, parentTor, fail);
     401        }
     402    }
     403}
     404
    217405int main(int argc, char **argv)
    218406{
     
    221409
    222410    QStringList args = app.arguments();
    223     QString defaultContext; // This was QLatin1String("@default") before.
    224     Translator fetchedTor;
    225     QByteArray codecForTr;
    226     QByteArray codecForSource;
    227411    QStringList tsFileNames;
    228412    QStringList proFiles;
     
    233417    QString targetLanguage;
    234418    QString sourceLanguage;
     419    QByteArray codecForTr;
    235420
    236421    UpdateOptions options =
     
    238423        HeuristicSameText | HeuristicSimilarText | HeuristicNumber;
    239424    int numFiles = 0;
    240     bool standardSyntax = true;
    241425    bool metTsFlag = false;
    242426    bool recursiveScan = true;
     
    244428    QString extensions = m_defaultExtensions;
    245429    QSet<QString> extensionsNameFilters;
    246 
    247     for (int  i = 1; i < argc; ++i) {
    248         if (args.at(i) == QLatin1String("-ts"))
    249             standardSyntax = false;
    250     }
    251430
    252431    for (int i = 1; i < argc; ++i) {
     
    337516            printOut(QObject::tr("lupdate version %1\n").arg(QLatin1String(QT_VERSION_STR)));
    338517            return 0;
     518        } else if (arg == QLatin1String("-codecfortr")) {
     519            ++i;
     520            if (i == argc) {
     521                qWarning("The -codecfortr option should be followed by a codec name.");
     522                return 1;
     523            }
     524            codecForTr = args[i].toLatin1();
     525            continue;
    339526        } else if (arg == QLatin1String("-ts")) {
    340527            metTsFlag = true;
     
    373560            return 1;
    374561        }
    375 
    376         numFiles++;
    377 
    378         QString fullText;
    379 
    380         codecForTr.clear();
    381         codecForSource.clear();
    382562
    383563        if (metTsFlag) {
     
    404584                || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
    405585            proFiles << arg;
     586            numFiles++;
    406587        } else {
    407588            QFileInfo fi(arg);
     
    448629                sourceFiles << QDir::cleanPath(fi.absoluteFilePath());;
    449630            }
     631            numFiles++;
    450632        }
    451633    } // for args
    452634
    453     foreach (const QString &proFile, proFiles)
    454         projectRoots.insert(QDir::cleanPath(QFileInfo(proFile).absolutePath()) + QLatin1Char('/'));
    455 
    456     bool firstPass = true;
     635    if (numFiles == 0) {
     636        printUsage();
     637        return 1;
     638    }
     639
     640    if (!targetLanguage.isEmpty() && tsFileNames.count() != 1)
     641        std::cerr << "lupdate warning: -target-language usually only "
     642                     "makes sense with exactly one TS file.\n";
     643    if (!codecForTr.isEmpty() && tsFileNames.isEmpty())
     644        std::cerr << "lupdate warning: -codecfortr has no effect without -ts.\n";
     645
    457646    bool fail = false;
    458     while (firstPass || !proFiles.isEmpty()) {
     647    if (proFiles.isEmpty()) {
     648        if (tsFileNames.isEmpty())
     649            std::cerr << "lupdate warning: no TS files specified. "
     650                         "Only diagnostics will be produced.\n";
     651
     652        Translator fetchedTor;
    459653        ConversionData cd;
    460         cd.m_defaultContext = defaultContext;
    461654        cd.m_noUiLines = options & NoUiLines;
    462655        cd.m_projectRoots = projectRoots;
    463656        cd.m_includePath = includePath;
    464657        cd.m_allCSources = allCSources;
    465 
    466         QStringList tsFiles = tsFileNames;
    467         if (proFiles.count() > 0) {
    468             QFileInfo pfi(proFiles.takeFirst());
    469             QHash<QByteArray, QStringList> variables;
    470 
    471             ProFileEvaluator visitor;
    472             visitor.setVerbose(options & Verbose);
    473 
    474             ProFile pro(pfi.absoluteFilePath());
    475             if (!visitor.queryProFile(&pro))
    476                 return 2;
    477             if (!visitor.accept(&pro))
    478                 return 2;
    479 
    480             if (visitor.templateType() == ProFileEvaluator::TT_Subdirs) {
    481                 QDir proDir(pfi.absoluteDir());
    482                 foreach (const QString &subdir, visitor.values(QLatin1String("SUBDIRS"))) {
    483                     QString subPro = QDir::cleanPath(proDir.absoluteFilePath(subdir));
    484                     QFileInfo subInfo(subPro);
    485                     if (subInfo.isDir())
    486                         proFiles << (subPro + QLatin1Char('/')
    487                                      + subInfo.fileName() + QLatin1String(".pro"));
    488                     else
    489                         proFiles << subPro;
    490                 }
    491                 continue;
    492             }
    493 
    494             cd.m_includePath += visitor.values(QLatin1String("INCLUDEPATH"));
    495 
    496             evaluateProFile(visitor, &variables, pfi.absolutePath());
    497 
    498             sourceFiles = variables.value("SOURCES");
    499 
    500             QStringList tmp = variables.value("CODECFORTR");
    501             if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
    502                 codecForTr = tmp.first().toLatin1();
    503                 fetchedTor.setCodecName(codecForTr);
    504                 cd.m_outputCodec = codecForTr;
    505             }
    506             tmp = variables.value("CODECFORSRC");
    507             if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
    508                 codecForSource = tmp.first().toLatin1();
    509                 if (!QTextCodec::codecForName(codecForSource))
    510                     qWarning("lupdate warning: Codec for source '%s' is invalid. Falling back to codec for tr().",
    511                              codecForSource.constData());
    512                 else
    513                     cd.m_codecForSource = codecForSource;
    514             }
    515 
    516             tsFiles += variables.value("TRANSLATIONS");
    517         }
    518 
    519         QStringList sourceFilesCpp;
    520         for (QStringList::iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) {
    521             if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive))
    522                 loadJava(fetchedTor, *it, cd);
    523             else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)
    524                      || it->endsWith(QLatin1String(".jui"), Qt::CaseInsensitive))
    525                 loadUI(fetchedTor, *it, cd);
    526             else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
    527                      || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive))
    528                 loadQScript(fetchedTor, *it, cd);
    529             else
    530                 sourceFilesCpp << *it;
    531         }
    532         loadCPP(fetchedTor, sourceFilesCpp, cd);
    533         if (!cd.error().isEmpty())
    534             printOut(cd.error());
    535 
    536         tsFiles.sort();
    537         tsFiles.removeDuplicates();
    538 
    539         if (!tsFiles.isEmpty())
    540             updateTsFiles(fetchedTor, tsFiles, codecForTr, sourceLanguage, targetLanguage, options, &fail);
    541 
    542         firstPass = false;
     658        fetchedTor.setCodecName(codecForTr);
     659        processSources(fetchedTor, sourceFiles, cd);
     660        updateTsFiles(fetchedTor, tsFileNames, codecForTr,
     661                      sourceLanguage, targetLanguage, options, &fail);
     662    } else {
     663        if (!sourceFiles.isEmpty() || !includePath.isEmpty()) {
     664            qWarning("lupdate error: Both project and source files / include paths specified.\n");
     665            return 1;
     666        }
     667        if (!tsFileNames.isEmpty()) {
     668            Translator fetchedTor;
     669            fetchedTor.setCodecName(codecForTr);
     670            processProjects(true, true, proFiles, options, QByteArray(),
     671                            targetLanguage, sourceLanguage, &fetchedTor, &fail);
     672            updateTsFiles(fetchedTor, tsFileNames, codecForTr,
     673                          sourceLanguage, targetLanguage, options, &fail);
     674        } else {
     675            processProjects(true, false, proFiles, options, QByteArray(),
     676                            targetLanguage, sourceLanguage, 0, &fail);
     677        }
    543678    }
    544 
    545     if (numFiles == 0) {
    546         printUsage();
    547         return 1;
    548     }
    549 
    550679    return fail ? 1 : 0;
    551680}
Note: See TracChangeset for help on using the changeset viewer.