<commit_before>//
//  Context.cpp
//  Cinder-Pipeline
//
//  Created by Jean-Pierre Mouilleseaux on 19 Apr 2014.
//  Copyright 2014 Chorded Constructions. All rights reserved.
//

#include "Context.h"
#include "SourceNode.h"
#include "EffectorNode.h"
#include "cinder/Utilities.h"

using namespace ci;

namespace Cinder { namespace Pipeline {

ContextRef Context::create() {
    return ContextRef(new Context())->shared_from_this();
}

Context::Context() {
}

Context::~Context() {
}

#pragma mark -

void Context::setup(const Vec2i size, int attachments) {
#if defined(DEBUG)
    const char* renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
    cinder::app::console() << "GL_RENDERER: " << renderer << std::endl;
    const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
    cinder::app::console() << "GL_VENDOR: " << vendor << std::endl;
    const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
    cinder::app::console() << "GL_VERSION: " << version << std::endl;
    const char* shadingLanguageVersion = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
    cinder::app::console() << "GL_SHADING_LANGUAGE_VERSION: " << shadingLanguageVersion << std::endl;

    std::string extensionsString = std::string(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
    std::vector<std::string> extensions = split(extensionsString, " ");
    extensions.erase(std::remove_if(extensions.begin(), extensions.end(), [](const std::string& s){ return s.empty(); }));
    cinder::app::console() << "GL_EXTENSIONS: " << std::endl;
    for (const std::string& e : extensions) {
        cinder::app::console() << " " << e << std::endl;
    }

    GLint texSize;
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
    cinder::app::console() << "GL_MAX_TEXTURE_SIZE: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &texSize);
    cinder::app::console() << "GL_MAX_3D_TEXTURE_SIZE: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texSize);
    cinder::app::console() << "GL_MAX_TEXTURE_IMAGE_UNITS: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &texSize);
    cinder::app::console() << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &texSize);
    cinder::app::console() << "GL_MAX_COLOR_ATTACHMENTS: " << texSize << std::endl;
    cinder::app::console() << std::string(13, '-') << std::endl;
#endif

//    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
//    if (size.x > texSize) {
//        // TODO - tile horizontally
//        cinder::app::console() << "ERROR - setup width '" << size.x << "' exceeds maximum texture size '" << texSize << "', tiling unimplemented" << std::endl;
//    }
//    if (size.y > texSize) {
//        // TODO - tile vertically
//        cinder::app::console() << "ERROR - setup height '" << size.y << "' exceeds maximum texture size '" << texSize << "', tiling unimplemented" << std::endl;
//    }
//
//    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &texSize);
//    if (attachments > GL_MAX_COLOR_ATTACHMENTS) {
//        cinder::app::console() << "ERROR - number of attachments '" << attachments << "' exceeds '" << texSize << "'" << std::endl;
//    }
//
//    float attachmentMemorySizeMB = size.x * size.y * 4 / 1024 / 1024;
//    float totalSizeMB = attachmentMemorySizeMB * attachments;
//
//    if (gl::isExtensionAvailable("GL_NV_texture_barrier")) {
//        if (texSize >= 2 * size.x && texSize >= size.y) {
//            // TODO - double-wide
//        } else if (texSize >= 2 * size.y && texSize >= size.x) {
//            // TODO - double-tall
//        } else {
//            // TODO - tile
//        }
//    }

    gl::Fbo::Format format;
    format.enableColorBuffer(true, attachments);
    format.enableDepthBuffer(false);

    mFBO = gl::Fbo(size.x, size.y, format);
    mFBO.bindFramebuffer(); {
        GLenum buffers[attachments];
        for (unsigned int idx = 0; idx < attachments; idx++) {
            buffers[idx] = GL_COLOR_ATTACHMENT0 + idx;
        }
        glDrawBuffers(attachments, buffers);
        gl::setViewport(mFBO.getBounds());
        gl::clear();
    } mFBO.unbindFramebuffer();
}

#pragma mark - CONNECTIONS

void Context::connectNodes(const NodeRef& sourceNode, const NodePortRef& sourcePort, const NodeRef& destinationNode, const NodePortRef& destinationPort) {
    // remove from output connections if destination port already connected
    if (mInputConnections[destinationNode].count(destinationPort->getKey()) > 0) {
        std::vector<NodePortConnectionRef> connections = mOutputConnections[sourceNode][sourcePort->getKey()];
        connections.erase(std::remove_if(connections.begin(), connections.end(), [destinationNode](const NodePortConnectionRef& c) {
            return c->getDestinationNode() == destinationNode;
        }), connections.end());
    }

    NodePortConnectionRef connection = NodePortConnection::create(sourceNode, sourcePort->getKey(), destinationNode, destinationPort->getKey());
    mInputConnections[destinationNode][destinationPort->getKey()] = connection;
    mOutputConnections[sourceNode][sourcePort->getKey()].push_back(connection);

    // wipe render stack to force a rebuild
    mRenderStack.clear();
}

void Context::connectNodes(const NodeRef& sourceNode, const std::string& sourceNodePortKey, const NodeRef& destinationNode, const std::string& destinationNodePortKey) {
    NodePortRef sourcePort = sourceNode->getOutputPortForKey(sourceNodePortKey);
    NodePortRef destinationPort = destinationNode->getInputPortForKey(destinationNodePortKey);
    connectNodes(sourceNode, sourcePort, destinationNode, destinationPort);
}

void Context::connectNodes(const NodeRef& sourceNode, const NodeRef& destinationNode) {
    connectNodes(sourceNode, "image", destinationNode, "image");
}

#pragma mark -

gl::Texture& Context::evaluate(const NodeRef& node) {
    // rebuild render stack (flush cache) if the stack is empty or the node changes (cache key)
    if (mRenderStack.size() == 0 || node != mRenderNode) {
        mRenderNode = node;
        BranchRef root = branchForNode(mRenderNode);
        mRenderStack = renderStackForRootBranch(root);
    }

#if defined(DEBUG)
    // ASCII visualization
    cinder::app::console() << std::string(3, '#') << std::endl;
    for (const BranchRef& b : mRenderStack) {
        printBranch(b);
    }
    cinder::app::console() << std::endl;
#endif

    // render branches
    unsigned int outAttachment = 0;

    Area viewport = gl::getViewport();
    gl::setViewport(mFBO.getBounds());
    mFBO.bindFramebuffer(); {
        gl::pushMatrices(); {
            gl::setMatricesWindow(mFBO.getSize(), false);

            // int instead of GLenum for Cinder's FBO bindTexture/getTexture
            std::vector<int> availableAttachments;
            for (unsigned int idx = 0; idx < mFBO.getFormat().getNumColorBuffers(); idx++) {
                availableAttachments.push_back(idx);
            }
            std::map<NodeRef, int> attachmentsMap;

            for (const BranchRef& b : mRenderStack) {
                size_t attachmentIndex = 0;
                outAttachment = availableAttachments.at(attachmentIndex);
                int inAttachment = -1;

                for (size_t nodeIdx = 0; nodeIdx < b->getNodes().size(); nodeIdx++) {
                    // TODO - hoist draw buffer assignment
                    NodeRef n = b->getNodes().at(nodeIdx);
                    SourceNodeRef s = std::dynamic_pointer_cast<SourceNode>(n);
                    if (s) {
                        glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                        FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                        s->render(outputFBOImage);

                        inAttachment = outAttachment;
                    } else {
                        EffectorNodeRef e = std::dynamic_pointer_cast<EffectorNode>(n);
                        if (e) {
                            std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n, NodePortType::FBOImage);
                            if (connections.size() == 1) {
                                NodePortConnectionRef c = connections.at(0);
                                // grab attachment from map when appropriate
                                if (inAttachment == -1) {
                                    inAttachment = attachmentsMap[c->getSourceNode()];
                                    attachmentsMap.erase(c->getSourceNode());
                                    availableAttachments.push_back(inAttachment);
                                }
                                FBOImageRef inputFBOImage = FBOImage::create(mFBO, inAttachment);
                                e->setValueForInputPortKey(inputFBOImage, c->getDestinationPortKey());

                                attachmentIndex = (attachmentIndex + 1) % availableAttachments.size();
                                outAttachment = availableAttachments.at(attachmentIndex);
                                glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                                FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                                e->render(outputFBOImage);

                                inAttachment = outAttachment;
                            } else if (connections.size() > 1) {
                                for (const NodePortConnectionRef& c : connections) {
                                    inAttachment = attachmentsMap[c->getSourceNode()];
                                    attachmentsMap.erase(c->getSourceNode());
                                    availableAttachments.push_back(inAttachment);

                                    FBOImageRef inputFBOImage = FBOImage::create(mFBO, inAttachment);
                                    e->setValueForInputPortKey(inputFBOImage, c->getDestinationPortKey());
                                }

                                glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                                FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                                e->render(outputFBOImage);

                                inAttachment = outAttachment;
                            }
                        }
                    }

                    // stash output attachment and accompanying node when branch concludes
                    if (nodeIdx == b->getNodes().size() - 1) {
                        attachmentsMap[n] = outAttachment;
                        availableAttachments.erase(std::find(availableAttachments.begin(), availableAttachments.end(), outAttachment));
                    }
                }
            }
        } gl::popMatrices();
    } mFBO.unbindFramebuffer();
    gl::setViewport(viewport);

