<commit_before>#include "UpdateInstaller.h"

#include "FileOps.h"
#include "Log.h"
#include "ProcessUtils.h"
#include "UpdateObserver.h"

UpdateInstaller::UpdateInstaller()
: m_mode(Setup)
, m_script(0)
, m_waitPid(0)
, m_observer(0)
{
}

void UpdateInstaller::setWaitPid(long long pid)
{
	m_waitPid = pid;
}

void UpdateInstaller::setInstallDir(const std::string& path)
{
	m_installDir = path;
}

void UpdateInstaller::setPackageDir(const std::string& path)
{
	m_packageDir = path;
}

void UpdateInstaller::setBackupDir(const std::string& path)
{
	m_backupDir = path;
}

void UpdateInstaller::setMode(Mode mode)
{
	m_mode = mode;
}

void UpdateInstaller::setScript(UpdateScript* script)
{
	m_script = script;
}

std::list<std::string> UpdateInstaller::updaterArgs() const
{
	std::list<std::string> args;
	args.push_back("--install-dir");
	args.push_back(m_installDir);
	args.push_back("--package-dir");
	args.push_back(m_packageDir);
	args.push_back("--script");
	args.push_back(m_script->path());
	return args;
}

void UpdateInstaller::run() throw ()
{
	std::string updaterPath;
	try
	{
		updaterPath = ProcessUtils::currentProcessPath();
	}
	catch (const FileOps::IOException& ex)
	{
		LOG(Error,"error reading process path with mode " + intToStr(m_mode));
		return;
	}

	if (m_mode == Setup)
	{
		LOG(Info,"Preparing update installation");
		LOG(Info,"Waiting for main app process to finish");
		ProcessUtils::waitForProcess(m_waitPid);

		std::list<std::string> args = updaterArgs();
		args.push_back("--mode");
		args.push_back("main");

		if (!checkAccess())
		{
			LOG(Info,"Insufficient rights to install app to " + m_installDir + " requesting elevation");

			// start a copy of the updater with admin rights
			ProcessUtils::runElevated(updaterPath,args);
		}
		else
		{
			LOG(Info,"Sufficient rights to install app - restarting with same permissions");

			// TODO - Change this to run synchronously
			ProcessUtils::runAsync(updaterPath,args);
		}
	}
	else if (m_mode == Main)
	{
		LOG(Info,"Starting update installation");

		std::string error;
		try
		{
			LOG(Info,"Installing new and updated files");
			installFiles();

			LOG(Info,"Uninstalling removed files");
			uninstallFiles();

			LOG(Info,"Removing backups");
			removeBackups();
		}
		catch (const FileOps::IOException& exception)
		{
			error = exception.what();
		}
		catch (const std::string& genericError)
		{
			error = genericError;
		}

		if (!error.empty())
		{
			LOG(Error,std::string("Error installing update ") + error);
			revert();
			if (m_observer)
			{
				m_observer->updateError(error);
			}
		}

		if (m_observer)
		{
			m_observer->updateFinished();
		}

		std::list<std::string> args = updaterArgs();
		args.push_back("--mode");
		args.push_back("cleanup");
		ProcessUtils::runAsync(updaterPath,args);
	}
	else if (m_mode == Cleanup)
	{
		LOG(Info,"Cleaning up temporary updater files");

		ProcessUtils::waitForProcess(m_waitPid);
		cleanup();

		LOG(Info,"Updater files removed");
	}
}

void UpdateInstaller::cleanup()
{
	FileOps::rmdirRecursive(m_packageDir.c_str());
}

void UpdateInstaller::revert()
{
	std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
	for (;iter != m_backups.end();iter++)
	{
		const std::string& installedFile = iter->first;
		const std::string& backupFile = iter->second;

		if (FileOps::fileExists(installedFile.c_str()))
		{
			FileOps::removeFile(installedFile.c_str());
		}
		FileOps::moveFile(backupFile.c_str(),installedFile.c_str());
	}
}

void UpdateInstaller::installFile(const UpdateScriptFile& file)
{
	std::string destPath = m_installDir + '/' + file.path;
	std::string target = file.linkTarget;

	// backup the existing file if any
	backupFile(destPath);

	// create the target directory if it does not exist
	std::string destDir = FileOps::dirname(destPath.c_str());
	if (!FileOps::fileExists(destDir.c_str()))
	{
		FileOps::mkdir(destDir.c_str());
	}

	if (target.empty())
	{
		// locate the package containing the file
		std::string packageFile = m_packageDir + '/' + file.package + ".zip";
		if (!FileOps::fileExists(packageFile.c_str()))
		{
			throw "Package file does not exist: " + packageFile;
		}

		// extract the file from the package and copy it to
		// the destination
		FileOps::extractFromZip(packageFile.c_str(),file.path.c_str(),destPath.c_str());

		// set the permissions on the newly extracted file
		FileOps::setQtPermissions(destPath.c_str(),file.permissions);
	}
	else
	{
		// create the symlink
		FileOps::createSymLink(destPath.c_str(),target.c_str());
	}
}

void UpdateInstaller::installFiles()
{
	std::vector<UpdateScriptFile>::const_iterator iter = m_script->filesToInstall().begin();
	int filesInstalled = 0;
	for (;iter != m_script->filesToInstall().end();iter++)
	{
		installFile(*iter);
		++filesInstalled;
		if (m_observer)
		{
			m_observer->updateProgress(static_cast<float>(filesInstalled) / m_script->filesToInstall().size() * 100);
		}
	}
}

void UpdateInstaller::uninstallFiles()
{
	std::vector<std::string>::const_iterator iter = m_script->filesToUninstall().begin();
	for (;iter != m_script->filesToUninstall().end();iter++)
	{
		std::string path = m_installDir + '/' + iter->c_str();
		if (FileOps::fileExists(path.c_str()))
		{
			FileOps::removeFile(path.c_str());
		}
		else
		{
			LOG(Warn,"Unable to uninstall file " + path + " because it does not exist.");
		}
	}
}

void UpdateInstaller::backupFile(const std::string& path)
{
	if (!FileOps::fileExists(path.c_str()))
	{
		// no existing file to backup
		return;
	}

	std::string backupPath = path + ".bak";
	FileOps::removeFile(backupPath.c_str());
	FileOps::moveFile(path.c_str(), backupPath.c_str());
	m_backups[path] = backupPath;
}

void UpdateInstaller::removeBackups()
{
	std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
	for (;iter != m_backups.end();iter++)
	{
		const std::string& installedFile = iter->first;
		const std::string& backupFile = iter->second;
		FileOps::removeFile(backupFile.c_str());
	}
}

bool UpdateInstaller::checkAccess()
{
	std::string testFile = m_installDir + "/update-installer-test-file";
	FileOps::removeFile(testFile.c_str());

	try
	{
		FileOps::touch(testFile.c_str());
		FileOps::removeFile(testFile.c_str());
		return true;
	}
	catch (const FileOps::IOException& error)
	{
		LOG(Info,"checkAccess() failed " + std::string(error.what()));
		return false;
	}
}

<commit_msg>Catch IO exceptions when trying to remove the existing write-access test file.<commit_after>#include "UpdateInstaller.h"

#include "FileOps.h"
#include "Log.h"
#include "ProcessUtils.h"
#include "UpdateObserver.h"

UpdateInstaller::UpdateInstaller()
: m_mode(Setup)
, m_script(0)
, m_waitPid(0)
, m_observer(0)
{
}

void UpdateInstaller::setWaitPid(long long pid)
{
	m_waitPid = pid;
}

void UpdateInstaller::setInstallDir(const std::string& path)
{
	m_installDir = path;
}

void UpdateInstaller::setPackageDir(const std::string& path)
{
	m_packageDir = path;
}

void UpdateInstaller::setBackupDir(const std::string& path)
{
	m_backupDir = path;
}

void UpdateInstaller::setMode(Mode mode)
{
	m_mode = mode;
}

void UpdateInstaller::setScript(UpdateScript* script)
{
	m_script = script;
}

std::list<std::string> UpdateInstaller::updaterArgs() const
{
	std::list<std::string> args;
	args.push_back("--install-dir");
	args.push_back(m_installDir);
	args.push_back("--package-dir");
	args.push_back(m_packageDir);
	args.push_back("--script");
	args.push_back(m_script->path());
	return args;
}

void UpdateInstaller::run() throw ()
{
	std::string updaterPath;
	try
	{
		updaterPath = ProcessUtils::currentProcessPath();
	}
	catch (const FileOps::IOException& ex)
	{
		LOG(Error,"error reading process path with mode " + intToStr(m_mode));
		return;
	}

	if (m_mode == Setup)
	{
		LOG(Info,"Preparing update installation");
		LOG(Info,"Waiting for main app process to finish");
		ProcessUtils::waitForProcess(m_waitPid);

		std::list<std::string> args = updaterArgs();
		args.push_back("--mode");
		args.push_back("main");

		if (!checkAccess())
		{
			LOG(Info,"Insufficient rights to install app to " + m_installDir + " requesting elevation");

			// start a copy of the updater with admin rights
			ProcessUtils::runElevated(updaterPath,args);
		}
		else
		{
			LOG(Info,"Sufficient rights to install app - restarting with same permissions");

			// TODO - Change this to run synchronously
			ProcessUtils::runAsync(updaterPath,args);
		}
	}
	else if (m_mode == Main)
	{
		LOG(Info,"Starting update installation");

		std::string error;
		try
		{
			LOG(Info,"Installing new and updated files");
			installFiles();

			LOG(Info,"Uninstalling removed files");
			uninstallFiles();

			LOG(Info,"Removing backups");
			removeBackups();
		}
		catch (const FileOps::IOException& exception)
		{
			error = exception.what();
		}
		catch (const std::string& genericError)
		{
			error = genericError;
		}

		if (!error.empty())
		{
			LOG(Error,std::string("Error installing update ") + error);
			revert();
			if (m_observer)
			{
				m_observer->updateError(error);
			}
		}

		if (m_observer)
		{
			m_observer->updateFinished();
		}

		std::list<std::string> args = updaterArgs();
		args.push_back("--mode");
		args.push_back("cleanup");
		ProcessUtils::runAsync(updaterPath,args);
	}
	else if (m_mode == Cleanup)
	{
		LOG(Info,"Cleaning up temporary updater files");

		ProcessUtils::waitForProcess(m_waitPid);
		cleanup();

		LOG(Info,"Updater files removed");
	}
}

void UpdateInstaller::cleanup()
{
	FileOps::rmdirRecursive(m_packageDir.c_str());
}

void UpdateInstaller::revert()
{
	std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
	for (;iter != m_backups.end();iter++)
	{
		const std::string& installedFile = iter->first;
		const std::string& backupFile = iter->second;

		if (FileOps::fileExists(installedFile.c_str()))
		{
			FileOps::removeFile(installedFile.c_str());
		}
		FileOps::moveFile(backupFile.c_str(),installedFile.c_str());
	}
}

