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
|
||||||
bin/qtpromaker.exe
|
bin/qtpromaker.exe
|
||||||
share/doc/qtcreator/*.qch
|
share/doc/qtcreator/*.qch
|
||||||
src/tools/gen-cpp-ast/generate-ast
|
src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor
|
||||||
src/tools/mkvisitor/cplusplus0
|
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/qml/qmldump/qmldump
|
||||||
src/tools/examplesscanner/examplesscanner
|
src/tools/examplesscanner/examplesscanner
|
||||||
src/tools/valgrindfake/valgrind-fake
|
src/tools/valgrindfake/valgrind-fake
|
||||||
@@ -118,13 +120,15 @@ bin/*.exe
|
|||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
#------
|
#------
|
||||||
tests/manual/cplusplus-frontend/cplusplus0
|
tests/manual/cplusplus-frontend/cplusplus-frontend
|
||||||
tests/manual/cplusplus-dump/cplusplus0
|
tests/manual/cplusplus-frontend/cplusplus-frontend.exe
|
||||||
tests/manual/qml-ast2dot/qml-ast2dot
|
tests/manual/qml-ast2dot/qml-ast2dot
|
||||||
tests/manual/debugger/simple/libsimple_test_plugin.*dylib
|
tests/manual/debugger/simple/libsimple_test_plugin.*dylib
|
||||||
tests/manual/debugger/simple/simple_test_app
|
tests/manual/debugger/simple/simple_test_app
|
||||||
tests/manual/plain-cplusplus/plain-c++
|
tests/manual/plain-cplusplus/plain-c++
|
||||||
tests/manual/preprocessor/pp
|
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/codegen/tst_codegen
|
||||||
tests/auto/cplusplus/ast/tst_ast
|
tests/auto/cplusplus/ast/tst_ast
|
||||||
tests/auto/cplusplus/codeformatter/tst_codeformatter
|
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
|
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
|
For methods which are hand-coded, or which should not be changed, make sure that
|
||||||
the comment is gone.
|
the comment is gone.
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
#include <Overview.h>
|
#include <Overview.h>
|
||||||
#include <LookupContext.h>
|
#include <LookupContext.h>
|
||||||
|
|
||||||
|
#include "cplusplus-tools-utils.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QCoreApplication>
|
#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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
|
QStringList args = app.arguments();
|
||||||
|
args.removeFirst();
|
||||||
|
|
||||||
QStringList files = app.arguments();
|
bool optionVerbose = false;
|
||||||
files.removeFirst();
|
|
||||||
|
|
||||||
foreach (const QString &fileName, files) {
|
// Process options & arguments
|
||||||
QFile file(fileName);
|
if (args.contains("-v")) {
|
||||||
if (! file.open(QFile::ReadOnly))
|
optionVerbose = true;
|
||||||
continue;
|
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();
|
const QByteArray source = file.readAll();
|
||||||
file.close();
|
file.close();
|
||||||
@@ -441,16 +475,14 @@ int main(int argc, char *argv[])
|
|||||||
//doc->control()->setDiagnosticClient(0);
|
//doc->control()->setDiagnosticClient(0);
|
||||||
doc->setUtf8Source(source);
|
doc->setUtf8Source(source);
|
||||||
doc->parse();
|
doc->parse();
|
||||||
|
|
||||||
doc->translationUnit()->blockErrors(true);
|
doc->translationUnit()->blockErrors(true);
|
||||||
|
|
||||||
doc->check();
|
doc->check();
|
||||||
|
|
||||||
Snapshot snapshot;
|
Snapshot snapshot;
|
||||||
snapshot.insert(doc);
|
snapshot.insert(doc);
|
||||||
|
|
||||||
LookupContext context(doc, snapshot);
|
LookupContext context(doc, snapshot);
|
||||||
MkVisitor mkVisitor(context);
|
MkVisitor mkVisitor(context);
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
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 __extension__
|
||||||
#define __context__
|
#define __context__
|
||||||
#define __range__
|
#define __range__
|
||||||
#define __asm(a...)
|
#if !defined(_WIN32) && !defined(_WIN64)
|
||||||
#define __asm__(a...)
|
# define __asm(a...)
|
||||||
|
# define __asm__(a...)
|
||||||
|
# define __stdcall
|
||||||
|
# define __fastcall
|
||||||
|
#endif
|
||||||
#define restrict
|
#define restrict
|
||||||
#define __restrict
|
#define __restrict
|
||||||
#define __restrict__
|
#define __restrict__
|
||||||
// #define __weak
|
// #define __weak
|
||||||
#define __builtin_va_arg(a,b) ((b)0)
|
#define __builtin_va_arg(a,b) ((b)0)
|
||||||
#define __stdcall
|
|
||||||
#define __fastcall
|
|
||||||
#define __imag__
|
#define __imag__
|
||||||
#define __real__
|
#define __real__
|
||||||
#define __complex__
|
#define __complex__
|
||||||
@@ -91,12 +91,21 @@ static const char generatedHeader[] =
|
|||||||
"// W A R N I N G\n"
|
"// W A R N I N G\n"
|
||||||
"// -------------\n"
|
"// -------------\n"
|
||||||
"//\n"
|
"//\n"
|
||||||
"// This file is automatically generated.\n"
|
"// This file is automatically generated by \"cplusplus-update-frontend\".\n"
|
||||||
"// Changes will be lost.\n"
|
"// Changes will be lost.\n"
|
||||||
"//\n"
|
"//\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
|
class ASTNodes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -226,6 +235,8 @@ public:
|
|||||||
"using namespace CPlusPlus;\n" << endl;
|
"using namespace CPlusPlus;\n" << endl;
|
||||||
|
|
||||||
accept(ast);
|
accept(ast);
|
||||||
|
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -354,7 +365,6 @@ public:
|
|||||||
|
|
||||||
QTextStream output(&file);
|
QTextStream output(&file);
|
||||||
out = &output;
|
out = &output;
|
||||||
|
|
||||||
*out << copyrightHeader << generatedHeader <<
|
*out << copyrightHeader << generatedHeader <<
|
||||||
"\n"
|
"\n"
|
||||||
"#include \"AST.h\"\n"
|
"#include \"AST.h\"\n"
|
||||||
@@ -363,6 +373,8 @@ public:
|
|||||||
"using namespace CPlusPlus;\n" << endl;
|
"using namespace CPlusPlus;\n" << endl;
|
||||||
|
|
||||||
accept(ast);
|
accept(ast);
|
||||||
|
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -480,6 +492,8 @@ public:
|
|||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
accept(ast);
|
accept(ast);
|
||||||
|
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -627,7 +641,7 @@ public:
|
|||||||
|
|
||||||
accept(ast);
|
accept(ast);
|
||||||
|
|
||||||
file.close();
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -761,7 +775,7 @@ public:
|
|||||||
|
|
||||||
d.accept(unit->ast());
|
d.accept(unit->ast());
|
||||||
|
|
||||||
file.close();
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -1220,6 +1234,7 @@ void generateAST_cpp(const Snapshot &snapshot, const QDir &cplusplusDir)
|
|||||||
if (file.open(QFile::WriteOnly)) {
|
if (file.open(QFile::WriteOnly)) {
|
||||||
QTextStream out(&file);
|
QTextStream out(&file);
|
||||||
out << cpp_document.toPlainText();
|
out << cpp_document.toPlainText();
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1312,6 +1327,8 @@ void generateASTVisitor_H(const Snapshot &, const QDir &cplusplusDir,
|
|||||||
"} // namespace CPlusPlus\n"
|
"} // namespace CPlusPlus\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#endif // CPLUSPLUS_ASTVISITOR_H\n";
|
"#endif // CPLUSPLUS_ASTVISITOR_H\n";
|
||||||
|
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
|
void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
|
||||||
@@ -1353,6 +1370,8 @@ void generateASTMatcher_H(const Snapshot &, const QDir &cplusplusDir,
|
|||||||
"} // namespace CPlusPlus\n"
|
"} // namespace CPlusPlus\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#endif // CPLUSPLUS_ASTMATCHER_H\n";
|
"#endif // CPLUSPLUS_ASTMATCHER_H\n";
|
||||||
|
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir, const QString &dumpersFile)
|
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)) {
|
if (file.open(QFile::WriteOnly)) {
|
||||||
QTextStream out(&file);
|
QTextStream out(&file);
|
||||||
out << document.toPlainText();
|
out << document.toPlainText();
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Accept0CG cg(cplusplusDir, AST_h_document->translationUnit());
|
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)) {
|
if (file.open(QFile::WriteOnly)) {
|
||||||
QTextStream out(&file);
|
QTextStream out(&file);
|
||||||
out << document.toPlainText();
|
out << document.toPlainText();
|
||||||
|
closeAndPrintFilePath(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1664,36 +1685,67 @@ void generateASTPatternBuilder_h(const QDir &cplusplusDir)
|
|||||||
<< "} // end of namespace CPlusPlus" << endl
|
<< "} // end of namespace CPlusPlus" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "#endif // CPLUSPLUS_AST_PATTERN_BUILDER_H" << 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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
MyQApplication app(argc, argv);
|
MyQApplication app(argc, argv);
|
||||||
|
QStringList args = app.arguments();
|
||||||
|
args.removeFirst();
|
||||||
|
|
||||||
QStringList files = app.arguments();
|
QString pathCppFrontend = PATH_CPP_FRONTEND;
|
||||||
files.removeFirst();
|
QString pathDumpersFile = PATH_DUMPERS_FILE;
|
||||||
|
|
||||||
if (files.size() != 1 && files.size() != 2) {
|
const bool helpRequested = args.contains("-h") || args.contains("-help");
|
||||||
std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl;
|
if (args.count() == 1 || args.count() >= 3 || helpRequested) {
|
||||||
std::cerr << " or: cplusplus [path to C++ front-end] [dumpers file name]" << std::endl;
|
printUsage();
|
||||||
return EXIT_FAILURE;
|
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()) {
|
if (!QFileInfo(cplusplusDir, QLatin1String("AST.h")).exists()) {
|
||||||
std::cerr << "Cannot find AST.h in " << qPrintable(cplusplusDir.absolutePath())
|
std::cerr << "Error: Cannot find AST.h in \"" << qPrintable(cplusplusDir.absolutePath())
|
||||||
<< std::endl;
|
<< "\"." << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (!QFile::exists(pathDumpersFile)) {
|
||||||
|
std::cerr << "Error: File \"" << qPrintable(pathDumpersFile)
|
||||||
|
<< "\" does not exist." << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString dumpersFile;
|
|
||||||
if (files.size() == 2)
|
|
||||||
dumpersFile = files.last();
|
|
||||||
|
|
||||||
Snapshot snapshot;
|
Snapshot snapshot;
|
||||||
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, dumpersFile);
|
QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir, pathDumpersFile);
|
||||||
astDerivedClasses.sort();
|
astDerivedClasses.sort();
|
||||||
generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
|
generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses);
|
||||||
|
|
||||||
generateASTPatternBuilder_h(cplusplusDir);
|
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 <CoreTypes.h>
|
||||||
#include <CppDocument.h>
|
#include <CppDocument.h>
|
||||||
|
|
||||||
|
#include "cplusplus-tools-utils.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -54,18 +56,47 @@
|
|||||||
|
|
||||||
using namespace CPlusPlus;
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
|
QStringList args = app.arguments();
|
||||||
|
args.removeFirst();
|
||||||
|
|
||||||
QStringList files = app.arguments();
|
bool optionVerbose = false;
|
||||||
files.removeFirst();
|
|
||||||
|
|
||||||
|
// 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) {
|
foreach (const QString &fileName, files) {
|
||||||
QFile file(fileName);
|
// Run preprocessor
|
||||||
if (! file.open(QFile::ReadOnly))
|
const QString fileNamePreprocessed = fileName + QLatin1String(".preprocessed");
|
||||||
continue;
|
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();
|
const QByteArray source = file.readAll();
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
@@ -1,21 +1,13 @@
|
|||||||
QT = core gui
|
QT = core gui
|
||||||
macx:CONFIG -= app_bundle
|
macx:CONFIG -= app_bundle
|
||||||
TARGET = cplusplus0
|
win32:CONFIG += console
|
||||||
|
TEMPLATE = app
|
||||||
|
TARGET = cplusplus-frontend
|
||||||
|
DESTDIR = ./
|
||||||
|
|
||||||
include(../../../qtcreator.pri)
|
include(../../../qtcreator.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus.pri)
|
include($$IDE_SOURCE_TREE/src/libs/cplusplus/cplusplus-lib.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/libs/languageutils/languageutils.pri)
|
include($$IDE_SOURCE_TREE/tests/auto/qttestrpath.pri)
|
||||||
include($$IDE_SOURCE_TREE/src/libs/utils/utils.pri)
|
include(../../../src/tools/cplusplus-tools-utils/cplusplus-tools-utils.pri)
|
||||||
|
|
||||||
# Input
|
SOURCES += cplusplus-frontend.cpp
|
||||||
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/
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -42,6 +42,9 @@
|
|||||||
#include <SymbolVisitor.h>
|
#include <SymbolVisitor.h>
|
||||||
#include <Overview.h>
|
#include <Overview.h>
|
||||||
|
|
||||||
|
#include "cplusplus-tools-utils.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -58,6 +61,22 @@
|
|||||||
# include <cxxabi.h>
|
# include <cxxabi.h>
|
||||||
#endif
|
#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;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
class ASTDump: protected ASTVisitor
|
class ASTDump: protected ASTVisitor
|
||||||
@@ -68,9 +87,6 @@ public:
|
|||||||
|
|
||||||
void operator()(AST *ast) {
|
void operator()(AST *ast) {
|
||||||
QByteArray basename = translationUnit()->fileName();
|
QByteArray basename = translationUnit()->fileName();
|
||||||
int dotIdx = basename.lastIndexOf('.');
|
|
||||||
if (dotIdx != -1)
|
|
||||||
basename.truncate(dotIdx);
|
|
||||||
basename.append(".ast.dot");
|
basename.append(".ast.dot");
|
||||||
out.open(basename.constData());
|
out.open(basename.constData());
|
||||||
|
|
||||||
@@ -89,11 +105,10 @@ public:
|
|||||||
|
|
||||||
out << "}" << std::endl;
|
out << "}" << std::endl;
|
||||||
out.close();
|
out.close();
|
||||||
std::cout << basename.constData() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the following file can be generated by using:
|
// 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"
|
#include "dumpers.inc"
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -195,9 +210,6 @@ public:
|
|||||||
|
|
||||||
void operator()(Symbol *s) {
|
void operator()(Symbol *s) {
|
||||||
QByteArray basename = translationUnit->fileName();
|
QByteArray basename = translationUnit->fileName();
|
||||||
int dotIdx = basename.lastIndexOf('.');
|
|
||||||
if (dotIdx != -1)
|
|
||||||
basename.truncate(dotIdx);
|
|
||||||
basename.append(".symbols.dot");
|
basename.append(".symbols.dot");
|
||||||
out.open(basename.constData());
|
out.open(basename.constData());
|
||||||
|
|
||||||
@@ -218,7 +230,6 @@ public:
|
|||||||
|
|
||||||
out << "}" << std::endl;
|
out << "}" << std::endl;
|
||||||
out.close();
|
out.close();
|
||||||
std::cout << basename.constData() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -351,19 +362,103 @@ private:
|
|||||||
Overview o;
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
|
QStringList args = app.arguments();
|
||||||
|
args.removeFirst();
|
||||||
|
|
||||||
QStringList files = app.arguments();
|
bool optionVerbose = false;
|
||||||
files.removeFirst();
|
|
||||||
|
|
||||||
|
// 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) {
|
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)) {
|
if (! file.open(QFile::ReadOnly)) {
|
||||||
std::cerr << "Cannot open \"" << qPrintable(fileName)
|
std::cerr << "Error: Could not open file \"" << qPrintable(fileNamePreprocessed)
|
||||||
<< "\", skipping it." << std::endl;
|
<< "\"" << std::endl;
|
||||||
continue;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray source = file.readAll();
|
const QByteArray source = file.readAll();
|
||||||
@@ -373,7 +468,6 @@ int main(int argc, char *argv[])
|
|||||||
doc->control()->setDiagnosticClient(0);
|
doc->control()->setDiagnosticClient(0);
|
||||||
doc->setUtf8Source(source);
|
doc->setUtf8Source(source);
|
||||||
doc->parse();
|
doc->parse();
|
||||||
|
|
||||||
doc->check();
|
doc->check();
|
||||||
|
|
||||||
ASTDump dump(doc->translationUnit());
|
ASTDump dump(doc->translationUnit());
|
||||||
@@ -381,6 +475,18 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
SymbolDump dump2(doc->translationUnit());
|
SymbolDump dump2(doc->translationUnit());
|
||||||
dump2(doc->globalNamespace());
|
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;
|
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
|
TEMPLATE=subdirs
|
||||||
|
|
||||||
SUBDIRS= \
|
SUBDIRS= \
|
||||||
cplusplus-dump \
|
cplusplus-ast2png \
|
||||||
qml-ast2dot
|
qml-ast2dot
|
||||||
|
|||||||
Reference in New Issue
Block a user