    return mFBO.getTexture(outAttachment);
}

#pragma mark -

void Context::printBranch(const BranchRef& branch) {
//    for (const NodeRef& n : branch->getNodes()) {
//        cinder::app::console() << n->getName() << " → ";
//    }
//    cinder::app::console() << " (" << branch->getMaxInputCost() << ")" << std::endl;
    for (const NodeRef& n : branch->getNodes()) {
        if (!std::dynamic_pointer_cast<SourceNode>(n)) {
            cinder::app::console() << " → ";
        }

        std::string name = n->getName();
        name.resize(3, ' ');
        cinder::app::console() << "[" << name << "]";
    }
    cinder::app::console() << " (" << branch->getMaxInputCost() << ")";
    cinder::app::console() << std::endl;
}

BranchRef Context::branchForNode(const NodeRef& node) {
    std::map<NodeRef, BranchRef> branchMap;
    std::deque<NodeRef> nodeStack;

    // create branches
    NodeRef n = node;
    while (n) {
        if (branchMap.count(n) == 0) {
            std::deque<NodeRef> nodes;

            NodeRef n2 = n;
            while (n2) {
                nodes.push_front(n2);

                std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n2, NodePortType::FBOImage);
                if (connections.size() == 0) {
                    n2 = nullptr;
                } else if (connections.size() == 1) {
                    NodePortConnectionRef connection = connections.at(0);
                    n2 = connection->getSourceNode();

                    if (getOutputConnectionsForNodeWithPortKey(n2, connection->getSourcePortKey()).size() > 1) {
                        nodeStack.push_front(n2);
                        n2 = nullptr;
                    }
                } else if (connections.size() > 1) {
                    for (const NodePortConnectionRef& c : connections) {
                        nodeStack.push_front(c->getSourceNode());
                    }
                    n2 = nullptr;
                }
            }

            BranchRef branch = Branch::create(nodes);
            branchMap[n] = branch;
        }

        if (nodeStack.empty()) {
            n = nullptr;
        } else {
            n = nodeStack.front();
            nodeStack.pop_front();
        }
    }

    // connect branches
    for (auto& kv : branchMap) {
        BranchRef destinationBranch = kv.second;
        n = destinationBranch->getNodes().front();

        std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n, NodePortType::FBOImage);
        for (const NodePortConnectionRef& c : connections) {
            BranchRef sourceBranch = branchMap[c->getSourceNode()];
            destinationBranch->connectInputBranch(sourceBranch);
        }
    }

    return branchMap[node];
}

std::deque<BranchRef> Context::renderStackForRootBranch(const BranchRef& branch) {
    std::deque<BranchRef> renderStack;
    std::deque<BranchRef> branchStack;

    BranchRef b = branch;
    while (b) {
        renderStack.push_front(b);

        std::vector<BranchConnectionRef> inputConnections = b->getInputConnections();
        if (inputConnections.empty()) {
            if (branchStack.empty()) {
                b = nullptr;
            } else {
                b = branchStack.front();
                branchStack.pop_front();
            }
        } else {
            // sort by cost DESC
            std::vector<BranchConnectionRef> sortedInputConnections = inputConnections;
            std::sort(sortedInputConnections.begin(), sortedInputConnections.end(), [](const BranchConnectionRef& c1, const BranchConnectionRef& c2) {
                return c1->getInputCost() > c2->getInputCost();
            });

            // follow cheapest path
            b = sortedInputConnections.back()->getSourceBranch();
            sortedInputConnections.pop_back();

            // push the others
            for (const BranchConnectionRef& c : sortedInputConnections) {
                branchStack.push_front(c->getSourceBranch());
            }
        }
    }

    return renderStack;
}

}}
<commit_msg>branch on multiple outputs not just multiple on a specific port<commit_after>//
//  Context.cpp
//  Cinder-Pipeline
//
//  Created by Jean-Pierre Mouilleseaux on 19 Apr 2014.
//  Copyright 2014 Chorded Constructions. All rights reserved.
//

#include "Context.h"
#include "SourceNode.h"
#include "EffectorNode.h"
#include "cinder/Utilities.h"

using namespace ci;

namespace Cinder { namespace Pipeline {

ContextRef Context::create() {
    return ContextRef(new Context())->shared_from_this();
}

Context::Context() {
}

Context::~Context() {
}

#pragma mark -

void Context::setup(const Vec2i size, int attachments) {
#if defined(DEBUG)
    const char* renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
    cinder::app::console() << "GL_RENDERER: " << renderer << std::endl;
    const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
    cinder::app::console() << "GL_VENDOR: " << vendor << std::endl;
    const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
    cinder::app::console() << "GL_VERSION: " << version << std::endl;
    const char* shadingLanguageVersion = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
    cinder::app::console() << "GL_SHADING_LANGUAGE_VERSION: " << shadingLanguageVersion << std::endl;

    std::string extensionsString = std::string(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
    std::vector<std::string> extensions = split(extensionsString, " ");
    extensions.erase(std::remove_if(extensions.begin(), extensions.end(), [](const std::string& s){ return s.empty(); }));
    cinder::app::console() << "GL_EXTENSIONS: " << std::endl;
    for (const std::string& e : extensions) {
        cinder::app::console() << " " << e << std::endl;
    }

    GLint texSize;
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
    cinder::app::console() << "GL_MAX_TEXTURE_SIZE: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &texSize);
    cinder::app::console() << "GL_MAX_3D_TEXTURE_SIZE: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texSize);
    cinder::app::console() << "GL_MAX_TEXTURE_IMAGE_UNITS: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &texSize);
    cinder::app::console() << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << texSize << std::endl;
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &texSize);
    cinder::app::console() << "GL_MAX_COLOR_ATTACHMENTS: " << texSize << std::endl;
    cinder::app::console() << std::string(13, '-') << std::endl;
#endif

//    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
//    if (size.x > texSize) {
//        // TODO - tile horizontally
//        cinder::app::console() << "ERROR - setup width '" << size.x << "' exceeds maximum texture size '" << texSize << "', tiling unimplemented" << std::endl;
//    }
//    if (size.y > texSize) {
//        // TODO - tile vertically
//        cinder::app::console() << "ERROR - setup height '" << size.y << "' exceeds maximum texture size '" << texSize << "', tiling unimplemented" << std::endl;
//    }
//
//    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &texSize);
//    if (attachments > GL_MAX_COLOR_ATTACHMENTS) {
//        cinder::app::console() << "ERROR - number of attachments '" << attachments << "' exceeds '" << texSize << "'" << std::endl;
//    }
//
//    float attachmentMemorySizeMB = size.x * size.y * 4 / 1024 / 1024;
//    float totalSizeMB = attachmentMemorySizeMB * attachments;
//
//    if (gl::isExtensionAvailable("GL_NV_texture_barrier")) {
//        if (texSize >= 2 * size.x && texSize >= size.y) {
//            // TODO - double-wide
//        } else if (texSize >= 2 * size.y && texSize >= size.x) {
//            // TODO - double-tall
//        } else {
//            // TODO - tile
//        }
//    }

    gl::Fbo::Format format;
    format.enableColorBuffer(true, attachments);
    format.enableDepthBuffer(false);

    mFBO = gl::Fbo(size.x, size.y, format);
    mFBO.bindFramebuffer(); {
        GLenum buffers[attachments];
        for (unsigned int idx = 0; idx < attachments; idx++) {
            buffers[idx] = GL_COLOR_ATTACHMENT0 + idx;
        }
        glDrawBuffers(attachments, buffers);
        gl::setViewport(mFBO.getBounds());
        gl::clear();
    } mFBO.unbindFramebuffer();
}

#pragma mark - CONNECTIONS

void Context::connectNodes(const NodeRef& sourceNode, const NodePortRef& sourcePort, const NodeRef& destinationNode, const NodePortRef& destinationPort) {
    // remove from output connections if destination port already connected
    if (mInputConnections[destinationNode].count(destinationPort->getKey()) > 0) {
        std::vector<NodePortConnectionRef> connections = mOutputConnections[sourceNode][sourcePort->getKey()];
        connections.erase(std::remove_if(connections.begin(), connections.end(), [destinationNode](const NodePortConnectionRef& c) {
            return c->getDestinationNode() == destinationNode;
        }), connections.end());
    }

    NodePortConnectionRef connection = NodePortConnection::create(sourceNode, sourcePort->getKey(), destinationNode, destinationPort->getKey());
    mInputConnections[destinationNode][destinationPort->getKey()] = connection;
    mOutputConnections[sourceNode][sourcePort->getKey()].push_back(connection);

    // wipe render stack to force a rebuild
    mRenderStack.clear();
}

void Context::connectNodes(const NodeRef& sourceNode, const std::string& sourceNodePortKey, const NodeRef& destinationNode, const std::string& destinationNodePortKey) {
    NodePortRef sourcePort = sourceNode->getOutputPortForKey(sourceNodePortKey);
    NodePortRef destinationPort = destinationNode->getInputPortForKey(destinationNodePortKey);
    connectNodes(sourceNode, sourcePort, destinationNode, destinationPort);
}

void Context::connectNodes(const NodeRef& sourceNode, const NodeRef& destinationNode) {
    connectNodes(sourceNode, "image", destinationNode, "image");
}

#pragma mark -

gl::Texture& Context::evaluate(const NodeRef& node) {
    // rebuild render stack (flush cache) if the stack is empty or the node changes (cache key)
    if (mRenderStack.size() == 0 || node != mRenderNode) {
        mRenderNode = node;
        BranchRef root = branchForNode(mRenderNode);
        mRenderStack = renderStackForRootBranch(root);
    }

#if defined(DEBUG)
    // ASCII visualization
    cinder::app::console() << std::string(3, '#') << std::endl;
    for (const BranchRef& b : mRenderStack) {
        printBranch(b);
    }
    cinder::app::console() << std::endl;
#endif

    // render branches
    unsigned int outAttachment = 0;

    Area viewport = gl::getViewport();
    gl::setViewport(mFBO.getBounds());
    mFBO.bindFramebuffer(); {
        gl::pushMatrices(); {
            gl::setMatricesWindow(mFBO.getSize(), false);

            // int instead of GLenum for Cinder's FBO bindTexture/getTexture
            std::vector<int> availableAttachments;
            for (unsigned int idx = 0; idx < mFBO.getFormat().getNumColorBuffers(); idx++) {
                availableAttachments.push_back(idx);
            }
            std::map<NodeRef, int> attachmentsMap;

            for (const BranchRef& b : mRenderStack) {
                size_t attachmentIndex = 0;
                outAttachment = availableAttachments.at(attachmentIndex);
                int inAttachment = -1;

                for (size_t nodeIdx = 0; nodeIdx < b->getNodes().size(); nodeIdx++) {
                    // TODO - hoist draw buffer assignment
                    NodeRef n = b->getNodes().at(nodeIdx);
                    SourceNodeRef s = std::dynamic_pointer_cast<SourceNode>(n);
                    if (s) {
                        glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                        FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                        s->render(outputFBOImage);

                        inAttachment = outAttachment;
                    } else {
                        EffectorNodeRef e = std::dynamic_pointer_cast<EffectorNode>(n);
                        if (e) {
                            std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n, NodePortType::FBOImage);
                            if (connections.size() == 1) {
                                NodePortConnectionRef c = connections.at(0);
                                // grab attachment from map when appropriate
                                if (inAttachment == -1) {
                                    inAttachment = attachmentsMap[c->getSourceNode()];
                                    attachmentsMap.erase(c->getSourceNode());
                                    availableAttachments.push_back(inAttachment);
                                }
                                FBOImageRef inputFBOImage = FBOImage::create(mFBO, inAttachment);
                                e->setValueForInputPortKey(inputFBOImage, c->getDestinationPortKey());

                                attachmentIndex = (attachmentIndex + 1) % availableAttachments.size();
                                outAttachment = availableAttachments.at(attachmentIndex);
                                glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                                FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                                e->render(outputFBOImage);

                                inAttachment = outAttachment;
                            } else if (connections.size() > 1) {
                                for (const NodePortConnectionRef& c : connections) {
                                    inAttachment = attachmentsMap[c->getSourceNode()];
                                    attachmentsMap.erase(c->getSourceNode());
                                    availableAttachments.push_back(inAttachment);

                                    FBOImageRef inputFBOImage = FBOImage::create(mFBO, inAttachment);
                                    e->setValueForInputPortKey(inputFBOImage, c->getDestinationPortKey());
                                }

                                glDrawBuffer(GL_COLOR_ATTACHMENT0 + outAttachment);

                                FBOImageRef outputFBOImage = FBOImage::create(mFBO, outAttachment);
                                e->render(outputFBOImage);

                                inAttachment = outAttachment;
                            }
                        }
                    }

                    // stash output attachment and accompanying node when branch concludes
                    if (nodeIdx == b->getNodes().size() - 1) {
                        attachmentsMap[n] = outAttachment;
                        availableAttachments.erase(std::find(availableAttachments.begin(), availableAttachments.end(), outAttachment));
                    }
                }
            }
        } gl::popMatrices();
    } mFBO.unbindFramebuffer();
    gl::setViewport(viewport);

