<commit_before>
// cFile.cpp

// Implements the cFile class providing an OS-independent abstraction of a file.

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "File.h"

/// Simple constructor - creates an unopened file object, use Open() to open / create a real file
cFile::cFile(void) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	// Nothing needed yet
}

/// Constructs and opens / creates the file specified, use IsOpen() to check for success
cFile::cFile(const AString & iFileName, eMode iMode) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	Open(iFileName, iMode);
}

/// Auto-closes the file, if open
cFile::~cFile()
{
	if (IsOpen())
	{
		Close();
	}
}

bool cFile::Open(const AString & iFileName, eMode iMode)
{
	ASSERT(!IsOpen());  // You should close the file before opening another one

	if (IsOpen())
	{
		Close();
	}

	const char * Mode = NULL;
	switch (iMode)
	{
		case fmRead:      Mode = "rb";  break;
		case fmWrite:     Mode = "wb";  break;
		case fmReadWrite: Mode = "rb+"; break;
		default:
		{
			ASSERT(!"Unhandled file mode");
			return false;
		}
	}
	m_File = fopen( (FILE_IO_PREFIX + iFileName).c_str(), Mode);
	if ((m_File == NULL) && (iMode == fmReadWrite))
	{
		// Fix for MS not following C spec, opening "a" mode files for writing at the end only
		// The file open operation has been tried with "read update", fails if file not found
		// So now we know either the file doesn't exist or we don't have rights, no need to worry about file contents.
		// Simply re-open for read-writing, erasing existing contents:
		m_File = fopen( (FILE_IO_PREFIX + iFileName).c_str(), "wb+");
	}
	return (m_File != NULL);
}

void cFile::Close(void)
{
	if (!IsOpen())
	{
		// Closing an unopened file is a legal nop
		return;
	}

	fclose(m_File);
	m_File = NULL;
}

bool cFile::IsOpen(void) const
{
	return (m_File != NULL);
}

bool cFile::IsEOF(void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		// Unopened files behave as at EOF
		return true;
	}

	return (feof(m_File) != 0);
}

/// Reads  up to iNumBytes bytes into iBuffer, returns the number of bytes actually read,    or -1 on failure; asserts if not open
int cFile::Read (void * iBuffer, int iNumBytes)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fread(iBuffer, 1, iNumBytes, m_File);  // fread() returns the portion of Count parameter actually read, so we need to send iNumBytes as Count
}

int cFile::Write(const void * iBuffer, int iNumBytes)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int res = fwrite(iBuffer, 1, iNumBytes, m_File);  // fwrite() returns the portion of Count parameter actually written, so we need to send iNumBytes as Count
	return res;
}

int cFile::Seek (int iPosition)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	if (fseek(m_File, iPosition, SEEK_SET) != 0)
	{
		return -1;
	}
	return ftell(m_File);
}

int cFile::Tell (void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return ftell(m_File);
}

int cFile::GetSize(void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int CurPos = ftell(m_File);
	if (CurPos < 0)
	{
		return -1;
	}
	if (fseek(m_File, 0, SEEK_END) != 0)
	{
		return -1;
	}
	int res = ftell(m_File);
	if (fseek(m_File, CurPos, SEEK_SET) != 0)
	{
		return -1;
	}
	return res;
}

int cFile::ReadRestOfFile(AString & a_Contents)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int DataSize = GetSize() - Tell();

	// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
	a_Contents.assign(DataSize, '\0');
	return Read((void *)a_Contents.data(), DataSize);
}

bool cFile::Exists(const AString & a_FileName)
{
	cFile test(a_FileName, fmRead);
	return test.IsOpen();
}

bool cFile::Delete(const AString & a_FileName)
{
	return (remove(a_FileName.c_str()) == 0);
}

bool cFile::Rename(const AString & a_OrigFileName, const AString & a_NewFileName)
{
	return (rename(a_OrigFileName.c_str(), a_NewFileName.c_str()) == 0);
}

bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName)
{
	#ifdef _WIN32
		return (CopyFile(a_SrcFileName.c_str(), a_DstFileName.c_str(), true) != 0);
	#else
		// Other OSs don't have a direct CopyFile equivalent, do it the harder way:
		ifstream src(a_SrcFileName, ios::binary);
		ofstream dst(a_DstFileName, ios::binary);
		if (dst.good())
		{
			dst << src.rdbuf();
			return true;
		}
		else
		{
			return false;
		}
	#endif
}

bool cFile::IsFolder(const AString & a_Path)
{
	#ifdef _WIN32
		DWORD FileAttrib = GetFileAttributes(a_Path.c_str());
		return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0));
	#else
		struct stat st;
		return ((stat(a_Path.c_str(), &st) == 0) && S_ISDIR(st.st_mode));
	#endif
}

bool cFile::IsFile(const AString & a_Path)
{
	#ifdef _WIN32
		DWORD FileAttrib = GetFileAttributes(a_Path.c_str());
		return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0));
	#else
		struct stat st;
		return ((stat(a_Path.c_str(), &st) == 0) && S_ISREG(st.st_mode));
	#endif
}

int cFile::GetSize(const AString & a_FileName)
{
	struct stat st;
	if (stat(a_FileName.c_str(), &st) == 0)
	{
		return st.st_size;
	}
	return -1;
}

bool cFile::CreateFolder(const AString & a_FolderPath)
{
	#ifdef _WIN32
		return (CreateDirectory(a_FolderPath.c_str(), NULL) != 0);
	#else
		return (mkdir(a_FolderPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
	#endif
}

int cFile::Printf(const char * a_Fmt, ...)
{
	AString buf;
	va_list args;
	va_start(args, a_Fmt);
	AppendVPrintf(buf, a_Fmt, args);
	va_end(args);
	return Write(buf.c_str(), buf.length());
}

<commit_msg>Fixed cFile::CopyFile Linux compilation.<commit_after>
// cFile.cpp

// Implements the cFile class providing an OS-independent abstraction of a file.

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "File.h"
#include <fstream>

cFile::cFile(void) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	// Nothing needed yet
}

cFile::cFile(const AString & iFileName, eMode iMode) :
	#ifdef USE_STDIO_FILE
	m_File(NULL)
	#else
	m_File(INVALID_HANDLE_VALUE)
	#endif  // USE_STDIO_FILE
{
	Open(iFileName, iMode);
}

cFile::~cFile()
{
	if (IsOpen())
	{
		Close();
	}
}

bool cFile::Open(const AString & iFileName, eMode iMode)
{
	ASSERT(!IsOpen());  // You should close the file before opening another one

	if (IsOpen())
	{
		Close();
	}

	const char * Mode = NULL;
	switch (iMode)
	{
		case fmRead:      Mode = "rb";  break;
		case fmWrite:     Mode = "wb";  break;
		case fmReadWrite: Mode = "rb+"; break;
		default:
		{
			ASSERT(!"Unhandled file mode");
			return false;
		}
	}
	m_File = fopen( (FILE_IO_PREFIX + iFileName).c_str(), Mode);
	if ((m_File == NULL) && (iMode == fmReadWrite))
	{
		// Fix for MS not following C spec, opening "a" mode files for writing at the end only
		// The file open operation has been tried with "read update", fails if file not found
		// So now we know either the file doesn't exist or we don't have rights, no need to worry about file contents.
		// Simply re-open for read-writing, erasing existing contents:
		m_File = fopen( (FILE_IO_PREFIX + iFileName).c_str(), "wb+");
	}
	return (m_File != NULL);
}

void cFile::Close(void)
{
	if (!IsOpen())
	{
		// Closing an unopened file is a legal nop
		return;
	}

	fclose(m_File);
	m_File = NULL;
}

bool cFile::IsOpen(void) const
{
	return (m_File != NULL);
}

bool cFile::IsEOF(void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		// Unopened files behave as at EOF
		return true;
	}

	return (feof(m_File) != 0);
}

int cFile::Read (void * iBuffer, int iNumBytes)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return fread(iBuffer, 1, iNumBytes, m_File);  // fread() returns the portion of Count parameter actually read, so we need to send iNumBytes as Count
}

int cFile::Write(const void * iBuffer, int iNumBytes)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int res = fwrite(iBuffer, 1, iNumBytes, m_File);  // fwrite() returns the portion of Count parameter actually written, so we need to send iNumBytes as Count
	return res;
}

int cFile::Seek (int iPosition)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	if (fseek(m_File, iPosition, SEEK_SET) != 0)
	{
		return -1;
	}
	return ftell(m_File);
}

int cFile::Tell (void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	return ftell(m_File);
}

int cFile::GetSize(void) const
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int CurPos = ftell(m_File);
	if (CurPos < 0)
	{
		return -1;
	}
	if (fseek(m_File, 0, SEEK_END) != 0)
	{
		return -1;
	}
	int res = ftell(m_File);
	if (fseek(m_File, CurPos, SEEK_SET) != 0)
	{
		return -1;
	}
	return res;
}

int cFile::ReadRestOfFile(AString & a_Contents)
{
	ASSERT(IsOpen());

	if (!IsOpen())
	{
		return -1;
	}

	int DataSize = GetSize() - Tell();

	// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
	a_Contents.assign(DataSize, '\0');
	return Read((void *)a_Contents.data(), DataSize);
}

bool cFile::Exists(const AString & a_FileName)
{
	cFile test(a_FileName, fmRead);
	return test.IsOpen();
}

bool cFile::Delete(const AString & a_FileName)
{
	return (remove(a_FileName.c_str()) == 0);
}

bool cFile::Rename(const AString & a_OrigFileName, const AString & a_NewFileName)
{
	return (rename(a_OrigFileName.c_str(), a_NewFileName.c_str()) == 0);
}

bool cFile::Copy(const AString & a_SrcFileName, const AString & a_DstFileName)
{
	#ifdef _WIN32
		return (CopyFile(a_SrcFileName.c_str(), a_DstFileName.c_str(), true) != 0);
	#else
		// Other OSs don't have a direct CopyFile equivalent, do it the harder way:
		std::ifstream src(a_SrcFileName.c_str(), std::ios::binary);
		std::ofstream dst(a_DstFileName.c_str(), std::ios::binary);
		if (dst.good())
		{
			dst << src.rdbuf();
			return true;
		}
		else
		{
			return false;
		}
	#endif
}

