forked from qt-creator/qt-creator
C++: Clean up dev tools.
* Add -h and -help options describing the tools and their usage.
* Make the tools compile and run on Windows (MinGW, MSVC).
* Rename project dirs, executables and main source files to more
meaningful names:
- Use same base name for project dir, *.pro file, main source file
and (if applicable) script file.
- Use the prefix "cplusplus-".
- The names are now:
- gen-cpp-ast/generate-ast --> cplusplus-update-frontend
- mkvisitor --> cplusplus-mkvisitor
- cplusplus-dump/cplusplus0 --> cplusplus-ast2png
* Get rid of 'c++' shell scripts.
* Get rid of duplicates of 'conf.c++'. Rename to 'pp-configuration.inc'.
* Introduce src/tools/cplusplus-tools-utils containing common stuff
that is used at least in two tools. 'pp-configuration.inc' can also be
found here.
* cplusplus-update-frontend:
- Print file paths of written files to stdout.
- Convenience: Use default values referencing the appropriate dirs and
files.
* cplusplus-mkvisitor:
- Take only one argument, namely the path to AST.h.
- Convenience: Use default path to AST.h.
* cplusplus-ast2png:
- Make it run without LD_LIBRARY_PATH.
- As the name suggests, generate image files in png format (needs
'dot' from graphviz).
- Convenience: Read from stdin, which useful for small snippets.
Change-Id: I79c4061fce4a1571c0588dfedd50d4a70715d9df
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
12
.gitignore
vendored
12
.gitignore
vendored
@@ -109,8 +109,10 @@ bin/qml2puppet.exe
|
||||
bin/qtpromaker
|
||||
bin/qtpromaker.exe
|
||||
share/doc/qtcreator/*.qch
|
||||
src/tools/gen-cpp-ast/generate-ast
|
||||
src/tools/mkvisitor/cplusplus0
|
||||
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor
|
||||
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.exe
|
||||
src/tools/cplusplus-update-frontend/cplusplus-update-frontend
|
||||
src/tools/cplusplus-update-frontend/cplusplus-update-frontend.exe
|
||||
src/tools/qml/qmldump/qmldump
|
||||
src/tools/examplesscanner/examplesscanner
|
||||
src/tools/valgrindfake/valgrind-fake
|
||||
@@ -118,13 +120,15 @@ bin/*.exe
|
||||
|
||||
# Tests
|
||||
#------
|
||||
tests/manual/cplusplus-frontend/cplusplus0
|
||||
tests/manual/cplusplus-dump/cplusplus0
|
||||
tests/manual/cplusplus-frontend/cplusplus-frontend
|
||||
tests/manual/cplusplus-frontend/cplusplus-frontend.exe
|
||||
tests/manual/qml-ast2dot/qml-ast2dot
|
||||
tests/manual/debugger/simple/libsimple_test_plugin.*dylib
|
||||
tests/manual/debugger/simple/simple_test_app
|
||||
tests/manual/plain-cplusplus/plain-c++
|
||||
tests/manual/preprocessor/pp
|
||||
tests/tools/cplusplus-ast2png/cplusplus-ast2png
|
||||
tests/tools/cplusplus-ast2png/cplusplus-ast2png.exe
|
||||
tests/auto/cplusplus/codegen/tst_codegen
|
||||
tests/auto/cplusplus/ast/tst_ast
|
||||
tests/auto/cplusplus/codeformatter/tst_codeformatter
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/AST.cpp
vendored
2
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -29,7 +29,7 @@
|
||||
|
||||
/*
|
||||
All firstToken/lastToken methods below which have a doxygen comment with
|
||||
\generated in it, will be re-generated when the tool "generate-ast" is run.
|
||||
\generated in it, will be re-generated when the tool "cplusplus-update-frontend" is run.
|
||||
|
||||
For methods which are hand-coded, or which should not be changed, make sure that
|
||||
the comment is gone.
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <Overview.h>
|
||||
#include <LookupContext.h>
|
||||
|
||||
#include "cplusplus-tools-utils.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QCoreApplication>
|
||||
@@ -422,17 +424,49 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
|
||||
<< " [-v] [path to AST.h]\n\n"
|
||||
<< "Print a visitor class based on AST.h to stdout.\n\n";
|
||||
const QString defaulPath = QFileInfo(PATH_AST_H).canonicalFilePath();
|
||||
std::cout << "Default path: " << qPrintable(defaulPath) << '.' << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QStringList args = app.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
QStringList files = app.arguments();
|
||||
files.removeFirst();
|
||||
bool optionVerbose = false;
|
||||
|
||||
foreach (const QString &fileName, files) {
|
||||
QFile file(fileName);
|
||||
if (! file.open(QFile::ReadOnly))
|
||||
continue;
|
||||
// Process options & arguments
|
||||
if (args.contains("-v")) {
|
||||
optionVerbose = true;
|
||||
args.removeOne("-v");
|
||||
}
|
||||
const bool helpRequested = args.contains("-h") || args.contains("-help");
|
||||
if (helpRequested || args.count() >= 2) {
|
||||
printUsage();
|
||||
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Run the preprocessor
|
||||
QString fileName = PATH_AST_H;
|
||||
if (!args.isEmpty())
|
||||
fileName = args.first();
|
||||
|
||||
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
|
||||
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
|
||||
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
|
||||
|
||||
QFile file(fileNamePreprocessed);
|
||||
if (! file.open(QFile::ReadOnly)) {
|
||||
std::cerr << "Error: Could not open file \"" << qPrintable(file.fileName()) << "\"."
|
||||
<< std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const QByteArray source = file.readAll();
|
||||
file.close();
|
||||
@@ -441,16 +475,14 @@ int main(int argc, char *argv[])
|
||||
//doc->control()->setDiagnosticClient(0);
|
||||
doc->setUtf8Source(source);
|
||||
doc->parse();
|
||||
|
||||
doc->translationUnit()->blockErrors(true);
|
||||
|
||||
doc->check();
|
||||
|
||||
Snapshot snapshot;
|
||||
snapshot.insert(doc);
|
||||
|
||||
LookupContext context(doc, snapshot);
|
||||
MkVisitor mkVisitor(context);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
13
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.pro
Normal file
13
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.pro
Normal file
@@ -0,0 +1,13 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
win32:CONFIG += console
|
||||
TEMPLATE = app
|
||||
TARGET = cplusplus-mkvisitor
|
||||
DESTDIR = ./
|
||||
|
||||
include(../../../qtcreator.pri)
|
||||
include(../../libs/cplusplus/cplusplus-lib.pri)
|
||||
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
|
||||
|
||||
DEFINES += PATH_AST_H=\\\"$$PWD/../../libs/3rdparty/cplusplus/AST.h\\\"
|
||||
SOURCES += cplusplus-mkvisitor.cpp
|
||||
140
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.cpp
Normal file
140
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "cplusplus-tools-utils.h"
|
||||
#include "environment.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
|
||||
namespace CplusplusToolsUtils {
|
||||
|
||||
QString portableExecutableName(const QString &executable)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return executable + QLatin1String(".exe");
|
||||
#else
|
||||
return executable;
|
||||
#endif
|
||||
}
|
||||
|
||||
void executeCommand(const QString &command, const QStringList &arguments, const QString &outputFile,
|
||||
bool verbose)
|
||||
{
|
||||
QTextStream out(stderr);
|
||||
if (command.isEmpty()) {
|
||||
out << "Error: " << Q_FUNC_INFO << "Got empty command to execute." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const QString fullCommand = command + QLatin1Char(' ') + arguments.join(QLatin1String(" "));
|
||||
if (verbose)
|
||||
out << "Executing: " << fullCommand << endl;
|
||||
|
||||
QProcess process;
|
||||
if (!outputFile.isEmpty())
|
||||
process.setStandardOutputFile(outputFile, QIODevice::Truncate);
|
||||
process.start(command, arguments);
|
||||
if (!process.waitForStarted()) {
|
||||
out << QString("Error: Process \"%1\" did not start within timeout: %2.")
|
||||
.arg(fullCommand, process.errorString())
|
||||
<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!process.waitForFinished()) {
|
||||
if (!verbose)
|
||||
out << process.readAll() << endl;
|
||||
out << QString("Error: Process \"%1\" did not finish within timeout.").arg(fullCommand)
|
||||
<< endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
const int exitCode = process.exitCode();
|
||||
if (exitCode != 0) {
|
||||
out << process.readAllStandardError() << endl;
|
||||
out << QString("Error: Process \"%1\" finished with non zero exit value %2")
|
||||
.arg(fullCommand, exitCode) << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
SystemPreprocessor::SystemPreprocessor(bool verbose)
|
||||
: m_verbose(verbose)
|
||||
{
|
||||
m_knownCompilers[portableExecutableName("gcc")]
|
||||
= QLatin1String("-DCPLUSPLUS_WITHOUT_QT -U__BLOCKS__ -xc++ -E -include");
|
||||
m_knownCompilers[portableExecutableName("cl")]
|
||||
= QLatin1String("/DCPLUSPLUS_WITHOUT_QT /U__BLOCKS__ /TP /E /I . /FI");
|
||||
|
||||
QMapIterator<QString, QString> i(m_knownCompilers);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
const QString executablePath
|
||||
= Utils::Environment::systemEnvironment().searchInPath(i.key());
|
||||
if (!executablePath.isEmpty()) {
|
||||
m_compiler = i.key();
|
||||
m_compilerArguments = i.value().split(QLatin1String(" "), QString::SkipEmptyParts);
|
||||
m_compilerArguments
|
||||
<< QDir::toNativeSeparators(QLatin1String(PATH_PREPROCESSOR_CONFIG));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPreprocessor::check() const
|
||||
{
|
||||
QTextStream out(stderr);
|
||||
if (!QFile::exists(PATH_PREPROCESSOR_CONFIG)) {
|
||||
out << QString("Error: File \"%1\" does not exist.").arg(PATH_PREPROCESSOR_CONFIG) << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (m_compiler.isEmpty()) {
|
||||
const QString triedCompilers
|
||||
= QStringList(m_knownCompilers.keys()).join(QLatin1String(", "));
|
||||
out << QString("Error: No compiler found. Tried %1.").arg(triedCompilers) << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPreprocessor::preprocessFile(const QString &inputFile, const QString &outputFile) const
|
||||
{
|
||||
check();
|
||||
if (!QFile::exists(inputFile)) {
|
||||
QTextStream out(stderr);
|
||||
out << QString("Error: File \"%1\" does not exist.").arg(inputFile) << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
const QStringList arguments = QStringList(m_compilerArguments)
|
||||
<< QDir::toNativeSeparators(inputFile);
|
||||
executeCommand(m_compiler, arguments, outputFile, m_verbose);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
62
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.h
Normal file
62
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** 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, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef CPLUSPLUSTOOLSUTILS_H
|
||||
#define CPLUSPLUSTOOLSUTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
|
||||
namespace CplusplusToolsUtils {
|
||||
|
||||
QString portableExecutableName(const QString &executable);
|
||||
void executeCommand(const QString &command, const QStringList &arguments, const QString &outputFile,
|
||||
bool verbose = false);
|
||||
|
||||
// Preprocess a file by calling an external compiler in preprocessor mode (-E, /E).
|
||||
class SystemPreprocessor
|
||||
{
|
||||
public:
|
||||
SystemPreprocessor(bool verbose = false);
|
||||
void preprocessFile(const QString &inputFile, const QString &outputFile) const;
|
||||
|
||||
private:
|
||||
void check() const;
|
||||
|
||||
QMap<QString, QString> m_knownCompilers;
|
||||
QString m_compiler; // Compiler that will be called in preprocessor mode
|
||||
QStringList m_compilerArguments;
|
||||
bool m_verbose;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // CPLUSPLUSTOOLSUTILS_H
|
||||
13
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri
Normal file
13
src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri
Normal file
@@ -0,0 +1,13 @@
|
||||
DEPENDPATH += $$PWD
|
||||
INCLUDEPATH += $$PWD $$PWD/../../libs/utils
|
||||
|
||||
DEFINES += PATH_PREPROCESSOR_CONFIG=\\\"$$PWD/pp-configuration.inc\\\"
|
||||
DEFINES += QTCREATOR_UTILS_STATIC_LIB
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/cplusplus-tools-utils.h \
|
||||
$$PWD/../../libs/utils/environment.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/cplusplus-tools-utils.cpp \
|
||||
$$PWD/../../libs/utils/environment.cpp
|
||||
@@ -1,15 +1,17 @@
|
||||
#define __extension__
|
||||
#define __context__
|
||||
#define __range__
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
# define __asm(a...)
|
||||
# define __asm__(a...)
|
||||
# define __stdcall
|
||||
# define __fastcall
|
||||
#endif
|
||||
#define restrict
|
||||
#define __restrict
|
||||
#define __restrict__
|
||||
// #define __weak
|
||||
#define __builtin_va_arg(a,b) ((b)0)
|
||||
#define __stdcall
|
||||
#define __fastcall
|
||||
#define __imag__
|
||||
#define __real__
|
||||
#define __complex__
|
||||
@@ -91,12 +91,21 @@ static const char generatedHeader[] =
|
||||
"// W A R N I N G\n"
|
||||
"// -------------\n"
|
||||
"//\n"
|
||||
"// This file is automatically generated.\n"
|
||||
"// This file is automatically generated by \"cplusplus-update-frontend\".\n"
|
||||
"// Changes will be lost.\n"
|
||||
"//\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static void closeAndPrintFilePath(QFile &file)
|
||||
{
|
||||
if (file.isOpen()) {
|
||||
const QString filePath = QFileInfo(file).canonicalFilePath();
|
||||
std::cout << QDir::toNativeSeparators(filePath).toLatin1().constData() << std::endl;
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
class ASTNodes
|
||||
{
|
||||
public:
|
||||
@@ -226,6 +235,8 @@ public:
|
||||
"using namespace CPlusPlus;\n" << endl;
|
||||
|
||||
accept(ast);
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -354,7 +365,6 @@ public:
|
||||
|
||||
QTextStream output(&file);
|
||||
out = &output;
|
||||
|
||||
*out << copyrightHeader << generatedHeader <<
|
||||
"\n"
|
||||
"#include \"AST.h\"\n"
|
||||
@@ -363,6 +373,8 @@ public:
|
||||
"using namespace CPlusPlus;\n" << endl;
|
||||
|
||||
accept(ast);
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -480,6 +492,8 @@ public:
|
||||
<< endl;
|
||||
|
||||
accept(ast);
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -627,7 +641,7 @@ public:
|
||||
|
||||
accept(ast);
|
||||
|
||||
file.close();
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -761,7 +775,7 @@ public:
|
||||
|
||||
d.accept(unit->ast());
|
||||
|
||||
file.close();
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -1220,6 +1234,7 @@ void generateAST_cpp(const Snapshot &snapshot, const QDir &cplusplusDir)
|
||||
if (file.open(QFile::WriteOnly)) {
|
||||
QTextStream out(&file);
|
||||
out << cpp_document.toPlainText();
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,6 +1327,8 @@ void generateASTVisitor_H(const Snapshot &, const QDir &cplusplusDir,
|
||||
"} // namespace CPlusPlus\n"
|
||||
"\n"
|
||||
"#endif // CPLUSPLUS_ASTVISITOR_H\n";
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
|
||||
@@ -1353,6 +1370,8 @@ void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
|
||||
"} // namespace CPlusPlus\n"
|
||||
"\n"
|
||||
"#endif // CPLUSPLUS_ASTMATCHER_H\n";
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, const QString &dumpersFile)
|
||||
@@ -1437,6 +1456,7 @@ QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, co
|
||||
if (file.open(QFile::WriteOnly)) {
|
||||
QTextStream out(&file);
|
||||
out << document.toPlainText();
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
Accept0CG cg(cplusplusDir, AST_h_document->translationUnit());
|
||||
@@ -1537,6 +1557,7 @@ void generateASTFwd_h(const Snapshot &snapshot, const QDir &cplusplusDir, const
|
||||
if (file.open(QFile::WriteOnly)) {
|
||||
QTextStream out(&file);
|
||||
out << document.toPlainText();
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1664,36 +1685,67 @@ void generateASTPatternBuilder_h(const QDir &cplusplusDir)
|
||||
<< "} // end of namespace CPlusPlus" << endl
|
||||
<< endl
|
||||
<< "#endif // CPLUSPLUS_AST_PATTERN_BUILDER_H" << endl;
|
||||
|
||||
closeAndPrintFilePath(file);
|
||||
}
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
const QByteArray executable = QFileInfo(qApp->arguments().first()).fileName().toLatin1();
|
||||
std::cout << "Usage: " << executable.constData() << "\n"
|
||||
<< " " << executable.constData() << " <frontend-dir> <dumpers-file>"
|
||||
<< "\n\n"
|
||||
<< "Generate appropriate header and source files of the C++ frontend accordingly\n"
|
||||
<< "to AST.h and print the paths of the written files. Run this tool after\n"
|
||||
<< "modifying AST.h."
|
||||
<< "\n\n";
|
||||
const QString defaultPathCppFrontend = QFileInfo(PATH_CPP_FRONTEND).canonicalFilePath();
|
||||
const QString defaultPathDumpersFile = QFileInfo(PATH_DUMPERS_FILE).canonicalFilePath();
|
||||
std::cout << "Default values:" << "\n"
|
||||
<< " frontend-dir: " << qPrintable(defaultPathCppFrontend) << "\n"
|
||||
<< " dumpers-file: " << qPrintable(defaultPathDumpersFile) << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MyQApplication app(argc, argv);
|
||||
QStringList args = app.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
QStringList files = app.arguments();
|
||||
files.removeFirst();
|
||||
QString pathCppFrontend = PATH_CPP_FRONTEND;
|
||||
QString pathDumpersFile = PATH_DUMPERS_FILE;
|
||||
|
||||
if (files.size() != 1 && files.size() != 2) {
|
||||
std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl;
|
||||
std::cerr << " or: cplusplus [path to C++ front-end] [dumpers file name]" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
const bool helpRequested = args.contains("-h") || args.contains("-help");
|
||||
if (args.count() == 1 || args.count() >= 3 || helpRequested) {
|
||||
printUsage();
|
||||
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
} else if (args.count() == 2) {
|
||||
pathCppFrontend = args.at(0);
|
||||
pathDumpersFile = args.at(1);
|
||||
}
|
||||
|
||||
QDir cplusplusDir(files.first());
|
||||
QDir cplusplusDir(pathCppFrontend);
|
||||
if (!QFile::exists(pathCppFrontend)) {
|
||||
std::cerr << "Error: Directory \"" << qPrintable(cplusplusDir.absolutePath())
|
||||
<< "\" does not exist." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!QFileInfo(cplusplusDir, QLatin1String("AST.h")).exists()) {
|
||||
std::cerr << "Cannot find AST.h in " << qPrintable(cplusplusDir.absolutePath())
|
||||
<< std::endl;
|
||||
std::cerr << "Error: Cannot find AST.h in \"" << qPrintable(cplusplusDir.absolutePath())
|
||||
<< "\"." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!QFile::exists(pathDumpersFile)) {
|
||||
std::cerr << "Error: File \"" << qPrintable(pathDumpersFile)
|
||||
<< "\" does not exist." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
QString dumpersFile;
|
||||
if (files.size() == 2)
|
||||
dumpersFile = files.last();
|
||||
|
||||
Snapshot snapshot;
|
||||
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, dumpersFile);
|
||||
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, pathDumpersFile);
|
||||
astDerivedClasses.sort();
|
||||
generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
|
||||
|
||||
generateASTPatternBuilder_h(cplusplusDir);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
win32:CONFIG += console
|
||||
TEMPLATE = app
|
||||
TARGET = cplusplus-update-frontend
|
||||
DESTDIR = ./
|
||||
DEFINES += QTCREATOR_UTILS_STATIC_LIB
|
||||
INCLUDEPATH += . ../../libs
|
||||
|
||||
include(../../../qtcreator.pri)
|
||||
include(../../libs/cplusplus/cplusplus-lib.pri)
|
||||
|
||||
DEFINES += PATH_CPP_FRONTEND=\\\"$$PWD/../../libs/3rdparty/cplusplus\\\"
|
||||
DEFINES += PATH_DUMPERS_FILE=\\\"$$PWD/../../../tests/tools/cplusplus-ast2png/dumpers.inc\\\"
|
||||
SOURCES += cplusplus-update-frontend.cpp ../../libs/utils/changeset.cpp
|
||||
@@ -1,10 +0,0 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
TEMPLATE = app
|
||||
TARGET = generate-ast
|
||||
INCLUDEPATH += . ../../libs
|
||||
|
||||
include(../../libs/cplusplus/cplusplus-lib.pri)
|
||||
|
||||
# Input
|
||||
SOURCES += generate-ast.cpp ../../libs/utils/changeset.cpp
|
||||
@@ -1,15 +0,0 @@
|
||||
#define __extension__
|
||||
#define __context__
|
||||
#define __range__
|
||||
#define __asm(a...)
|
||||
#define __asm__(a...)
|
||||
#define restrict
|
||||
#define __restrict
|
||||
#define __restrict__
|
||||
// #define __weak
|
||||
#define __builtin_va_arg(a,b) ((b)0)
|
||||
#define __stdcall
|
||||
#define __fastcall
|
||||
#define __imag__
|
||||
#define __real__
|
||||
#define __complex__
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
me=$(dirname $0)
|
||||
${CPP-gcc} -DCPLUSPLUS_WITHOUT_QT -U__BLOCKS__ -xc++ -E -include $me/conf.c++ ../../libs/3rdparty/cplusplus/AST.h > $me/file.i
|
||||
$me/cplusplus0 $me/file.i
|
||||
rm -f $me/file.i
|
||||
@@ -1,20 +0,0 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
TARGET = cplusplus0
|
||||
INCLUDEPATH += . ../../libs
|
||||
|
||||
include(../../libs/cplusplus/cplusplus-lib.pri)
|
||||
|
||||
# Input
|
||||
SOURCES += main.cpp
|
||||
|
||||
unix {
|
||||
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
|
||||
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
|
||||
|
||||
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
|
||||
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
|
||||
|
||||
RCC_DIR = $${OUT_PWD}/.rcc/
|
||||
UI_DIR = $${OUT_PWD}/.uic/
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
me=$(dirname $0)
|
||||
${CPP-gcc} -U__BLOCKS__ -xc++ -E -include $me/conf.c++ $* > $me/file.i
|
||||
$me/cplusplus0 $me/file.i
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <CoreTypes.h>
|
||||
#include <CppDocument.h>
|
||||
|
||||
#include "cplusplus-tools-utils.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QCoreApplication>
|
||||
@@ -54,18 +56,47 @@
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
|
||||
<< " [-v] <file1> <file2> ...\n\n"
|
||||
<< "Run the parser with the given files.\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QStringList args = app.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
QStringList files = app.arguments();
|
||||
files.removeFirst();
|
||||
bool optionVerbose = false;
|
||||
|
||||
// Process options & arguments
|
||||
if (args.contains("-v")) {
|
||||
optionVerbose = true;
|
||||
args.removeOne("-v");
|
||||
}
|
||||
const bool helpRequested = args.contains("-h") || args.contains("-help");
|
||||
if (args.isEmpty() || helpRequested) {
|
||||
printUsage();
|
||||
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Process files
|
||||
const QStringList files = args;
|
||||
foreach (const QString &fileName, files) {
|
||||
QFile file(fileName);
|
||||
if (! file.open(QFile::ReadOnly))
|
||||
continue;
|
||||
// Run preprocessor
|
||||
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
|
||||
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
|
||||
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
|
||||
|
||||
// Run parser
|
||||
QFile file(fileNamePreprocessed);
|
||||
if (! file.open(QFile::ReadOnly)) {
|
||||
std::cerr << "Error: Could not open file \"" << qPrintable(file.fileName()) << "\"."
|
||||
<< std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
const QByteArray source = file.readAll();
|
||||
file.close();
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
TARGET = cplusplus0
|
||||
win32:CONFIG += console
|
||||
TEMPLATE = app
|
||||
TARGET = cplusplus-frontend
|
||||
DESTDIR = ./
|
||||
|
||||
include(../../../qtcreator.pri)
|
||||
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
|
||||
include($$IDE_SOURCE_TREE/src/libs/languageutils/languageutils.pri)
|
||||
include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri)
|
||||
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus-lib.pri)
|
||||
include($$IDE_SOURCE_TREE/tests/auto/qttestrpath.pri)
|
||||
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
|
||||
|
||||
# Input
|
||||
SOURCES += main.cpp
|
||||
|
||||
unix {
|
||||
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
|
||||
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
|
||||
|
||||
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
|
||||
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
|
||||
|
||||
RCC_DIR = $${OUT_PWD}/.rcc/
|
||||
UI_DIR = $${OUT_PWD}/.uic/
|
||||
}
|
||||
SOURCES += cplusplus-frontend.cpp
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
#include <SymbolVisitor.h>
|
||||
#include <Overview.h>
|
||||
|
||||
#include "cplusplus-tools-utils.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QCoreApplication>
|
||||
@@ -58,6 +61,22 @@
|
||||
# include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
// For isatty(), _isatty()
|
||||
#if defined(Q_OS_WIN)
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
bool tty_for_stdin()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return _isatty(_fileno(stdin));
|
||||
#else
|
||||
return isatty(fileno(stdin));
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
class ASTDump: protected ASTVisitor
|
||||
@@ -68,9 +87,6 @@ public:
|
||||
|
||||
void operator()(AST *ast) {
|
||||
QByteArray basename = translationUnit()->fileName();
|
||||
int dotIdx = basename.lastIndexOf('.');
|
||||
if (dotIdx != -1)
|
||||
basename.truncate(dotIdx);
|
||||
basename.append(".ast.dot");
|
||||
out.open(basename.constData());
|
||||
|
||||
@@ -89,11 +105,10 @@ public:
|
||||
|
||||
out << "}" << std::endl;
|
||||
out.close();
|
||||
std::cout << basename.constData() << std::endl;
|
||||
}
|
||||
|
||||
// the following file can be generated by using:
|
||||
// generate-ast <path to cpp stuff> <path to dumpers.inc>
|
||||
// cplusplus-update-frontend <frontend-dir> <dumpers-file>
|
||||
#include "dumpers.inc"
|
||||
|
||||
protected:
|
||||
@@ -195,9 +210,6 @@ public:
|
||||
|
||||
void operator()(Symbol *s) {
|
||||
QByteArray basename = translationUnit->fileName();
|
||||
int dotIdx = basename.lastIndexOf('.');
|
||||
if (dotIdx != -1)
|
||||
basename.truncate(dotIdx);
|
||||
basename.append(".symbols.dot");
|
||||
out.open(basename.constData());
|
||||
|
||||
@@ -218,7 +230,6 @@ public:
|
||||
|
||||
out << "}" << std::endl;
|
||||
out.close();
|
||||
std::cout << basename.constData() << std::endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -351,19 +362,103 @@ private:
|
||||
Overview o;
|
||||
};
|
||||
|
||||
|
||||
void createImageFromDot(const QString &inputFile, const QString &outputFile, bool verbose)
|
||||
{
|
||||
const QString command = CplusplusToolsUtils::portableExecutableName(QLatin1String("dot"));
|
||||
const QStringList arguments = QStringList()
|
||||
<< QLatin1String("-Tpng") << QLatin1String("-o") << outputFile << inputFile;
|
||||
CplusplusToolsUtils::executeCommand(command, arguments, QString(), verbose);
|
||||
}
|
||||
|
||||
const char PATH_STDIN_FILE[] = "_stdincontents.cpp";
|
||||
|
||||
QString example()
|
||||
{
|
||||
return
|
||||
#if defined(Q_OS_WIN)
|
||||
QString::fromLatin1("> echo int foo() {} | %1 && %2.ast.png")
|
||||
#elif defined(Q_OS_MAC)
|
||||
QString::fromLatin1("$ echo \"int foo() {}\" | ./%1 && open %2.ast.png")
|
||||
#else
|
||||
QString::fromLatin1("$ echo \"int foo() {}\" | ./%1 && xdg-open %2.ast.png")
|
||||
#endif
|
||||
.arg(QFileInfo(qApp->arguments().at(0)).fileName(), PATH_STDIN_FILE);
|
||||
}
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
std::cout << "Usage: " << qPrintable(QFileInfo(qApp->arguments().at(0)).fileName())
|
||||
<< " [-v] <file1> <file2> ...\n\n";
|
||||
|
||||
std::cout << qPrintable(QString::fromLatin1(
|
||||
"Visualize AST and symbol hierarchy of given C++ files by generating png image files\n"
|
||||
"in the same directory as the input files. Print paths to generated image files.\n"
|
||||
"\n"
|
||||
"Standard input is also read. The resulting files starts with \"%1\"\n"
|
||||
"and are created in the current working directory. To show the AST for simple snippets\n"
|
||||
"you might want to execute:\n"
|
||||
"\n"
|
||||
" %2\n"
|
||||
"\n"
|
||||
"Prerequisites:\n"
|
||||
" 1) Make sure to have 'dot' from graphviz locatable by PATH.\n"
|
||||
" 2) Make sure to have an up to date dumpers file by using 'cplusplus-update-frontend'.\n"
|
||||
).arg(PATH_STDIN_FILE, example()));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QStringList args = app.arguments();
|
||||
args.removeFirst();
|
||||
|
||||
QStringList files = app.arguments();
|
||||
files.removeFirst();
|
||||
bool optionVerbose = false;
|
||||
|
||||
// Data from stdin?
|
||||
if (!tty_for_stdin()) {
|
||||
QFile file("_stdincontents.cpp");
|
||||
if (! file.open(QFile::WriteOnly)) {
|
||||
std::cerr << "Error: Cannot open file for writing\"" << qPrintable(file.fileName())
|
||||
<< "\"" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
file.write(QTextStream(stdin).readAll().toLocal8Bit());
|
||||
file.close();
|
||||
args.append(file.fileName());
|
||||
}
|
||||
|
||||
// Process options & arguments
|
||||
if (args.contains("-v")) {
|
||||
optionVerbose = true;
|
||||
args.removeOne("-v");
|
||||
}
|
||||
const bool helpRequested = args.contains("-h") || args.contains("-help");
|
||||
if (args.isEmpty() || helpRequested) {
|
||||
printUsage();
|
||||
return helpRequested ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Process files
|
||||
const QStringList files = args;
|
||||
foreach (const QString &fileName, files) {
|
||||
QFile file(fileName);
|
||||
if (! QFile::exists(fileName)) {
|
||||
std::cerr << "Error: File \"" << qPrintable(fileName) << "\" does not exist."
|
||||
<< std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Run the preprocessor
|
||||
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
|
||||
CplusplusToolsUtils::SystemPreprocessor preprocessor(optionVerbose);
|
||||
preprocessor.preprocessFile(fileName, fileNamePreprocessed);
|
||||
|
||||
// Convert to dot
|
||||
QFile file(fileNamePreprocessed);
|
||||
if (! file.open(QFile::ReadOnly)) {
|
||||
std::cerr << "Cannot open \"" << qPrintable(fileName)
|
||||
<< "\", skipping it." << std::endl;
|
||||
continue;
|
||||
std::cerr << "Error: Could not open file \"" << qPrintable(fileNamePreprocessed)
|
||||
<< "\"" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const QByteArray source = file.readAll();
|
||||
@@ -373,7 +468,6 @@ int main(int argc, char *argv[])
|
||||
doc->control()->setDiagnosticClient(0);
|
||||
doc->setUtf8Source(source);
|
||||
doc->parse();
|
||||
|
||||
doc->check();
|
||||
|
||||
ASTDump dump(doc->translationUnit());
|
||||
@@ -381,6 +475,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
SymbolDump dump2(doc->translationUnit());
|
||||
dump2(doc->globalNamespace());
|
||||
|
||||
// Create images
|
||||
typedef QPair<QString, QString> Pair;
|
||||
QList<Pair> inputOutputFiles;
|
||||
inputOutputFiles.append(qMakePair(QString(fileName + QLatin1String(".ast.dot")),
|
||||
QString(fileName + QLatin1String(".ast.png"))));
|
||||
inputOutputFiles.append(qMakePair(QString(fileName + QLatin1String(".symbols.dot")),
|
||||
QString(fileName + QLatin1String(".symbols.png"))));
|
||||
foreach (const Pair &pair, inputOutputFiles) {
|
||||
createImageFromDot(pair.first, pair.second, optionVerbose);
|
||||
std::cout << qPrintable(QDir::toNativeSeparators(pair.second)) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
12
tests/tools/cplusplus-ast2png/cplusplus-ast2png.pro
Normal file
12
tests/tools/cplusplus-ast2png/cplusplus-ast2png.pro
Normal file
@@ -0,0 +1,12 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
win32:CONFIG += console
|
||||
TEMPLATE = app
|
||||
TARGET = cplusplus-ast2png
|
||||
DESTDIR = ./
|
||||
|
||||
include(../../../qtcreator.pri)
|
||||
include(../../../src/libs/cplusplus/cplusplus-lib.pri)
|
||||
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
|
||||
|
||||
SOURCES += cplusplus-ast2png.cpp
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
me=$(dirname $0)
|
||||
${CPP-gcc} -U__BLOCKS__ -xc++ -E -include $me/conf.c++ $* > $me/file.i
|
||||
$me/cplusplus0 $me/file.i
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#define __extension__
|
||||
#define __context__
|
||||
#define __range__
|
||||
#define __asm(a...)
|
||||
#define __asm__(a...)
|
||||
#define restrict
|
||||
#define __restrict
|
||||
#define __restrict__
|
||||
// #define __weak
|
||||
#define __builtin_va_arg(a,b) ((b)0)
|
||||
#define __stdcall
|
||||
#define __fastcall
|
||||
#define __imag__
|
||||
#define __real__
|
||||
#define __complex__
|
||||
@@ -1,20 +0,0 @@
|
||||
QT = core gui
|
||||
macx:CONFIG -= app_bundle
|
||||
TARGET = cplusplus0
|
||||
|
||||
include(../../../qtcreator.pri)
|
||||
include(../../../src/libs/cplusplus/cplusplus.pri)
|
||||
|
||||
# Input
|
||||
SOURCES += main.cpp
|
||||
|
||||
unix {
|
||||
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
|
||||
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
|
||||
|
||||
debug:MOC_DIR = $${OUT_PWD}/.moc/debug-shared
|
||||
release:MOC_DIR = $${OUT_PWD}/.moc/release-shared
|
||||
|
||||
RCC_DIR = $${OUT_PWD}/.rcc/
|
||||
UI_DIR = $${OUT_PWD}/.uic/
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
TEMPLATE=subdirs
|
||||
|
||||
SUBDIRS= \
|
||||
cplusplus-dump \
|
||||
cplusplus-ast2png \
|
||||
qml-ast2dot
|
||||
|
||||
Reference in New Issue
Block a user