void UpdateInstaller::installFile(const UpdateScriptFile& file)
{
	std::string destPath = m_installDir + '/' + file.path;
	std::string target = file.linkTarget;

	// backup the existing file if any
	backupFile(destPath);

	// create the target directory if it does not exist
	std::string destDir = FileOps::dirname(destPath.c_str());
	if (!FileOps::fileExists(destDir.c_str()))
	{
		FileOps::mkdir(destDir.c_str());
	}

	if (target.empty())
	{
		// locate the package containing the file
		std::string packageFile = m_packageDir + '/' + file.package + ".zip";
		if (!FileOps::fileExists(packageFile.c_str()))
		{
			throw "Package file does not exist: " + packageFile;
		}

		// extract the file from the package and copy it to
		// the destination
		FileOps::extractFromZip(packageFile.c_str(),file.path.c_str(),destPath.c_str());

		// set the permissions on the newly extracted file
		FileOps::setQtPermissions(destPath.c_str(),file.permissions);
	}
	else
	{
		// create the symlink
		FileOps::createSymLink(destPath.c_str(),target.c_str());
	}
}

void UpdateInstaller::installFiles()
{
	std::vector<UpdateScriptFile>::const_iterator iter = m_script->filesToInstall().begin();
	int filesInstalled = 0;
	for (;iter != m_script->filesToInstall().end();iter++)
	{
		installFile(*iter);
		++filesInstalled;
		if (m_observer)
		{
			m_observer->updateProgress(static_cast<float>(filesInstalled) / m_script->filesToInstall().size() * 100);
		}
	}
}

void UpdateInstaller::uninstallFiles()
{
	std::vector<std::string>::const_iterator iter = m_script->filesToUninstall().begin();
	for (;iter != m_script->filesToUninstall().end();iter++)
	{
		std::string path = m_installDir + '/' + iter->c_str();
		if (FileOps::fileExists(path.c_str()))
		{
			FileOps::removeFile(path.c_str());
		}
		else
		{
			LOG(Warn,"Unable to uninstall file " + path + " because it does not exist.");
		}
	}
}

void UpdateInstaller::backupFile(const std::string& path)
{
	if (!FileOps::fileExists(path.c_str()))
	{
		// no existing file to backup
		return;
	}

	std::string backupPath = path + ".bak";
	FileOps::removeFile(backupPath.c_str());
	FileOps::moveFile(path.c_str(), backupPath.c_str());
	m_backups[path] = backupPath;
}

void UpdateInstaller::removeBackups()
{
	std::map<std::string,std::string>::const_iterator iter = m_backups.begin();
	for (;iter != m_backups.end();iter++)
	{
		const std::string& installedFile = iter->first;
		const std::string& backupFile = iter->second;
		FileOps::removeFile(backupFile.c_str());
	}
}

bool UpdateInstaller::checkAccess()
{
	std::string testFile = m_installDir + "/update-installer-test-file";

	try
	{
		FileOps::removeFile(testFile.c_str());
	}
	catch (const FileOps::IOException& error)
	{
		LOG(Info,"Removing existing access check file failed " + std::string(error.what()));
	}

	try
	{
		FileOps::touch(testFile.c_str());
		FileOps::removeFile(testFile.c_str());
		return true;
	}
	catch (const FileOps::IOException& error)
	{
		LOG(Info,"checkAccess() failed " + std::string(error.what()));
		return false;
	}
}

<|endoftext|>


<commit_before>#include "../compiler/Parser.h"
#include "../compiler/CodeGen/CSourceContext.h"
#include "../compiler/AST/ASTNode.h"
#include "../compiler/CSourceIndexer.h"

#include <getopt.h>
#include <iostream>
#include <fstream>

#include <sys/stat.h>
#include <unistd.h>

typedef struct {
    bool debug;
    bool printAST;
    bool trace;

    std::string outputFile;
} build_options_t;

void getOptions(build_options_t* options, int argc, char** argv) {
    int32_t c;

    static struct option longopts[] = {
        { "debug",     no_argument,       NULL, 'd' },
        { "help",      no_argument,       NULL, 'h' },
        { "output",    required_argument, NULL, 'o' },
        { "print",     no_argument,       NULL, 'p' },
        { "trace",     no_argument,       NULL, 't' },
        { "version",   no_argument,       NULL, 'v' },
        { NULL,        0,                 NULL, 0   }
    };

    options->debug    = false;
    options->printAST = false;
    options->trace    = false;

    while ((c = getopt_long(argc, argv, "dho:ptv", longopts, NULL)) != -1) {
        switch (c) {
            case 'd':
                options->debug = true;
                break;
            case 'o':
                options->outputFile = std::string(optarg);
                break;
            case 'p':
                options->printAST = true;
                break;
            case 't':
                options->trace = true;
                break;
            case 'v':
                printf("Three Release: %s\n\n", "0.1");
                exit(0);
                break;
            case 'h':
            default:
                printf("usage: three [options] [--] [file] [arguments]\n");
                printf("\n");
                printf("  -d (--debug)      disable optimizations\n");
                printf("  -h (--help)       print this help message and exit\n");
                printf("  -o (--output)     name of output file\n");
                printf("  -p (--print)      print out the AST representation for the input file\n");
                printf("  -t (--trace)      trace compilation steps\n");
                printf("  -v (--version)    print versions\n");
                exit(0);
                break;
        }
    }
}

bool createCOutputs(Three::ParsingContext* context, const std::string& basePath) {
    Three::CSourceContext outputContext;

    context->rootNode()->codeGen(outputContext);

    std::ofstream bodyFile(basePath + ".c");

    // make sure to import the headers
    outputContext.internalDeclarations()->addHeader(true, basePath + ".h");
    outputContext.declarations()->addHeader(true, basePath + "_internal.h");

    bodyFile << "// Declarations" << std::endl;
    bodyFile << outputContext.declarations()->renderToString();
    bodyFile << std::endl << "// Definitions" << std::endl;
    bodyFile << outputContext.body()->renderToString();

    std::ofstream internalHeaderFile(basePath + "_internal.h");

    internalHeaderFile << outputContext.internalDeclarations()->renderToStringWithIncludeGuard("__" + basePath + "_internal__");

    std::ofstream externalHeaderFile(basePath + ".h");

    externalHeaderFile << outputContext.externalDeclarations()->renderToStringWithIncludeGuard("__" + basePath + "__");

    return true;
}

std::vector<std::string> defaultCIncludePaths(void) {
    std::vector<std::string> paths = *Three::CSourceIndexer::defaultCIncludePaths();

    paths.push_back("/usr/local/include/three/runtime");

    return paths;
}

std::vector<std::string> splitString(const std::string& string, const std::string& delimiter) {
    std::vector<std::string> parts;

    std::string::const_iterator substart = string.begin();
    std::string::const_iterator subend;

    for (;;) {
        subend = std::search(substart, string.end(), delimiter.begin(), delimiter.end());
        std::string temp(substart, subend);

        if (!temp.empty()) {
            parts.push_back(temp);
        }

        if (subend == string.end()) {
            break;
        }

        substart = subend + delimiter.size();
    }

    return parts;
}

bool createPath(const std::string& path) {
    std::vector<std::string> components = splitString(path, "/");

    std::string partial;
    for (const std::string& component : components) {
        partial += component + "/";

        if (mkdir(partial.c_str(), 00777) != 0) {
            if (errno != EEXIST) {
                return false;
            }
        }
    }

    return true;
}

bool compileCSource(const std::string& cSourcePath, const std::string& outputPath) {
    std::stringstream s;

    s << "clang -std=c11";
    s << " -o '" << outputPath << "'" ;

    s << " -I.";

    for (const std::string& string : defaultCIncludePaths()) {
        s << " '-I" << string << "'";
    }

    s << " -c '" << cSourcePath << "'";

    // std::cout << s.str() << std::endl;

    return system(s.str().c_str()) == 0;
}

void adjustOutputFileName(build_options_t* options, const std::string& inputFile) {
    // create a sensible output path default, if none was supplied
    if (options->outputFile.length() == 0) {
        if (inputFile.substr(inputFile.length() - 2, 2) == ".3") {
            options->outputFile = inputFile.substr(0, inputFile.length() - 2);
        } else {
            options->outputFile = std::string("three_output");
        }
    }
}

int buildCSources(const std::string& inputFile) {
    Three::ParsingContext* parsingContext = Three::Parser::contextFromFile(inputFile);

    std::string output = inputFile.substr(0, inputFile.length() - 2);
    createCOutputs(parsingContext, output);

    return 0;
}

int linkExecutable(const std::string& inputFile, const std::string& outputPath) {
    std::stringstream s;

    s << "clang ";
    s << "-L/usr/local/lib -lthree_runtime";

    s << " -o '" << outputPath << "'" ;

    s << " '" << inputFile << "'";

    return system(s.str().c_str()) == 0;
}

int buildExecutable(build_options_t* options, const std::string& inputFile, Three::ParsingContext* context) {
    createCOutputs(context, options->outputFile);
    compileCSource(options->outputFile + ".c", options->outputFile + ".o");

    linkExecutable(options->outputFile + ".o", options->outputFile);

    return 1;
}

bool buildLibrary(const std::vector<std::string>& inputs, const std::string& outputPath) {
    std::stringstream s;

    s << "ar rs";
    s << " '" << outputPath << "'";

    for (const std::string& string : inputs) {
        s << " '" << string << "'";
    }

    return system(s.str().c_str()) == 0;
}

int buildModule(build_options_t* options, Three::ParsingContext* context) {
    std::vector<std::string> pathComponents = splitString(context->currentModule()->name, "_3_");

    std::string path;

    for (const std::string& component : pathComponents) {
        path += component + "/";
    }

    if (!createPath(path)) {
        std::cerr << "Unable to create path" << std::endl;
        return 1;
    }

    for (const std::string& submodule : context->currentModule()->importedModules) {
        std::cout << "[Compile] building subcomponent '" << submodule << "'" << std::endl;

        buildCSources(submodule + ".3");
        compileCSource(submodule + ".c", submodule + ".o");
    }

    std::vector<std::string> objects;

    // now move the headers
    for (const std::string& submodule : context->currentModule()->importedModules) {
        rename((submodule + ".c").c_str(), (path + "/" + submodule + ".c").c_str());
        rename((submodule + ".h").c_str(), (path + "/" + submodule + ".h").c_str());
        rename((submodule + "_internal.h").c_str(), (path + "/" + submodule + "_internal.h").c_str());

        objects.push_back(submodule + ".o");
    }

    buildLibrary(objects, path + "/" + "lib" + options->outputFile + ".a");

    for (const std::string& object_file : objects) {
        unlink(object_file.c_str());
    }

    return 0;
}

int processInput(build_options_t* options, const std::string& inputFile) {
    Three::ParsingContext* parsingContext = Three::Parser::contextFromFile(inputFile);

    if (options->printAST) {
        std::cout << parsingContext->rootNode()->recursiveStr() << std::endl;
        return 0;
    }

    adjustOutputFileName(options, inputFile);

    if (parsingContext->currentModule()->hasMainFunction()) {
        std::cout << "[Compile] Building executable" << std::endl;
        return buildExecutable(options, inputFile, parsingContext);
    }

    return buildModule(options, parsingContext);
}