bool cFile::IsFolder(const AString & a_Path)
{
	#ifdef _WIN32
		DWORD FileAttrib = GetFileAttributes(a_Path.c_str());
		return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0));
	#else
		struct stat st;
		return ((stat(a_Path.c_str(), &st) == 0) && S_ISDIR(st.st_mode));
	#endif
}

bool cFile::IsFile(const AString & a_Path)
{
	#ifdef _WIN32
		DWORD FileAttrib = GetFileAttributes(a_Path.c_str());
		return ((FileAttrib != INVALID_FILE_ATTRIBUTES) && ((FileAttrib & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0));
	#else
		struct stat st;
		return ((stat(a_Path.c_str(), &st) == 0) && S_ISREG(st.st_mode));
	#endif
}

int cFile::GetSize(const AString & a_FileName)
{
	struct stat st;
	if (stat(a_FileName.c_str(), &st) == 0)
	{
		return st.st_size;
	}
	return -1;
}

bool cFile::CreateFolder(const AString & a_FolderPath)
{
	#ifdef _WIN32
		return (CreateDirectory(a_FolderPath.c_str(), NULL) != 0);
	#else
		return (mkdir(a_FolderPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
	#endif
}

int cFile::Printf(const char * a_Fmt, ...)
{
	AString buf;
	va_list args;
	va_start(args, a_Fmt);
	AppendVPrintf(buf, a_Fmt, args);
	va_end(args);
	return Write(buf.c_str(), buf.length());
}

<|endoftext|>


<commit_before>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <fs.h>
#include <interfaces/node.h>
#include <qt/forms/ui_intro.h>
#include <qt/guiutil.h>
#include <qt/intro.h>
#include <util/system.h>

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>

#include <cmath>

static const uint64_t GB_BYTES = 1000000000LL;
/**
 * Minimum free space (in GB) needed for data directory.
 */
static const uint64_t BLOCK_CHAIN_SIZE = 220;
/**
 * Minimum free space (in GB) needed for data directory when pruned; Does not
 * include prune target.
 */
static const uint64_t CHAIN_STATE_SIZE = 4;
/**
 * Total required space (in GB) depending on user choice (prune, not prune).
 */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the
   check()
   function runs, the current path is requested from the associated Intro
   object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is
   checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject {
    Q_OBJECT

public:
    explicit FreespaceChecker(Intro *intro);

    enum Status { ST_OK, ST_ERROR };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include <qt/intro.moc>

FreespaceChecker::FreespaceChecker(Intro *_intro) {
    this->intro = _intro;
}

void FreespaceChecker::check() {
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage = tr("A new data directory will be created.");

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while (parentDir.has_parent_path() && !fs::exists(parentDir)) {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite
         * loop here */
        if (parentDirOld == parentDir) break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if (fs::exists(dataDir)) {
            if (fs::is_directory(dataDir)) {
                QString separator = "" + QDir::toNativeSeparators("/") +
                                    tr("name") + "";
                replyStatus = ST_OK;
                replyMessage = tr("Directory already exists. Add %1 if you "
                                  "intend to create a new directory here.")
                                   .arg(separator);
            } else {
                replyStatus = ST_ERROR;
                replyMessage =
                    tr("Path already exists, and is not a directory.");
            }
        }
    } catch (const fs::filesystem_error &) {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot create data directory here.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent)
    : QDialog(parent), ui(new Ui::Intro), thread(0), signalled(false) {
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));

    ui->lblExplanation1->setText(ui->lblExplanation1->text()
                                     .arg(tr(PACKAGE_NAME))
                                     .arg(BLOCK_CHAIN_SIZE)
                                     .arg(2009)
                                     .arg(tr("Bitcoin")));
    ui->lblExplanation2->setText(
        ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));

    uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
    requiredSpace = BLOCK_CHAIN_SIZE;
    QString storageRequiresMsg =
        tr("At least %1 GB of data will be stored in this directory, and it "
           "will grow over time.");
    if (pruneTarget) {
        uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
        if (prunedGBs <= requiredSpace) {
            requiredSpace = prunedGBs;
            storageRequiresMsg = tr("Approximately %1 GB of data will be "
                                    "stored in this directory.");
        }
        ui->lblExplanation3->setVisible(true);
    } else {
        ui->lblExplanation3->setVisible(false);
    }
    requiredSpace += CHAIN_STATE_SIZE;
    ui->sizeWarningLabel->setText(
        tr("%1 will download and store a copy of the Bitcoin block chain.")
            .arg(tr(PACKAGE_NAME)) +
        " " + storageRequiresMsg.arg(requiredSpace) + " " +
        tr("The wallet will also be stored in this directory."));
    startThread();
}

Intro::~Intro() {
    delete ui;
    /* Ensure thread is finished before it is deleted */
    Q_EMIT stopThread();
    thread->wait();
}

QString Intro::getDataDirectory() {
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir) {
    ui->dataDirectory->setText(dataDir);
    if (dataDir == getDefaultDataDirectory()) {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory() {
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

bool Intro::pickDataDirectory(interfaces::Node &node) {
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if (!gArgs.GetArg("-datadir", "").empty()) return true;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if (!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) ||
        gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) ||
        settings.value("fReset", false).toBool() ||
        gArgs.GetBoolArg("-resetguisettings", false)) {
        /* If current default data directory does not exist, let the user choose
         * one */
        Intro intro;
        intro.setDataDirectory(dataDir);
        intro.setWindowIcon(QIcon(":icons/bitcoin"));

        while (true) {
            if (!intro.exec()) {
                /* Cancel clicked */
                return false;
            }
            dataDir = intro.getDataDirectory();
            try {
                if (TryCreateDirectories(
                        GUIUtil::qstringToBoostPath(dataDir))) {
                    // If a new data directory has been created, make wallets
                    // subdirectory too
                    TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) /
                                         "wallets");
                }
                break;
            } catch (const fs::filesystem_error &) {
                QMessageBox::critical(0, tr(PACKAGE_NAME),
                                      tr("Error: Specified data directory "
                                         "\"%1\" cannot be created.")
                                          .arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
        settings.setValue("fReset", false);
    }
    /* Only override -datadir if different from the default, to make it possible
     * to
     * override -datadir in the bitcoin.conf file in the default data directory
     * (to be consistent with bitcoind behavior)
     */
    if (dataDir != getDefaultDataDirectory()) {
        // use OS locale for path setting
        node.softSetArg("-datadir",
                        GUIUtil::qstringToBoostPath(dataDir).string());
    }
    return true;
}

void Intro::setStatus(int status, const QString &message,
                      quint64 bytesAvailable) {
    switch (status) {
        case FreespaceChecker::ST_OK:
            ui->errorMessage->setText(message);
            ui->errorMessage->setStyleSheet("");
            break;
        case FreespaceChecker::ST_ERROR:
            ui->errorMessage->setText(tr("Error") + ": " + message);
            ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
            break;
    }
    /* Indicate number of bytes available */
    if (status == FreespaceChecker::ST_ERROR) {
        ui->freeSpace->setText("");
    } else {
        QString freeString =
            tr("%n GB of free space available", "", bytesAvailable / GB_BYTES);
        if (bytesAvailable < requiredSpace * GB_BYTES) {
            freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
            ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
        } else {
            ui->freeSpace->setStyleSheet("");
        }
        ui->freeSpace->setText(freeString + ".");
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)
        ->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr) {
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked() {
    QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(
        0, "Choose data directory", ui->dataDirectory->text()));
    if (!dir.isEmpty()) ui->dataDirectory->setText(dir);
}

void Intro::on_dataDirDefault_clicked() {
    setDataDirectory(getDefaultDataDirectory());
}

void Intro::on_dataDirCustom_clicked() {
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
}

void Intro::startThread() {
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, SIGNAL(reply(int, QString, quint64)), this,
            SLOT(setStatus(int, QString, quint64)));
    connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
    /*  make sure executor object is deleted in its own thread */
    connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));

    thread->start();
}

void Intro::checkPath(const QString &dataDir) {
    mutex.lock();
    pathToCheck = dataDir;
    if (!signalled) {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck() {
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<commit_msg>Update qt/intro.cpp to use Qt5 connect syntax<commit_after>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif

#include <fs.h>
#include <interfaces/node.h>
#include <qt/forms/ui_intro.h>
#include <qt/guiutil.h>
#include <qt/intro.h>
#include <util/system.h>

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>

#include <cmath>

static const uint64_t GB_BYTES = 1000000000LL;
/**
 * Minimum free space (in GB) needed for data directory.
 */
static const uint64_t BLOCK_CHAIN_SIZE = 220;
/**
 * Minimum free space (in GB) needed for data directory when pruned; Does not
 * include prune target.
 */
static const uint64_t CHAIN_STATE_SIZE = 4;
/**
 * Total required space (in GB) depending on user choice (prune, not prune).
 */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the
   check()
   function runs, the current path is requested from the associated Intro
   object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is
   checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject {
    Q_OBJECT

public:
    explicit FreespaceChecker(Intro *intro);

    enum Status { ST_OK, ST_ERROR };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include <qt/intro.moc>

FreespaceChecker::FreespaceChecker(Intro *_intro) {
    this->intro = _intro;
}

void FreespaceChecker::check() {
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage = tr("A new data directory will be created.");

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while (parentDir.has_parent_path() && !fs::exists(parentDir)) {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite
         * loop here */
        if (parentDirOld == parentDir) break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if (fs::exists(dataDir)) {
            if (fs::is_directory(dataDir)) {
                QString separator = "" + QDir::toNativeSeparators("/") +
                                    tr("name") + "";
                replyStatus = ST_OK;
                replyMessage = tr("Directory already exists. Add %1 if you "
                                  "intend to create a new directory here.")
                                   .arg(separator);
            } else {
                replyStatus = ST_ERROR;
                replyMessage =
                    tr("Path already exists, and is not a directory.");
            }
        }
    } catch (const fs::filesystem_error &) {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot create data directory here.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent)
    : QDialog(parent), ui(new Ui::Intro), thread(0), signalled(false) {
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));

    ui->lblExplanation1->setText(ui->lblExplanation1->text()
                                     .arg(tr(PACKAGE_NAME))
                                     .arg(BLOCK_CHAIN_SIZE)
                                     .arg(2009)
                                     .arg(tr("Bitcoin")));
    ui->lblExplanation2->setText(
        ui->lblExplanation2->text().arg(tr(PACKAGE_NAME)));

    uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
    requiredSpace = BLOCK_CHAIN_SIZE;
    QString storageRequiresMsg =
        tr("At least %1 GB of data will be stored in this directory, and it "
           "will grow over time.");
    if (pruneTarget) {
        uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
        if (prunedGBs <= requiredSpace) {
            requiredSpace = prunedGBs;
            storageRequiresMsg = tr("Approximately %1 GB of data will be "
                                    "stored in this directory.");
        }
        ui->lblExplanation3->setVisible(true);
    } else {
        ui->lblExplanation3->setVisible(false);
    }
    requiredSpace += CHAIN_STATE_SIZE;
    ui->sizeWarningLabel->setText(
        tr("%1 will download and store a copy of the Bitcoin block chain.")
            .arg(tr(PACKAGE_NAME)) +
        " " + storageRequiresMsg.arg(requiredSpace) + " " +
        tr("The wallet will also be stored in this directory."));
    startThread();
}

Intro::~Intro() {
    delete ui;
    /* Ensure thread is finished before it is deleted */
    Q_EMIT stopThread();
    thread->wait();
}

QString Intro::getDataDirectory() {
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir) {
    ui->dataDirectory->setText(dataDir);
    if (dataDir == getDefaultDataDirectory()) {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory() {
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

bool Intro::pickDataDirectory(interfaces::Node &node) {
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if (!gArgs.GetArg("-datadir", "").empty()) return true;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if (!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) ||
        gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) ||
        settings.value("fReset", false).toBool() ||
        gArgs.GetBoolArg("-resetguisettings", false)) {
        /* If current default data directory does not exist, let the user choose
         * one */
        Intro intro;
        intro.setDataDirectory(dataDir);
        intro.setWindowIcon(QIcon(":icons/bitcoin"));

        while (true) {
            if (!intro.exec()) {
                /* Cancel clicked */
                return false;
            }
            dataDir = intro.getDataDirectory();
            try {
                if (TryCreateDirectories(
                        GUIUtil::qstringToBoostPath(dataDir))) {
                    // If a new data directory has been created, make wallets
                    // subdirectory too
                    TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) /
                                         "wallets");
                }
                break;
            } catch (const fs::filesystem_error &) {
                QMessageBox::critical(0, tr(PACKAGE_NAME),
                                      tr("Error: Specified data directory "
                                         "\"%1\" cannot be created.")
                                          .arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
        settings.setValue("fReset", false);
    }
    /* Only override -datadir if different from the default, to make it possible
     * to
     * override -datadir in the bitcoin.conf file in the default data directory
     * (to be consistent with bitcoind behavior)
     */
    if (dataDir != getDefaultDataDirectory()) {
        // use OS locale for path setting
        node.softSetArg("-datadir",
                        GUIUtil::qstringToBoostPath(dataDir).string());
    }
    return true;
}

void Intro::setStatus(int status, const QString &message,
                      quint64 bytesAvailable) {
    switch (status) {
        case FreespaceChecker::ST_OK:
            ui->errorMessage->setText(message);
            ui->errorMessage->setStyleSheet("");
            break;
        case FreespaceChecker::ST_ERROR:
            ui->errorMessage->setText(tr("Error") + ": " + message);
            ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
            break;
    }
    /* Indicate number of bytes available */
    if (status == FreespaceChecker::ST_ERROR) {
        ui->freeSpace->setText("");
    } else {
        QString freeString =
            tr("%n GB of free space available", "", bytesAvailable / GB_BYTES);
        if (bytesAvailable < requiredSpace * GB_BYTES) {
            freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
            ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
        } else {
            ui->freeSpace->setStyleSheet("");
        }
        ui->freeSpace->setText(freeString + ".");
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)
        ->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr) {
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked() {
    QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(
        0, "Choose data directory", ui->dataDirectory->text()));
    if (!dir.isEmpty()) ui->dataDirectory->setText(dir);
}

void Intro::on_dataDirDefault_clicked() {
    setDataDirectory(getDefaultDataDirectory());
}

void Intro::on_dataDirCustom_clicked() {
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
}

void Intro::startThread() {
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, &FreespaceChecker::reply, this, &Intro::setStatus);
    connect(this, &Intro::requestCheck, executor, &FreespaceChecker::check);
    /*  make sure executor object is deleted in its own thread */
    connect(this, &Intro::stopThread, executor, &QObject::deleteLater);
    connect(this, &Intro::stopThread, thread, &QThread::quit);

    thread->start();
}

void Intro::checkPath(const QString &dataDir) {
    mutex.lock();
    pathToCheck = dataDir;
    if (!signalled) {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck() {
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>
#include <iostream>

#include "Options.hpp"
#include "Compiler.hpp"
#include "Utils.hpp"
#include "Platform.hpp"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE EddicTestSuites
#include <boost/test/unit_test.hpp>

/* Macros to ease the tests  */

#define TEST_SAMPLE(file)\
BOOST_AUTO_TEST_CASE( samples_##file ){\
    assertCompiles("samples/" #file ".eddi", "--32");\
    assertCompiles("samples/" #file ".eddi", "--64");\
}

#define ASSERT_OUTPUT_32(file, output) assertOutputEquals(file, output, "--32");
#define ASSERT_OUTPUT_64(file, output) assertOutputEquals(file, output, "--64");

#define ASSERT_OUTPUT(file, output)\
    ASSERT_OUTPUT_32(file, output);\
    ASSERT_OUTPUT_64(file, output);

#include <boost/test/detail/unit_test_parameters.hpp>

/* Config Fixture  */

struct ConfigFixture {
    ConfigFixture(){
        //TODO Configure the show progress parameter
    }

    ~ConfigFixture(){
        /* Nothing to teard down */
    }
};

/* Fixture to delete the a.out file after the compilation */

struct DeleteOutFixture {
    DeleteOutFixture(){
        /* Nothing to setup  */
    }

    ~DeleteOutFixture(){
        BOOST_TEST_MESSAGE( "Delete the a.out file" );
        remove("a.out");
    }
};

void assertCompiles(const std::string& file, const std::string& param){
    const char* argv[4];
    argv[0] = "./bin/test";
    argv[1] = param.c_str();
    argv[2] = "--quiet";
    argv[3] = file.c_str();

    BOOST_REQUIRE (eddic::parseOptions(4, argv));

    eddic::Compiler compiler;
    int code = compiler.compile(file);

    BOOST_REQUIRE_EQUAL (code, 0);
}

void assertOutputEquals(const std::string& file, const std::string& output, const std::string& param){
    assertCompiles("test/cases/" + file, param);

    std::string out = eddic::execCommand("./a.out");

    BOOST_CHECK_EQUAL (output, out);
}

/* Configure a global fixture for the configuration */

BOOST_GLOBAL_FIXTURE ( ConfigFixture  )

/* Compiles all the samples */

BOOST_FIXTURE_TEST_SUITE( SamplesSuite, DeleteOutFixture )

TEST_SAMPLE(arrays)
TEST_SAMPLE(asm)
TEST_SAMPLE(assembly)
TEST_SAMPLE(bool)
TEST_SAMPLE(compound)
TEST_SAMPLE(concat)
TEST_SAMPLE(const)
TEST_SAMPLE(functions)
TEST_SAMPLE(float)
TEST_SAMPLE(casts)
TEST_SAMPLE(inc)
TEST_SAMPLE(includes)
TEST_SAMPLE(optimize)
TEST_SAMPLE(problem)
TEST_SAMPLE(sort)
TEST_SAMPLE(identifiers)
TEST_SAMPLE(structures)

BOOST_AUTO_TEST_SUITE_END()

/* Specific tests */

BOOST_FIXTURE_TEST_SUITE(SpecificSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( array_foreach_local ){
    ASSERT_OUTPUT("array_foreach_local.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_global ){
    ASSERT_OUTPUT("array_foreach_global.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_local ){
    ASSERT_OUTPUT("array_foreach_param_local.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_global ){
    ASSERT_OUTPUT("array_foreach_param_global.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_param ){
    ASSERT_OUTPUT("array_foreach_param_param.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( if_ ){
    ASSERT_OUTPUT("if.eddi", "Cool");
}

BOOST_AUTO_TEST_CASE( while_ ){
    ASSERT_OUTPUT("while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( do_while_ ){
    ASSERT_OUTPUT("do_while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( float_ ){
    //TODO Could be better to split this test
    ASSERT_OUTPUT_32("float.eddi", "5.4990|100.0|-100.0|100.0|2.0889|4.2000|3.3300|1.5000|3.0|5.0|4.5000|5.7500|1.5000|-2.0|7.5000|2.2700|7.5590|14.4927|3.0|8.0|3.0910|2.0934|5.1844|1|1|11111|8.0|13.7500|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|3.3300|");
    ASSERT_OUTPUT_64("float.eddi", "5.4989|100.0|-100.0|100.0|2.0889|4.2000|3.3300|1.5000|3.0|5.0|4.5000|5.7500|1.5000|-2.0|7.5000|2.2700|7.5590|14.4927|3.0|8.0|3.0910|2.0934|5.1844|1|1|11111|8.0|13.7500|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|3.3300|");
}

BOOST_AUTO_TEST_CASE( for_ ){
    ASSERT_OUTPUT("for.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( foreach_ ){
    ASSERT_OUTPUT("foreach.eddi", "012345");
}

BOOST_AUTO_TEST_CASE( globals_ ){
    ASSERT_OUTPUT("globals.eddi", "1000a2000aa");
}

BOOST_AUTO_TEST_CASE( void_functions ){
    ASSERT_OUTPUT("void.eddi", "4445");
}

BOOST_AUTO_TEST_CASE( string_functions ){
    ASSERT_OUTPUT("return_string.eddi", "abcdef");
}

BOOST_AUTO_TEST_CASE( int_functions ){
    ASSERT_OUTPUT("return_int.eddi", "484");
}

BOOST_AUTO_TEST_CASE( recursive_functions ){
    ASSERT_OUTPUT("recursive.eddi", "362880");
}

BOOST_AUTO_TEST_CASE( math ){
    ASSERT_OUTPUT("math.eddi", "333|111|-111|0|24642|2|-2|-1|1|2|0|-111|");
}

BOOST_AUTO_TEST_CASE( builtin ){
    ASSERT_OUTPUT("builtin.eddi", "10|11|12|13|12|13|10|11|4|8|13|8|0|3|");
}

BOOST_AUTO_TEST_CASE( assign_value ){
    ASSERT_OUTPUT("assign_value.eddi", "66779921");
}

BOOST_AUTO_TEST_CASE( concat ){
    ASSERT_OUTPUT("concat.eddi", "asdf1234|1234asdf|asdfasdf|12341234|");
}

BOOST_AUTO_TEST_CASE( prints ){
    ASSERT_OUTPUT_32("prints.eddi", "111|0|-111|0|1|999.9899|1.0089|0.0|-1.0089|-999.9899||-0|asdf|1234asdf|");
    ASSERT_OUTPUT_64("prints.eddi", "111|0|-111|0|1|999.9900|1.0089|0.0|-1.0089|-999.9900||-0|asdf|1234asdf|");
}

BOOST_AUTO_TEST_CASE( structures ){
    ASSERT_OUTPUT_32("structures.eddi", "222|666|3.2300|0|asdf|333|888|4.3299|1|ertz|333|888|4.3299|1|ertz|");
    ASSERT_OUTPUT_64("structures.eddi", "222|666|3.2300|0|asdf|333|888|4.3300|1|ertz|333|888|4.3300|1|ertz|");
}

BOOST_AUTO_TEST_CASE( args ){
    assertCompiles("test/cases/args.eddi", "--32");

    std::string out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);

    assertCompiles("test/cases/args.eddi", "--64");

    out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);
}

BOOST_AUTO_TEST_SUITE_END()

/* Standard library test suite  */

BOOST_FIXTURE_TEST_SUITE(StandardLibSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( std_lib_arrays_sum ){
    ASSERT_OUTPUT("stdlib_array_sum.eddi", "100");
}

BOOST_AUTO_TEST_CASE( std_lib_math_min ){
    ASSERT_OUTPUT("stdlib_math_min.eddi", "999|0|0|-1|0|-1");
}

BOOST_AUTO_TEST_CASE( std_lib_math_max ){
    ASSERT_OUTPUT("stdlib_math_max.eddi", "1000|1|1|0|0|0");
}

BOOST_AUTO_TEST_CASE( std_lib_math_factorial ){
    ASSERT_OUTPUT("stdlib_math_factorial.eddi", "1|1|2|362880");
}

BOOST_AUTO_TEST_CASE( std_lib_math_pow ){
    ASSERT_OUTPUT("stdlib_math_pow.eddi", "0|1|10|100|1024|1");
}

BOOST_AUTO_TEST_SUITE_END()

/* Unit test for bug fixes regression */

BOOST_FIXTURE_TEST_SUITE(BugFixesSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( while_bug ){
    ASSERT_OUTPUT("while_bug.eddi", "W1W2W3W4W5");
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix precisions of floats<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>
#include <iostream>

#include "Options.hpp"
#include "Compiler.hpp"
#include "Utils.hpp"
#include "Platform.hpp"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE EddicTestSuites
#include <boost/test/unit_test.hpp>

/* Macros to ease the tests  */

#define TEST_SAMPLE(file)\
BOOST_AUTO_TEST_CASE( samples_##file ){\
    assertCompiles("samples/" #file ".eddi", "--32");\
    assertCompiles("samples/" #file ".eddi", "--64");\
}

#define ASSERT_OUTPUT_32(file, output) assertOutputEquals(file, output, "--32");
#define ASSERT_OUTPUT_64(file, output) assertOutputEquals(file, output, "--64");

#define ASSERT_OUTPUT(file, output)\
    ASSERT_OUTPUT_32(file, output);\
    ASSERT_OUTPUT_64(file, output);

#include <boost/test/detail/unit_test_parameters.hpp>

/* Config Fixture  */

struct ConfigFixture {
    ConfigFixture(){
        //TODO Configure the show progress parameter
    }

    ~ConfigFixture(){
        /* Nothing to teard down */
    }
};

/* Fixture to delete the a.out file after the compilation */

struct DeleteOutFixture {
    DeleteOutFixture(){
        /* Nothing to setup  */
    }

    ~DeleteOutFixture(){
        BOOST_TEST_MESSAGE( "Delete the a.out file" );
        remove("a.out");
    }
};

void assertCompiles(const std::string& file, const std::string& param){
    const char* argv[4];
    argv[0] = "./bin/test";
    argv[1] = param.c_str();
    argv[2] = "--quiet";
    argv[3] = file.c_str();

    BOOST_REQUIRE (eddic::parseOptions(4, argv));

    eddic::Compiler compiler;
    int code = compiler.compile(file);

    BOOST_REQUIRE_EQUAL (code, 0);
}

void assertOutputEquals(const std::string& file, const std::string& output, const std::string& param){
    assertCompiles("test/cases/" + file, param);

    std::string out = eddic::execCommand("./a.out");

    BOOST_CHECK_EQUAL (output, out);
}

/* Configure a global fixture for the configuration */

BOOST_GLOBAL_FIXTURE ( ConfigFixture  )

/* Compiles all the samples */

BOOST_FIXTURE_TEST_SUITE( SamplesSuite, DeleteOutFixture )

TEST_SAMPLE(arrays)
TEST_SAMPLE(asm)
TEST_SAMPLE(assembly)
TEST_SAMPLE(bool)
TEST_SAMPLE(compound)
TEST_SAMPLE(concat)
TEST_SAMPLE(const)
TEST_SAMPLE(functions)
TEST_SAMPLE(float)
TEST_SAMPLE(casts)
TEST_SAMPLE(inc)
TEST_SAMPLE(includes)
TEST_SAMPLE(optimize)
TEST_SAMPLE(problem)
TEST_SAMPLE(sort)
TEST_SAMPLE(identifiers)
TEST_SAMPLE(structures)

BOOST_AUTO_TEST_SUITE_END()

/* Specific tests */

BOOST_FIXTURE_TEST_SUITE(SpecificSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( array_foreach_local ){
    ASSERT_OUTPUT("array_foreach_local.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_global ){
    ASSERT_OUTPUT("array_foreach_global.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_local ){
    ASSERT_OUTPUT("array_foreach_param_local.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_global ){
    ASSERT_OUTPUT("array_foreach_param_global.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( array_foreach_param_param ){
    ASSERT_OUTPUT("array_foreach_param_param.eddi", "43210");
}

BOOST_AUTO_TEST_CASE( if_ ){
    ASSERT_OUTPUT("if.eddi", "Cool");
}

BOOST_AUTO_TEST_CASE( while_ ){
    ASSERT_OUTPUT("while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( do_while_ ){
    ASSERT_OUTPUT("do_while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( float_ ){
    //TODO Could be better to split this test
    ASSERT_OUTPUT_32("float.eddi", "5.4990|100.0|-100.0|100.0|2.0889|4.1999|3.3299|1.5000|3.0|5.0|4.5000|5.7500|1.5000|-2.0|7.5000|2.2699|7.5590|14.4927|3.0|8.0|3.0910|2.0934|5.1844|1|1|11111|8.0|13.7500|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|3.3299|");
    ASSERT_OUTPUT_64("float.eddi", "5.4989|100.0|-100.0|100.0|2.0889|4.2000|3.3300|1.5000|3.0|5.0|4.5000|5.7500|1.5000|-2.0|7.5000|2.2700|7.5590|14.4927|3.0|8.0|3.0910|2.0934|5.1844|1|1|11111|8.0|13.7500|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|2.5000|5.5000|3.3300|");
}

BOOST_AUTO_TEST_CASE( for_ ){
    ASSERT_OUTPUT("for.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( foreach_ ){
    ASSERT_OUTPUT("foreach.eddi", "012345");
}

BOOST_AUTO_TEST_CASE( globals_ ){
    ASSERT_OUTPUT("globals.eddi", "1000a2000aa");
}

BOOST_AUTO_TEST_CASE( void_functions ){
    ASSERT_OUTPUT("void.eddi", "4445");
}

BOOST_AUTO_TEST_CASE( string_functions ){
    ASSERT_OUTPUT("return_string.eddi", "abcdef");
}

BOOST_AUTO_TEST_CASE( int_functions ){
    ASSERT_OUTPUT("return_int.eddi", "484");
}

BOOST_AUTO_TEST_CASE( recursive_functions ){
    ASSERT_OUTPUT("recursive.eddi", "362880");
}

BOOST_AUTO_TEST_CASE( math ){
    ASSERT_OUTPUT("math.eddi", "333|111|-111|0|24642|2|-2|-1|1|2|0|-111|");
}

BOOST_AUTO_TEST_CASE( builtin ){
    ASSERT_OUTPUT("builtin.eddi", "10|11|12|13|12|13|10|11|4|8|13|8|0|3|");
}

BOOST_AUTO_TEST_CASE( assign_value ){
    ASSERT_OUTPUT("assign_value.eddi", "66779921");
}

BOOST_AUTO_TEST_CASE( concat ){
    ASSERT_OUTPUT("concat.eddi", "asdf1234|1234asdf|asdfasdf|12341234|");
}

BOOST_AUTO_TEST_CASE( prints ){
    ASSERT_OUTPUT_32("prints.eddi", "111|0|-111|0|1|999.9899|1.0089|0.0|-1.0089|-999.9899||-0|asdf|1234asdf|");
    ASSERT_OUTPUT_64("prints.eddi", "111|0|-111|0|1|999.9900|1.0089|0.0|-1.0089|-999.9900||-0|asdf|1234asdf|");
}

BOOST_AUTO_TEST_CASE( structures ){
    ASSERT_OUTPUT_32("structures.eddi", "222|666|3.2300|0|asdf|333|888|4.3299|1|ertz|333|888|4.3299|1|ertz|");
    ASSERT_OUTPUT_64("structures.eddi", "222|666|3.2300|0|asdf|333|888|4.3300|1|ertz|333|888|4.3300|1|ertz|");
}

BOOST_AUTO_TEST_CASE( args ){
    assertCompiles("test/cases/args.eddi", "--32");

    std::string out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);

    assertCompiles("test/cases/args.eddi", "--64");

    out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);
}

BOOST_AUTO_TEST_SUITE_END()

/* Standard library test suite  */

BOOST_FIXTURE_TEST_SUITE(StandardLibSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( std_lib_arrays_sum ){
    ASSERT_OUTPUT("stdlib_array_sum.eddi", "100");
}

BOOST_AUTO_TEST_CASE( std_lib_math_min ){
    ASSERT_OUTPUT("stdlib_math_min.eddi", "999|0|0|-1|0|-1");
}

BOOST_AUTO_TEST_CASE( std_lib_math_max ){
    ASSERT_OUTPUT("stdlib_math_max.eddi", "1000|1|1|0|0|0");
}

BOOST_AUTO_TEST_CASE( std_lib_math_factorial ){
    ASSERT_OUTPUT("stdlib_math_factorial.eddi", "1|1|2|362880");
}

BOOST_AUTO_TEST_CASE( std_lib_math_pow ){
    ASSERT_OUTPUT("stdlib_math_pow.eddi", "0|1|10|100|1024|1");
}

BOOST_AUTO_TEST_SUITE_END()

/* Unit test for bug fixes regression */

BOOST_FIXTURE_TEST_SUITE(BugFixesSuite, DeleteOutFixture)

BOOST_AUTO_TEST_CASE( while_bug ){
    ASSERT_OUTPUT("while_bug.eddi", "W1W2W3W4W5");
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>

#include "Options.hpp"
#include "Compiler.hpp"
#include "Utils.hpp"
#include "Platform.hpp"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Eddic Tests
#include <boost/test/unit_test.hpp>

#define TEST_SAMPLE(file)\
BOOST_AUTO_TEST_CASE( samples_##file ){\
    assertCompiles("samples/" #file ".eddi");\
}

void assertCompiles(const std::string& file){
    eddic::parseOptions(0, {});

    eddic::Compiler compiler;

    eddic::Platform platform = eddic::Platform::INTEL_X86;
    int code = compiler.compileOnly(file, platform);

    BOOST_CHECK_EQUAL (code, 0);
}

void assertOutputEquals(const std::string& file, const std::string& output){
    assertCompiles("test/cases/" + file);

    std::string out = eddic::execCommand("./a.out");

    BOOST_CHECK_EQUAL (output, out);
}

/* Compiles all the samples */

TEST_SAMPLE(arrays)
TEST_SAMPLE(asm)
TEST_SAMPLE(assembly)
TEST_SAMPLE(bool)
TEST_SAMPLE(compound)
TEST_SAMPLE(concat)
TEST_SAMPLE(const)
TEST_SAMPLE(functions)
TEST_SAMPLE(inc)
TEST_SAMPLE(includes)
TEST_SAMPLE(optimize)
TEST_SAMPLE(problem)
TEST_SAMPLE(sort)
TEST_SAMPLE(identifiers)

/* Specific tests */

BOOST_AUTO_TEST_CASE( if_ ){
    assertOutputEquals("if.eddi", "Cool");
}

BOOST_AUTO_TEST_CASE( while_ ){
    assertOutputEquals("while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( for_ ){
    assertOutputEquals("for.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( foreach_ ){
    assertOutputEquals("foreach.eddi", "012345");
}

BOOST_AUTO_TEST_CASE( globals_ ){
    assertOutputEquals("globals.eddi", "1000a2000aa");
}

BOOST_AUTO_TEST_CASE( void_functions ){
    assertOutputEquals("void.eddi", "4445");
}

BOOST_AUTO_TEST_CASE( string_functions ){
    assertOutputEquals("return_string.eddi", "abcdef");
}

BOOST_AUTO_TEST_CASE( int_functions ){
    assertOutputEquals("return_int.eddi", "484");
}

BOOST_AUTO_TEST_CASE( recursive_functions ){
    assertOutputEquals("recursive.eddi", "362880");
}

BOOST_AUTO_TEST_CASE( math ){
    assertOutputEquals("math.eddi", "333|111|-111|0|24642|2|-2|-1|1|2|0|-111|");
}

BOOST_AUTO_TEST_CASE( builtin ){
    assertOutputEquals("builtin.eddi", "10|11|12|13|12|13|10|11|4|8|13|8|0|3|");
}

BOOST_AUTO_TEST_CASE( args ){
    assertCompiles("test/cases/args.eddi");

    std::string out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);
}

/* Unit test for bug fixes regression */
BOOST_AUTO_TEST_CASE( while_bug ){
    assertOutputEquals("while_bug.eddi", "W1W2W3W4W5");
}
<commit_msg>Make tests in 32 bits<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>

#include "Options.hpp"
#include "Compiler.hpp"
#include "Utils.hpp"
#include "Platform.hpp"

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Eddic Tests
#include <boost/test/unit_test.hpp>

#define TEST_SAMPLE(file)\
BOOST_AUTO_TEST_CASE( samples_##file ){\
    assertCompiles("samples/" #file ".eddi");\
}

void assertCompiles(const std::string& file){
    const char* options[1] = {"-32"};
    eddic::parseOptions(1, options);

    eddic::Compiler compiler;

    eddic::Platform platform = eddic::Platform::INTEL_X86;
    int code = compiler.compileOnly(file, platform);

    BOOST_CHECK_EQUAL (code, 0);
}

void assertOutputEquals(const std::string& file, const std::string& output){
    assertCompiles("test/cases/" + file);

    std::string out = eddic::execCommand("./a.out");

    BOOST_CHECK_EQUAL (output, out);
}

/* Compiles all the samples */

TEST_SAMPLE(arrays)
TEST_SAMPLE(asm)
TEST_SAMPLE(assembly)
TEST_SAMPLE(bool)
TEST_SAMPLE(compound)
TEST_SAMPLE(concat)
TEST_SAMPLE(const)
TEST_SAMPLE(functions)
TEST_SAMPLE(inc)
TEST_SAMPLE(includes)
TEST_SAMPLE(optimize)
TEST_SAMPLE(problem)
TEST_SAMPLE(sort)
TEST_SAMPLE(identifiers)

/* Specific tests */

BOOST_AUTO_TEST_CASE( if_ ){
    assertOutputEquals("if.eddi", "Cool");
}

BOOST_AUTO_TEST_CASE( while_ ){
    assertOutputEquals("while.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( for_ ){
    assertOutputEquals("for.eddi", "01234");
}

BOOST_AUTO_TEST_CASE( foreach_ ){
    assertOutputEquals("foreach.eddi", "012345");
}

BOOST_AUTO_TEST_CASE( globals_ ){
    assertOutputEquals("globals.eddi", "1000a2000aa");
}

BOOST_AUTO_TEST_CASE( void_functions ){
    assertOutputEquals("void.eddi", "4445");
}

BOOST_AUTO_TEST_CASE( string_functions ){
    assertOutputEquals("return_string.eddi", "abcdef");
}

BOOST_AUTO_TEST_CASE( int_functions ){
    assertOutputEquals("return_int.eddi", "484");
}

BOOST_AUTO_TEST_CASE( recursive_functions ){
    assertOutputEquals("recursive.eddi", "362880");
}

BOOST_AUTO_TEST_CASE( math ){
    assertOutputEquals("math.eddi", "333|111|-111|0|24642|2|-2|-1|1|2|0|-111|");
}

BOOST_AUTO_TEST_CASE( builtin ){
    assertOutputEquals("builtin.eddi", "10|11|12|13|12|13|10|11|4|8|13|8|0|3|");
}

BOOST_AUTO_TEST_CASE( args ){
    assertCompiles("test/cases/args.eddi");

    std::string out = eddic::execCommand("./a.out");
    BOOST_CHECK_EQUAL ("./a.out|", out);

    out = eddic::execCommand("./a.out arg1 arg2 arg3");
    BOOST_CHECK_EQUAL ("./a.out|arg1|arg2|arg3|", out);
}

/* Unit test for bug fixes regression */
BOOST_AUTO_TEST_CASE( while_bug ){
    assertOutputEquals("while_bug.eddi", "W1W2W3W4W5");
}
<|endoftext|>


<commit_before>#ifdef _MSC_VER
#pragma warning(disable: 4786 4250 4503)
#endif
#include "../CppUnit/framework/TestCase.h"
#include "../CppUnit/framework/TestSuite.h"
#include "../CppUnit/framework/TestCaller.h"
#include <sstream>
#include <DOM/SAX2DOM/SAX2DOM.h>

class SAXTest : public TestCase
{
  public:
    SAXTest(std::string name) :
        TestCase(name)
    {
    } // SAXTest

    void setUp()
    {
    } // setUp

    DOM::Document<std::string> parse(std::string str)
    {
      std::stringstream ss;
      ss << str;

      SAX::InputSource is(ss);
      SAX2DOM::Parser<std::string> parser;
      parser.parse(is);
      return parser.getDocument();
    } // parse

    void test1()
    {
      DOM::Element<std::string> d;
      DOM::Node<std::string> n;
      assert(d == 0);
      assert(n == 0);
      assert(n == d);
    } // test1

    void test2()
    {
      DOM::Document<std::string> d = parse("<root/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assert(elem.getParentNode() == d);
      assert(elem.getOwnerDocument() == d);
    } // test2

    void test3()
    {
      DOM::Document<std::string> d = parse("<root attr=\"poop\"/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assert(elem.hasAttributes() == true);
      assert(elem.getAttribute("attr") == "poop");
    } // test3

    void test4()
    {
      DOM::Document<std::string> d = parse("<root><child attr=\"poop\"/></root>");
      DOM::Element<std::string> elem = DOM::Element<std::string>(d.getDocumentElement().getFirstChild());
      assertEquals("child", elem.getNodeName());
      assertEquals(true, elem.hasAttributes());
      assertEquals("poop", elem.getAttribute("attr"));
    } // test4

    void test5()
    {
      DOM::Document<std::string> d = parse("<stuff:elem attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(true, elem.hasNamespaceURI());
      assertEquals("http://example.com/stuff", elem.getNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNode("attr");
      assertEquals(false, attr.hasNamespaceURI());
    } // test5

    void test6()
    {
      DOM::Document<std::string> d = parse("<stuff:elem stuff:attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(true, elem.hasNamespaceURI());
      assertEquals("http://example.com/stuff", elem.getNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNodeNS("http://example.com/stuff", "attr");
      assertEquals(true, attr.hasNamespaceURI());
      assertEquals("http://example.com/stuff", attr.getNamespaceURI());
    } // test6

    void test7()
    {
      DOM::Document<std::string> d = parse("<elem stuff:attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(false, elem.hasNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNodeNS("http://example.com/stuff", "attr");
      assertEquals(true, attr.hasNamespaceURI());
      assertEquals("http://example.com/stuff", attr.getNamespaceURI());
    } // test7

    void test8()
    {
      DOM::Document<std::string> d = parse("<root attr=\"poop\"><child/></root>");
      DOM::Element<std::string> elem = d.getDocumentElement();

      DOM::Element<std::string> e2 = DOM::Element<std::string>(elem.cloneNode(true));
      assert(e2.getOwnerDocument() == d);
      assert(e2.getParentNode() == 0);
      assert(e2.hasAttributes() == true);
      assert(e2.getAttribute("attr") == "poop");
      assert(e2.getFirstChild().getNodeName() == "child");
    } // test8

    void test9()
    {
      DOM::Document<std::string> d = parse("<elem attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(false, elem.hasNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNode("attr");
      assertEquals(false, attr.hasNamespaceURI());
    } // test9

    void test10()
    {
      DOM::Document<std::string> d = parse("<elem stuff:attr='something' poop:attr='fail' xmlns:stuff='http://example.com/stuff'/>");
      assert(d == 0);
    } // test10
};

TestSuite* SAXTest_suite()
{
    TestSuite *suiteOfTests = new TestSuite;
    suiteOfTests->addTest(new TestCaller<SAXTest>("test1", &SAXTest::test1));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test2", &SAXTest::test2));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test3", &SAXTest::test3));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test4", &SAXTest::test4));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test5", &SAXTest::test5));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test6", &SAXTest::test6));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test7", &SAXTest::test7));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test8", &SAXTest::test8));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test9", &SAXTest::test9));
    suiteOfTests->addTest(new TestCaller<SAXTest>("test10", &SAXTest::test10));
    return suiteOfTests;
} // MathTest_suite

<commit_msg>add a couple of getFeature/setFeature tests<commit_after>#ifdef _MSC_VER
#pragma warning(disable: 4786 4250 4503)
#endif
#include "../CppUnit/framework/TestCase.h"
#include "../CppUnit/framework/TestSuite.h"
#include "../CppUnit/framework/TestCaller.h"
#include <sstream>
#include <DOM/SAX2DOM/SAX2DOM.h>

class SAXTest : public TestCase
{
  public:
    SAXTest(std::string name) :
        TestCase(name)
    {
    } // SAXTest

    void setUp()
    {
    } // setUp

    DOM::Document<std::string> parse(std::string str)
    {
      std::stringstream ss;
      ss << str;

      SAX::InputSource is(ss);
      SAX2DOM::Parser<std::string> parser;
      parser.parse(is);
      return parser.getDocument();
    } // parse

    void test1()
    {
      DOM::Element<std::string> d;
      DOM::Node<std::string> n;
      assert(d == 0);
      assert(n == 0);
      assert(n == d);
    } // test1

    void test2()
    {
      DOM::Document<std::string> d = parse("<root/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assert(elem.getParentNode() == d);
      assert(elem.getOwnerDocument() == d);
    } // test2

    void test3()
    {
      DOM::Document<std::string> d = parse("<root attr=\"poop\"/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assert(elem.hasAttributes() == true);
      assert(elem.getAttribute("attr") == "poop");
    } // test3

    void test4()
    {
      DOM::Document<std::string> d = parse("<root><child attr=\"poop\"/></root>");
      DOM::Element<std::string> elem = DOM::Element<std::string>(d.getDocumentElement().getFirstChild());
      assertEquals("child", elem.getNodeName());
      assertEquals(true, elem.hasAttributes());
      assertEquals("poop", elem.getAttribute("attr"));
    } // test4

    void test5()
    {
      DOM::Document<std::string> d = parse("<stuff:elem attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(true, elem.hasNamespaceURI());
      assertEquals("http://example.com/stuff", elem.getNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNode("attr");
      assertEquals(false, attr.hasNamespaceURI());
    } // test5

    void test6()
    {
      DOM::Document<std::string> d = parse("<stuff:elem stuff:attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(true, elem.hasNamespaceURI());
      assertEquals("http://example.com/stuff", elem.getNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNodeNS("http://example.com/stuff", "attr");
      assertEquals(true, attr.hasNamespaceURI());
      assertEquals("http://example.com/stuff", attr.getNamespaceURI());
    } // test6

    void test7()
    {
      DOM::Document<std::string> d = parse("<elem stuff:attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(false, elem.hasNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNodeNS("http://example.com/stuff", "attr");
      assertEquals(true, attr.hasNamespaceURI());
      assertEquals("http://example.com/stuff", attr.getNamespaceURI());
    } // test7

    void test8()
    {
      DOM::Document<std::string> d = parse("<root attr=\"poop\"><child/></root>");
      DOM::Element<std::string> elem = d.getDocumentElement();

      DOM::Element<std::string> e2 = DOM::Element<std::string>(elem.cloneNode(true));
      assert(e2.getOwnerDocument() == d);
      assert(e2.getParentNode() == 0);
      assert(e2.hasAttributes() == true);
      assert(e2.getAttribute("attr") == "poop");
      assert(e2.getFirstChild().getNodeName() == "child");
    } // test8

    void test9()
    {
      DOM::Document<std::string> d = parse("<elem attr='something' xmlns:stuff='http://example.com/stuff'/>");
      DOM::Element<std::string> elem = d.getDocumentElement();
      assertEquals(false, elem.hasNamespaceURI());

      DOM::Attr<std::string> attr = elem.getAttributeNode("attr");
      assertEquals(false, attr.hasNamespaceURI());
    } // test9

    void test10()
    {
      DOM::Document<std::string> d = parse("<elem stuff:attr='something' poop:attr='fail' xmlns:stuff='http://example.com/stuff'/>");
      assert(d == 0);
    } // test10

    void test11()
    {
      SAX2DOM::Parser<std::string> parser;
      assert(parser.getFeature("http://xml.org/sax/features/validation") == true);
      parser.setFeature("http://xml.org/sax/features/validation", false);
      assert(parser.getFeature("http://xml.org/sax/features/validation") == false);

      parser.parse("<root attr=\"poop\"><child/></root>");
    } // test11

    void test12()
    {
      SAX2DOM::Parser<std::string> parser;
      try
      {
        parser.getFeature("made up name");
        assert(false);
      }
      catch(const SAX::SAXNotRecognizedException&)
      {
      }
    } // test12
};

TestSuite* SAXTest_suite()
{
  TestSuite *suiteOfTests = new TestSuite;
  suiteOfTests->addTest(new TestCaller<SAXTest>("test1", &SAXTest::test1));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test2", &SAXTest::test2));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test3", &SAXTest::test3));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test4", &SAXTest::test4));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test5", &SAXTest::test5));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test6", &SAXTest::test6));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test7", &SAXTest::test7));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test8", &SAXTest::test8));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test9", &SAXTest::test9));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test10", &SAXTest::test10));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test11", &SAXTest::test11));
  suiteOfTests->addTest(new TestCaller<SAXTest>("test12", &SAXTest::test12));
  return suiteOfTests;
} // MathTest_suite

<|endoftext|>


<commit_before>#include "parsertests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>

namespace Test
{
    namespace Parser {
		TEST NoEndOfMapFlow()
        {
            try {
                HANDLE("---{header: {id: 1");
            } catch(const YAML::ParserException& e) {
                YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW));
                return true;
            }
            return "  no exception caught";
        }
    }

	namespace {
		void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
			TEST ret;
			try {
				ret = test();
			} catch(const YAML::Exception& e) {
				ret.ok = false;
				ret.error = std::string("  Exception caught: ") + e.what();
			}

			if(!ret.ok) {
				std::cout << "Parser test failed: " << name << "\n";
				std::cout << ret.error << "\n";
			}

			if(ret.ok)
				passed++;
			total++;
		}
	}

	bool RunParserTests()
	{
		int passed = 0;
		int total = 0;
		RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total);

		std::cout << "Parser tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<commit_msg>Added failing test for parsing a ? at the start of a value<commit_after>#include "parsertests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>

namespace Test
{
    namespace Parser {
		TEST NoEndOfMapFlow()
        {
            try {
                HANDLE("---{header: {id: 1");
            } catch(const YAML::ParserException& e) {
                YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW));
                return true;
            }
            return "  no exception caught";
        }

        TEST PlainScalarStartingWithQuestionMark()
        {
            HANDLE("foo: ?bar");
            EXPECT_DOC_START();
            EXPECT_MAP_START("?", 0);
            EXPECT_SCALAR("?", 0, "foo");
            EXPECT_SCALAR("?", 0, "?bar");
            EXPECT_MAP_END();
            EXPECT_DOC_END();
            DONE();
        }
    }

	namespace {
		void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
			TEST ret;
			try {
				ret = test();
			} catch(const YAML::Exception& e) {
				ret.ok = false;
				ret.error = std::string("  Exception caught: ") + e.what();
			}

			if(!ret.ok) {
				std::cout << "Parser test failed: " << name << "\n";
				std::cout << ret.error << "\n";
			}

			if(ret.ok)
				passed++;
			total++;
		}
	}

	bool RunParserTests()
	{
		int passed = 0;
		int total = 0;
		RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total);
		RunParserTest(&Parser::PlainScalarStartingWithQuestionMark, "Plain scalar starting with question mark", passed, total);

		std::cout << "Parser tests: " << passed << "/" << total << " passed\n";
		return passed == total;
	}
}
<|endoftext|>


<commit_before>#include <ros/ros.h>

#include <ompl/geometric/SimpleSetup.h>
#include <ompl/geometric/planners/rrt/RRT.h>
#include <ompl/base/spaces/SE2StateSpace.h>

#include <cmath>
#include <iostream>
#include <fstream>

namespace ob = ompl::base;
namespace og = ompl::geometric;

void planWithSimpleSetup(){
    ob::StateSpacePtr space(new ob::SE2StateSpace());
    ob::RealVectorBounds bounds(2);
    bounds.setLow(-1);
    bounds.setHigh(1);
    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    og::SimpleSetup ss(space);

    //TODO: Set state validity checker

    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setXY(-0.9, -0.9);
    std::cout << "start: "; start.print(std::cout);

    ob::ScopedState<ob::SE2StateSpace> goal(space);
    goal->setXY(0.9, 0.9);
    std::cout << "goal: "; goal.print(std::cout);

    ss.setStartAndGoalStates(start, goal);

    ob::PlannerPtr planner(new og::PRM(ss.getSpaceInformation()));
    ss.setPlanner(planner);

    std::cout << "-----------------" << std::endl;

    ob::PlannerStatus solved = ss.solve(1.0);

    if(solved){
        ss.simplifySolution();
        std::cout << "------------" << std::endl;
        std::cout << "Found solution:" << std::endl;
        ss.getSolutionPath().print(std::cout);

        std::ofstream ofs("path.dat");
        ss.getSolutionPath().printAsMatrix(ofs);
    }else{
        ROS_ERROR("Solution is not found");
    }
}

int main(int argc, char *argv[]){
    ros::init(argc, argv, "global_path_planner");
    planWithSimpleSetup();
    return 0;
}

<commit_msg>Change the planner type<commit_after>#include <ros/ros.h>

#include <ompl/geometric/SimpleSetup.h>
#include <ompl/geometric/planners/rrt/RRT.h>
#include <ompl/base/spaces/SE2StateSpace.h>

#include <cmath>
#include <iostream>
#include <fstream>

namespace ob = ompl::base;
namespace og = ompl::geometric;

void planWithSimpleSetup(){
    ob::StateSpacePtr space(new ob::SE2StateSpace());
    ob::RealVectorBounds bounds(2);
    bounds.setLow(-1);
    bounds.setHigh(1);
    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    og::SimpleSetup ss(space);

    //TODO: Set state validity checker

    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setXY(-0.9, -0.9);
    std::cout << "start: "; start.print(std::cout);

    ob::ScopedState<ob::SE2StateSpace> goal(space);
    goal->setXY(0.9, 0.9);
    std::cout << "goal: "; goal.print(std::cout);

    ss.setStartAndGoalStates(start, goal);

    ob::PlannerPtr planner(new og::RRT(ss.getSpaceInformation()));
    ss.setPlanner(planner);

    std::cout << "-----------------" << std::endl;

    ob::PlannerStatus solved = ss.solve(1.0);

    if(solved){
        ss.simplifySolution();
        std::cout << "------------" << std::endl;
        std::cout << "Found solution:" << std::endl;
        ss.getSolutionPath().print(std::cout);

        std::ofstream ofs("path.dat");
        ss.getSolutionPath().printAsMatrix(ofs);
    }else{
        ROS_ERROR("Solution is not found");
    }
}

int main(int argc, char *argv[]){
    ros::init(argc, argv, "global_path_planner");
    planWithSimpleSetup();
    return 0;
}

<|endoftext|>


<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2016 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/exceptions.h>
#include <deal.II/base/logstream.h>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sstream>

#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
#  include <execinfo.h>
#endif

#ifdef DEAL_II_HAVE_LIBSTDCXX_DEMANGLER
#  include <cxxabi.h>
#endif

DEAL_II_NAMESPACE_OPEN

namespace deal_II_exceptions
{

  std::string additional_assert_output;

  void set_additional_assert_output (const char *const p)
  {
    additional_assert_output = p;
  }

  bool show_stacktrace = true;

  void suppress_stacktrace_in_exceptions ()
  {
    show_stacktrace = false;
  }

  bool abort_on_exception = true;

  void disable_abort_on_exception ()
  {
    abort_on_exception = false;
  }

}

ExceptionBase::ExceptionBase ()
  :
  file(""),
  line(0),
  function(""),
  cond(""),
  exc(""),
  stacktrace (NULL),
  n_stacktrace_frames (0),
  what_str("")
{}

ExceptionBase::ExceptionBase (const ExceptionBase &exc)
  :
  file(exc.file),
  line(exc.line),
  function(exc.function),
  cond(exc.cond),
  exc(exc.exc),
  stacktrace (NULL), // don't copy stacktrace to avoid double de-allocation problem
  n_stacktrace_frames (0),
  what_str("") // don't copy the error message, it gets generated dynamically by what()
{}

ExceptionBase::~ExceptionBase () DEAL_II_NOEXCEPT
{
  free (stacktrace); // free(NULL) is allowed
  stacktrace = NULL;
}

void ExceptionBase::set_fields (const char *f,
                                const int  l,
                                const char *func,
                                const char *c,
                                const char *e)
{
  file = f;
  line = l;
  function = func;
  cond = c;
  exc  = e;

  // If the system supports this, get a stacktrace how we got here:
  // Note that we defer the symbol lookup done by backtrace_symbols()
  // to when we need it (see what() below). This is for performance
  // reasons, as this requires loading libraries and can take in the
  // order of seconds on some machines.
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
  n_stacktrace_frames = backtrace(raw_stacktrace, 25);
#endif
}

const char *ExceptionBase::what() const DEAL_II_NOEXCEPT
{
  // If no error c_string was generated so far, do it now:
  if (what_str == "")
    {
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
      // We have deferred the symbol lookup to this point to avoid costly
      // runtime penalties due to linkage of external libraries by
      // backtrace_symbols.

      // first delete old stacktrace if necessary
      free (stacktrace); // free(NULL) is allowed
      stacktrace = backtrace_symbols(raw_stacktrace, n_stacktrace_frames);
#endif

      generate_message();
    }

  return what_str.c_str();
}

const char *ExceptionBase::get_exc_name () const
{
  return exc;
}

void ExceptionBase::print_exc_data (std::ostream &out) const
{
  // print a header for the exception
  out << "An error occurred in line <" << line
      << "> of file <" << file
      << "> in function" << std::endl
      << "    " << function << std::endl
      << "The violated condition was: "<< std::endl
      << "    " << cond << std::endl;

  // print the way the additional information message was generated.
  // this is useful if the names of local variables appear in the
  // generation of the error message, because it allows the identification
  // of parts of the error text with what variables may have cause this
  //
  // On the other hand, this is almost never the case for ExcMessage
  // exceptions which would simply print the same text twice: once for
  // the way the message was composed, and once for the additional
  // information. Furthermore, the former of these two is often spread
  // between numerous "..."-enclosed strings that the preprocessor
  // collates into a single string, making it awkward to read. Consequently,
  // elide this text if the message was generated via an ExcMessage object
  if (std::strstr(cond, "dealii::ExcMessage") != NULL)
    out << "The name and call sequence of the exception was:" << std::endl
        << "    " << exc  << std::endl;

  // finally print the additional information the exception provides:
  out << "Additional information: " << std::endl;
}

void ExceptionBase::print_info (std::ostream &out) const
{
  out << "    (none)" << std::endl;
}

void ExceptionBase::print_stack_trace (std::ostream &out) const
{
  if (n_stacktrace_frames == 0)
    return;

  if (deal_II_exceptions::show_stacktrace == false)
    return;

  // if there is a stackframe stored, print it
  out << std::endl;
  out << "Stacktrace:" << std::endl
      << "-----------" << std::endl;

  // print the stacktrace. first omit all those frames that have
  // ExceptionBase or deal_II_exceptions in their names, as these
  // correspond to the exception raising mechanism themselves, rather than
  // the place where the exception was triggered
  int frame = 0;
  while ((frame < n_stacktrace_frames)
         &&
         ((std::string(stacktrace[frame]).find ("ExceptionBase") != std::string::npos)
          ||
          (std::string(stacktrace[frame]).find ("deal_II_exceptions") != std::string::npos)))
    ++frame;

  // output the rest
  const unsigned int first_significant_frame = frame;
  for (; frame < n_stacktrace_frames; ++frame)
    {
      out << '#' << frame - first_significant_frame
          << "  ";

      // the stacktrace frame is actually of the format
      // "filename(functionname+offset) [address]". let's try to get the
      // mangled functionname out:
      std::string stacktrace_entry (stacktrace[frame]);
      const unsigned int pos_start = stacktrace_entry.find('('),
                         pos_end   = stacktrace_entry.find('+');
      std::string functionname = stacktrace_entry.substr (pos_start+1,
                                                          pos_end-pos_start-1);

      // demangle, and if successful replace old mangled string by
      // unmangled one (skipping address and offset). treat "main"
      // differently, since it is apparently demangled as "unsigned int"
      // for unknown reasons :-) if we can, demangle the function name
#ifdef DEAL_II_HAVE_LIBSTDCXX_DEMANGLER
      int         status;
      char *p = abi::__cxa_demangle(functionname.c_str(), 0, 0, &status);

      if ((status == 0) && (functionname != "main"))
        {
          std::string realname(p);
          // in MT mode, one often gets backtraces spanning several lines
          // because we have so many boost::tuple arguments in the MT
          // calling functions. most of the trailing arguments of these
          // tuples are actually unused boost::tuples::null_type, so we
          // should split them off if they are trailing a template argument
          // list
          while (realname.find (", boost::tuples::null_type>")
                 != std::string::npos)
            realname.erase (realname.find (", boost::tuples::null_type>"),
                            std::string (", boost::tuples::null_type").size());

          stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                             +
                             ": "
                             +
                             realname;
        }
      else
        stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                           +
                           ": "
                           +
                           functionname;

      free (p);

#else

      stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                         +
                         ": "
                         +
                         functionname;
#endif

      // then output what we have
      out << stacktrace_entry
          << std::endl;

      // stop if we're in main()
      if (functionname == "main")
        break;
    }
}

void ExceptionBase::generate_message () const
{
  // build up a c_string with the error message.
  // Guard this procedure with a try block, we shall not throw at this
  // place...
  try
    {
      std::ostringstream converter;

      converter << std::endl
                << "--------------------------------------------------------"
                << std::endl;

      // print out general data
      print_exc_data (converter);
      // print out exception specific data
      print_info (converter);
      print_stack_trace (converter);

      if (!deal_II_exceptions::additional_assert_output.empty())
        {
          converter << "--------------------------------------------------------"
                    << std::endl
                    << deal_II_exceptions::additional_assert_output
                    << std::endl;
        }

      converter << "--------------------------------------------------------"
                << std::endl;

      what_str = converter.str();
    }
  catch (...)
    {
      // On error, resume next. There is nothing better we can do...
      what_str = "ExceptionBase::generate_message () failed";
    }
}

namespace deal_II_exceptions
{
  namespace internals
  {

    void abort (const ExceptionBase &exc, bool nothrow /*= false*/)
    {
      if (dealii::deal_II_exceptions::abort_on_exception)
        {
          // Print the error message and bail out:
          std::cerr << exc.what() << std::endl;
          std::abort();
        }
      else if (nothrow)
        {
          // We are not allowed to throw, and not allowed to abort.
          // Just print the exception name to deallog and continue
          // normally:
          deallog << "Exception: " << exc.get_exc_name() << std::endl;
        }
      else
        {
          // We are not allowed to abort, so just throw the error so just
          // throw the error so just throw the error so just throw the
          // error:
          throw exc;
        }
    }

  } /*namespace internals*/
} /*namespace deal_II_exceptions*/

DEAL_II_NAMESPACE_CLOSE

// Newer versions of gcc have a very nice feature: you can set a verbose
// terminate handler, that not only aborts a program when an exception is
// thrown and not caught somewhere, but before aborting it prints that an
// exception has been thrown, and possibly what the std::exception::what()
// function has to say. Since many people run into the trap of not having a
// catch clause in main(), they wonder where that abort may be coming from.
// The terminate handler then at least says what is missing in their
// program.
#ifdef DEAL_II_HAVE_VERBOSE_TERMINATE
namespace __gnu_cxx
{
  extern void __verbose_terminate_handler ();
}

namespace
{
  struct preload_terminate_dummy
  {
    preload_terminate_dummy()
    {
      std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
    }
  };

  static preload_terminate_dummy dummy;
}
#endif
<commit_msg>Initialize member variables in class ExceptionBase.<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2016 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/exceptions.h>
#include <deal.II/base/logstream.h>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <sstream>

#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
#  include <execinfo.h>
#endif

#ifdef DEAL_II_HAVE_LIBSTDCXX_DEMANGLER
#  include <cxxabi.h>
#endif

DEAL_II_NAMESPACE_OPEN

namespace deal_II_exceptions
{

  std::string additional_assert_output;

  void set_additional_assert_output (const char *const p)
  {
    additional_assert_output = p;
  }

  bool show_stacktrace = true;

  void suppress_stacktrace_in_exceptions ()
  {
    show_stacktrace = false;
  }

  bool abort_on_exception = true;

  void disable_abort_on_exception ()
  {
    abort_on_exception = false;
  }

}

ExceptionBase::ExceptionBase ()
  :
  file(""),
  line(0),
  function(""),
  cond(""),
  exc(""),
  stacktrace (NULL),
  n_stacktrace_frames (0),
  what_str("")
{
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
  for (unsigned int i=0; i<sizeof(raw_stacktrace)/sizeof(raw_stacktrace[0]); ++i)
    raw_stacktrace[0] = NULL;
#endif
}

ExceptionBase::ExceptionBase (const ExceptionBase &exc)
  :
  file(exc.file),
  line(exc.line),
  function(exc.function),
  cond(exc.cond),
  exc(exc.exc),
  stacktrace (NULL), // don't copy stacktrace to avoid double de-allocation problem
  n_stacktrace_frames (0),
  what_str("") // don't copy the error message, it gets generated dynamically by what()
{
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
  for (unsigned int i=0; i<sizeof(raw_stacktrace)/sizeof(raw_stacktrace[0]); ++i)
    raw_stacktrace[0] = NULL;
#endif
}

ExceptionBase::~ExceptionBase () DEAL_II_NOEXCEPT
{
  free (stacktrace); // free(NULL) is allowed
  stacktrace = NULL;
}

void ExceptionBase::set_fields (const char *f,
                                const int  l,
                                const char *func,
                                const char *c,
                                const char *e)
{
  file = f;
  line = l;
  function = func;
  cond = c;
  exc  = e;

  // If the system supports this, get a stacktrace how we got here:
  // Note that we defer the symbol lookup done by backtrace_symbols()
  // to when we need it (see what() below). This is for performance
  // reasons, as this requires loading libraries and can take in the
  // order of seconds on some machines.
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
  n_stacktrace_frames = backtrace(raw_stacktrace, 25);
#endif
}

const char *ExceptionBase::what() const DEAL_II_NOEXCEPT
{
  // If no error c_string was generated so far, do it now:
  if (what_str == "")
    {
#ifdef DEAL_II_HAVE_GLIBC_STACKTRACE
      // We have deferred the symbol lookup to this point to avoid costly
      // runtime penalties due to linkage of external libraries by
      // backtrace_symbols.

      // first delete old stacktrace if necessary
      free (stacktrace); // free(NULL) is allowed
      stacktrace = backtrace_symbols(raw_stacktrace, n_stacktrace_frames);
#endif

      generate_message();
    }

  return what_str.c_str();
}

const char *ExceptionBase::get_exc_name () const
{
  return exc;
}

void ExceptionBase::print_exc_data (std::ostream &out) const
{
  // print a header for the exception
  out << "An error occurred in line <" << line
      << "> of file <" << file
      << "> in function" << std::endl
      << "    " << function << std::endl
      << "The violated condition was: "<< std::endl
      << "    " << cond << std::endl;

  // print the way the additional information message was generated.
  // this is useful if the names of local variables appear in the
  // generation of the error message, because it allows the identification
  // of parts of the error text with what variables may have cause this
  //
  // On the other hand, this is almost never the case for ExcMessage
  // exceptions which would simply print the same text twice: once for
  // the way the message was composed, and once for the additional
  // information. Furthermore, the former of these two is often spread
  // between numerous "..."-enclosed strings that the preprocessor
  // collates into a single string, making it awkward to read. Consequently,
  // elide this text if the message was generated via an ExcMessage object
  if (std::strstr(cond, "dealii::ExcMessage") != NULL)
    out << "The name and call sequence of the exception was:" << std::endl
        << "    " << exc  << std::endl;

  // finally print the additional information the exception provides:
  out << "Additional information: " << std::endl;
}

void ExceptionBase::print_info (std::ostream &out) const
{
  out << "    (none)" << std::endl;
}

void ExceptionBase::print_stack_trace (std::ostream &out) const
{
  if (n_stacktrace_frames == 0)
    return;

  if (deal_II_exceptions::show_stacktrace == false)
    return;

  // if there is a stackframe stored, print it
  out << std::endl;
  out << "Stacktrace:" << std::endl
      << "-----------" << std::endl;

  // print the stacktrace. first omit all those frames that have
  // ExceptionBase or deal_II_exceptions in their names, as these
  // correspond to the exception raising mechanism themselves, rather than
  // the place where the exception was triggered
  int frame = 0;
  while ((frame < n_stacktrace_frames)
         &&
         ((std::string(stacktrace[frame]).find ("ExceptionBase") != std::string::npos)
          ||
          (std::string(stacktrace[frame]).find ("deal_II_exceptions") != std::string::npos)))
    ++frame;

  // output the rest
  const unsigned int first_significant_frame = frame;
  for (; frame < n_stacktrace_frames; ++frame)
    {
      out << '#' << frame - first_significant_frame
          << "  ";

      // the stacktrace frame is actually of the format
      // "filename(functionname+offset) [address]". let's try to get the
      // mangled functionname out:
      std::string stacktrace_entry (stacktrace[frame]);
      const unsigned int pos_start = stacktrace_entry.find('('),
                         pos_end   = stacktrace_entry.find('+');
      std::string functionname = stacktrace_entry.substr (pos_start+1,
                                                          pos_end-pos_start-1);

      // demangle, and if successful replace old mangled string by
      // unmangled one (skipping address and offset). treat "main"
      // differently, since it is apparently demangled as "unsigned int"
      // for unknown reasons :-) if we can, demangle the function name
#ifdef DEAL_II_HAVE_LIBSTDCXX_DEMANGLER
      int         status;
      char *p = abi::__cxa_demangle(functionname.c_str(), 0, 0, &status);

      if ((status == 0) && (functionname != "main"))
        {
          std::string realname(p);
          // in MT mode, one often gets backtraces spanning several lines
          // because we have so many boost::tuple arguments in the MT
          // calling functions. most of the trailing arguments of these
          // tuples are actually unused boost::tuples::null_type, so we
          // should split them off if they are trailing a template argument
          // list
          while (realname.find (", boost::tuples::null_type>")
                 != std::string::npos)
            realname.erase (realname.find (", boost::tuples::null_type>"),
                            std::string (", boost::tuples::null_type").size());

          stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                             +
                             ": "
                             +
                             realname;
        }
      else
        stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                           +
                           ": "
                           +
                           functionname;

      free (p);

#else

      stacktrace_entry = stacktrace_entry.substr(0, pos_start)
                         +
                         ": "
                         +
                         functionname;
#endif

      // then output what we have
      out << stacktrace_entry
          << std::endl;

      // stop if we're in main()
      if (functionname == "main")
        break;
    }
}

void ExceptionBase::generate_message () const
{
  // build up a c_string with the error message.
  // Guard this procedure with a try block, we shall not throw at this
  // place...
  try
    {
      std::ostringstream converter;

      converter << std::endl
                << "--------------------------------------------------------"
                << std::endl;

      // print out general data
      print_exc_data (converter);
      // print out exception specific data
      print_info (converter);
      print_stack_trace (converter);

      if (!deal_II_exceptions::additional_assert_output.empty())
        {
          converter << "--------------------------------------------------------"
                    << std::endl
                    << deal_II_exceptions::additional_assert_output
                    << std::endl;
        }

      converter << "--------------------------------------------------------"
                << std::endl;

      what_str = converter.str();
    }
  catch (...)
    {
      // On error, resume next. There is nothing better we can do...
      what_str = "ExceptionBase::generate_message () failed";
    }
}

namespace deal_II_exceptions
{
  namespace internals
  {

    void abort (const ExceptionBase &exc, bool nothrow /*= false*/)
    {
      if (dealii::deal_II_exceptions::abort_on_exception)
        {
          // Print the error message and bail out:
          std::cerr << exc.what() << std::endl;
          std::abort();
        }
      else if (nothrow)
        {
          // We are not allowed to throw, and not allowed to abort.
          // Just print the exception name to deallog and continue
          // normally:
          deallog << "Exception: " << exc.get_exc_name() << std::endl;
        }
      else
        {
          // We are not allowed to abort, so just throw the error so just
          // throw the error so just throw the error so just throw the
          // error:
          throw exc;
        }
    }

  } /*namespace internals*/
} /*namespace deal_II_exceptions*/

DEAL_II_NAMESPACE_CLOSE

// Newer versions of gcc have a very nice feature: you can set a verbose
// terminate handler, that not only aborts a program when an exception is
// thrown and not caught somewhere, but before aborting it prints that an
// exception has been thrown, and possibly what the std::exception::what()
// function has to say. Since many people run into the trap of not having a
// catch clause in main(), they wonder where that abort may be coming from.
// The terminate handler then at least says what is missing in their
// program.
#ifdef DEAL_II_HAVE_VERBOSE_TERMINATE
namespace __gnu_cxx
{
  extern void __verbose_terminate_handler ();
}

namespace
{
  struct preload_terminate_dummy
  {
    preload_terminate_dummy()
    {
      std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
    }
  };

  static preload_terminate_dummy dummy;
}
#endif
<|endoftext|>