    return mFBO.getTexture(outAttachment);
}

#pragma mark -

void Context::printBranch(const BranchRef& branch) {
//    for (const NodeRef& n : branch->getNodes()) {
//        cinder::app::console() << n->getName() << " → ";
//    }
//    cinder::app::console() << " (" << branch->getMaxInputCost() << ")" << std::endl;
    for (const NodeRef& n : branch->getNodes()) {
        if (!std::dynamic_pointer_cast<SourceNode>(n)) {
            cinder::app::console() << " → ";
        }

        std::string name = n->getName();
        name.resize(3, ' ');
        cinder::app::console() << "[" << name << "]";
    }
    cinder::app::console() << " (" << branch->getMaxInputCost() << ")";
    cinder::app::console() << std::endl;
}

BranchRef Context::branchForNode(const NodeRef& node) {
    std::map<NodeRef, BranchRef> branchMap;
    std::deque<NodeRef> nodeStack;

    // create branches
    NodeRef n = node;
    while (n) {
        if (branchMap.count(n) == 0) {
            std::deque<NodeRef> nodes;

            NodeRef n2 = n;
            while (n2) {
                nodes.push_front(n2);

                std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n2, NodePortType::FBOImage);
                if (connections.size() == 0) {
                    n2 = nullptr;
                } else if (connections.size() == 1) {
                    NodePortConnectionRef connection = connections.at(0);
                    n2 = connection->getSourceNode();

                    // branch on multiple outputs
                    if (getOutputConnectionsForNodeWithPortType(n2, NodePortType::FBOImage).size() > 1) {
                        nodeStack.push_front(n2);
                        n2 = nullptr;
                    }
                } else if (connections.size() > 1) {
                    // branch on multiple inputs
                    for (const NodePortConnectionRef& c : connections) {
                        nodeStack.push_front(c->getSourceNode());
                    }
                    n2 = nullptr;
                }
            }

            BranchRef branch = Branch::create(nodes);
            branchMap[n] = branch;
        }

        if (nodeStack.empty()) {
            n = nullptr;
        } else {
            n = nodeStack.front();
            nodeStack.pop_front();
        }
    }

    // connect branches
    for (auto& kv : branchMap) {
        BranchRef destinationBranch = kv.second;
        n = destinationBranch->getNodes().front();

        std::vector<NodePortConnectionRef> connections = getInputConnectionsForNodeWithPortType(n, NodePortType::FBOImage);
        for (const NodePortConnectionRef& c : connections) {
            BranchRef sourceBranch = branchMap[c->getSourceNode()];
            destinationBranch->connectInputBranch(sourceBranch);
        }
    }

    return branchMap[node];
}

std::deque<BranchRef> Context::renderStackForRootBranch(const BranchRef& branch) {
    std::deque<BranchRef> renderStack;
    std::deque<BranchRef> branchStack;

    BranchRef b = branch;
    while (b) {
        renderStack.push_front(b);

        std::vector<BranchConnectionRef> inputConnections = b->getInputConnections();
        if (inputConnections.empty()) {
            if (branchStack.empty()) {
                b = nullptr;
            } else {
                b = branchStack.front();
                branchStack.pop_front();
            }
        } else {
            // sort by cost DESC
            std::vector<BranchConnectionRef> sortedInputConnections = inputConnections;
            std::sort(sortedInputConnections.begin(), sortedInputConnections.end(), [](const BranchConnectionRef& c1, const BranchConnectionRef& c2) {
                return c1->getInputCost() > c2->getInputCost();
            });

            // follow cheapest path
            b = sortedInputConnections.back()->getSourceBranch();
            sortedInputConnections.pop_back();

            // push the others
            for (const BranchConnectionRef& c : sortedInputConnections) {
                branchStack.push_front(c->getSourceBranch());
            }
        }
    }

    return renderStack;
}

}}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cassert>

#include "CubeCmd.h"
#include "HdfWriter.h"
#include "TextWriter.h"
#include "VtkWriter.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

// ---------------------------------------------------------------------------

cigma::CubeCmd::CubeCmd()
{
    name = "cube";

    L = M = N = 0;
    mesh = 0;
    writer = 0;
}

cigma::CubeCmd::~CubeCmd()
{
}

// ---------------------------------------------------------------------------

void cigma::CubeCmd::setupOptions(AnyOption *opt)
{
    //cout << "Calling cigma::CubeCmd::setupOptions()" << endl;
    assert(opt != 0);

    /* setup usage */
    opt->addUsage("Usage:");
    opt->addUsage("  cigma cube [options]");
    opt->addUsage("    -x               Number of elements along x-dimension");
    opt->addUsage("    -y               Number of elements along y-dimension");
    opt->addUsage("    -z               Number of elements along z-dimension");
    opt->addUsage("    --hex8           Create hexahedral partition (default)");
    opt->addUsage("    --tet4           Create tetrahedral partition");
    opt->addUsage("    --output         Target output file");
    opt->addUsage("    --coords-path    Target path for coordinates (.h5 only)");
    opt->addUsage("    --connect-path   Target path for connectivity (.h5 only)");

    /* setup flags and options */

    opt->setFlag("help", 'h');
    opt->setFlag("verbose", 'v');

    opt->setFlag("hex8");
    opt->setFlag("tet4");

    opt->setOption('x');
    opt->setOption('y');
    opt->setOption('z');

    opt->setOption("output");
    opt->setOption("coords-path");
    opt->setOption("connect-path");

}