int main(int argc, char** argv) {
    build_options_t options;

    // read options, and then adjust the inputs
    getOptions(&options, argc, argv);
    argc -= optind;
    argv += optind;

    if (argc == 0) {
        // no input files, REPL should be kicked off here
        std::cerr << "[Compile] No input files" << std::endl;
        return 1;
    }

    if (argc > 1) {
        std::cerr << "[Compile] Two many inputs given" << std::endl;
        return 2;
    }

    processInput(&options, std::string(argv[0]));

    return 0;
}
<commit_msg>Make sure to unlink a library before recreating it.  Suppress ar's output<commit_after>#include "../compiler/Parser.h"
#include "../compiler/CodeGen/CSourceContext.h"
#include "../compiler/AST/ASTNode.h"
#include "../compiler/CSourceIndexer.h"

#include <getopt.h>
#include <iostream>
#include <fstream>

#include <sys/stat.h>
#include <unistd.h>

typedef struct {
    bool debug;
    bool printAST;
    bool trace;

    std::string outputFile;
} build_options_t;

void getOptions(build_options_t* options, int argc, char** argv) {
    int32_t c;

    static struct option longopts[] = {
        { "debug",     no_argument,       NULL, 'd' },
        { "help",      no_argument,       NULL, 'h' },
        { "output",    required_argument, NULL, 'o' },
        { "print",     no_argument,       NULL, 'p' },
        { "trace",     no_argument,       NULL, 't' },
        { "version",   no_argument,       NULL, 'v' },
        { NULL,        0,                 NULL, 0   }
    };

    options->debug    = false;
    options->printAST = false;
    options->trace    = false;

    while ((c = getopt_long(argc, argv, "dho:ptv", longopts, NULL)) != -1) {
        switch (c) {
            case 'd':
                options->debug = true;
                break;
            case 'o':
                options->outputFile = std::string(optarg);
                break;
            case 'p':
                options->printAST = true;
                break;
            case 't':
                options->trace = true;
                break;
            case 'v':
                printf("Three Release: %s\n\n", "0.1");
                exit(0);
                break;
            case 'h':
            default:
                printf("usage: three [options] [--] [file] [arguments]\n");
                printf("\n");
                printf("  -d (--debug)      disable optimizations\n");
                printf("  -h (--help)       print this help message and exit\n");
                printf("  -o (--output)     name of output file\n");
                printf("  -p (--print)      print out the AST representation for the input file\n");
                printf("  -t (--trace)      trace compilation steps\n");
                printf("  -v (--version)    print versions\n");
                exit(0);
                break;
        }
    }
}

bool createCOutputs(Three::ParsingContext* context, const std::string& basePath) {
    Three::CSourceContext outputContext;

    context->rootNode()->codeGen(outputContext);

    std::ofstream bodyFile(basePath + ".c");

    // make sure to import the headers
    outputContext.internalDeclarations()->addHeader(true, basePath + ".h");
    outputContext.declarations()->addHeader(true, basePath + "_internal.h");

    bodyFile << "// Declarations" << std::endl;
    bodyFile << outputContext.declarations()->renderToString();
    bodyFile << std::endl << "// Definitions" << std::endl;
    bodyFile << outputContext.body()->renderToString();

    std::ofstream internalHeaderFile(basePath + "_internal.h");

    internalHeaderFile << outputContext.internalDeclarations()->renderToStringWithIncludeGuard("__" + basePath + "_internal__");

    std::ofstream externalHeaderFile(basePath + ".h");

    externalHeaderFile << outputContext.externalDeclarations()->renderToStringWithIncludeGuard("__" + basePath + "__");

    return true;
}

std::vector<std::string> defaultCIncludePaths(void) {
    std::vector<std::string> paths = *Three::CSourceIndexer::defaultCIncludePaths();

    paths.push_back("/usr/local/include/three/runtime");

    return paths;
}

std::vector<std::string> splitString(const std::string& string, const std::string& delimiter) {
    std::vector<std::string> parts;

    std::string::const_iterator substart = string.begin();
    std::string::const_iterator subend;

    for (;;) {
        subend = std::search(substart, string.end(), delimiter.begin(), delimiter.end());
        std::string temp(substart, subend);

        if (!temp.empty()) {
            parts.push_back(temp);
        }

        if (subend == string.end()) {
            break;
        }

        substart = subend + delimiter.size();
    }

    return parts;
}

bool createPath(const std::string& path) {
    std::vector<std::string> components = splitString(path, "/");

    std::string partial;
    for (const std::string& component : components) {
        partial += component + "/";

        if (mkdir(partial.c_str(), 00777) != 0) {
            if (errno != EEXIST) {
                return false;
            }
        }
    }

    return true;
}

bool compileCSource(const std::string& cSourcePath, const std::string& outputPath) {
    std::stringstream s;

    s << "clang -std=c11";
    s << " -o '" << outputPath << "'" ;

    s << " -I.";

    for (const std::string& string : defaultCIncludePaths()) {
        s << " '-I" << string << "'";
    }

    s << " -c '" << cSourcePath << "'";

    // std::cout << s.str() << std::endl;

    return system(s.str().c_str()) == 0;
}

void adjustOutputFileName(build_options_t* options, const std::string& inputFile) {
    // create a sensible output path default, if none was supplied
    if (options->outputFile.length() == 0) {
        if (inputFile.substr(inputFile.length() - 2, 2) == ".3") {
            options->outputFile = inputFile.substr(0, inputFile.length() - 2);
        } else {
            options->outputFile = std::string("three_output");
        }
    }
}

int buildCSources(const std::string& inputFile) {
    Three::ParsingContext* parsingContext = Three::Parser::contextFromFile(inputFile);

    std::string output = inputFile.substr(0, inputFile.length() - 2);
    createCOutputs(parsingContext, output);

    return 0;
}

int linkExecutable(const std::string& inputFile, const std::string& outputPath) {
    std::stringstream s;

    s << "clang ";
    s << "-L/usr/local/lib -lthree_runtime";

    s << " -o '" << outputPath << "'" ;

    s << " '" << inputFile << "'";

    return system(s.str().c_str()) == 0;
}

int buildExecutable(build_options_t* options, const std::string& inputFile, Three::ParsingContext* context) {
    createCOutputs(context, options->outputFile);
    compileCSource(options->outputFile + ".c", options->outputFile + ".o");

    linkExecutable(options->outputFile + ".o", options->outputFile);

    return 1;
}

bool buildLibrary(const std::vector<std::string>& inputs, const std::string& outputPath) {
    // The output needs to be removed first
    unlink(outputPath.c_str());

    std::stringstream s;

    s << "ar crs";
    s << " '" << outputPath << "'";

    for (const std::string& string : inputs) {
        s << " '" << string << "'";
    }

    return system(s.str().c_str()) == 0;
}

int buildModule(build_options_t* options, Three::ParsingContext* context) {
    std::vector<std::string> pathComponents = splitString(context->currentModule()->name, "_3_");

    std::string path;

    for (const std::string& component : pathComponents) {
        path += component + "/";
    }

    if (!createPath(path)) {
        std::cerr << "Unable to create path" << std::endl;
        return 1;
    }

    for (const std::string& submodule : context->currentModule()->importedModules) {
        std::cout << "[Compile] building subcomponent '" << submodule << "'" << std::endl;

        buildCSources(submodule + ".3");
        compileCSource(submodule + ".c", submodule + ".o");
    }

    std::vector<std::string> objects;

    // now move the headers
    for (const std::string& submodule : context->currentModule()->importedModules) {
        rename((submodule + ".c").c_str(), (path + "/" + submodule + ".c").c_str());
        rename((submodule + ".h").c_str(), (path + "/" + submodule + ".h").c_str());
        rename((submodule + "_internal.h").c_str(), (path + "/" + submodule + "_internal.h").c_str());

        objects.push_back(submodule + ".o");
    }

    buildLibrary(objects, path + "/" + "lib" + options->outputFile + ".a");

    for (const std::string& object_file : objects) {
        unlink(object_file.c_str());
    }

    return 0;
}

int processInput(build_options_t* options, const std::string& inputFile) {
    Three::ParsingContext* parsingContext = Three::Parser::contextFromFile(inputFile);

    if (options->printAST) {
        std::cout << parsingContext->rootNode()->recursiveStr() << std::endl;
        return 0;
    }

    adjustOutputFileName(options, inputFile);

    if (parsingContext->currentModule()->hasMainFunction()) {
        std::cout << "[Compile] Building executable" << std::endl;
        return buildExecutable(options, inputFile, parsingContext);
    }

    return buildModule(options, parsingContext);
}

