tools/porting/src/port.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the qt3to4 porting application of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "projectporter.h"
       
    43 #include "fileporter.h"
       
    44 #include "logger.h"
       
    45 #include "preprocessorcontrol.h"
       
    46 
       
    47 #include <QString>
       
    48 #include <QFile>
       
    49 #include <QFileInfo>
       
    50 #include <QDir>
       
    51 #include <QByteArray>
       
    52 #include <QBuffer>
       
    53 #include <QTextStream>
       
    54 #include <QCoreApplication>
       
    55 #include <QLibraryInfo>
       
    56 #include <QtDebug>
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 QString rulesFilePath;
       
    61 QString applicationDirPath;
       
    62 
       
    63 QString findRulesFile(const QString &fileName)
       
    64 {
       
    65     // Check QLibraryInfo::DataPath/filename
       
    66     QString filePath;
       
    67     filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/") + fileName)  ;
       
    68     if (QFile::exists(filePath))
       
    69         return QFileInfo(filePath).canonicalFilePath();
       
    70 
       
    71     // Check QLibraryInfo::PrefixPath/tools/porting/src/filename
       
    72     filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::PrefixPath) + QLatin1String("/tools/porting/src/") + fileName);
       
    73     if (QFile::exists(filePath))
       
    74         return QFileInfo(filePath).canonicalFilePath();
       
    75 
       
    76     //no luck
       
    77     return QString();
       
    78 }
       
    79 
       
    80 /*
       
    81     A option contains an argument and its help text.
       
    82 */
       
    83 class Option
       
    84 {
       
    85 public:
       
    86     Option(const QString &argument, const QString &description)
       
    87     :argument(argument), description(description) {}
       
    88 
       
    89     /*
       
    90         Checks if candidateArgument matches the options argument.
       
    91     */
       
    92     bool checkArgument(const QString &candidateArgument) const
       
    93     {
       
    94         return (candidateArgument == argument) ||
       
    95                (candidateArgument.toLower() == argument.toLower());
       
    96     }
       
    97 
       
    98     QString argument;
       
    99     QString description;
       
   100 };
       
   101 
       
   102 typedef QList<Option> OptionList;
       
   103 
       
   104 void usage(const OptionList &optionList)
       
   105 {
       
   106     printf("Tool for porting Qt 3 applications to Qt 4, using the compatibility library\n");
       
   107     printf("and compatibility functions in the core library.\n");
       
   108     printf("Usage: qt3to4 [options] <Infile>, [Infile], ...\n");
       
   109     printf("\n");
       
   110     printf("Infile can be a source file or a project file.\n");
       
   111     printf("If you specify a project file, ending with .pro or .pri,\n");
       
   112     printf("qt3to4 will port all files specified in that project.\n");
       
   113     printf("\n");
       
   114     printf("Options:\n");
       
   115 
       
   116     // Find the length of the longest argument.
       
   117     int argumentMaxLenght = 0;
       
   118     foreach (const Option option, optionList) {
       
   119         if (option.argument.count() > argumentMaxLenght)
       
   120             argumentMaxLenght = option.argument.count();
       
   121     }
       
   122 
       
   123     // Print the options, pad with spaces between the argument and description where needed.
       
   124     const int extraSpaces = 5;
       
   125     foreach (const Option option, optionList) {
       
   126         printf("%s", option.argument.toLocal8Bit().constData());
       
   127         for (int i = 0; i < argumentMaxLenght - option.argument.count() + extraSpaces; ++i)
       
   128             printf(" ");
       
   129         puts(option.description.toLocal8Bit().constData());
       
   130     }
       
   131 
       
   132     printf("\n");
       
   133     printf("The porting documentation contains more information on how\n");
       
   134     printf("to use qt3to4 as well as general porting information.\n");
       
   135 }
       
   136 
       
   137 int runPort(int argc, char**argv)
       
   138 {
       
   139     QCoreApplication app(argc, argv);
       
   140     applicationDirPath = app.applicationDirPath();
       
   141     QString defaultRulesFileName = QLatin1String("q3porting.xml");
       
   142     QStringList inFileNames;
       
   143     QStringList includeSearchDirectories;
       
   144     bool enableCppParsing = true;
       
   145     bool useBuildtinQt3Headers = true;
       
   146     bool showMissingFilesWarnings = false;
       
   147     bool alwaysOverwrite = false;
       
   148     int currentArg = 1;
       
   149 
       
   150     const Option helpOption(QLatin1String("-h"), QLatin1String("Display this help."));
       
   151     const Option rulesFileOption(QLatin1String("-rulesFile"), QLatin1String("Specify the location for the rules file."));
       
   152     const Option includeDirectoryOption(QLatin1String("-I"), QLatin1String("Add directory to the list of directories to be searched for header files."));
       
   153     const Option disableCppParsingOption(QLatin1String("-disableCppParsing"), QLatin1String("Disable the C++ parsing component."));
       
   154     const Option disableBuiltinQt3HeadersOption(QLatin1String("-disableBuiltinQt3Headers"), QLatin1String("Do not use the built-in Qt 3 headers."));
       
   155     const Option missingFileWarningsOption(QLatin1String("-missingFileWarnings"), QLatin1String("Warn about files not found while searching for header files."));
       
   156     const Option alwaysOverwriteOption(QLatin1String("-alwaysOverwrite"), QLatin1String("Port all files without prompting."));
       
   157     const Option strictOption(QLatin1String("-strict"), QLatin1String("Be stricter when selecting which tokens to replace."));
       
   158 
       
   159     const OptionList optionList = OptionList() << helpOption << alwaysOverwriteOption << rulesFileOption
       
   160                                                << includeDirectoryOption << disableCppParsingOption
       
   161                                                << disableBuiltinQt3HeadersOption << missingFileWarningsOption
       
   162                                                << strictOption;
       
   163 
       
   164     if (argc == 1) {
       
   165         usage(optionList);
       
   166         return 0;
       
   167     }
       
   168 
       
   169     // Read arguments.
       
   170     while (currentArg < argc) {
       
   171         QString argText = QLatin1String(argv[currentArg]);
       
   172         if(argText.isEmpty()) {
       
   173             continue;
       
   174         } else if (argText == QLatin1String("--help") || argText == QLatin1String("/h") || argText == QLatin1String("-help")
       
   175             || argText == QLatin1String("-h")  || argText == QLatin1String("-?") || argText == QLatin1String("/?")) {
       
   176             usage(optionList);
       
   177             return 0;
       
   178         } else if (rulesFileOption.checkArgument(argText)) {
       
   179             ++currentArg;
       
   180             if (currentArg >= argc) {
       
   181                 printf("You must specify a file name along with %s \n", argText.toLocal8Bit().constData());
       
   182                 return 0;
       
   183             }
       
   184             rulesFilePath = QLatin1String(argv[currentArg]);
       
   185 
       
   186             if (!QFile::exists(rulesFilePath)) {
       
   187                 printf("File not found: %s\n", rulesFilePath.toLocal8Bit().constData());
       
   188                 return 0;
       
   189             }
       
   190         } else if (includeDirectoryOption.checkArgument(argText)) {
       
   191             ++currentArg;
       
   192             if (currentArg >= argc) {
       
   193                 printf("You must specify a directory name along with %s\n",
       
   194                      argText.toLocal8Bit().constData());
       
   195                 return 0;
       
   196             }
       
   197             includeSearchDirectories += QLatin1String(argv[currentArg]);
       
   198         } else if (disableCppParsingOption.checkArgument(argText)) {
       
   199             enableCppParsing = false;
       
   200         } else if (strictOption.checkArgument(argText)) {
       
   201             // Enable strict mode, this is used by the ScopedTokenReplacement constructor. 
       
   202             Logger::instance()->globalState.insert(QLatin1String("strictMode"), QLatin1String(""));
       
   203         } else if (disableBuiltinQt3HeadersOption.checkArgument(argText)) {
       
   204             useBuildtinQt3Headers = false;
       
   205         } else if (missingFileWarningsOption.checkArgument(argText)) {
       
   206             showMissingFilesWarnings = true;
       
   207         } else if (alwaysOverwriteOption.checkArgument(argText)) {
       
   208             alwaysOverwrite = true;
       
   209             FileWriter::instance()->setOverwriteFiles(FileWriter::AlwaysOverWrite);
       
   210         } else if (argText[0]  == QLatin1Char('-')) {
       
   211             printf("Unknown option %s\n", argText.toLocal8Bit().constData());
       
   212             return 0;
       
   213         } else {
       
   214             inFileNames.append(argText);
       
   215         }
       
   216         ++currentArg;
       
   217     }
       
   218 
       
   219     if (rulesFilePath.isEmpty())
       
   220         rulesFilePath = findRulesFile(defaultRulesFileName);
       
   221 
       
   222     // Check if we have a rule file.
       
   223     if (!QFile::exists(rulesFilePath)) {
       
   224         printf("Error: Could not find the %s rule file: ", defaultRulesFileName.toLocal8Bit().constData());
       
   225         printf("Please try specifying the location of the file with the %s option \n", 
       
   226             rulesFileOption.argument.toLocal8Bit().constData());
       
   227         return 0;
       
   228     }
       
   229 
       
   230     // Check if we have any infiles
       
   231     if (inFileNames.isEmpty()) {
       
   232         printf("You must specify a file name. \n");
       
   233         return 0;
       
   234     }
       
   235 
       
   236     // Read rule file and create PortingRules instance.
       
   237     printf("Using rules file: ");
       
   238     puts(QDir::toNativeSeparators(rulesFilePath).toLocal8Bit().constData());
       
   239     PortingRules::createInstance(rulesFilePath);
       
   240 
       
   241 
       
   242     // Construct a ProjectPorter object add pass it the options.
       
   243     QStringList builtinQtheaders;
       
   244     if (useBuildtinQt3Headers) {
       
   245         builtinQtheaders += QLatin1String(":qt3headers0.resource");
       
   246         builtinQtheaders += QLatin1String(":qt3headers1.resource");
       
   247         builtinQtheaders += QLatin1String(":qt3headers2.resource");
       
   248         builtinQtheaders += QLatin1String(":qt3headers3.resource");
       
   249     }
       
   250 
       
   251     ProjectPorter porter(QDir::currentPath(), includeSearchDirectories, builtinQtheaders);
       
   252     porter.enableCppParsing(enableCppParsing);
       
   253     porter.enableMissingFilesWarnings(showMissingFilesWarnings);
       
   254 
       
   255     // Determine mode based on file exstesions and port.
       
   256     // (The ProjectPorter class is also used for porting single files :)
       
   257     foreach (QString inFileName, inFileNames) {
       
   258         const QString canonicalFileName = QFileInfo(inFileName).canonicalFilePath();
       
   259         if (QFile::exists(canonicalFileName)) {
       
   260             if (canonicalFileName.endsWith(QLatin1String(".pro")) || canonicalFileName.endsWith(QLatin1String(".pri")))
       
   261                 porter.portProject(canonicalFileName);
       
   262             else
       
   263                 porter.portFile(canonicalFileName);
       
   264         } else {
       
   265             printf("File not found: %s \n", QDir::toNativeSeparators(inFileName).toLocal8Bit().constData());
       
   266         }
       
   267     }
       
   268 
       
   269     // Write log
       
   270     if (Logger::instance()->numEntries() > 0) {
       
   271         QStringList report = Logger::instance()->fullReport();
       
   272         QString logFileName =  QLatin1String("portinglog.txt");
       
   273         printf("Writing log to %s \n", logFileName.toLocal8Bit().constData());
       
   274         QByteArray logContents;
       
   275         QBuffer logBuffer(&logContents);
       
   276         logBuffer.open(QIODevice::Text | QIODevice::WriteOnly);
       
   277         QTextStream logStream(&logBuffer);
       
   278         foreach (QString logLine, report) {
       
   279             logStream << logLine << endl;
       
   280         }
       
   281         logStream << endl;
       
   282 
       
   283         QFile logFile(logFileName);
       
   284         logFile.open(QIODevice::WriteOnly | QIODevice::Append);
       
   285         logFile.write(logContents);
       
   286     }
       
   287     Logger::deleteInstance();
       
   288     PortingRules::deleteInstance();
       
   289     return 0;
       
   290 }
       
   291 
       
   292 QT_END_NAMESPACE
       
   293 
       
   294 int main(int argc, char**argv)
       
   295 {
       
   296     return QT_PREPEND_NAMESPACE(runPort)(argc, argv);
       
   297 }