void cigma::CubeCmd::configure(AnyOption *opt)
{
    //std::cout << "Calling cigma::CubeCmd::configure()" << std::endl;
    assert(opt != 0);

    if (!opt->hasOptions())
    {
        //std::cerr << "No options?" << std::endl;
        opt->printUsage();
        exit(1);
    }

    char *in;
    string inputstr;

    // read verbose flag
    verbose = opt->getFlag("verbose");

    // read L
    in = opt->getValue('x');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -x" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, L);

    // read M
    in = opt->getValue('y');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -y" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, M);

    // read N
    in = opt->getValue('z');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -z" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, N);

    // read output file
    in = opt->getValue("output");
    if (in == 0)
    {
        cerr << "cube: Please specify the option --output" << endl;
        exit(1);
    }
    output_filename = in;

    // determine the extension and instantiate appropriate writer object
    string root, ext;
    path_splitext(output_filename, root, ext);
    new_writer(&writer, ext);
    if (writer == 0)
    {
        cerr << "cube: File with bad extension (" << ext << ")" << endl;
        exit(1);
    }

    // read target path for coordinates array
    in = opt->getValue("coords-path");
    if (in == 0)
    {
        if (writer->getType() == Writer::HDF_WRITER)
        {
            coords_path = "/coordinates";
        }
    }
    else
    {
        coords_path = in;
    }
    if ((coords_path != "") && (writer->getType() != Writer::HDF_WRITER))
    {
        cerr << "cube: Can only use --coords-path "
             << "when writing to an HDF5 (.h5) file" << endl;
        exit(1);

    }

    // read target path for connectivity array
    in = opt->getValue("connect-path");
    if (in == 0)
    {
        if (writer->getType() == Writer::HDF_WRITER)
        {
            connect_path = "/connectivity";
        }
    }
    else
    {
        connect_path = in;
    }
    if ((connect_path != "") && (writer->getType() != Writer::HDF_WRITER))
    {
        cerr << "cube: Can only use --connect-path "
             << "when writing to an HDF5 (.h5) file" << endl;
        exit(1);
    }

    // read tet/hex flags
    bool hexFlag = opt->getFlag("hex8");
    bool tetFlag = opt->getFlag("tet4");
    if (hexFlag && tetFlag)
    {
        std::cerr << "cube: Please specify only one of the flags "
                  << "--hex8 or --tet8" << std::endl;
        exit(1);
    }
    if (!tetFlag)
    {
        hexFlag = true;
    }
    assert(hexFlag != tetFlag);

    // initialize mesh object
    mesh = new cigma::CubeMeshPart();
    mesh->calc_coordinates(L,M,N);
    if (hexFlag) { mesh->calc_hex8_connectivity(); }
    if (tetFlag) { mesh->calc_tet4_connectivity(); }
}

int cigma::CubeCmd::run()
{
    //std::cout << "Calling cigma::CubeCmd::run()" << std::endl;
    assert(mesh != 0);
    assert(writer != 0);

    if (verbose)
    {
        std::cout << "L, M, N = (" << L << ", " << M << ", " << N << ")" << std::endl;
        std::cout << "mesh->nno = " << mesh->nno << std::endl;
        std::cout << "mesh->nel = " << mesh->nel << std::endl;
        std::cout << "mesh->ndofs = " << mesh->ndofs << std::endl;
    }

    if (verbose)
    {
        int e = 0;
        double pts[2][3] = {{0.5, 0.5, 0.5},
                            {1.0, 1.0, 1.0}};

        cout << "Looking for centroid..." << endl;
        bool found = mesh->find_cell(pts[0], &e);

        if (!found)
        {
            cerr << "Error: Could not find cell "
                 << "containing centroid (0.5,0.5,0.5)" << endl;
            exit(1);
        }
        else
        {
            cout << "Found centroid in cell " << e << endl;
        }
    }

    int ierr;

    cout << "Creating file " << output_filename << endl;

    if (writer->getType() == Writer::HDF_WRITER)
    {
        HdfWriter *hdfWriter = static_cast<HdfWriter*>(writer);
        ierr = hdfWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not open (or create) the HDF5 file " << output_filename << endl;
            exit(1);
        }

        ierr = hdfWriter->write_coordinates(coords_path.c_str(), mesh->coords, mesh->nno, mesh->nsd);
        if (ierr < 0)
        {
            cerr << "Error: Could not write dataset " << coords_path << endl;
            exit(1);
        }

        ierr = hdfWriter->write_connectivity(connect_path.c_str(), mesh->connect, mesh->nel, mesh->ndofs);
        if (ierr < 0)
        {
            cerr << "Error: Could not write dataset " << connect_path << endl;
            exit(1);
        }

        hdfWriter->close();
    }
    else if (writer->getType() == Writer::TXT_WRITER)
    {
        TextWriter *txtWriter = static_cast<TextWriter*>(writer);
        ierr = txtWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not create output text file " << output_filename << endl;
            exit(1);
        }

        txtWriter->write_coordinates(mesh->coords, mesh->nno, mesh->nsd);
        txtWriter->write_connectivity(mesh->connect, mesh->nel, mesh->ndofs);
        txtWriter->close();
    }
    else if (writer->getType() == Writer::VTK_WRITER)
    {
        VtkWriter *vtkWriter = static_cast<VtkWriter*>(writer);
        ierr = vtkWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not create output VTK file " << output_filename << endl;
            exit(1);
        }

        vtkWriter->write_header();
        vtkWriter->write_points(mesh->coords, mesh->nno, mesh->nsd);
        vtkWriter->write_cells(mesh->connect, mesh->nel, mesh->ndofs);
        vtkWriter->write_cell_types(mesh->nsd, mesh->nel, mesh->ndofs);
        vtkWriter->close();
    }
    else
    {
        /* this should be unreachable */
        cerr << "Fatal Error: Unsupported extension in output filename?" << endl;
        return 1;
    }

    if (writer != 0)
    {
        delete writer;
    }

    return 0;
}

// ---------------------------------------------------------------------------

<commit_msg>Clarified message in CubeCmd (quick test on -v flag)<commit_after>#include <iostream>
#include <string>
#include <cassert>

#include "CubeCmd.h"
#include "HdfWriter.h"
#include "TextWriter.h"
#include "VtkWriter.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

// ---------------------------------------------------------------------------

cigma::CubeCmd::CubeCmd()
{
    name = "cube";

    L = M = N = 0;
    mesh = 0;
    writer = 0;
}

cigma::CubeCmd::~CubeCmd()
{
}

// ---------------------------------------------------------------------------

void cigma::CubeCmd::setupOptions(AnyOption *opt)
{
    //cout << "Calling cigma::CubeCmd::setupOptions()" << endl;
    assert(opt != 0);

    /* setup usage */
    opt->addUsage("Usage:");
    opt->addUsage("  cigma cube [options]");
    opt->addUsage("    -x               Number of elements along x-dimension");
    opt->addUsage("    -y               Number of elements along y-dimension");
    opt->addUsage("    -z               Number of elements along z-dimension");
    opt->addUsage("    --hex8           Create hexahedral partition (default)");
    opt->addUsage("    --tet4           Create tetrahedral partition");
    opt->addUsage("    --output         Target output file");
    opt->addUsage("    --coords-path    Target path for coordinates (.h5 only)");
    opt->addUsage("    --connect-path   Target path for connectivity (.h5 only)");

    /* setup flags and options */

    opt->setFlag("help", 'h');
    opt->setFlag("verbose", 'v');

    opt->setFlag("hex8");
    opt->setFlag("tet4");

    opt->setOption('x');
    opt->setOption('y');
    opt->setOption('z');

    opt->setOption("output");
    opt->setOption("coords-path");
    opt->setOption("connect-path");

}

void cigma::CubeCmd::configure(AnyOption *opt)
{
    //std::cout << "Calling cigma::CubeCmd::configure()" << std::endl;
    assert(opt != 0);

    if (!opt->hasOptions())
    {
        //std::cerr << "No options?" << std::endl;
        opt->printUsage();
        exit(1);
    }

    char *in;
    string inputstr;

    // read verbose flag
    verbose = opt->getFlag("verbose");

    // read L
    in = opt->getValue('x');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -x" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, L);

    // read M
    in = opt->getValue('y');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -y" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, M);

    // read N
    in = opt->getValue('z');
    if (in == 0)
    {
        cerr << "cube: Please specify the option -z" << endl;
        exit(1);
    }
    inputstr = in;
    string_to_int(inputstr, N);

    // read output file
    in = opt->getValue("output");
    if (in == 0)
    {
        cerr << "cube: Please specify the option --output" << endl;
        exit(1);
    }
    output_filename = in;

    // determine the extension and instantiate appropriate writer object
    string root, ext;
    path_splitext(output_filename, root, ext);
    new_writer(&writer, ext);
    if (writer == 0)
    {
        cerr << "cube: File with bad extension (" << ext << ")" << endl;
        exit(1);
    }

    // read target path for coordinates array
    in = opt->getValue("coords-path");
    if (in == 0)
    {
        if (writer->getType() == Writer::HDF_WRITER)
        {
            coords_path = "/coordinates";
        }
    }
    else
    {
        coords_path = in;
    }
    if ((coords_path != "") && (writer->getType() != Writer::HDF_WRITER))
    {
        cerr << "cube: Can only use --coords-path "
             << "when writing to an HDF5 (.h5) file" << endl;
        exit(1);

    }

    // read target path for connectivity array
    in = opt->getValue("connect-path");
    if (in == 0)
    {
        if (writer->getType() == Writer::HDF_WRITER)
        {
            connect_path = "/connectivity";
        }
    }
    else
    {
        connect_path = in;
    }
    if ((connect_path != "") && (writer->getType() != Writer::HDF_WRITER))
    {
        cerr << "cube: Can only use --connect-path "
             << "when writing to an HDF5 (.h5) file" << endl;
        exit(1);
    }

    // read tet/hex flags
    bool hexFlag = opt->getFlag("hex8");
    bool tetFlag = opt->getFlag("tet4");
    if (hexFlag && tetFlag)
    {
        std::cerr << "cube: Please specify only one of the flags "
                  << "--hex8 or --tet8" << std::endl;
        exit(1);
    }
    if (!tetFlag)
    {
        hexFlag = true;
    }
    assert(hexFlag != tetFlag);

    // initialize mesh object
    mesh = new cigma::CubeMeshPart();
    mesh->calc_coordinates(L,M,N);
    if (hexFlag) { mesh->calc_hex8_connectivity(); }
    if (tetFlag) { mesh->calc_tet4_connectivity(); }
}