int main(int argc, char** argv) {
    build_options_t options;

    // read options, and then adjust the inputs
    getOptions(&options, argc, argv);
    argc -= optind;
    argv += optind;

    if (argc == 0) {
        // no input files, REPL should be kicked off here
        std::cerr << "[Compile] No input files" << std::endl;
        return 1;
    }

    if (argc > 1) {
        std::cerr << "[Compile] Two many inputs given" << std::endl;
        return 2;
    }

    processInput(&options, std::string(argv[0]));

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>[X86][SSE] Don't merge known undef/zero elements into target shuffle masks.<commit_after><|endoftext|>


<commit_before>#ifndef MODULO_FILAS_H//include de guarda
#define MODULO_FILAS_H
#include <deque>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//para usar funcoes como strlen
#include "../include/arquivos.hpp"//para poder criar uma lista de processos
class filas{
public:
	std::deque<int> Fila0;
	std::deque<int> Fila1;
	std::deque<int> Fila2;
	std::deque<int> Fila3;
	filas();
	void insereFilas(arquivos);
	int existe_processo_para_executar_fila0(arquivos, int);
	int existe_processo_para_executar_fila1(arquivos, int);
	int existe_processo_para_executar_fila2(arquivos, int);
	int existe_processo_para_executar_fila3(arquivos, int);
	void retira_processo_fila0(int);
	void retira_processo_fila1(int);
	void retira_processo_fila2(int);
	void retira_processo_fila3(int);
	void destroiFilas(void);
};
#endif<commit_msg>adicionando comentarios<commit_after>#ifndef MODULO_FILAS_H//include de guarda
#define MODULO_FILAS_H
#include <deque>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>//para usar funcoes como strlen
#include "../include/arquivos.hpp"//para poder criar uma lista de processos
class filas{
public:
	std::deque<int> Fila0; //fila de prioridade máxima: processos de tempo real
	//Filas destinadas aos processos de usuário:
	std::deque<int> Fila1; //prioridade 1
	std::deque<int> Fila2; //prioridade 2
	std::deque<int> Fila3; //prioridade 3
	filas();
	/**
	metodo que verifica a prioridade de cada processo e os separa entre as filas
	@param : uma lista de processos
	**/
	void insereFilas(arquivos);
	/**
	metodo que verifica de acordo com o tempo de chegada de cada processo pertencente
	a Fila0 se existe um processo que está pronto pra ser executado
	@param : uma lista de processos
	@param : tempo da CPU
	**/
	int existe_processo_para_executar_fila0(arquivos, int);
	/**
	metodo que verifica de acordo com o tempo de chegada de cada processo pertencente
	a Fila1 se existe um processo que está pronto pra ser executado
	@param : uma lista de processos
	@param : tempo da CPU
	**/
	int existe_processo_para_executar_fila1(arquivos, int);
	/**
	metodo que verifica de acordo com o tempo de chegada de cada processo pertencente
	a Fila2 se existe um processo que está pronto pra ser executado
	@param : uma lista de processos
	@param : tempo da CPU
	**/
	int existe_processo_para_executar_fila2(arquivos, int);
	/**
	metodo que verifica de acordo com o tempo de chegada de cada processo pertencente
	a Fila3 se existe um processo que está pronto pra ser executado
	@param : uma lista de processos
	@param : tempo da CPU
	**/
	int existe_processo_para_executar_fila3(arquivos, int);
	/**
	metodo que retira aquele processo da fila0
	@param : o identificador de um processo PID
	**/
	void retira_processo_fila0(int);
	/**
	metodo que retira aquele processo da fila1
	@param : o identificador de um processo PID
	**/
	void retira_processo_fila1(int);
	/**
	metodo que retira aquele processo da fila2
	@param : o identificador de um processo PID
	**/
	void retira_processo_fila2(int);
	/**
	metodo que retira aquele processo da fila3
	@param : o identificador de um processo PID
	**/
	void retira_processo_fila3(int);
	/**
	metodo que destroi todas as filas
	**/
	void destroiFilas(void);
};
#endif<|endoftext|>


<commit_before><commit_msg>Nested classes need to be marked separately DLLPUBLIC, apparently<commit_after><|endoftext|>


<commit_before>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_ArrayType.h"
#include "jnc_ct_Module.h"
#include "jnc_rt_GcHeap.h"

namespace jnc {
namespace ct {

//..............................................................................

ArrayType::ArrayType()
{
	m_typeKind = TypeKind_Array;
	m_flags = TypeFlag_StructRet;
	m_elementType = NULL;
	m_rootType = NULL;
	m_elementCount = -1;
	m_getDynamicSizeFunction = NULL;
	m_parentUnit = NULL;
	m_parentNamespace = NULL;
}

Type*
ArrayType::getRootType()
{
	if (!m_rootType)
		m_rootType = m_elementType->getTypeKind() == TypeKind_Array ?
			((ArrayType*)m_elementType)->getRootType() :
			m_elementType;

	return m_rootType;
}

void
ArrayType::prepareTypeString()
{
	TypeStringTuple* tuple = getTypeStringTuple();
	tuple->m_typeStringPrefix = getRootType()->getTypeString();
	tuple->m_typeStringSuffix = createDimensionString();
}

void
ArrayType::prepareDoxyLinkedText()
{
	TypeStringTuple* tuple = getTypeStringTuple();
	tuple->m_doxyLinkedTextPrefix = getRootType()->getDoxyLinkedTextPrefix();
	tuple->m_doxyLinkedTextSuffix = createDimensionString();
}

sl::String
ArrayType::createDimensionString()
{
	sl::String string;

	if (m_elementCount == -1)
		string = "[]";
	else
		string.format("[%d]", m_elementCount);

	Type* elementType = m_elementType;
	while (elementType->getTypeKind() == TypeKind_Array)
	{
		ArrayType* arrayType = (ArrayType*)elementType;
		string.appendFormat(" [%d]", arrayType->m_elementCount);
		elementType = arrayType->m_elementType;
	}

	return string;
}

bool
ArrayType::ensureDynamicLayout(
	StructType* dynamicStruct,
	Field* dynamicField
	)
{
	bool result;

	if (m_flags & ModuleItemFlag_LayoutReady)
		return true;

	result = calcLayoutImpl(dynamicStruct, dynamicField);
	if (!result)
		return false;

	m_flags |= ModuleItemFlag_LayoutReady;
	return true;
}

bool
ArrayType::calcLayoutImpl(
	StructType* dynamicStruct,
	Field* dynamicField
	)
{
	bool result = m_elementType->ensureLayout();
	if (!result)
		return false;

	if (m_elementType->getTypeKind() == TypeKind_Class ||
		m_elementType->getFlags() & TypeFlag_Dynamic)
	{
		err::setFormatStringError("'%s' cannot be an element of an array", m_elementType->getTypeString().sz());
		return false;
	}

	// ensure update

	m_rootType = NULL;
	if (m_typeStringTuple)
	{
		AXL_MEM_DELETE(m_typeStringTuple);
		m_typeStringTuple = NULL;
	}

	uint_t rootTypeFlags = getRootType()->getFlags();
	if (rootTypeFlags & TypeFlag_Pod)
		m_flags |= TypeFlag_Pod;
	else if (rootTypeFlags & TypeFlag_GcRoot)
		m_flags |= TypeFlag_GcRoot;

	m_alignment = m_elementType->getAlignment();

	// calculate size

	if (!m_elementCountInitializer.isEmpty())
	{
		ASSERT(m_parentUnit && m_parentNamespace);

		Unit* prevUnit = m_module->m_unitMgr.setCurrentUnit(m_parentUnit);
		m_module->m_namespaceMgr.openNamespace(m_parentNamespace);

		int64_t value = 0;
		result = m_module->m_operatorMgr.parseConstIntegerExpression(m_elementCountInitializer, &value);

		m_module->m_namespaceMgr.closeNamespace();
		m_module->m_unitMgr.setCurrentUnit(prevUnit);

		if (!result)
		{
			if (!dynamicStruct)
				return false;

			sl::String qualifiedName = sl::formatString(
				"%s.%s.getDynamicSize",
				dynamicStruct->getQualifiedName().sz(),
				dynamicField->getName().sz()
				);

			Type* returnType = m_module->m_typeMgr.getPrimitiveType(TypeKind_SizeT);
			FunctionType* type = m_module->m_typeMgr.getFunctionType(returnType, NULL, 0);

			m_getDynamicSizeFunction = m_module->m_functionMgr.createInternalFunction<GetDynamicSizeFunction>(
				qualifiedName,
				type
				);

			m_getDynamicSizeFunction->m_arrayType = this;
			m_getDynamicSizeFunction->m_storageKind = StorageKind_Member;
			m_getDynamicSizeFunction->convertToMemberMethod(dynamicStruct);
			m_module->markForCompile(m_getDynamicSizeFunction);

			m_flags |= TypeFlag_Dynamic;
			m_elementCount = 0;
			m_size = 0;
			return true;
		}

		if (value <= 0)
		{
			err::setFormatStringError("invalid array size '%lld'\n", value);
			lex::pushSrcPosError(
				m_parentUnit->getFilePath(),
				m_elementCountInitializer.getHead()->m_pos
				);

			return false;
		}

#if (JNC_PTR_SIZE == 4)
		if (value >= (uint32_t) -1)
		{
			err::setFormatStringError("array size '%lld' is too big\n", value);
			lex::pushSrcPosError(
				m_parentUnit->getFilePath(),
				m_elementCountInitializer.getHead()->m_pos
				);

			return false;
		}
#endif

		m_elementCount = (size_t)value;
	}

	m_size = m_elementType->getSize() * m_elementCount;
	if (m_size > TypeSizeLimit_StackAllocSize)
		m_flags |= TypeFlag_NoStack;

	return true;
}

sl::String
ArrayType::getValueString(
	const void* p0,
	const char* formatSpec
	)
{
	if (m_flags & TypeFlag_Dynamic)
	{
		AXL_TODO("format dynamic arrays")
		return "{ dynamic-array }";
	}

	if (!m_elementCount)
		return "{}";

	const char* p = (char*)p0;

	sl::String string = "{ " + m_elementType->getValueString(p);

	for (size_t i = 1; i < m_elementCount; i++)
	{
		p += m_elementType->getSize();

		string += ", ";
		string += m_elementType->getValueString(p, formatSpec);
	}

	string += " }";
	return string;
}

void
ArrayType::markGcRoots(
	const void* p,
	rt::GcHeap* gcHeap
	)
{
	ASSERT(m_flags & TypeFlag_GcRoot);
	gcHeap->addRootArray(p, m_elementType, m_elementCount);
}

void
ArrayType::prepareLlvmDiType()
{
	m_llvmDiType = m_module->m_llvmDiBuilder.createArrayType(this);
}

bool
ArrayType::compileGetDynamicSizeFunction(Function* function)
{
	ASSERT(function == m_getDynamicSizeFunction);

	bool result;

	Unit* parentUnit = function->getParentUnit();
	if (parentUnit)
		m_module->m_unitMgr.setCurrentUnit(parentUnit);

	m_module->m_namespaceMgr.openNamespace(function->getParentNamespace());
	m_module->m_functionMgr.internalPrologue(function);
	m_module->m_functionMgr.createThisValue();

	Value resultValue;
	result = m_module->m_operatorMgr.parseExpression(m_elementCountInitializer, &resultValue);
	if (!result)
		return false;

	size_t size = m_elementType->getSize();
	if (size != 1)
	{
		Value sizeValue(size, m_module->m_typeMgr.getPrimitiveType(TypeKind_SizeT));
		result = m_module->m_operatorMgr.binaryOperator(
			BinOpKind_Mul,
			&resultValue,
			sizeValue
			);

		if (!result)
			return false;
	}

	result = m_module->m_controlFlowMgr.ret(resultValue);
	if (!result)
		return false;

	m_module->m_functionMgr.internalEpilogue();
	m_module->m_namespaceMgr.closeNamespace();
	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<commit_msg>[jnc_ct] added special handing for char literals to ArrayType::getValueString<commit_after>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_ArrayType.h"
#include "jnc_ct_Module.h"
#include "jnc_rt_GcHeap.h"

namespace jnc {
namespace ct {

//..............................................................................

ArrayType::ArrayType()
{
	m_typeKind = TypeKind_Array;
	m_flags = TypeFlag_StructRet;
	m_elementType = NULL;
	m_rootType = NULL;
	m_elementCount = -1;
	m_getDynamicSizeFunction = NULL;
	m_parentUnit = NULL;
	m_parentNamespace = NULL;
}

Type*
ArrayType::getRootType()
{
	if (!m_rootType)
		m_rootType = m_elementType->getTypeKind() == TypeKind_Array ?
			((ArrayType*)m_elementType)->getRootType() :
			m_elementType;

	return m_rootType;
}

void
ArrayType::prepareTypeString()
{
	TypeStringTuple* tuple = getTypeStringTuple();
	tuple->m_typeStringPrefix = getRootType()->getTypeString();
	tuple->m_typeStringSuffix = createDimensionString();
}

void
ArrayType::prepareDoxyLinkedText()
{
	TypeStringTuple* tuple = getTypeStringTuple();
	tuple->m_doxyLinkedTextPrefix = getRootType()->getDoxyLinkedTextPrefix();
	tuple->m_doxyLinkedTextSuffix = createDimensionString();
}

sl::String
ArrayType::createDimensionString()
{
	sl::String string;

	if (m_elementCount == -1)
		string = "[]";
	else
		string.format("[%d]", m_elementCount);

	Type* elementType = m_elementType;
	while (elementType->getTypeKind() == TypeKind_Array)
	{
		ArrayType* arrayType = (ArrayType*)elementType;
		string.appendFormat(" [%d]", arrayType->m_elementCount);
		elementType = arrayType->m_elementType;
	}

	return string;
}

bool
ArrayType::ensureDynamicLayout(
	StructType* dynamicStruct,
	Field* dynamicField
	)
{
	bool result;

	if (m_flags & ModuleItemFlag_LayoutReady)
		return true;

	result = calcLayoutImpl(dynamicStruct, dynamicField);
	if (!result)
		return false;

	m_flags |= ModuleItemFlag_LayoutReady;
	return true;
}

bool
ArrayType::calcLayoutImpl(
	StructType* dynamicStruct,
	Field* dynamicField
	)
{
	bool result = m_elementType->ensureLayout();
	if (!result)
		return false;

	if (m_elementType->getTypeKind() == TypeKind_Class ||
		m_elementType->getFlags() & TypeFlag_Dynamic)
	{
		err::setFormatStringError("'%s' cannot be an element of an array", m_elementType->getTypeString().sz());
		return false;
	}

	// ensure update

	m_rootType = NULL;
	if (m_typeStringTuple)
	{
		AXL_MEM_DELETE(m_typeStringTuple);
		m_typeStringTuple = NULL;
	}

	uint_t rootTypeFlags = getRootType()->getFlags();
	if (rootTypeFlags & TypeFlag_Pod)
		m_flags |= TypeFlag_Pod;
	else if (rootTypeFlags & TypeFlag_GcRoot)
		m_flags |= TypeFlag_GcRoot;

	m_alignment = m_elementType->getAlignment();

	// calculate size

	if (!m_elementCountInitializer.isEmpty())
	{
		ASSERT(m_parentUnit && m_parentNamespace);

		Unit* prevUnit = m_module->m_unitMgr.setCurrentUnit(m_parentUnit);
		m_module->m_namespaceMgr.openNamespace(m_parentNamespace);

		int64_t value = 0;
		result = m_module->m_operatorMgr.parseConstIntegerExpression(m_elementCountInitializer, &value);

		m_module->m_namespaceMgr.closeNamespace();
		m_module->m_unitMgr.setCurrentUnit(prevUnit);

		if (!result)
		{
			if (!dynamicStruct)
				return false;

			sl::String qualifiedName = sl::formatString(
				"%s.%s.getDynamicSize",
				dynamicStruct->getQualifiedName().sz(),
				dynamicField->getName().sz()
				);

			Type* returnType = m_module->m_typeMgr.getPrimitiveType(TypeKind_SizeT);
			FunctionType* type = m_module->m_typeMgr.getFunctionType(returnType, NULL, 0);

			m_getDynamicSizeFunction = m_module->m_functionMgr.createInternalFunction<GetDynamicSizeFunction>(
				qualifiedName,
				type
				);

			m_getDynamicSizeFunction->m_arrayType = this;
			m_getDynamicSizeFunction->m_storageKind = StorageKind_Member;
			m_getDynamicSizeFunction->convertToMemberMethod(dynamicStruct);
			m_module->markForCompile(m_getDynamicSizeFunction);

			m_flags |= TypeFlag_Dynamic;
			m_elementCount = 0;
			m_size = 0;
			return true;
		}

		if (value <= 0)
		{
			err::setFormatStringError("invalid array size '%lld'\n", value);
			lex::pushSrcPosError(
				m_parentUnit->getFilePath(),
				m_elementCountInitializer.getHead()->m_pos
				);

			return false;
		}

#if (JNC_PTR_SIZE == 4)
		if (value >= (uint32_t) -1)
		{
			err::setFormatStringError("array size '%lld' is too big\n", value);
			lex::pushSrcPosError(
				m_parentUnit->getFilePath(),
				m_elementCountInitializer.getHead()->m_pos
				);

			return false;
		}
#endif

		m_elementCount = (size_t)value;
	}

	m_size = m_elementType->getSize() * m_elementCount;
	if (m_size > TypeSizeLimit_StackAllocSize)
		m_flags |= TypeFlag_NoStack;

	return true;
}

sl::String
ArrayType::getValueString(
	const void* p0,
	const char* formatSpec
	)
{
	if (m_flags & TypeFlag_Dynamic)
	{
		AXL_TODO("format dynamic arrays")
		return "{ dynamic-array }";
	}

	const char* p = (char*)p0;

	if (m_elementType->getTypeKind() == TypeKind_Char)
	{
		const char* null = (const char*)memchr(p, 0, m_elementCount);
		return sl::String(p, null ? null - p : m_elementCount);
	}

	if (!m_elementCount)
		return "{}";

	sl::String string = "{ " + m_elementType->getValueString(p);

	for (size_t i = 1; i < m_elementCount; i++)
	{
		p += m_elementType->getSize();

		string += ", ";
		string += m_elementType->getValueString(p, formatSpec);
	}

	string += " }";
	return string;
}

void
ArrayType::markGcRoots(
	const void* p,
	rt::GcHeap* gcHeap
	)
{
	ASSERT(m_flags & TypeFlag_GcRoot);
	gcHeap->addRootArray(p, m_elementType, m_elementCount);
}

void
ArrayType::prepareLlvmDiType()
{
	m_llvmDiType = m_module->m_llvmDiBuilder.createArrayType(this);
}

bool
ArrayType::compileGetDynamicSizeFunction(Function* function)
{
	ASSERT(function == m_getDynamicSizeFunction);

	bool result;

	Unit* parentUnit = function->getParentUnit();
	if (parentUnit)
		m_module->m_unitMgr.setCurrentUnit(parentUnit);

	m_module->m_namespaceMgr.openNamespace(function->getParentNamespace());
	m_module->m_functionMgr.internalPrologue(function);
	m_module->m_functionMgr.createThisValue();

	Value resultValue;
	result = m_module->m_operatorMgr.parseExpression(m_elementCountInitializer, &resultValue);
	if (!result)
		return false;

	size_t size = m_elementType->getSize();
	if (size != 1)
	{
		Value sizeValue(size, m_module->m_typeMgr.getPrimitiveType(TypeKind_SizeT));
		result = m_module->m_operatorMgr.binaryOperator(
			BinOpKind_Mul,
			&resultValue,
			sizeValue
			);

		if (!result)
			return false;
	}

	result = m_module->m_controlFlowMgr.ret(resultValue);
	if (!result)
		return false;

	m_module->m_functionMgr.internalEpilogue();
	m_module->m_namespaceMgr.closeNamespace();
	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2003-2014.
//  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)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : unit test for class properties facility
// ***************************************************************************

// Boost.Test
#define BOOST_TEST_MODULE Boost.Test algorithms test
#include <boost/test/unit_test.hpp>
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/algorithm.hpp>
namespace utf = boost::unit_test;
using utf::const_string;

// STL
#include <cctype>
#include <functional>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::toupper; }
# endif

//____________________________________________________________________________//

bool predicate( char c1, char c2 ) { return (std::toupper)( c1 ) == (std::toupper)( c2 ); }

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_mismatch )
{
    const_string cs1( "test_string" );
    const_string cs2( "test_stream" );

    BOOST_TEST( utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin() == 8 );

    cs2 = "trest";
    BOOST_TEST( utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin() == 1 );

    cs2 = "test_string_klmn";
    BOOST_TEST( utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin() == 11 );

    cs2 = "TeSt_liNk";
    BOOST_TEST(
        utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end(), std::ptr_fun( predicate ) ).first - cs1.begin() == 5 );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_first_not_of )
{
    const_string cs( "test_string" );
    const_string another( "tes" );

    BOOST_TEST( utf::find_first_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin() == 4 );

    another = "T_sE";
    BOOST_TEST(
        utf::find_first_not_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin() == 7 );

    another = "tes_ring";
    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_last_of )
{
    const_string cs( "test_string" );
    const_string another( "tes" );

    BOOST_TEST( utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin() == 6 );

    another = "_Se";
    BOOST_TEST( utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin() == 5 );

    another = "qw";
    BOOST_TEST( utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );

    cs = "qerty";
    BOOST_TEST( utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin() == 0 );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_last_not_of )
{
    const_string cs( "test_string" );
    const_string another( "string" );

    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin() == 4 );

    another = "_SeG";
    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin() == 9 );

    another = "e_string";
    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );
}

//____________________________________________________________________________//

// EOF
<commit_msg>MSVC-9 Fixing the tests No (non mutating) operator overload other than comparisons are defined for compilers lacking decltype<commit_after>//  (C) Copyright Gennadiy Rozental 2003-2014.
//  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)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : unit test for class properties facility
// ***************************************************************************

// Boost.Test
#define BOOST_TEST_MODULE Boost.Test algorithms test
#include <boost/test/unit_test.hpp>
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/algorithm.hpp>
namespace utf = boost::unit_test;
using utf::const_string;

// STL
#include <cctype>
#include <functional>

# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::toupper; }
# endif

#ifdef BOOST_NO_CXX11_DECLTYPE
#define TEST_SURROUND_EXPRESSION(x) (x)
#else
#define TEST_SURROUND_EXPRESSION(x) x
#endif

//____________________________________________________________________________//

bool predicate( char c1, char c2 ) { return (std::toupper)( c1 ) == (std::toupper)( c2 ); }

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_mismatch )
{
    const_string cs1( "test_string" );
    const_string cs2( "test_stream" );

    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin()) == 8 );

    cs2 = "trest";
    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin()) == 1 );

    cs2 = "test_string_klmn";
    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end() ).first - cs1.begin()) == 11 );

    cs2 = "TeSt_liNk";
    BOOST_TEST(
        TEST_SURROUND_EXPRESSION(utf::mismatch( cs1.begin(), cs1.end(), cs2.begin(), cs2.end(), std::ptr_fun( predicate ) ).first - cs1.begin()) == 5 );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_first_not_of )
{
    const_string cs( "test_string" );
    const_string another( "tes" );

    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_first_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin()) == 4 );

    another = "T_sE";
    BOOST_TEST(
        TEST_SURROUND_EXPRESSION(utf::find_first_not_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin()) == 7 );

    another = "tes_ring";
    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_last_of )
{
    const_string cs( "test_string" );
    const_string another( "tes" );

    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin()) == 6 );

    another = "_Se";
    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin()) == 5 );

    another = "qw";
    BOOST_TEST( utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );

    cs = "qerty";
    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_last_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin()) == 0 );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_find_last_not_of )
{
    const_string cs( "test_string" );
    const_string another( "string" );

    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) - cs.begin()) == 4 );

    another = "_SeG";
    BOOST_TEST( TEST_SURROUND_EXPRESSION(utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end(), std::ptr_fun( predicate ) ) - cs.begin()) == 9 );

    another = "e_string";
    BOOST_TEST( utf::find_last_not_of( cs.begin(), cs.end(), another.begin(), another.end() ) == cs.end() );
}

