diff --git a/gui/gui.pro b/gui/gui.pro index f2e54ce7c..b45ed9229 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -5,7 +5,7 @@ DEPENDPATH += . \ ../lib INCLUDEPATH += . \ ../lib - +QT += xml greaterThan(QT_MAJOR_VERSION, 4) { QT += widgets # In Qt 5 widgets are in separate module QT += printsupport # In Qt 5 QPrinter/QPrintDialog are in separate module @@ -50,7 +50,8 @@ FORMS = about.ui \ resultsview.ui \ scratchpad.ui \ settings.ui \ - stats.ui + stats.ui \ + librarydialog.ui TRANSLATIONS = cppcheck_de.ts \ cppcheck_es.ts \ @@ -105,7 +106,8 @@ HEADERS += aboutdialog.h \ txtreport.h \ xmlreport.h \ xmlreportv1.h \ - xmlreportv2.h + xmlreportv2.h \ + librarydialog.h SOURCES += aboutdialog.cpp \ application.cpp \ @@ -139,7 +141,8 @@ SOURCES += aboutdialog.cpp \ txtreport.cpp \ xmlreport.cpp \ xmlreportv1.cpp \ - xmlreportv2.cpp + xmlreportv2.cpp \ + librarydialog.cpp win32 { DEFINES += _CRT_SECURE_NO_WARNINGS diff --git a/gui/librarydialog.cpp b/gui/librarydialog.cpp new file mode 100644 index 000000000..d8da78a43 --- /dev/null +++ b/gui/librarydialog.cpp @@ -0,0 +1,182 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "librarydialog.h" +#include "ui_librarydialog.h" + +#include +#include +#include +#include +#include +#include + +const unsigned int LibraryDialog::Function::Arg::ANY = ~0U; + +// TODO: get/compare functions from header + +LibraryDialog::LibraryDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LibraryDialog) +{ + ui->setupUi(this); +} + +LibraryDialog::~LibraryDialog() +{ + delete ui; +} + +void LibraryDialog::updateui() +{ + ui->functions->clear(); + for (const struct Function &function : functions) { + ui->functions->addItem(function.name); + } +} + + +QStringList getFunctions(QFile &file) +{ + QStringList ret; + + QDomDocument doc; + if (!doc.setContent(&file)) + return ret; + + + return ret; +} + +static LibraryDialog::Function::Arg loadFunctionArg(const QDomElement &functionArgElement) +{ + LibraryDialog::Function::Arg arg; + if (functionArgElement.attribute("nr") == "any") + arg.nr = LibraryDialog::Function::Arg::ANY; + else + arg.nr = functionArgElement.attribute("nr").toUInt(); + for (QDomElement childElement = functionArgElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { + if (childElement.tagName() == "not-bool") + arg.notbool = true; + else if (childElement.tagName() == "not-null") + arg.notnull = true; + else if (childElement.tagName() == "not-uninit") + arg.notuninit = true; + else if (childElement.tagName() == "strz") + arg.strz = true; + else if (childElement.tagName() == "formatstr") + arg.formatstr = true; + else if (childElement.tagName() == "valid") + arg.valid = childElement.text(); + else if (childElement.tagName() == "minsize") { + arg.minsize.type = childElement.attribute("type"); + arg.minsize.arg = childElement.attribute("arg"); + arg.minsize.arg2 = childElement.attribute("arg2"); + } + } + return arg; +} + +static LibraryDialog::Function loadFunction(const QDomElement &functionElement) +{ + LibraryDialog::Function function; + function.name = functionElement.attribute("name"); + for (QDomElement childElement = functionElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { + const QString tagName = childElement.tagName(); + if (childElement.tagName() == "noreturn") + function.noreturn = (childElement.text() == "true"); + else if (childElement.tagName() == "pure") + function.gccPure = true; + else if (childElement.tagName() == "const") + function.gccConst = true; + else if (childElement.tagName() == "leak-ignore") + function.leakignore = true; + else if (childElement.tagName() == "use-retval") + function.useretval = true; + else if (childElement.tagName() == "formatstr") { + function.formatstr.scan = childElement.attribute("scan"); + function.formatstr.secure = childElement.attribute("secure"); + } else if (childElement.tagName() == "arg") { + const LibraryDialog::Function::Arg fa = loadFunctionArg(childElement); + function.args.append(fa); + } else { + int x = 123; + x++; + + } + } + return function; +} + +bool LibraryDialog::loadFile(QFile &file) +{ + QDomDocument doc; + if (!doc.setContent(&file)) + return false; + + QDomElement rootElement = doc.firstChildElement("def"); + for (QDomElement functionElement = rootElement.firstChildElement("function"); !functionElement.isNull(); functionElement = functionElement.nextSiblingElement("function")) { + functions.append(loadFunction(functionElement)); + } + + return true; +} + +void LibraryDialog::openCfg() +{ + const QSettings settings; + const QString datadir = settings.value("DATADIR",QString()).toString(); + + QString selectedFilter; + const QString filter(tr("Library files (*.cfg)")); + const QString selectedFile = QFileDialog::getOpenFileName(this, + tr("Open library file"), + datadir, + filter, + &selectedFilter); + + if (!selectedFile.isEmpty()) { + QFile file(selectedFile); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + loadFile(file); + updateui(); + } + } + +} + +void LibraryDialog::selectFunction(int row) +{ + const Function &function = functions[row]; + ui->functionreturn->setChecked(!function.noreturn); + ui->useretval->setChecked(function.useretval); + ui->leakignore->setChecked(function.leakignore); + ui->arguments->clear(); + for (const Function::Arg &arg : function.args) { + QString s("arg"); + if (arg.nr != Function::Arg::ANY) + s += QString::number(arg.nr); + if (arg.formatstr) + s += " formatstr"; + else if (!arg.strz) + s += " strz"; + else if (!arg.valid.isNull()) + s += " " + arg.valid; + ui->arguments->addItem(s); + } +} diff --git a/gui/librarydialog.h b/gui/librarydialog.h new file mode 100644 index 000000000..daa34c3be --- /dev/null +++ b/gui/librarydialog.h @@ -0,0 +1,78 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBRARYDIALOG_H +#define LIBRARYDIALOG_H + +#include +#include + +namespace Ui { + class LibraryDialog; +} + +class LibraryDialog : public QDialog { + Q_OBJECT + +public: + explicit LibraryDialog(QWidget *parent = 0); + ~LibraryDialog(); + + struct Function { + QString name; + bool noreturn = false; + bool gccPure = false; + bool gccConst = false; + bool leakignore = false; + bool useretval = false; + struct { + QString scan; + QString secure; + } formatstr; + struct Arg { + QString name; + unsigned int nr = 0; + static const unsigned int ANY; + bool notbool = false; + bool notnull = false; + bool notuninit = false; + bool formatstr = false; + bool strz = false; + QString valid; + struct { + QString type; + QString arg; + QString arg2; + } minsize; + }; + QList args; + }; + +private slots: + void openCfg(); + void selectFunction(int row); + +private: + Ui::LibraryDialog *ui; + + void updateui(); + bool loadFile(QFile &file); + QList functions; +}; + +#endif // LIBRARYDIALOG_H diff --git a/gui/librarydialog.ui b/gui/librarydialog.ui new file mode 100644 index 000000000..3566d0cc4 --- /dev/null +++ b/gui/librarydialog.ui @@ -0,0 +1,165 @@ + + + LibraryDialog + + + + 0 + 0 + 547 + 300 + + + + Library Editor + + + + + + false + + + QLabel { background-color : red; color : blue; } + + + EXPERIMENTAL + + + + + + + + + Open + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Functions + + + + + + + QAbstractItemView::SingleSelection + + + + + + + + + + + function always return + + + + + + + return value must be used + + + + + + + ignore function in leaks checking + + + + + + + Arguments + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + functions + currentRowChanged(int) + LibraryDialog + selectFunction(int) + + + 155 + 218 + + + 327 + 299 + + + + + pushButton + clicked() + LibraryDialog + openCfg() + + + 56 + 36 + + + 72 + 21 + + + + + + selectFunction(int) + openCfg() + + diff --git a/gui/main.ui b/gui/main.ui index d579518ab..9f3b2e55f 100644 --- a/gui/main.ui +++ b/gui/main.ui @@ -62,7 +62,7 @@ 0 0 640 - 21 + 20 @@ -115,6 +115,7 @@ + @@ -702,6 +703,14 @@ Open a Print Preview Dialog for the Current Results + + + LibraryEditor... + + + Open library editor + + diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index b086d82ae..64bb2e949 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -44,6 +44,7 @@ #include "logview.h" #include "filelist.h" #include "showtypes.h" +#include "librarydialog.h" static const QString OnlineHelpURL("http://cppcheck.sourceforge.net/manual.html"); @@ -99,6 +100,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : connect(mUI.mActionShowHidden, SIGNAL(triggered()), mUI.mResults, SLOT(ShowHiddenResults())); connect(mUI.mActionViewLog, SIGNAL(triggered()), this, SLOT(ShowLogView())); connect(mUI.mActionViewStats, SIGNAL(triggered()), this, SLOT(ShowStatistics())); + connect(mUI.mActionLibraryEditor, SIGNAL(triggered()), this, SLOT(ShowLibraryEditor())); connect(mUI.mActionRecheck, SIGNAL(triggered()), this, SLOT(ReCheck())); @@ -1215,6 +1217,12 @@ void MainWindow::ShowStatistics() statsDialog.exec(); } +void MainWindow::ShowLibraryEditor() +{ + LibraryDialog libraryDialog(this); + libraryDialog.exec(); +} + void MainWindow::Log(const QString &logline) { if (mLogView) { diff --git a/gui/mainwindow.h b/gui/mainwindow.h index b7036331a..587018d86 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -220,6 +220,12 @@ public slots: */ void ShowStatistics(); + /** + * @brief Slot for showing the library editor + * + */ + void ShowLibraryEditor(); + protected slots: /**