int cigma::CubeCmd::run()
{
    //std::cout << "Calling cigma::CubeCmd::run()" << std::endl;
    assert(mesh != 0);
    assert(writer != 0);

    if (verbose)
    {
        std::cout << "L, M, N = (" << L << ", " << M << ", " << N << ")" << std::endl;
        std::cout << "mesh->nno = " << mesh->nno << std::endl;
        std::cout << "mesh->nel = " << mesh->nel << std::endl;
        std::cout << "mesh->ndofs = " << mesh->ndofs << std::endl;
    }

    if (verbose)
    {
        int e = 0;
        double pts[2][3] = {{0.5, 0.5, 0.5},
                            {1.0, 1.0, 1.0}};

        cout << "cube test: Looking for centroid..." << endl;
        bool found = mesh->find_cell(pts[0], &e);

        if (!found)
        {
            cerr << "cube test error: Could not find cell "
                 << "containing centroid (0.5,0.5,0.5)" << endl;
            exit(1);
        }
        else
        {
            cout << "cube test: Found centroid in cell " << e << endl;
        }
    }

    int ierr;

    cout << "Creating file " << output_filename << endl;

    if (writer->getType() == Writer::HDF_WRITER)
    {
        HdfWriter *hdfWriter = static_cast<HdfWriter*>(writer);
        ierr = hdfWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not open (or create) the HDF5 file " << output_filename << endl;
            exit(1);
        }

        ierr = hdfWriter->write_coordinates(coords_path.c_str(), mesh->coords, mesh->nno, mesh->nsd);
        if (ierr < 0)
        {
            cerr << "Error: Could not write dataset " << coords_path << endl;
            exit(1);
        }

        ierr = hdfWriter->write_connectivity(connect_path.c_str(), mesh->connect, mesh->nel, mesh->ndofs);
        if (ierr < 0)
        {
            cerr << "Error: Could not write dataset " << connect_path << endl;
            exit(1);
        }

        hdfWriter->close();
    }
    else if (writer->getType() == Writer::TXT_WRITER)
    {
        TextWriter *txtWriter = static_cast<TextWriter*>(writer);
        ierr = txtWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not create output text file " << output_filename << endl;
            exit(1);
        }

        txtWriter->write_coordinates(mesh->coords, mesh->nno, mesh->nsd);
        txtWriter->write_connectivity(mesh->connect, mesh->nel, mesh->ndofs);
        txtWriter->close();
    }
    else if (writer->getType() == Writer::VTK_WRITER)
    {
        VtkWriter *vtkWriter = static_cast<VtkWriter*>(writer);
        ierr = vtkWriter->open(output_filename);
        if (ierr < 0)
        {
            cerr << "Error: Could not create output VTK file " << output_filename << endl;
            exit(1);
        }

        vtkWriter->write_header();
        vtkWriter->write_points(mesh->coords, mesh->nno, mesh->nsd);
        vtkWriter->write_cells(mesh->connect, mesh->nel, mesh->ndofs);
        vtkWriter->write_cell_types(mesh->nsd, mesh->nel, mesh->ndofs);
        vtkWriter->close();
    }
    else
    {
        /* this should be unreachable */
        cerr << "Fatal Error: Unsupported extension in output filename?" << endl;
        return 1;
    }

    if (writer != 0)
    {
        delete writer;
    }

    return 0;
}

// ---------------------------------------------------------------------------

<|endoftext|>


<commit_before>                                                                         /*
 * ISR.cpp
 *
 *  Created on: 27.04.2017 based on tutorium-example
 *      Author: abt674
 */

#include <iostream>
#include <cstdlib>
#include <sys/neutrino.h>
#include <sys/siginfo.h>
#include "HWaccess.h"
#include "Control.h"
#include "ISR.h"

using namespace std;

int isrId = 0;
int isrChannel = 0;
int isrConnection = 0;
struct sigevent isrEvent;
int portbc = 0;
Control * ctrl;

bool button_start_active = true;
bool button_stop_active = true;
bool button_reset_active = true;
bool button_estop_active = true;
bool lb_entry_active = true;
bool lb_exit_active = true;
bool lb_height_active = true;
bool lb_ramp_active = true;
bool lb_switch_active = true;
bool sensor_height_active = true;
bool sensor_metal_active = true;
bool switch_open = true;

// ISR (c-Function)
const struct sigevent* ISR_DIO(void* arg, int id) {
    struct sigevent* event = (struct sigevent*) arg;
    out8(0x30F, 0);

    event->sigev_notify = SIGEV_PULSE ;
    event->__sigev_un1.__sigev_coid = isrConnection;
    event->__sigev_un2.__st.__sigev_code = 0;
    event->sigev_value.sival_int = in8(0x301) | (in8(0x302) << 8);
    return event;
}

//ISR anmelden
void registerISR(void){
	//Lichtschranken und Sensoren
    out8(0x30F, 0);
    out8(0x30B, 0b11111101);
    //Buttons
    out8(0x30B, 0b11111001);

    SIGEV_PULSE_INIT(&isrEvent, isrConnection, SIGEV_PULSE_PRIO_INHERIT, 0, 0);
    isrId = InterruptAttach(11, ISR_DIO, &isrEvent, sizeof(isrEvent), 0);
    if (isrId == -1) {
        exit(EXIT_FAILURE);
    }
}

//nach Thread Ende ISR abmelden
void unregisterISR(void){
    if( InterruptDetach(isrId) == -1 ){
        exit(EXIT_FAILURE);
    }
    out8(0x30B, 0b11111111);
    out8(0x30F,0);
}

/*
 * Creates the ISR-Channel
 * @param [control] Control Object for Methodcalls
 * */
ISR::ISR(Control * control) {
    cout << "ctor: ISR_Thread" << endl;
    ctrl = control;
    if ((isrChannel = ChannelCreate(0)) == -1) {
    		exit(EXIT_FAILURE);
    	}
    	cout<< "isrchannel " << isrChannel <<endl;

    	if ((isrConnection = ConnectAttach(0, 0, isrChannel, 0, 0)) == -1) {
    		exit(EXIT_FAILURE);
    	}

}
/*
 * deconstructor
 * */
ISR::~ISR() {
    cout << "dtor: ISR_Thread" << endl;

}
/*
 * "main"-function, call this to start the ISR
 * this function registers the ISR and determines the origin of an interrupt
 * */
void ISR::operator()(){
    // Init and Register ISR
    if (ThreadCtl(_NTO_TCTL_IO_PRIV, 0) == -1){
        exit(EXIT_FAILURE);
    }
    // Register Interrupt Service Routine
    registerISR();

    struct _pulse pulse;

    portbc = in8(0x301) | (in8(0x302) << 8);
    // Wait for Pulse Message
    do{
    	//pulse message empfangen(warten)
        MsgReceivePulse(isrChannel,&pulse,sizeof(pulse),NULL);

        //register zuordnen
        int diff = pulse.value.sival_int ^ portbc;
        portbc =  pulse.value.sival_int;

        			if((diff & LightBarrier_ENTRY) == LightBarrier_ENTRY){
        					if (lb_entry_active) {
        						cout << "LightBarrier_entry_" << endl;
        						ctrl->lightBarrier_ENTRY_IN();
        						lb_entry_active = false;
        					} else {
        						lb_entry_active = true;
        						ctrl->lightBarrier_ENTRY_OUT();
        					}
        			}
        			else if((diff & LightBarrier_HEIGHT) == LightBarrier_HEIGHT){
        					if (lb_height_active) {
        						cout << "LightBarrier_height" << endl;
        						ctrl->lightBarrier_HEIGHT_IN();
        						lb_height_active = false;
        					} else {
        						lb_height_active = true;
        						ctrl->lightBarrier_HEIGHT_OUT();
        					}
        			}

        			else  if((diff & LightBarrier_SWITCH) == LightBarrier_SWITCH){
        					if (lb_switch_active){
        						cout << "LightBarrier_switch" << endl;
        						ctrl->lightBarrier_SWITCH_IN();
        						lb_switch_active = false;
        					} else {
        						ctrl->lightBarrier_SWITCH_OUT();
        						lb_switch_active = true;
        					}
        			}

        			else if((diff & LightBarrier_RAMP) == LightBarrier_RAMP){
        					if (lb_ramp_active) {
        						cout << "LightBarrier_ramp" << endl;
        						ctrl->lightBarrier_RAMP_IN();
        						lb_ramp_active = false;
        					} else {
        						ctrl->lightBarrier_RAMP_OUT();
        						lb_ramp_active = true;
        					}
        			}

    				else if((diff & LightBarrier_EXIT) == LightBarrier_EXIT){
        					if (lb_exit_active) {
        						cout << "LightBarrier_exit" << endl;
        						ctrl->lightBarrier_EXIT_IN();
        						lb_exit_active = false;
        					} else {
        						ctrl->lightBarrier_EXIT_OUT();
        						lb_exit_active = true;
        					}
    					}

    				else if((diff & BUTTONSTART) == BUTTONSTART){
        					if (button_start_active) {
        						cout << "button_start" << endl;
        						ctrl->b_Start();
        						button_start_active = false;
        					} else {
        						button_start_active = true;
        					}
        			}

    				else if((diff & BUTTONSTOP) == BUTTONSTOP){
        					if (button_stop_active) {
        						cout << "button_stop" << endl;
        						ctrl->b_STOP();
        						button_stop_active = false;
        					} else {
        						button_stop_active = true;
        					}
        			}

    				else if((diff & BUTTONRESET) == BUTTONRESET){
        					if (button_reset_active) {
        						cout << "button_reset" << endl;
        						ctrl->b_Reset();
        						button_reset_active = false;
        					} else {
        						button_reset_active = true;
        					}
        			}

    				else if ((diff & BUTTONESTOP) == BUTTONESTOP){

        					if (button_estop_active) {
        						cout << "button_estop" << endl;
        						ctrl->b_EStop();
        						button_estop_active = false;
        					} else {
        						button_estop_active = true;
        					}
    					}

    				else if ((diff & SENSOR_METAL) == SENSOR_METAL){
        			        if (sensor_metal_active) {
        			        	cout << "metal" << endl;
        			        	ctrl->metal();
        			        	sensor_metal_active = false;
        			        	} else {
        			        	cout << "no_metal" << endl;
        			            sensor_metal_active = true;
        			        }
        			}

    				else if ((diff & SENSOR_HEIGHT) == SENSOR_HEIGHT){
        					if (sensor_height_active) {
        						cout << "sensor_height" << endl;
        						ctrl->height();
        						sensor_height_active = false;
        					} else {
        						sensor_height_active = true;
        					}
        			}

    				else if ((diff & SWITCH_OPEND) == SWITCH_OPEND){
        					if (switch_open) {
        						cout << "switch is open" << endl;
        						ctrl->switchen();
        						switch_open = false;
        					} else {
        						cout << "switch is closed" << endl;
        						switch_open = true;
        					}
        			}

    }while(1);

    // Cleanup
    unregisterISR();
    //isr verbindung aufheben
    if( ConnectDetach(isrConnection) == -1){
        exit(EXIT_FAILURE);
    }
    //channel lschen
    if( ChannelDestroy(isrChannel) == -1 ){
        exit(EXIT_FAILURE);
    }

	}