//____________________________________________________________________________//

// EOF
<|endoftext|>


<commit_before>/************************************************************************/
/* ZigBeeInterface                                                      */
/*                                                                      */
/* ZigBee Terminal - ZigBee Interface                                   */
/*                                                                      */
/* ZigBeeInterface.cpp                                                  */
/*                                                                      */
/* Alex Forencich <alex@alexforencich.com>                              */
/*                                                                      */
/* Copyright (c) 2011 Alex Forencich                                    */
/*                                                                      */
/* Permission is hereby granted, free of charge, to any person          */
/* obtaining a copy of this software and associated documentation       */
/* files(the "Software"), to deal in the Software without restriction,  */
/* including without limitation the rights to use, copy, modify, merge, */
/* publish, distribute, sublicense, and/or sell copies of the Software, */
/* and to permit persons to whom the Software is furnished to do so,    */
/* subject to the following conditions:                                 */
/*                                                                      */
/* The above copyright notice and this permission notice shall be       */
/* included in all copies or substantial portions of the Software.      */
/*                                                                      */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                            */
/*                                                                      */
/************************************************************************/

#include "ZigBeeInterface.h"

#include <iostream>
#include <sstream>
#include <iomanip>

ZigBeeInterface::ZigBeeInterface() :
        debug(false)
{
        // nothing
}