<commit_msg>ISR_Schleife abbrechbar<commit_after>                                                                         /*
 * ISR.cpp
 *
 *  Created on: 27.04.2017 based on tutorium-example
 *      Author: abt674
 */

#include <iostream>
#include <cstdlib>
#include <sys/neutrino.h>
#include <sys/siginfo.h>
#include "HWaccess.h"
#include "Control.h"
#include "ISR.h"

using namespace std;

int isrId = 0;
int isrChannel = 0;
int isrConnection = 0;
struct sigevent isrEvent;
int portbc = 0;
Control * ctrl;

bool button_start_active = true;
bool button_stop_active = true;
bool button_reset_active = true;
bool button_estop_active = true;
bool lb_entry_active = true;
bool lb_exit_active = true;
bool lb_height_active = true;
bool lb_ramp_active = true;
bool lb_switch_active = true;
bool sensor_height_active = true;
bool sensor_metal_active = true;
bool switch_open = true;

// ISR (c-Function)
const struct sigevent* ISR_DIO(void* arg, int id) {
    struct sigevent* event = (struct sigevent*) arg;
    out8(0x30F, 0);

    event->sigev_notify = SIGEV_PULSE ;
    event->__sigev_un1.__sigev_coid = isrConnection;
    event->__sigev_un2.__st.__sigev_code = 0;
    event->sigev_value.sival_int = in8(0x301) | (in8(0x302) << 8);
    return event;
}

//ISR anmelden
void registerISR(void){
	//Lichtschranken und Sensoren
    out8(0x30F, 0);
    out8(0x30B, 0b11111101);
    //Buttons
    out8(0x30B, 0b11111001);

    SIGEV_PULSE_INIT(&isrEvent, isrConnection, SIGEV_PULSE_PRIO_INHERIT, 0, 0);
    isrId = InterruptAttach(11, ISR_DIO, &isrEvent, sizeof(isrEvent), 0);
    if (isrId == -1) {
        exit(EXIT_FAILURE);
    }
}

//nach Thread Ende ISR abmelden
void unregisterISR(void){
    if( InterruptDetach(isrId) == -1 ){
        exit(EXIT_FAILURE);
    }
    out8(0x30B, 0b11111111);
    out8(0x30F,0);
}

/*
 * Creates the ISR-Channel
 * @param [control] Control Object for Methodcalls
 * */
ISR::ISR(Control * control) {
    cout << "ctor: ISR_Thread" << endl;
    ctrl = control;
    if ((isrChannel = ChannelCreate(0)) == -1) {
    		exit(EXIT_FAILURE);
    	}
    	cout<< "isrchannel " << isrChannel <<endl;

    	if ((isrConnection = ConnectAttach(0, 0, isrChannel, 0, 0)) == -1) {
    		exit(EXIT_FAILURE);
    	}

}
/*
 * deconstructor
 * */
ISR::~ISR() {
    cout << "dtor: ISR_Thread" << endl;

}
/*
 * "main"-function, call this to start the ISR
 * this function registers the ISR and determines the origin of an interrupt
 * */
void ISR::operator()(){
	bool running = true;

    // Init and Register ISR
    if (ThreadCtl(_NTO_TCTL_IO_PRIV, 0) == -1){
        exit(EXIT_FAILURE);
    }
    // Register Interrupt Service Routine
    registerISR();

    struct _pulse pulse;

    portbc = in8(0x301) | (in8(0x302) << 8);
    // Wait for Pulse Message
    do{
    	//pulse message empfangen(warten)
        MsgReceivePulse(isrChannel,&pulse,sizeof(pulse),NULL);

        //register zuordnen
        int diff = pulse.value.sival_int ^ portbc;
        portbc =  pulse.value.sival_int;

        			if((diff & BUTTONESTOP) == BUTTONESTOP){

    					if (button_estop_active) {
    						cout << "button_estop" << endl;
    						ctrl->b_EStop();
    						button_estop_active = false;
    						running = false;
    					} else {
    						button_estop_active = true;
    					}
					}

        			else if((diff & LightBarrier_HEIGHT) == LightBarrier_HEIGHT){
        					if (lb_height_active) {
        						cout << "LightBarrier_height" << endl;
        						ctrl->lightBarrier_HEIGHT_IN();
        						lb_height_active = false;
        					} else {
        						lb_height_active = true;
        						ctrl->lightBarrier_HEIGHT_OUT();
        					}
        			}

        			else  if((diff & LightBarrier_SWITCH) == LightBarrier_SWITCH){
        					if (lb_switch_active){
        						cout << "LightBarrier_switch" << endl;
        						ctrl->lightBarrier_SWITCH_IN();
        						lb_switch_active = false;
        					} else {
        						ctrl->lightBarrier_SWITCH_OUT();
        						lb_switch_active = true;
        					}
        			}

        			else if((diff & LightBarrier_RAMP) == LightBarrier_RAMP){
        					if (lb_ramp_active) {
        						cout << "LightBarrier_ramp" << endl;
        						ctrl->lightBarrier_RAMP_IN();
        						lb_ramp_active = false;
        					} else {
        						ctrl->lightBarrier_RAMP_OUT();
        						lb_ramp_active = true;
        					}
        			}

    				else if((diff & LightBarrier_EXIT) == LightBarrier_EXIT){
        					if (lb_exit_active) {
        						cout << "LightBarrier_exit" << endl;
        						ctrl->lightBarrier_EXIT_IN();
        						lb_exit_active = false;
        					} else {
        						ctrl->lightBarrier_EXIT_OUT();
        						lb_exit_active = true;
        					}
    					}

    				else if((diff & BUTTONSTART) == BUTTONSTART){
        					if (button_start_active) {
        						cout << "button_start" << endl;
        						ctrl->b_Start();
        						button_start_active = false;
        					} else {
        						button_start_active = true;
        					}
        			}

    				else if((diff & BUTTONSTOP) == BUTTONSTOP){
        					if (button_stop_active) {
        						cout << "button_stop" << endl;
        						ctrl->b_STOP();
        						button_stop_active = false;
        					} else {
        						button_stop_active = true;
        					}
        			}

    				else if((diff & BUTTONRESET) == BUTTONRESET){
        					if (button_reset_active) {
        						cout << "button_reset" << endl;
        						ctrl->b_Reset();
        						button_reset_active = false;
        					} else {
        						button_reset_active = true;
        					}
        			}

    				else if ((diff & LightBarrier_ENTRY) == LightBarrier_ENTRY){
    					if (lb_entry_active) {
    						cout << "LightBarrier_entry_" << endl;
    						ctrl->lightBarrier_ENTRY_IN();
    						lb_entry_active = false;
    					} else {
    						lb_entry_active = true;
    						ctrl->lightBarrier_ENTRY_OUT();
    					}
    			}

    				else if ((diff & SENSOR_METAL) == SENSOR_METAL){
        			        if (sensor_metal_active) {
        			        	cout << "metal" << endl;
        			        	ctrl->metal();
        			        	sensor_metal_active = false;
        			        	} else {
        			        	cout << "no_metal" << endl;
        			            sensor_metal_active = true;
        			        }
        			}

    				else if ((diff & SENSOR_HEIGHT) == SENSOR_HEIGHT){
        					if (sensor_height_active) {
        						cout << "sensor_height" << endl;
        						ctrl->height();
        						sensor_height_active = false;
        					} else {
        						sensor_height_active = true;
        					}
        			}

    				else if ((diff & SWITCH_OPEND) == SWITCH_OPEND){
        					if (switch_open) {
        						cout << "switch is open" << endl;
        						ctrl->switchen();
        						switch_open = false;
        					} else {
        						cout << "switch is closed" << endl;
        						switch_open = true;
        					}
        			}

    }while(running);

    cout << "Shutdown ISR..."<<endl;
    // Cleanup
    unregisterISR();
    //isr verbindung aufheben
    if( ConnectDetach(isrConnection) == -1){
        exit(EXIT_FAILURE);
    }
    //channel lschen
    if( ChannelDestroy(isrChannel) == -1 ){
        exit(EXIT_FAILURE);
    }
    cout << "ISR detached and channel destroyed!" << endl;
	}