ZigBeeInterface::~ZigBeeInterface()
{
        // nothing
}

void ZigBeeInterface::set_serial_interface(std::tr1::shared_ptr<SerialInterface> si)
{
        clear_serial_interface();
        if (!si)
                return;
        ser_int = si;
        c_port_opened = ser_int->port_opened().connect( sigc::mem_fun(*this, &ZigBeeInterface::reset_buffer) );
        c_port_closed = ser_int->port_closed().connect( sigc::mem_fun(*this, &ZigBeeInterface::reset_buffer) );
        c_port_receive_data = ser_int->port_receive_data().connect( sigc::mem_fun(*this, &ZigBeeInterface::on_receive_data) );
}

void ZigBeeInterface::clear_serial_interface()
{
        if (!ser_int)
                return;
        c_port_opened.disconnect();
        c_port_closed.disconnect();
        c_port_receive_data.disconnect();
        ser_int = std::tr1::shared_ptr<SerialInterface>();
}

bool ZigBeeInterface::has_serial_interface()
{
        return ser_int;
}

void ZigBeeInterface::reset_buffer()
{
        read_data_queue.clear();
}

void ZigBeeInterface::send_packet(ZigBeePacket pkt)
{
        gsize num;
        int ret;
        int len;
        char *ptr;

        if (!ser_int)
        {
                std::cerr << "[ZigBeeInterface] No SerialInterface associated!" << std::endl;
                m_signal_error.emit();
                return;
        }

        std::vector<uint8_t> data = pkt.get_raw_packet();

        len = data.size();
        ptr = (char *)&data[0];

        // write packet
        while (len > 0)
        {
                ret = ser_int->write(ptr, len, num);

                if (ret != SerialInterface::SS_Success)
                {
                        std::cerr << "[ZigBeeInterface] Error: unable to write packet!";
                        m_signal_error.emit();
                        return;
                }

                if (num > 0)
                        m_signal_send_raw_data.emit(ptr, num);

                len -= num;
                ptr += num;
        }
}

bool ZigBeeInterface::set_debug(bool d)
{
        debug = d;
        return debug;
}

bool ZigBeeInterface::get_debug()
{
        return debug;
}

sigc::signal<void, ZigBeePacket> ZigBeeInterface::signal_receive_packet()
{
        return m_signal_receive_packet;
}

sigc::signal<void, const char*, size_t> ZigBeeInterface::signal_send_raw_data()
{
        return m_signal_send_raw_data;
}

sigc::signal<void, const char*, size_t> ZigBeeInterface::signal_receive_raw_data()
{
        return m_signal_receive_raw_data;
}

sigc::signal<void> ZigBeeInterface::signal_error()
{
        return m_signal_error;
}

void ZigBeeInterface::on_receive_data()
{
        gsize num;
        int status;
        static char buf[1024];
        ZigBeePacket pkt;
        size_t len;

        if (!ser_int)
        {
                std::cerr << "[ZigBeeInterface] No SerialInterface associated!" << std::endl;
                m_signal_error.emit();
                return;
        }

        // read raw data from serial port
        do
        {
                status = ser_int->read(buf, 1024, num);

                if (status == SerialInterface::SS_Error)
                {
                        std::cerr << "[ZigBeeInterface] Read error!" << std::endl;
                        m_signal_error.emit();
                        ser_int->close_port();
                        return;
                }

                if (status == SerialInterface::SS_EOF)
                {
                        std::cerr << "[ZigBeeInterface] End of file!" << std::endl;
                        m_signal_error.emit();
                        ser_int->close_port();
                        return;
                }

                if (debug)
                {
                        std::cout << "[ZigBeeInterface] Read " << std::dec << num << " bytes" << std::endl;
                }

                for (int i = 0; i < num; i++)
                {
                        read_data_queue.push_back(buf[i]);
                }

                if (num > 0)
                        m_signal_receive_raw_data.emit(buf, num);
        }
        while (num == 1024);

        // try to read packets
        do
        {
                len = 0;
                if (pkt.read_packet(read_data_queue, len))
                {
                        pkt.decode_packet();
                        m_signal_receive_packet.emit(pkt);
                }
                for (int i = 0; i < len; i++)
                        read_data_queue.pop_front();
        }
        while (read_data_queue.size() > 0 && len > 0);
}

<commit_msg>Added missing newline<commit_after>/************************************************************************/
/* ZigBeeInterface                                                      */
/*                                                                      */
/* ZigBee Terminal - ZigBee Interface                                   */
/*                                                                      */
/* ZigBeeInterface.cpp                                                  */
/*                                                                      */
/* Alex Forencich <alex@alexforencich.com>                              */
/*                                                                      */
/* Copyright (c) 2011 Alex Forencich                                    */
/*                                                                      */
/* Permission is hereby granted, free of charge, to any person          */
/* obtaining a copy of this software and associated documentation       */
/* files(the "Software"), to deal in the Software without restriction,  */
/* including without limitation the rights to use, copy, modify, merge, */
/* publish, distribute, sublicense, and/or sell copies of the Software, */
/* and to permit persons to whom the Software is furnished to do so,    */
/* subject to the following conditions:                                 */
/*                                                                      */
/* The above copyright notice and this permission notice shall be       */
/* included in all copies or substantial portions of the Software.      */
/*                                                                      */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                            */
/*                                                                      */
/************************************************************************/

#include "ZigBeeInterface.h"

#include <iostream>
#include <sstream>
#include <iomanip>

ZigBeeInterface::ZigBeeInterface() :
        debug(false)
{
        // nothing
}

ZigBeeInterface::~ZigBeeInterface()
{
        // nothing
}

void ZigBeeInterface::set_serial_interface(std::tr1::shared_ptr<SerialInterface> si)
{
        clear_serial_interface();
        if (!si)
                return;
        ser_int = si;
        c_port_opened = ser_int->port_opened().connect( sigc::mem_fun(*this, &ZigBeeInterface::reset_buffer) );
        c_port_closed = ser_int->port_closed().connect( sigc::mem_fun(*this, &ZigBeeInterface::reset_buffer) );
        c_port_receive_data = ser_int->port_receive_data().connect( sigc::mem_fun(*this, &ZigBeeInterface::on_receive_data) );
}

void ZigBeeInterface::clear_serial_interface()
{
        if (!ser_int)
                return;
        c_port_opened.disconnect();
        c_port_closed.disconnect();
        c_port_receive_data.disconnect();
        ser_int = std::tr1::shared_ptr<SerialInterface>();
}

bool ZigBeeInterface::has_serial_interface()
{
        return ser_int;
}

void ZigBeeInterface::reset_buffer()
{
        read_data_queue.clear();
}

void ZigBeeInterface::send_packet(ZigBeePacket pkt)
{
        gsize num;
        int ret;
        int len;
        char *ptr;

        if (!ser_int)
        {
                std::cerr << "[ZigBeeInterface] No SerialInterface associated!" << std::endl;
                m_signal_error.emit();
                return;
        }

        std::vector<uint8_t> data = pkt.get_raw_packet();

        len = data.size();
        ptr = (char *)&data[0];

        // write packet
        while (len > 0)
        {
                ret = ser_int->write(ptr, len, num);

                if (ret != SerialInterface::SS_Success)
                {
                        std::cerr << "[ZigBeeInterface] Error: unable to write packet!" << std::endl;
                        m_signal_error.emit();
                        return;
                }

                if (num > 0)
                        m_signal_send_raw_data.emit(ptr, num);

                len -= num;
                ptr += num;
        }
}

bool ZigBeeInterface::set_debug(bool d)
{
        debug = d;
        return debug;
}

bool ZigBeeInterface::get_debug()
{
        return debug;
}

sigc::signal<void, ZigBeePacket> ZigBeeInterface::signal_receive_packet()
{
        return m_signal_receive_packet;
}

sigc::signal<void, const char*, size_t> ZigBeeInterface::signal_send_raw_data()
{
        return m_signal_send_raw_data;
}

sigc::signal<void, const char*, size_t> ZigBeeInterface::signal_receive_raw_data()
{
        return m_signal_receive_raw_data;
}

sigc::signal<void> ZigBeeInterface::signal_error()
{
        return m_signal_error;
}

void ZigBeeInterface::on_receive_data()
{
        gsize num;
        int status;
        static char buf[1024];
        ZigBeePacket pkt;
        size_t len;

        if (!ser_int)
        {
                std::cerr << "[ZigBeeInterface] No SerialInterface associated!" << std::endl;
                m_signal_error.emit();
                return;
        }

        // read raw data from serial port
        do
        {
                status = ser_int->read(buf, 1024, num);

                if (status == SerialInterface::SS_Error)
                {
                        std::cerr << "[ZigBeeInterface] Read error!" << std::endl;
                        m_signal_error.emit();
                        ser_int->close_port();
                        return;
                }

                if (status == SerialInterface::SS_EOF)
                {
                        std::cerr << "[ZigBeeInterface] End of file!" << std::endl;
                        m_signal_error.emit();
                        ser_int->close_port();
                        return;
                }

                if (debug)
                {
                        std::cout << "[ZigBeeInterface] Read " << std::dec << num << " bytes" << std::endl;
                }

                for (int i = 0; i < num; i++)
                {
                        read_data_queue.push_back(buf[i]);
                }

                if (num > 0)
                        m_signal_receive_raw_data.emit(buf, num);
        }
        while (num == 1024);

        // try to read packets
        do
        {
                len = 0;
                if (pkt.read_packet(read_data_queue, len))
                {
                        pkt.decode_packet();
                        m_signal_receive_packet.emit(pkt);
                }
                for (int i = 0; i < len; i++)
                        read_data_queue.pop_front();
        }
        while (read_data_queue.size() > 0 && len > 0);
}

<|endoftext|>


<commit_before>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2017 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// ==========================================
//  FDLIB, CFDLAB, BEMLIB
//
//  Copyright by C. Pozrikidis, 1999
//  All rights reserved.
//
//  This program is to be used only under the
//  stipulations of the licensing agreement.
// ==========================================
//
// ---------------------------------------------------
//  Axisymmetric streaming (uniform)
//  potential flow past a stationary body.
//
//  This program solves
//  an integral equation of the second kind
//  for the disturbance harmonic potential
//  over the body contour
//  and computes streamlines
//
//  The contour of the body in the xy upper half-plane
//  consists of a Number of SeGments (NSG)
//
//  The segments may be straight lines or circular arcs.
//
//  Each segment is discretized into a number of elements
//
//
//  Symbols:
//  --------
//
//  NSG: Number of segments defining the body contour
//
//  NE(i): Number of elements on the ith segment
//
//  RT(i): Stretch ratio of elements on ith segment
//
//  Itp(i): Index for shape of the ith segment:
//          1 for a straight segment
//          2 for a circular arc
//
//  (Xe, Ye):  end-nodes of elements on a segment
//  (Xm, Ym):  mid-nodes of elements on a segment
//  (Xw, Yw):  end-nodes of elements on all segments
//
//  (X0, Y0):  coordinates of collocation points
//
//  T0(i): angle subtended from the center of a circular element
//         at ith collocation point
//
//  arel(i):  axisymmetric surface area of ith element
//
//  phi: disturbance potential at collocation points
//
//  dphidn0: normal derivative of disturbance potential
//                  at collocation points
//
//  dphids0: tangential derivative of potential
//                  at collocation points
//
//  cp:      pressure coefficient at collocation points
//
//  NGL: Number of Gaussian points for integration
//       over each element
//
//  Icross: Index for stopping the computation of the streamlines
//          Default value is 0
//          If Icross = 1, computation stops when a streamline
//          crosses the yz plane
//
//  Notes:
//  ------
//
//  Normal vector points into the flow
//
// ----------------------------

#include <iostream>
#include <fstream>
#include <string>
#include <chrono>
#include <boost/program_options.hpp>
#include "parameters.hpp"
#include "program_options.hpp"
#include "lin_alg_types.hpp"
#include "body_ax_geo.hpp"
#include "body_ax_sdlp.tcc"
#include "body_ax_vel.tcc"

program_options parse_command_line(int argc, char** argv)
{
    namespace po = boost::program_options;
    po::options_description desc("allowed options");
    desc.add_options()
            ("help",                   "describe arguments")
            ("verbose",                "be verbose")
            ("flow_type",              po::value<int>(), "legacy Fortran constants for flow type, 50 for sphere, 51 for torus")
            ("input_data",             po::value<std::string>(), "name of the input file e.g. `sphere.dat`, `torus_trgl.dat`")
            ("asy_name",               po::value<std::string>(), "dump streamlines to vector `.asy` file if name is given");
    try
    {
        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
        program_options popt;

        if (vm.count("help")) {
            std::cout << desc << std::endl;
            std::exit(1);
        }

        popt.verbose = vm.count("verbose");
        if (vm.count("flow_type")) {
            popt.flow_type = vm["flow_type"].as<int>();
        }
        if (vm.count("input_data")) {
            popt.input_data = vm["input_data"].as<std::string>();
        }
        if (vm.count("asy_name")) {
            popt.asy_name = vm["asy_name"].as<std::string>();
        }

        return popt;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        std::cout << desc << std::endl;
        std::exit(-1);
    }
}

int main(int argc, char **argv)
{
    auto popt = parse_command_line(argc, argv);
    if (popt.verbose) {
        std::cout << popt;
    }

    matg_t<FLOATING_TYPE> phi;
    vecg_t<FLOATING_TYPE> velt, veln, cp;
    matg_t<FLOATING_TYPE> al;      // for the linear system
    vecg_t<FLOATING_TYPE> bl, sol; // ditto

    auto const& run_params = body_ax_geo<FLOATING_TYPE>(popt);
    if (popt.verbose) {
        std::cout << "-I- ngl: " << run_params.ngl << "\n";
        std::cout << "-I- vx: " << run_params.vx << "\n";
        std::cout << "-I- cr: " << run_params.cr << "\n";
        std::cout << "-I- ne[0]: " << run_params.ne[0] << "\n";
        std::cout << "-I- xwmin: " << run_params.xwmin << "\n";
        std::cout << "-I- ywmin: " << run_params.ywmin << "\n";
    }

    // ...

    //---------------------------------------------
    // Generate the linear system
    // for the potential at the collocation points
    //
    // Generate the influence matrix
    // consisting of integrals of the
    // single-layer potential
    //
    // Compute the rhs by evaluating the dlp
    //-------------------------------------------------------

    // resizing
    al.resize(run_params.ncl, run_params.ncl);
    bl.resize(run_params.ncl);
    // stiffness matrix and rhs
    for (int i = 0; i < run_params.ncl; ++i) {           // loop over collocation points
        bl(i) = ZERO<FLOATING_TYPE>;
        int j = -1;
        for (int k = 0; k < run_params.nsg; ++k) {       // loop over segments
            FLOATING_TYPE rad = NaN<FLOATING_TYPE>, xcnt = NaN<FLOATING_TYPE>, ycnt = NaN<FLOATING_TYPE>;
            if (run_params.itp[k] == 2) {
                rad  = run_params.actis[k];
                xcnt = run_params.xcntr[k];
                ycnt = run_params.ycntr[k];
            }
            for (int l = 0; l < run_params.ne[k]; ++l) { // loop over elements
                FLOATING_TYPE x1 = run_params.xw(k,l);
                FLOATING_TYPE y1 = run_params.yw(k,l);
                FLOATING_TYPE t1 = run_params.tw(k,l);

                FLOATING_TYPE x2 = run_params.xw(k,l+1);
                FLOATING_TYPE y2 = run_params.yw(k,l+1);
                FLOATING_TYPE t2 = run_params.tw(k,l+1);

                j = j+1;
                bool ising = (i == j);
                FLOATING_TYPE qqq, www;
                body_ax_sdlp (run_params.x0[i], run_params.y0[i], run_params.t0[i],
                              x1, y1, t1, x2, y2, t2, run_params.gl, ising,
                              run_params.itp[k], rad,xcnt,ycnt,
                              qqq, www);

                al(i, j) = www;
                bl(i) += qqq * run_params.dphidn0[j];

            }

        }
        al(i, i) -= HALF<FLOATING_TYPE>;

    }

    //------------------------
    // Solve the linear system
    //------------------------
    sol = al.lu().solve(bl.transpose());

    if (popt.verbose) {
        for (size_t i = 0; i < run_params.ncl; ++i) {
            std::cout << "sol(" << i << ") : " << sol(i) << std::endl;
        }
    }

    //------------------------
    // Distribute the solution
    //------------------------

    size_t max_elems = run_params.ne.maxCoeff();
    phi.resize(run_params.nsg, max_elems);
    velt.resize(run_params.nsg * max_elems);
    veln.resize(run_params.nsg * max_elems);
    cp.resize(run_params.nsg * max_elems);

    size_t k = 0;        // counter
    for (size_t i = 0; i < run_params.nsg; ++i) {
        for (size_t j = 0; j < run_params.ne[i]; ++j) {
            phi(i, j) = sol(k++);
        }
    }

    //------------------------------------------------
    // Compute the tangential disturbance velocity
    //             by taking tangential derivative of \phi
    //
    // Compute the pressure coefficient cp
    //             drag force
    //------------------------------------------------

    FLOATING_TYPE forcex = ZERO<FLOATING_TYPE>, dphids0;
    k = 0;        // counter
    for (size_t i = 0; i < run_params.nsg; ++i) {
        for (size_t j = 0; j < run_params.ne[i]; ++j) {
            //--------------------------------
            // tangential disturbance velocity
            // computed by differentiating phi
            //--------------------------------
            if (j == 0) {                          // forward differencing
                dphids0 = (phi(i,j+1)-phi(i,j))/(run_params.s0(k+1)-run_params.s0(k));
            } else if(j == run_params.ne(i) - 1) { // backward differencing
                dphids0 = (phi(i,j)-phi(i,j-1))/(run_params.s0(k)-run_params.s0(k-1));
            } else {                               // second-order differencing
                FLOATING_TYPE g1 = phi(i,j-1);
                FLOATING_TYPE g2 = phi(i,j);
                FLOATING_TYPE g3 = phi(i,j+1);
                FLOATING_TYPE h1 = run_params.s0(k-1);
                FLOATING_TYPE h2 = run_params.s0(k);
                FLOATING_TYPE h3 = run_params.s0(k+1);
                FLOATING_TYPE aa = ((g3-g2)/(h3-h2)-(g1-g2)/(h1-h2))/(h3-h1);
                FLOATING_TYPE bb = (g3-g2)/(h3-h2)-aa*(h3-h2);
                dphids0 = bb;
            }
            //---------------
            // total velocity
            //---------------

            FLOATING_TYPE velx = run_params.dphidn0(k)*run_params.vnx0(k)+dphids0*run_params.tnx0(k);
            FLOATING_TYPE vely = run_params.dphidn0(k)*run_params.vny0(k)+dphids0*run_params.tny0(k);

            velx = velx + run_params.vx;        // add incident flow

            //---
            // add line vortex ring
            //---

            int iopt = 1;
            FLOATING_TYPE ulvr, vlvr, psi;
            lvr_fs<FLOATING_TYPE>(iopt, run_params.x0[i], run_params.y0[i], run_params.xlvr, run_params.ylvr, ulvr, vlvr, psi);

            velx = velx + run_params.cr*ulvr;
            vely = vely + run_params.cr*vlvr;

            //-------------------------------
            // tangential and normal velocity
            // and pressure coefficient
            //-------------------------------

            // ...
            velt(k) = velx*run_params.tnx0(k)+vely*run_params.tny0(k);
            veln(k) = velx*run_params.vnx0(k)+vely*run_params.vny0(k);

            //------------
            // axial force
            //------------

            cp(k) = ONE<FLOATING_TYPE> - (velt(k)*velt(k)) / (run_params.vx*run_params.vx);

            forcex = forcex + cp(k)*run_params.vnx0(k)*run_params.arel(k);

            ++k;
        }
    }

    std::cout << "Axial Force: " << forcex << std::endl;

    FLOATING_TYPE x00, y00, ux1, uy1;
    //---------------
    // integrate ODEs
    //---------------

    velocity<FLOATING_TYPE>(run_params, phi, run_params.dphidn0, x00,y00, ux1,uy1);

}