<|endoftext|>


<commit_before>/*
    Copyright © 2010 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "IdentityShader.h"

namespace Magnum { namespace Examples {

IdentityShader::IdentityShader() {
    Shader* vertexShader = Shader::fromFile(Shader::Vertex, "identity.vert");
    Shader* fragmentShader = Shader::fromFile(Shader::Fragment, "identity.frag");

    loadShader(vertexShader);
    loadShader(fragmentShader);

    bindAttribute(Vertex, "vertex");
    bindAttribute(Color, "color");

    link();

    delete vertexShader;
    delete fragmentShader;
}

}}
<commit_msg>Renamed AbstractShaderProgram::{load -> attach}Shader().<commit_after>/*
    Copyright © 2010 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "IdentityShader.h"

namespace Magnum { namespace Examples {

IdentityShader::IdentityShader() {
    Shader* vertexShader = Shader::fromFile(Shader::Vertex, "identity.vert");
    Shader* fragmentShader = Shader::fromFile(Shader::Fragment, "identity.frag");

    attachShader(vertexShader);
    attachShader(fragmentShader);

    bindAttribute(Vertex, "vertex");
    bindAttribute(Color, "color");

    link();

    delete vertexShader;
    delete fragmentShader;
}

}}
<|endoftext|>


<commit_before>#ifndef _MATCHER_HPP
#define _MATCHER_HPP
class Matcher {
public:
  virtual ~Matcher(){}
  virtual bool isMatched(CB) const = 0;
  virtual int getLastMatched(int) const = 0;
  virtual const std::set<CB> & findMatchedSends() const = 0;
};
#endif
<commit_msg>Better naming.<commit_after>#ifndef _MATCHER_HPP
#define _MATCHER_HPP
class Matcher {
public:
  virtual ~Matcher(){}
  virtual bool isMatched(CB) const = 0;
  virtual int findLastMatched(int) const = 0;
  virtual const std::set<CB> & findMatchedSends() const = 0;
};
#endif
<|endoftext|>


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

#include <string>
#include <iostream>
#include <vector>
#include <atomic>

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include "assert.hpp"
#include "Options.hpp"

using namespace eddic;

namespace po = boost::program_options;

namespace {

std::pair<std::string, std::string> numeric_parser(const std::string& s){
    if (s.find("-32") == 0) {
        return make_pair("32", std::string("true"));
    } else if (s.find("-64") == 0) {
        return make_pair("64", std::string("true"));
    } else {
        return make_pair(std::string(), std::string());
    }
}

std::atomic<bool> description_flag;

po::options_description visible("Usage : eddic [options] source.eddi");
po::options_description all("Usage : eddic [options] source.eddi");

std::unordered_map<std::string, std::vector<std::string>> triggers;

void add_trigger(const std::string& option, const std::vector<std::string>& childs){
   triggers[option] = childs;
}

void init_descriptions(){
    po::options_description general("General options");
    general.add_options()
        ("help,h", "Generate this help message")
        ("assembly,S", "Generate only the assembly")
        ("keep,k", "Keep the assembly file")
        ("version", "Print the version of eddic")
        ("output,o", po::value<std::string>()->default_value("a.out"), "Set the name of the executable")

        ("debug,g", "Add debugging symbols")

        ("template-depth", po::value<int>()->default_value(100), "Define the maximum template depth")

        ("32", "Force the compilation for 32 bits platform")
        ("64", "Force the compilation for 64 bits platform")

        ("warning-all", "Enable all the warning messages")
        ("warning-unused", "Warn about unused variables, parameters and functions")
        ("warning-cast", "Warn about useless casts")
        ("warning-effects", "Warn about statements without effect")
        ;

    po::options_description display("Display options");
    display.add_options()
        ("ast", "Print the Abstract Syntax Tree representation of the source")
        ("ast-raw", "Print the Abstract Syntax Tree representation of the source coming directly from the parser before any pass is run on the AST. ")
        ("ast-only", "Only print the Abstract Syntax Tree representation of the source (do not continue compilation after printing)")

        ("mtac", "Print the medium-level Three Address Code representation of the source")
        ("mtac-opt", "Print the medium-level Three Address Code representation of the source before any optimization has been performed")
        ("mtac-only", "Only print the medium-level Three Address Code representation of the source (do not continue compilation after printing)")

        ("ltac-pre", "Print the low-level Three Address Code representation of the source before allocation of registers")
        ("ltac-alloc", "Print the low-level Three Address Code representation of the source before optimization")
        ("ltac", "Print the final low-level Three Address Code representation of the source")
        ("ltac-only", "Only print the low-level Three Address Code representation of the source (do not continue compilation after printing)")
        ;

    po::options_description optimization("Optimization options");
    optimization.add_options()
        ("Opt,O", po::value<int>()->implicit_value(0)->default_value(2), "Define the optimization level")
        ("O0", "Disable all optimizations")
        ("O1", "Enable low-level optimizations")
        ("O2", "Enable all optimizations. This can be slow for big programs.")

        ("fglobal-optimization", "Enable optimizer engine")
        ("fparameter-allocation", "Enable parameter allocation in register")
        ("fpeephole-optimization", "Enable peephole optimizer")
        ("fomit-frame-pointer", "Omit frame pointer from functions")
        ("finline-functions", "Enable inlining")
        ("fno-inline-functions", "Disable inlining")
        ;

    po::options_description backend("Backend options");
    backend.add_options()
        ("log", po::value<int>()->default_value(0), "Define the logging")
        ("quiet,q", "Do not print anything")
        ("verbose,v", "Make the compiler verbose")
        ("single-threaded", "Disable the multi-threaded optimization")
        ("time", "Activate timing system")
        ("input", po::value<std::string>(), "Input file")
        ;

    all.add(general).add(display).add(optimization).add(backend);
    visible.add(general).add(display).add(optimization);

    add_trigger("warning-all", {"warning-unused", "warning-cast", "warning-effects"});

    //Special triggers for optimization levels
    add_trigger("__1", {"fpeephole-optimization"});
    add_trigger("__2", {"fglobal-optimization", "fomit-frame-pointer", "fparameter-allocation", "finline-functions"});
}

inline void trigger_childs(std::shared_ptr<Configuration> configuration, const std::vector<std::string>& childs){
    for(auto& child : childs){
        configuration->values[child].defined = true;
        configuration->values[child].value = std::string("true");
    }
}

} //end of anonymous namespace

std::shared_ptr<Configuration> eddic::parseOptions(int argc, const char* argv[]) {
    //Create a new configuration
    auto configuration = std::make_shared<Configuration>();

    try {
        //Only if the description has not been already defined
        if(!description_flag.load()){
            bool old_value = description_flag.load();
            if(description_flag.compare_exchange_strong(old_value, true)){
                init_descriptions();
            }
        }

        //Add the option of the input file
        po::positional_options_description p;
        p.add("input", -1);

        //Create a new set of options
        po::variables_map options;

        //Parse the command line options
        po::store(po::command_line_parser(argc, argv).options(all).extra_parser(numeric_parser).positional(p).run(), options);
        po::notify(options);

        //Transfer the options in the eddic configuration
        for(auto& option : all.options()){
            ConfigValue value;

            if(options.count(option->long_name())){
                value.defined = true;
                value.value = options[option->long_name()].value();
            } else {
                value.defined = false;
                value.value = std::string("false");
            }

            configuration->values[option->long_name()] = value;
        }

        if(options.count("O0") + options.count("O1") + options.count("O2") > 1){
            std::cout << "Invalid command line options : only one optimization level should be set" << std::endl;

            return nullptr;
        }

        if(options.count("64") && options.count("32")){
            std::cout << "Invalid command line options : a compilation cannot be both 32 and 64 bits" << std::endl;

            return nullptr;
        }

        //Update optimization level based on special switches
        if(options.count("O0")){
            configuration->values["Opt"].value = 0;
        } else if(options.count("O1")){
            configuration->values["Opt"].value = 1;
        } else if(options.count("O2")){
            configuration->values["Opt"].value = 2;
        }

        //Triggers dependent options
        for(auto& trigger : triggers){
            if(configuration->option_defined(trigger.first)){
                trigger_childs(configuration, trigger.second);
            }
        }

        if(configuration->option_int_value("Opt") >= 1){
            trigger_childs(configuration, triggers["__1"]);
        }

        if(configuration->option_int_value("Opt") >= 2){
            trigger_childs(configuration, triggers["__2"]);
        }
    } catch (const po::ambiguous_option& e) {
        std::cout << "Invalid command line options : " << e.what() << std::endl;

        return nullptr;
    } catch (const po::unknown_option& e) {
        std::cout << "Invalid command line options : " << e.what() << std::endl;

        return nullptr;
    } catch (const po::multiple_occurrences& e) {
        std::cout << "Only one file can be compiled" << std::endl;

        return nullptr;
    }

    return configuration;
}

bool Configuration::option_defined(const std::string& option_name){
    return values[option_name].defined;
}

std::string Configuration::option_value(const std::string& option_name){
    return boost::any_cast<std::string>(values[option_name].value);
}

int Configuration::option_int_value(const std::string& option_name){
    return boost::any_cast<int>(values[option_name].value);
}

void eddic::print_help(){
    std::cout << visible << std::endl;
}

void eddic::print_version(){
    std::cout << "eddic version 1.2.0" << std::endl;
}
<commit_msg>Add a new option for the statistics system<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>
#include <iostream>
#include <vector>
#include <atomic>

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include "assert.hpp"
#include "Options.hpp"

using namespace eddic;

namespace po = boost::program_options;

namespace {

std::pair<std::string, std::string> numeric_parser(const std::string& s){
    if (s.find("-32") == 0) {
        return make_pair("32", std::string("true"));
    } else if (s.find("-64") == 0) {
        return make_pair("64", std::string("true"));
    } else {
        return make_pair(std::string(), std::string());
    }
}

std::atomic<bool> description_flag;

po::options_description visible("Usage : eddic [options] source.eddi");
po::options_description all("Usage : eddic [options] source.eddi");

std::unordered_map<std::string, std::vector<std::string>> triggers;

void add_trigger(const std::string& option, const std::vector<std::string>& childs){
   triggers[option] = childs;
}

void init_descriptions(){
    po::options_description general("General options");
    general.add_options()
        ("help,h", "Generate this help message")
        ("assembly,S", "Generate only the assembly")
        ("keep,k", "Keep the assembly file")
        ("version", "Print the version of eddic")
        ("output,o", po::value<std::string>()->default_value("a.out"), "Set the name of the executable")

        ("debug,g", "Add debugging symbols")

        ("template-depth", po::value<int>()->default_value(100), "Define the maximum template depth")

        ("32", "Force the compilation for 32 bits platform")
        ("64", "Force the compilation for 64 bits platform")

        ("warning-all", "Enable all the warning messages")
        ("warning-unused", "Warn about unused variables, parameters and functions")
        ("warning-cast", "Warn about useless casts")
        ("warning-effects", "Warn about statements without effect")
        ;

    po::options_description display("Display options");
    display.add_options()
        ("ast", "Print the Abstract Syntax Tree representation of the source")
        ("ast-raw", "Print the Abstract Syntax Tree representation of the source coming directly from the parser before any pass is run on the AST. ")
        ("ast-only", "Only print the Abstract Syntax Tree representation of the source (do not continue compilation after printing)")

        ("mtac", "Print the medium-level Three Address Code representation of the source")
        ("mtac-opt", "Print the medium-level Three Address Code representation of the source before any optimization has been performed")
        ("mtac-only", "Only print the medium-level Three Address Code representation of the source (do not continue compilation after printing)")

        ("ltac-pre", "Print the low-level Three Address Code representation of the source before allocation of registers")
        ("ltac-alloc", "Print the low-level Three Address Code representation of the source before optimization")
        ("ltac", "Print the final low-level Three Address Code representation of the source")
        ("ltac-only", "Only print the low-level Three Address Code representation of the source (do not continue compilation after printing)")
        ;

    po::options_description optimization("Optimization options");
    optimization.add_options()
        ("Opt,O", po::value<int>()->implicit_value(0)->default_value(2), "Define the optimization level")
        ("O0", "Disable all optimizations")
        ("O1", "Enable low-level optimizations")
        ("O2", "Enable all optimizations. This can be slow for big programs.")

        ("fglobal-optimization", "Enable optimizer engine")
        ("fparameter-allocation", "Enable parameter allocation in register")
        ("fpeephole-optimization", "Enable peephole optimizer")
        ("fomit-frame-pointer", "Omit frame pointer from functions")
        ("finline-functions", "Enable inlining")
        ("fno-inline-functions", "Disable inlining")
        ;

    po::options_description backend("Backend options");
    backend.add_options()
        ("log", po::value<int>()->default_value(0), "Define the logging")
        ("quiet,q", "Do not print anything")
        ("verbose,v", "Make the compiler verbose")
        ("single-threaded", "Disable the multi-threaded optimization")
        ("time", "Activate the timing system")
        ("stats", "Activate the statistics system")
        ("input", po::value<std::string>(), "Input file")
        ;

    all.add(general).add(display).add(optimization).add(backend);
    visible.add(general).add(display).add(optimization);

    add_trigger("warning-all", {"warning-unused", "warning-cast", "warning-effects"});

    //Special triggers for optimization levels
    add_trigger("__1", {"fpeephole-optimization"});
    add_trigger("__2", {"fglobal-optimization", "fomit-frame-pointer", "fparameter-allocation", "finline-functions"});
}

inline void trigger_childs(std::shared_ptr<Configuration> configuration, const std::vector<std::string>& childs){
    for(auto& child : childs){
        configuration->values[child].defined = true;
        configuration->values[child].value = std::string("true");
    }
}

} //end of anonymous namespace

std::shared_ptr<Configuration> eddic::parseOptions(int argc, const char* argv[]) {
    //Create a new configuration
    auto configuration = std::make_shared<Configuration>();

    try {
        //Only if the description has not been already defined
        if(!description_flag.load()){
            bool old_value = description_flag.load();
            if(description_flag.compare_exchange_strong(old_value, true)){
                init_descriptions();
            }
        }

        //Add the option of the input file
        po::positional_options_description p;
        p.add("input", -1);

        //Create a new set of options
        po::variables_map options;

        //Parse the command line options
        po::store(po::command_line_parser(argc, argv).options(all).extra_parser(numeric_parser).positional(p).run(), options);
        po::notify(options);

        //Transfer the options in the eddic configuration
        for(auto& option : all.options()){
            ConfigValue value;

            if(options.count(option->long_name())){
                value.defined = true;
                value.value = options[option->long_name()].value();
            } else {
                value.defined = false;
                value.value = std::string("false");
            }

            configuration->values[option->long_name()] = value;
        }

        if(options.count("O0") + options.count("O1") + options.count("O2") > 1){
            std::cout << "Invalid command line options : only one optimization level should be set" << std::endl;

            return nullptr;
        }

        if(options.count("64") && options.count("32")){
            std::cout << "Invalid command line options : a compilation cannot be both 32 and 64 bits" << std::endl;

            return nullptr;
        }

        //Update optimization level based on special switches
        if(options.count("O0")){
            configuration->values["Opt"].value = 0;
        } else if(options.count("O1")){
            configuration->values["Opt"].value = 1;
        } else if(options.count("O2")){
            configuration->values["Opt"].value = 2;
        }

        //Triggers dependent options
        for(auto& trigger : triggers){
            if(configuration->option_defined(trigger.first)){
                trigger_childs(configuration, trigger.second);
            }
        }

        if(configuration->option_int_value("Opt") >= 1){
            trigger_childs(configuration, triggers["__1"]);
        }

        if(configuration->option_int_value("Opt") >= 2){
            trigger_childs(configuration, triggers["__2"]);
        }
    } catch (const po::ambiguous_option& e) {
        std::cout << "Invalid command line options : " << e.what() << std::endl;

        return nullptr;
    } catch (const po::unknown_option& e) {
        std::cout << "Invalid command line options : " << e.what() << std::endl;

        return nullptr;
    } catch (const po::multiple_occurrences& e) {
        std::cout << "Only one file can be compiled" << std::endl;

        return nullptr;
    }

    return configuration;
}

bool Configuration::option_defined(const std::string& option_name){
    return values[option_name].defined;
}

std::string Configuration::option_value(const std::string& option_name){
    return boost::any_cast<std::string>(values[option_name].value);
}

int Configuration::option_int_value(const std::string& option_name){
    return boost::any_cast<int>(values[option_name].value);
}

void eddic::print_help(){
    std::cout << visible << std::endl;
}

void eddic::print_version(){
    std::cout << "eddic version 1.2.0" << std::endl;
}
<|endoftext|>


<commit_before>// An example how to display PS, EPS, PDF files in canvas
//Author: Valeriy Onoutchin

#include "TROOT.h"
#include "TCanvas.h"
#include "TImage.h"

void psview()
{
   // set to batch mode -> do not display graphics
   gROOT->SetBatch(1);

   // create a PostScript file
   gROOT->Macro("feynman.C");
   gPad->Print("feynman.ps");

   // back to graphics mode
   gROOT->SetBatch(0);

   // create an image from PS file
   TImage *ps = TImage::Open("feynman.ps");

   if (!ps) {
      printf("GhostScript (gs) program must be installed\n");
      return;
   }

   new TCanvas("psexam", "Example how to display PS file in canvas", 500, 650);
   ps->Draw("xxx");
}
<commit_msg>- Add a comment about ghostscript<commit_after>// An example how to display PS, EPS, PDF files in canvas
// To load a PS file in a TCanvas, the ghostscript program needs to be install.
// On most unix systems it is usually installed. On Windows it has to be
// installed from http://pages.cs.wisc.edu/~ghost/
//Author: Valeriy Onoutchin

#include "TROOT.h"
#include "TCanvas.h"
#include "TImage.h"

void psview()
{
   // set to batch mode -> do not display graphics
   gROOT->SetBatch(1);

   // create a PostScript file
   gROOT->Macro("feynman.C");
   gPad->Print("feynman.ps");

   // back to graphics mode
   gROOT->SetBatch(0);

   // create an image from PS file
   TImage *ps = TImage::Open("feynman.ps");

   if (!ps) {
      printf("GhostScript (gs) program must be installed\n");
      return;
   }

   new TCanvas("psexam", "Example how to display PS file in canvas", 500, 650);
   ps->Draw("xxx");
}
<|endoftext|>