<commit_msg>fix axial force computation.<commit_after>// -*- C++ -*-

// The MIT License (MIT)
//
// Copyright (c) 2017 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// ==========================================
//  FDLIB, CFDLAB, BEMLIB
//
//  Copyright by C. Pozrikidis, 1999
//  All rights reserved.
//
//  This program is to be used only under the
//  stipulations of the licensing agreement.
// ==========================================
//
// ---------------------------------------------------
//  Axisymmetric streaming (uniform)
//  potential flow past a stationary body.
//
//  This program solves
//  an integral equation of the second kind
//  for the disturbance harmonic potential
//  over the body contour
//  and computes streamlines
//
//  The contour of the body in the xy upper half-plane
//  consists of a Number of SeGments (NSG)
//
//  The segments may be straight lines or circular arcs.
//
//  Each segment is discretized into a number of elements
//
//
//  Symbols:
//  --------
//
//  NSG: Number of segments defining the body contour
//
//  NE(i): Number of elements on the ith segment
//
//  RT(i): Stretch ratio of elements on ith segment
//
//  Itp(i): Index for shape of the ith segment:
//          1 for a straight segment
//          2 for a circular arc
//
//  (Xe, Ye):  end-nodes of elements on a segment
//  (Xm, Ym):  mid-nodes of elements on a segment
//  (Xw, Yw):  end-nodes of elements on all segments
//
//  (X0, Y0):  coordinates of collocation points
//
//  T0(i): angle subtended from the center of a circular element
//         at ith collocation point
//
//  arel(i):  axisymmetric surface area of ith element
//
//  phi: disturbance potential at collocation points
//
//  dphidn0: normal derivative of disturbance potential
//                  at collocation points
//
//  dphids0: tangential derivative of potential
//                  at collocation points
//
//  cp:      pressure coefficient at collocation points
//
//  NGL: Number of Gaussian points for integration
//       over each element
//
//  Icross: Index for stopping the computation of the streamlines
//          Default value is 0
//          If Icross = 1, computation stops when a streamline
//          crosses the yz plane
//
//  Notes:
//  ------
//
//  Normal vector points into the flow
//
// ----------------------------

#include <iostream>
#include <fstream>
#include <string>
#include <chrono>
#include <boost/program_options.hpp>
#include "parameters.hpp"
#include "program_options.hpp"
#include "lin_alg_types.hpp"
#include "body_ax_geo.hpp"
#include "body_ax_sdlp.tcc"
#include "body_ax_vel.tcc"

program_options parse_command_line(int argc, char** argv)
{
    namespace po = boost::program_options;
    po::options_description desc("allowed options");
    desc.add_options()
            ("help",                   "describe arguments")
            ("verbose",                "be verbose")
            ("flow_type",              po::value<int>(), "legacy Fortran constants for flow type, 50 for sphere, 51 for torus")
            ("input_data",             po::value<std::string>(), "name of the input file e.g. `sphere.dat`, `torus_trgl.dat`")
            ("asy_name",               po::value<std::string>(), "dump streamlines to vector `.asy` file if name is given");
    try
    {
        po::variables_map vm;
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
        program_options popt;

        if (vm.count("help")) {
            std::cout << desc << std::endl;
            std::exit(1);
        }

        popt.verbose = vm.count("verbose");
        if (vm.count("flow_type")) {
            popt.flow_type = vm["flow_type"].as<int>();
        }
        if (vm.count("input_data")) {
            popt.input_data = vm["input_data"].as<std::string>();
        }
        if (vm.count("asy_name")) {
            popt.asy_name = vm["asy_name"].as<std::string>();
        }

        return popt;
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        std::cout << desc << std::endl;
        std::exit(-1);
    }
}

int main(int argc, char **argv)
{
    auto popt = parse_command_line(argc, argv);
    if (popt.verbose) {
        std::cout << popt;
    }

    matg_t<FLOATING_TYPE> phi;
    vecg_t<FLOATING_TYPE> velt, veln, cp;
    matg_t<FLOATING_TYPE> al;      // for the linear system
    vecg_t<FLOATING_TYPE> bl, sol; // ditto

    auto const& run_params = body_ax_geo<FLOATING_TYPE>(popt);
    if (popt.verbose) {
        std::cout << "-I- ngl: " << run_params.ngl << "\n";
        std::cout << "-I- vx: " << run_params.vx << "\n";
        std::cout << "-I- cr: " << run_params.cr << "\n";
        std::cout << "-I- ne[0]: " << run_params.ne[0] << "\n";
        std::cout << "-I- xwmin: " << run_params.xwmin << "\n";
        std::cout << "-I- ywmin: " << run_params.ywmin << "\n";
    }

    // ...

    //---------------------------------------------
    // Generate the linear system
    // for the potential at the collocation points
    //
    // Generate the influence matrix
    // consisting of integrals of the
    // single-layer potential
    //
    // Compute the rhs by evaluating the dlp
    //-------------------------------------------------------

    // resizing
    al.resize(run_params.ncl, run_params.ncl);
    bl.resize(run_params.ncl);
    // stiffness matrix and rhs
    for (int i = 0; i < run_params.ncl; ++i) {           // loop over collocation points
        bl(i) = ZERO<FLOATING_TYPE>;
        int j = -1;
        for (int k = 0; k < run_params.nsg; ++k) {       // loop over segments
            FLOATING_TYPE rad = NaN<FLOATING_TYPE>, xcnt = NaN<FLOATING_TYPE>, ycnt = NaN<FLOATING_TYPE>;
            if (run_params.itp[k] == 2) {
                rad  = run_params.actis[k];
                xcnt = run_params.xcntr[k];
                ycnt = run_params.ycntr[k];
            }
            for (int l = 0; l < run_params.ne[k]; ++l) { // loop over elements
                FLOATING_TYPE x1 = run_params.xw(k,l);
                FLOATING_TYPE y1 = run_params.yw(k,l);
                FLOATING_TYPE t1 = run_params.tw(k,l);

                FLOATING_TYPE x2 = run_params.xw(k,l+1);
                FLOATING_TYPE y2 = run_params.yw(k,l+1);
                FLOATING_TYPE t2 = run_params.tw(k,l+1);

                j = j+1;
                bool ising = (i == j);
                FLOATING_TYPE qqq, www;
                body_ax_sdlp (run_params.x0[i], run_params.y0[i], run_params.t0[i],
                              x1, y1, t1, x2, y2, t2, run_params.gl, ising,
                              run_params.itp[k], rad,xcnt,ycnt,
                              qqq, www);

                al(i, j) = www;
                bl(i) += qqq * run_params.dphidn0[j];

            }

        }
        al(i, i) -= HALF<FLOATING_TYPE>;

    }

    //------------------------
    // Solve the linear system
    //------------------------
    sol = al.lu().solve(bl.transpose());

    if (popt.verbose) {
        for (size_t i = 0; i < run_params.ncl; ++i) {
            std::cout << "sol(" << i << ") : " << sol(i) << std::endl;
        }
    }

    //------------------------
    // Distribute the solution
    //------------------------

    size_t max_elems = run_params.ne.maxCoeff();
    phi.resize(run_params.nsg, max_elems);
    velt.resize(run_params.nsg * max_elems);
    veln.resize(run_params.nsg * max_elems);
    cp.resize(run_params.nsg * max_elems);

    size_t k = 0;        // counter
    for (size_t i = 0; i < run_params.nsg; ++i) {
        for (size_t j = 0; j < run_params.ne[i]; ++j) {
            phi(i, j) = sol(k++);
        }
    }

    //------------------------------------------------
    // Compute the tangential disturbance velocity
    //             by taking tangential derivative of \phi
    //
    // Compute the pressure coefficient cp
    //             drag force
    //------------------------------------------------

    FLOATING_TYPE forcex = ZERO<FLOATING_TYPE>, dphids0;
    k = 0;        // counter
    for (size_t i = 0; i < run_params.nsg; ++i) {
        for (size_t j = 0; j < run_params.ne[i]; ++j) {
            //--------------------------------
            // tangential disturbance velocity
            // computed by differentiating phi
            //--------------------------------
            if (j == 0) {                          // forward differencing
                dphids0 = (phi(i,j+1)-phi(i,j))/(run_params.s0(k+1)-run_params.s0(k));
            } else if(j == run_params.ne(i) - 1) { // backward differencing
                dphids0 = (phi(i,j)-phi(i,j-1))/(run_params.s0(k)-run_params.s0(k-1));
            } else {                               // second-order differencing
                FLOATING_TYPE g1 = phi(i,j-1);
                FLOATING_TYPE g2 = phi(i,j);
                FLOATING_TYPE g3 = phi(i,j+1);
                FLOATING_TYPE h1 = run_params.s0(k-1);
                FLOATING_TYPE h2 = run_params.s0(k);
                FLOATING_TYPE h3 = run_params.s0(k+1);
                FLOATING_TYPE aa = ((g3-g2)/(h3-h2)-(g1-g2)/(h1-h2))/(h3-h1);
                FLOATING_TYPE bb = (g3-g2)/(h3-h2)-aa*(h3-h2);
                dphids0 = bb;
            }
            //---------------
            // total velocity
            //---------------

            FLOATING_TYPE velx = run_params.dphidn0(k)*run_params.vnx0(k)+dphids0*run_params.tnx0(k);
            FLOATING_TYPE vely = run_params.dphidn0(k)*run_params.vny0(k)+dphids0*run_params.tny0(k);

            velx = velx + run_params.vx;        // add incident flow

            //---
            // add line vortex ring
            //---

            int iopt = 1;
            FLOATING_TYPE ulvr, vlvr, psi;
            lvr_fs<FLOATING_TYPE>(iopt, run_params.x0[k], run_params.y0[k], run_params.xlvr, run_params.ylvr, ulvr, vlvr, psi);

            velx = velx + run_params.cr*ulvr;
            vely = vely + run_params.cr*vlvr;

            //-------------------------------
            // tangential and normal velocity
            // and pressure coefficient
            //-------------------------------

            // ...
            velt(k) = velx*run_params.tnx0(k)+vely*run_params.tny0(k);
            veln(k) = velx*run_params.vnx0(k)+vely*run_params.vny0(k);

            //------------
            // axial force
            //------------

            cp(k) = ONE<FLOATING_TYPE> - (velt(k)*velt(k)) / (run_params.vx*run_params.vx);

            forcex = forcex + cp(k)*run_params.vnx0(k)*run_params.arel(k);
            if (popt.verbose) {
                std::cout << "velt(" << k << "): " << velt(k) << " veln(" << k << "): " << veln(k)
                          << " cp(" << k << "): " << cp(k) << std::endl;
            }

            ++k;
        }
    }

    std::cout << "Axial Force: " << forcex << std::endl;

    FLOATING_TYPE x00, y00, ux1, uy1;
    //---------------
    // integrate ODEs
    //---------------

    velocity<FLOATING_TYPE>(run_params, phi, run_params.dphidn0, x00,y00, ux1,uy1);

}

<|endoftext|>