<commit_before>#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include "cmdAnd.h"
#include "cmdOr.h"
#include "cmdBase.h"
#include "cmdSemi.h"
#include "cmdExecutable.h"
#include <vector>
#include <stack>
#include <list>
#include <iterator>

using namespace std;

void printPrompt();
char* getInput();
cmdBase* parse(char* input);
vector<char*> infixToPostfix(list<char*> vInfix);
int priority(char*);

int main()
{
    while(true)
    {
        printPrompt();

        char* userInput = getInput();

        if ( userInput != NULL )
        {
            cmdBase* head = parse(userInput);

            if (head != NULL)
            {
                head->execute( );
            }

            //delete userInput;
            //delete head;
        }
    }
}

// prints the prompt for the user
// displays the user name and host name
void printPrompt()
{
    char *User;
    char host[30];

    User = getlogin( );
    gethostname( host, 30 );

    cout << User << "@" << host << "$ ";
}

//takes in user input and returns the char*
char* getInput()
{
    //takes in user input as string w/ getline
    string temp;

    getline(cin, temp);

    if ( temp.size( ) == 0 )
    {
        return NULL;
    }

    int i = 0;
    while (temp.at(i) == ' ')
    {
        i++;
    }
    if (temp.at(i) == ';' || temp.at(i) == '|' || temp.at(i) == '&')
    {
        cout << "syntax error found near unexpected token '"
            << temp.at(i) << "'" << endl;
        return NULL;
    }

    //creates char array and sets it equal to string
    char* input = new char[temp.size() + 1];

    for (int i = 0, n = temp.size(); i < n; i++)
    {
        input[i] = temp.at(i);
    }

    input[temp.size()] = '\0'; //adds NULL to end of char array

    return input;
}

//creates tree of command connectors by parsing the entered line
cmdBase* parse(char* input)
{
    if ( input[0] == '\0' || input[0] == ';' )
        return NULL;

    list<char*> vInfix;
    char* cmdPtr;

    cmdPtr = strtok(input, ";");

    while (cmdPtr != NULL)
    {
        vInfix.push_back(cmdPtr);
        char* temp = new char[2];
        temp[0] = ';';
        temp[1] = '\0';
        vInfix.push_back(temp);
        cmdPtr = strtok(NULL, ";");
    }

    if (*vInfix.back() == ';')
    {
        vInfix.pop_back();
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        cmdPtr = strtok(*it, "&");
        char* cmdPtr2 = strtok(NULL, "");

        if (cmdPtr2 != NULL)
        {
           cmdPtr2 += 1;
           *it = cmdPtr;
           char* temp = new char[3];
           temp[0] = '&';
           temp[1] = '&';
           temp[2] = '\0';
           it++;
           if(it == vInfix.end())
           {
               it--;
               vInfix.push_back(temp);
               vInfix.push_back(cmdPtr2);
               it++;
           }

           else
           {
               vInfix.insert(it, temp);
               vInfix.insert(it, cmdPtr2);
           }
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        cmdPtr = strtok(*it, "|");
        char* cmdPtr2 = strtok(NULL, "");

        if (cmdPtr2 != NULL)
        {
           cmdPtr2 += 1;
           *it = cmdPtr;
           char* temp = new char[3];
           temp[0] = '|';
           temp[1] = '|';
           temp[2] = '\0';
           it++;

           if(it == vInfix.end())
           {
               it--;
               vInfix.push_back(temp);
               vInfix.push_back(cmdPtr2);
               it++;
           }

           else
           {
               vInfix.insert(it, temp);
               vInfix.insert(it, cmdPtr2);
           }
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* c = *it;
        int i = 0;

        while (c[i] == ' ')
        {
            i++;
        }

        if (c[i] == '(')
        {
           char* temp = new char[2];
           temp[0] = '(';
           temp[1] = '\0';
           vInfix.insert(it, temp);
           c[i] = '\0';
           c += i + 1;
           *it = c;
           it--;
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* c =  strpbrk(*it, ")");

        if (c != NULL)
        {
            c[0] = '\0';
            int i = 1;

            while (c[i] == ' ')
            {
                i++;
            }

            if (c[i] != '\0')
            {
                c += i;
                it++;

                if (it == vInfix.end())
                {
                    it--;
                    vInfix.push_back(c);
                    it++;
                }

                else
                {
                    vInfix.insert(it, c);
                }

                it--;
            }

            char* temp = new char[2];
            temp[0] = ')';
            temp[1] = '\0';
            it++;

            if (it == vInfix.end())
            {
                it--;
                vInfix.push_back(temp);
                it++;
            }

            else
            {
                vInfix.insert(it, temp);
            }
        }
    }

    int numOfLP = 0, numOfRP = 0, rptCmdCheck = 0;
    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* wrdPtr = *it;

        if (strcmp(wrdPtr, "&&") == 0 || strcmp(wrdPtr, "||") == 0
            || strcmp(wrdPtr, ";") == 0)
        {
            if (rptCmdCheck == 1)
            {
                cout << "syntax error near unexpected token '" << wrdPtr << "'" << endl;;
                return NULL;
            }
            else
            {
                rptCmdCheck++;
            }
        }
        else if (strcmp(wrdPtr, "(") == 0)
        {
            numOfLP++;
        }
        else if (strcmp(wrdPtr, ")") == 0)
        {
            numOfRP++;
        }
        else
        {
            int i = 0;
            while (wrdPtr[i] == ' ')
            {
                i++;
            }
            if (wrdPtr[i] != '\0')
            {
               rptCmdCheck = 0;
            }
        }
    }
    if (numOfRP != numOfLP)
    {
        cout << "Error: uneven number of parentheses" << endl;
        return NULL;
    }

    vector<char*> vPostfix = infixToPostfix(vInfix);

    stack<cmdBase*> cmdStack;

    for (int i = 0, n = vPostfix.size(); i < n; i++)
    {
        cmdBase* temp;

        if (strcmp(vPostfix.at(i), "&&") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdAnd(left, right);
        }

        else if (strcmp(vPostfix.at(i), "||") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdOr(left, right);
        }

        else if (strcmp(vPostfix.at(i), ";") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdSemi(left, right);
        }

        else
        {
            temp = new cmdExecutable(vPostfix.at(i));
        }

        cmdStack.push(temp);
    }

    return cmdStack.top();
}

vector<char*> infixToPostfix(list<char*> vInfix)
{
    stack<char*> cntrStack;
    vector<char*> vPostfix;

    char* wrdPtr;

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        wrdPtr = *it;

        if (strcmp(wrdPtr, "&&") == 0 || strcmp(wrdPtr, "||") == 0
            || strcmp(wrdPtr, ";") == 0 || strcmp(wrdPtr, "(") == 0
            || strcmp(wrdPtr, ")") == 0) {

            if (strcmp(wrdPtr, "(") == 0)
            {
                cntrStack.push(wrdPtr);
            }

            else if (strcmp(wrdPtr, ")") == 0)
            {
                while (strcmp(cntrStack.top(), "(") != 0)
                {
                    vPostfix.push_back(cntrStack.top());
                    cntrStack.pop();
                }

                cntrStack.pop();
            }

            else
            {
                while (!cntrStack.empty() && priority(wrdPtr)
                        <= priority(cntrStack.top()))
                {
                    if (strcmp(cntrStack.top(), "(") == 0)
                    {
                        break;
                    }

                    vPostfix.push_back(cntrStack.top());
                    cntrStack.pop();
                }

                cntrStack.push(wrdPtr);
            }
        }

        else
        {
            vPostfix.push_back(wrdPtr);
        }
    }

    while (!cntrStack.empty())
    {
        vPostfix.push_back(cntrStack.top());
        cntrStack.pop();
    }

    return vPostfix;
}

int priority(char* c)
{
    if (strcmp(c, "(") == 0)
    {
        return 3;
    }

    else if (strcmp(c, ";") == 0)
    {
        return 1;
    }

    return 2;
}
<commit_msg>Readded commenting parse<commit_after>#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <unistd.h>
#include "cmdAnd.h"
#include "cmdOr.h"
#include "cmdBase.h"
#include "cmdSemi.h"
#include "cmdExecutable.h"
#include <vector>
#include <stack>
#include <list>
#include <iterator>

using namespace std;

void printPrompt();
char* getInput();
cmdBase* parse(char* input);
vector<char*> infixToPostfix(list<char*> vInfix);
int priority(char*);

int main()
{
    while(true)
    {
        printPrompt();

        char* userInput = getInput();

        if ( userInput != NULL )
        {
            cmdBase* head = parse(userInput);

            if (head != NULL)
            {
                head->execute( );
            }

            //delete userInput;
            //delete head;
        }
    }
}

// prints the prompt for the user
// displays the user name and host name
void printPrompt()
{
    char *User;
    char host[30];

    User = getlogin( );
    gethostname( host, 30 );

    cout << User << "@" << host << "$ ";
}

//takes in user input and returns the char*
char* getInput()
{
    //takes in user input as string w/ getline
    string temp;

    getline(cin, temp);

    if ( temp.size( ) == 0 )
    {
        return NULL;
    }

    int i = 0;
    while (temp.at(i) == ' ')
    {
        i++;
    }
    if (temp.at(i) == ';' || temp.at(i) == '|' || temp.at(i) == '&')
    {
        cout << "syntax error found near unexpected token '"
            << temp.at(i) << "'" << endl;
        return NULL;
    }

    //creates char array and sets it equal to string
    char* input = new char[temp.size() + 1];

    for (int i = 0, n = temp.size(); i < n; i++)
    {
        input[i] = temp.at(i);
    }

    input[temp.size()] = '\0'; //adds NULL to end of char array

    return input;
}

//creates tree of command connectors by parsing the entered line
cmdBase* parse(char* input)
{
    if ( input[0] == '\0' || input[0] == '#' )
        return NULL;

    input = strtok(input, "#");

    list<char*> vInfix;
    char* cmdPtr;

    cmdPtr = strtok(input, ";");

    while (cmdPtr != NULL)
    {
        vInfix.push_back(cmdPtr);
        char* temp = new char[2];
        temp[0] = ';';
        temp[1] = '\0';
        vInfix.push_back(temp);
        cmdPtr = strtok(NULL, ";");
    }

    if (*vInfix.back() == ';')
    {
        vInfix.pop_back();
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        cmdPtr = strtok(*it, "&");
        char* cmdPtr2 = strtok(NULL, "");

        if (cmdPtr2 != NULL)
        {
           cmdPtr2 += 1;
           *it = cmdPtr;
           char* temp = new char[3];
           temp[0] = '&';
           temp[1] = '&';
           temp[2] = '\0';
           it++;
           if(it == vInfix.end())
           {
               it--;
               vInfix.push_back(temp);
               vInfix.push_back(cmdPtr2);
               it++;
           }

           else
           {
               vInfix.insert(it, temp);
               vInfix.insert(it, cmdPtr2);
           }
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        cmdPtr = strtok(*it, "|");
        char* cmdPtr2 = strtok(NULL, "");

        if (cmdPtr2 != NULL)
        {
           cmdPtr2 += 1;
           *it = cmdPtr;
           char* temp = new char[3];
           temp[0] = '|';
           temp[1] = '|';
           temp[2] = '\0';
           it++;

           if(it == vInfix.end())
           {
               it--;
               vInfix.push_back(temp);
               vInfix.push_back(cmdPtr2);
               it++;
           }

           else
           {
               vInfix.insert(it, temp);
               vInfix.insert(it, cmdPtr2);
           }
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* c = *it;
        int i = 0;

        while (c[i] == ' ')
        {
            i++;
        }

        if (c[i] == '(')
        {
           char* temp = new char[2];
           temp[0] = '(';
           temp[1] = '\0';
           vInfix.insert(it, temp);
           c[i] = '\0';
           c += i + 1;
           *it = c;
           it--;
        }
    }

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* c =  strpbrk(*it, ")");

        if (c != NULL)
        {
            c[0] = '\0';
            int i = 1;

            while (c[i] == ' ')
            {
                i++;
            }

            if (c[i] != '\0')
            {
                c += i;
                it++;

                if (it == vInfix.end())
                {
                    it--;
                    vInfix.push_back(c);
                    it++;
                }

                else
                {
                    vInfix.insert(it, c);
                }

                it--;
            }

            char* temp = new char[2];
            temp[0] = ')';
            temp[1] = '\0';
            it++;

            if (it == vInfix.end())
            {
                it--;
                vInfix.push_back(temp);
                it++;
            }

            else
            {
                vInfix.insert(it, temp);
            }
        }
    }

    int numOfLP = 0, numOfRP = 0, rptCmdCheck = 0;
    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        char* wrdPtr = *it;

        if (strcmp(wrdPtr, "&&") == 0 || strcmp(wrdPtr, "||") == 0
            || strcmp(wrdPtr, ";") == 0)
        {
            if (rptCmdCheck == 1)
            {
                cout << "syntax error near unexpected token '" << wrdPtr << "'" << endl;;
                return NULL;
            }
            else
            {
                rptCmdCheck++;
            }
        }
        else if (strcmp(wrdPtr, "(") == 0)
        {
            numOfLP++;
        }
        else if (strcmp(wrdPtr, ")") == 0)
        {
            numOfRP++;
        }
        else
        {
            int i = 0;
            while (wrdPtr[i] == ' ')
            {
                i++;
            }
            if (wrdPtr[i] != '\0')
            {
               rptCmdCheck = 0;
            }
        }
    }
    if (numOfRP != numOfLP)
    {
        cout << "Error: uneven number of parentheses" << endl;
        return NULL;
    }

    vector<char*> vPostfix = infixToPostfix(vInfix);

    stack<cmdBase*> cmdStack;

    for (int i = 0, n = vPostfix.size(); i < n; i++)
    {
        cmdBase* temp;

        if (strcmp(vPostfix.at(i), "&&") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdAnd(left, right);
        }

        else if (strcmp(vPostfix.at(i), "||") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdOr(left, right);
        }

        else if (strcmp(vPostfix.at(i), ";") == 0)
        {
            cmdBase* right = cmdStack.top();
            cmdStack.pop();
            cmdBase* left = cmdStack.top();
            cmdStack.pop();
            temp = new cmdSemi(left, right);
        }

        else
        {
            temp = new cmdExecutable(vPostfix.at(i));
        }

        cmdStack.push(temp);
    }

    return cmdStack.top();
}

vector<char*> infixToPostfix(list<char*> vInfix)
{
    stack<char*> cntrStack;
    vector<char*> vPostfix;

    char* wrdPtr;

    for (list<char*>::iterator it = vInfix.begin(); it != vInfix.end(); it++)
    {
        wrdPtr = *it;

        if (strcmp(wrdPtr, "&&") == 0 || strcmp(wrdPtr, "||") == 0
            || strcmp(wrdPtr, ";") == 0 || strcmp(wrdPtr, "(") == 0
            || strcmp(wrdPtr, ")") == 0) {

            if (strcmp(wrdPtr, "(") == 0)
            {
                cntrStack.push(wrdPtr);
            }

            else if (strcmp(wrdPtr, ")") == 0)
            {
                while (strcmp(cntrStack.top(), "(") != 0)
                {
                    vPostfix.push_back(cntrStack.top());
                    cntrStack.pop();
                }

                cntrStack.pop();
            }

            else
            {
                while (!cntrStack.empty() && priority(wrdPtr)
                        <= priority(cntrStack.top()))
                {
                    if (strcmp(cntrStack.top(), "(") == 0)
                    {
                        break;
                    }

                    vPostfix.push_back(cntrStack.top());
                    cntrStack.pop();
                }

                cntrStack.push(wrdPtr);
            }
        }

        else
        {
            vPostfix.push_back(wrdPtr);
        }
    }

    while (!cntrStack.empty())
    {
        vPostfix.push_back(cntrStack.top());
        cntrStack.pop();
    }

    return vPostfix;
}

int priority(char* c)
{
    if (strcmp(c, "(") == 0)
    {
        return 3;
    }

    else if (strcmp(c, ";") == 0)
    {
        return 1;
    }

    return 2;
}
<|endoftext|>


<commit_before>

#include <iostream>
#include "Machine.h"

enum states{

    OFF,
    ON

};
class AbstractLightState : public AbstractState {

protected:

    bool* _lightSwitchOnPtr;
    bool* _lightSwitchOffPtr;

public:

    AbstractLightState(Machine *context)  : AbstractState(context) {}

    //Trick to pass next state in the case we use static memory, you will see..
    AbstractLightState* _NextStateHolder;

    void attachSwitches(bool* onSig, bool* offsig){

        _lightSwitchOffPtr = offsig;
        _lightSwitchOnPtr = onSig;

    }

};

class LightOnState  : public AbstractLightState{

public:

    LightOnState(Machine *context) : AbstractLightState(context) {
        setId();
    }

    void setId() override {

        _id = states ::ON;

    }
    virtual void handle(){

        if(*_lightSwitchOnPtr){

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }else if (!*_lightSwitchOnPtr) {

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }

        if(*_lightSwitchOffPtr && _lightSwitchOnPtr){

            //You can handle strange behaviors here
            std::cout << "WARNING: both signals ON. This will couse an infinite switching between states in this case."<<std::endl;

        }

        //Real state changer
        if (*_lightSwitchOffPtr){

            //Next state is OFF
            _context->setStatePtr(_NextStateHolder);
            std::cout << "OFF" << std::endl;

        }

    }

};

class LightOffState : public AbstractLightState{
public:

    LightOffState(Machine *context) : AbstractLightState(context) {
        setId();
    }

    void setId() override {

        _id = states ::OFF;

    }
    virtual void handle(){

        if(*_lightSwitchOffPtr){

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }else if (!*_lightSwitchOffPtr) {

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }

        if(*_lightSwitchOffPtr && _lightSwitchOnPtr){

            //You can handle strange behaviors here
            std::cout << "WARNING: both signals ON. This will couse an infinite switching between states in this case."<<std::endl;

        }

        //Real state changer
        if (*_lightSwitchOnPtr){

            //Next state is OFF
            _context->setStatePtr(_NextStateHolder);

        }

    }

};

/*
 *
 * This is an Example!
 *
 * Let us simulate a light with two switches, namely switchOn and switchOff.
 * The state machine has two states (ON (id=1),OFF(id=0)) depending on the status of the switches.
 *
 * If the light is OFF, we need to set the switchOn to true and the state will change.
 * In the off state, the switchOff signal will not affect the state.
 *
 * If the light is ON, we need to set the switchOff to true and the state will change.
 * In the on state, the switchOn signal will not affect the state.
 *
 */

int main() {

    std::cout << "Hello, this is an example for the superFantasticMachine library!" << std::endl;

    //Create a Machine Object

    Machine context;
    Machine* contextPtr = &context;

    //Simulate two switces
    bool switchOn  = false;
    bool switchOff = true;

    //Create a bunch of nodes
    LightOnState  on (contextPtr);
    LightOffState off(contextPtr);

    //Initialize to off
    context.setStatePtr(&off);

    //Initialize states
    on.attachSwitches(&switchOn,&switchOff);
    off.attachSwitches(&switchOn,&switchOff);

    //Set Holders
    on._NextStateHolder  = &off;
    off._NextStateHolder = &on;

    char in;
    bool done = false;
    do {

        std::cout<<std::endl;
        std::cout << "***************************************"<<std::endl;
        std::cout << "ON BUTTON: " << switchOn << "; OFF BUTTON: " << switchOff<<std::endl;
        std::cout << "Press 'a' to switch the OFF button, 's' to switch the ON button or 'c' to continue"<<std::endl;
        std::cout << "Machine STATE is: "<<context.getActualNodeId() << std::endl;
        std::cout << "***************************************"<<std::endl;

        std::cin  >> in;

        switch (in) {

            case 'a':

                switchOff = !switchOff;

                break;

            case 's':

                switchOn = !switchOn;
                break;
            case 'q':
                done = true;
                break;
            default :

                std::cout << "Wrong command"<< std::endl;
                done = false;
                break;
        }

        context.handle();
    }while(!done);

    //Return the answer to life the universe and everything...
    std::cout << "Return the answer to life the universe and everything..."<< std::endl;
    return 42;

}<commit_msg>fix bugs<commit_after>

#include <iostream>
#include "Machine.h"

enum states{

    OFF,
    ON

};
class AbstractLightState : public AbstractState {

protected:

    bool* _lightSwitchOnPtr;
    bool* _lightSwitchOffPtr;

public:

    AbstractLightState(Machine *context)  : AbstractState(context) {}

    //Trick to pass next state in the case we use static memory, you will see..
    AbstractLightState* _NextStateHolder;

    void attachSwitches(bool* onSig, bool* offsig){

        _lightSwitchOffPtr = offsig;
        _lightSwitchOnPtr = onSig;

    }

};

class LightOnState  : public AbstractLightState{

public:

    LightOnState(Machine *context) : AbstractLightState(context) {
        setId();
    }

    void setId() override {

        _id = states ::ON;

    }
    virtual void handle(){

        if(*_lightSwitchOnPtr){

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }else if (!*_lightSwitchOnPtr) {

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }

        if(*_lightSwitchOffPtr && _lightSwitchOnPtr){

            //You can handle strange behaviors here
            std::cout << "WARNING: both signals ON. This will couse an infinite switching between states in this case."<<std::endl;

        }

        //Real state changer
        if (*_lightSwitchOffPtr){

            //Next state is OFF
            _context->setStatePtr(_NextStateHolder);
            std::cout << "OFF" << std::endl;

        }

    }

};

class LightOffState : public AbstractLightState{
public:

    LightOffState(Machine *context) : AbstractLightState(context) {
        setId();
    }

    void setId() override {

        _id = states ::OFF;

    }
    virtual void handle(){

        if(*_lightSwitchOffPtr){

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }else if (!*_lightSwitchOffPtr) {

            //Avoidable but for demonstration (we can manage multiple nextStates)
            //Stay in the same state if actual is ON and user pushes On button
            _context->setStatePtr(this);

        }

        if(*_lightSwitchOffPtr && _lightSwitchOnPtr){

            //You can handle strange behaviors here
            std::cout << "WARNING: both signals ON. This will cause an infinite switching between states."<<std::endl;

        }

        //Real state changer
        if (*_lightSwitchOnPtr){

            //Next state is OFF
            _context->setStatePtr(_NextStateHolder);

        }

    }

};

/*
 *
 * This is an Example!
 *
 * Let us simulate a light with two switches, namely switchOn and switchOff.
 * The state machine has two states (ON (id=1),OFF(id=0)) depending on the status of the switches.
 *
 * If the light is OFF, we need to set the switchOn to true and the state will change.
 * In the off state, the switchOff signal will not affect the state.
 *
 * If the light is ON, we need to set the switchOff to true and the state will change.
 * In the on state, the switchOn signal will not affect the state.
 *
 */

int main() {

    std::cout << "Hello, this is an example for the superFantasticMachine library!" << std::endl;

    //Create a Machine Object

    Machine context;
    Machine* contextPtr = &context;

    //Simulate two switces
    bool switchOn  = false;
    bool switchOff = true;

    //Create a bunch of nodes
    LightOnState  on (contextPtr);
    LightOffState off(contextPtr);

    //Initialize to off
    context.setStatePtr(&off);

    //Initialize states
    on.attachSwitches(&switchOn,&switchOff);
    off.attachSwitches(&switchOn,&switchOff);

    //Set Holders
    on._NextStateHolder  = &off;
    off._NextStateHolder = &on;

    char in;
    bool done = false;
    do {

        std::cout<<std::endl;
        std::cout << "***************************************"<<std::endl;
        std::cout << "ON BUTTON: " << switchOn << "; OFF BUTTON: " << switchOff<<std::endl;
        std::cout << "Press 'a' to switch the OFF button, 's' to switch the ON button or 'c' to continue"<<std::endl;
        std::cout << "Machine STATE is: "<<context.getActualNodeId() << std::endl;
        std::cout << "***************************************"<<std::endl;

        std::cin  >> in;

        switch (in) {

            case 'a':

                switchOff = !switchOff;

                break;

            case 's':

                switchOn = !switchOn;
                break;
            case 'q':
                done = true;
                break;
            case 'c':
                break;

            default :

                std::cout << "Wrong command"<< std::endl;
                done = false;
                break;
        }

        context.handle();
    }while(!done);

    //Return the answer to life the universe and everything...
    std::cout << "Return the answer to life the universe and everything..."<< std::endl;
    return 42;

}<|endoftext|>


<commit_before>#include <iostream>
#include <array>
#include <vector>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <ospray.h>
#include <ospcommon/vec.h>
#include <openvr.h>
#include "gl_core_3_3.h"
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"

static int WIN_WIDTH = 1280/2;
static int WIN_HEIGHT = 720/2;

// We only have final resolve textures for the eyes
// since we don't need MSAA render targets on the GPU like
// in the samples
struct EyeResolveFB {
	GLuint resolve_fb;
	GLuint resolve_texture;
};

int main(int argc, const char **argv) {
	if (argc < 2) {
		std::cerr << "You must specify a model to render\n";
		return 1;
	}
	const std::string model_file = argv[1];
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		std::cerr << "Failed to initialize SDL\n";
		return 1;
	}
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
#ifndef NDEBUG
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif

	SDL_Window *win = SDL_CreateWindow("OSPRay + Vive", SDL_WINDOWPOS_CENTERED,
			SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_OPENGL);
	if (!win){
		std::cout << "Failed to open SDL window: " << SDL_GetError() << "\n";
		return 1;
	}
	SDL_GLContext ctx = SDL_GL_CreateContext(win);
	if (!ctx){
		std::cout << "Failed to get OpenGL context: " << SDL_GetError() << "\n";
		return 1;
	}
	if (ogl_LoadFunctions() == ogl_LOAD_FAILED){
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to Load OpenGL Functions",
				"Could not load OpenGL functions for 3.3, OpenGL 3.3 or higher is required",
				NULL);
		SDL_GL_DeleteContext(ctx);
		SDL_DestroyWindow(win);
		SDL_Quit();
		return 1;
	}
	SDL_GL_SetSwapInterval(0);

	// Setup OpenVR system
	vr::EVRInitError vr_error;
	vr::IVRSystem *vr_system = vr::VR_Init(&vr_error, vr::VRApplication_Scene);
	if (vr_error != vr::VRInitError_None) {
		std::cout << "OpenVR Init error " << vr_error << "\n";
		return 1;
	}
	if (!vr_system->IsTrackedDeviceConnected(vr::k_unTrackedDeviceIndex_Hmd)) {
		std::cout << "OpenVR HMD not tracking! Check connection and restart\n";
		return 1;
	}
	if (!vr::VRCompositor()) {
		std::cout << "OpenVR Failed to initialize compositor\n";
		return 1;
	}
	std::array<uint32_t, 2> vr_render_dims;
	vr_system->GetRecommendedRenderTargetSize(&vr_render_dims[0], &vr_render_dims[1]);
	std::cout << "OpenVR recommended render target resolution = " << vr_render_dims[0]
		<< "x" << vr_render_dims[1] << "\n";

	GLuint fbo, texture;
	glGenFramebuffers(1, &fbo);
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, vr_render_dims[0] * 2, vr_render_dims[1], 0, GL_RGBA,
			GL_UNSIGNED_BYTE, nullptr);

	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	// Setup resolve targets for the eyes
	std::array<EyeResolveFB, 2> eye_targets;
	for (size_t i = 0; i < eye_targets.size(); ++i) {
		glGenFramebuffers(1, &eye_targets[i].resolve_fb);
		glGenTextures(1, &eye_targets[i].resolve_texture);
		glBindTexture(GL_TEXTURE_2D, eye_targets[i].resolve_texture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, vr_render_dims[0], vr_render_dims[1], 0, GL_RGBA,
				GL_UNSIGNED_BYTE, nullptr);

		glBindFramebuffer(GL_FRAMEBUFFER, eye_targets[i].resolve_fb);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
				eye_targets[i].resolve_texture, 0);
	}
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	ospInit(&argc, argv);

	using namespace ospcommon;
	// We render both left/right eye to the same framebuffer so we need it to be
	// 2x the width
	const vec2i imageSize(vr_render_dims[0] * 2, vr_render_dims[1]);
	const vec3f camPos(0, 50, 240);
	const vec3f camDir = vec3f(0, 40, 0) - camPos;
	const vec3f camUp(0, 1, 0);

	OSPCamera camera = ospNewCamera("perspective");
	ospSetf(camera, "aspect", imageSize.x / static_cast<float>(imageSize.y));
	ospSet1i(camera, "stereoMode", 3);
	// TODO: Get this from OpenVR note that ospray's units are in meters
	ospSet1f(camera, "interpupillaryDistance", 0.0635);
	ospSetVec3f(camera, "pos", (osp::vec3f&)camPos);
	ospSetVec3f(camera, "dir", (osp::vec3f&)camDir);
	ospSetVec3f(camera, "up",  (osp::vec3f&)camUp);
	ospCommit(camera);

	// Load the model w/ tinyobjloader
	tinyobj::attrib_t attrib;
	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> materials;
	std::string err;
	bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, model_file.c_str(),
			nullptr, true);
	if (!err.empty()) {
		std::cerr << "Error loading model: " << err << "\n";
	}
	if (!ret) {
		return 1;
	}

	OSPModel world = ospNewModel();

	// Load all the objects into ospray
	OSPData pos_data = ospNewData(attrib.vertices.size() / 3, OSP_FLOAT3,
			attrib.vertices.data(), OSP_DATA_SHARED_BUFFER);
	ospCommit(pos_data);

	for (size_t s = 0; s < shapes.size(); ++s) {
		std::cout << "Loading mesh " << shapes[s].name
			<< ", has " << shapes[s].mesh.indices.size() << " vertices\n";
		const tinyobj::mesh_t &mesh = shapes[s].mesh;
		std::vector<int32_t> indices;
		indices.reserve(mesh.indices.size());
		for (const auto &idx : mesh.indices) {
			indices.push_back(idx.vertex_index);
		}
		OSPData idx_data = ospNewData(indices.size() / 3, OSP_INT3, indices.data());
		ospCommit(idx_data);
		OSPGeometry geom = ospNewGeometry("triangles");
		ospSetObject(geom, "vertex", pos_data);
		ospSetObject(geom, "index", idx_data);
		ospCommit(geom);
		ospAddGeometry(world, geom);
	}
	ospCommit(world);

	OSPRenderer renderer = ospNewRenderer("ao");
	ospSetObject(renderer, "model", world);
	ospSetObject(renderer, "camera", camera);
	ospSetVec3f(renderer, "bgColor", (osp::vec3f&)vec3f(0.05, 0.05, 0.05));
	ospCommit(renderer);

	OSPFrameBuffer framebuffer = ospNewFrameBuffer((osp::vec2i&)imageSize, OSP_FB_SRGBA,
			OSP_FB_COLOR | OSP_FB_ACCUM);
	ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);

	std::array<vr::TrackedDevicePose_t, vr::k_unMaxTrackedDeviceCount> tracked_device_poses;
	bool quit = false;
	uint32_t prev_time = SDL_GetTicks();
	const std::string win_title = "OSPRay + Vive - frame time ";
	while (!quit) {
		vr::VRCompositor()->WaitGetPoses(tracked_device_poses.data(), tracked_device_poses.size(), NULL, 0);
		// TODO: update camera based on HMD position

		const uint32_t cur_time = SDL_GetTicks();
		const float elapsed = (cur_time - prev_time) / 1000.f;
		prev_time = cur_time;
		SDL_Event e;
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)){
				quit = true;
				break;
			}
		}
		ospFrameBufferClear(framebuffer, OSP_FB_COLOR);
		ospRenderFrame(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);
		const uint32_t *fb = static_cast<const uint32_t*>(ospMapFrameBuffer(framebuffer, OSP_FB_COLOR));
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, vr_render_dims[0] * 2, vr_render_dims[1],
				GL_RGBA, GL_UNSIGNED_BYTE, fb);
		ospUnmapFrameBuffer(fb, framebuffer);

		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);

		// Blit the left/right eye halves of the ospray framebuffer to the left/right resolve targets
		// and submit them
		for (size_t i = 0; i < eye_targets.size(); ++i) {
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, eye_targets[i].resolve_fb);
			glBlitFramebuffer(vr_render_dims[0] * i, 0, vr_render_dims[0] * i + vr_render_dims[0], vr_render_dims[1],
					0, 0, vr_render_dims[0], vr_render_dims[1], GL_COLOR_BUFFER_BIT, GL_NEAREST);
		}
		vr::Texture_t left_eye = {};
		left_eye.handle = reinterpret_cast<void*>(eye_targets[0].resolve_texture);
		left_eye.eType = vr::TextureType_OpenGL;
		left_eye.eColorSpace = vr::ColorSpace_Gamma;

		vr::Texture_t right_eye = {};
		right_eye.handle = reinterpret_cast<void*>(eye_targets[1].resolve_texture);
		right_eye.eType = vr::TextureType_OpenGL;
		right_eye.eColorSpace = vr::ColorSpace_Gamma;

		vr::VRCompositor()->Submit(vr::Eye_Left, &left_eye);
		vr::VRCompositor()->Submit(vr::Eye_Right, &right_eye);

		// Blit the app window display
#if 0
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
		glBlitFramebuffer(0, 0, vr_render_dims[0] * 2, vr_render_dims[1], 0, 0, WIN_WIDTH, WIN_HEIGHT,
				GL_COLOR_BUFFER_BIT, GL_NEAREST);
#endif
		SDL_GL_SwapWindow(win);

#if 1
		const std::string title = win_title + std::to_string(elapsed) + "ms";
		SDL_SetWindowTitle(win, title.c_str());
#endif
	}

	vr::VR_Shutdown();
	SDL_GL_DeleteContext(ctx);
	SDL_DestroyWindow(win);
	SDL_Quit();
	return 0;
}

<commit_msg>Debugging incorrect stereo<commit_after>#include <iostream>
#include <array>
#include <vector>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <ospray.h>
#include <ospcommon/vec.h>
#include <openvr.h>
#include "gl_core_3_3.h"
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"

static int WIN_WIDTH = 1280/2;
static int WIN_HEIGHT = 720/2;

// We only have final resolve textures for the eyes
// since we don't need MSAA render targets on the GPU like
// in the samples
struct EyeResolveFB {
	GLuint resolve_fb;
	GLuint resolve_texture;
};

int main(int argc, const char **argv) {
	if (argc < 2) {
		std::cerr << "You must specify a model to render\n";
		return 1;
	}
	const std::string model_file = argv[1];
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		std::cerr << "Failed to initialize SDL\n";
		return 1;
	}
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
#ifndef NDEBUG
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif

	SDL_Window *win = SDL_CreateWindow("OSPRay + Vive", SDL_WINDOWPOS_CENTERED,
			SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_OPENGL);
	if (!win){
		std::cout << "Failed to open SDL window: " << SDL_GetError() << "\n";
		return 1;
	}
	SDL_GLContext ctx = SDL_GL_CreateContext(win);
	if (!ctx){
		std::cout << "Failed to get OpenGL context: " << SDL_GetError() << "\n";
		return 1;
	}
	if (ogl_LoadFunctions() == ogl_LOAD_FAILED){
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Failed to Load OpenGL Functions",
				"Could not load OpenGL functions for 3.3, OpenGL 3.3 or higher is required",
				NULL);
		SDL_GL_DeleteContext(ctx);
		SDL_DestroyWindow(win);
		SDL_Quit();
		return 1;
	}
	SDL_GL_SetSwapInterval(0);

	// Setup OpenVR system
	vr::EVRInitError vr_error;
	vr::IVRSystem *vr_system = vr::VR_Init(&vr_error, vr::VRApplication_Scene);
	if (vr_error != vr::VRInitError_None) {
		std::cout << "OpenVR Init error " << vr_error << "\n";
		return 1;
	}
	if (!vr_system->IsTrackedDeviceConnected(vr::k_unTrackedDeviceIndex_Hmd)) {
		std::cout << "OpenVR HMD not tracking! Check connection and restart\n";
		return 1;
	}
	if (!vr::VRCompositor()) {
		std::cout << "OpenVR Failed to initialize compositor\n";
		return 1;
	}
	std::array<uint32_t, 2> vr_render_dims;
	vr_system->GetRecommendedRenderTargetSize(&vr_render_dims[0], &vr_render_dims[1]);
	std::cout << "OpenVR recommended render target resolution = " << vr_render_dims[0]
		<< "x" << vr_render_dims[1] << "\n";

	GLuint fbo, texture;
	glGenFramebuffers(1, &fbo);
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, vr_render_dims[0] * 2, vr_render_dims[1], 0, GL_RGBA,
			GL_UNSIGNED_BYTE, nullptr);

	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	// Setup resolve targets for the eyes
	std::array<EyeResolveFB, 2> eye_targets;
	for (size_t i = 0; i < eye_targets.size(); ++i) {
		glGenFramebuffers(1, &eye_targets[i].resolve_fb);
		glGenTextures(1, &eye_targets[i].resolve_texture);
		glBindTexture(GL_TEXTURE_2D, eye_targets[i].resolve_texture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, vr_render_dims[0], vr_render_dims[1], 0, GL_RGBA,
				GL_UNSIGNED_BYTE, nullptr);

		glBindFramebuffer(GL_FRAMEBUFFER, eye_targets[i].resolve_fb);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
				eye_targets[i].resolve_texture, 0);
	}
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	ospInit(&argc, argv);

	using namespace ospcommon;
	// We render both left/right eye to the same framebuffer so we need it to be
	// 2x the width
	const vec2i image_size(vr_render_dims[0], vr_render_dims[1]);
	const vec3f cam_pos(0, 50, 280);
	const vec3f cam_target = vec3f(0, 40, 0);
	const vec3f cam_up(0, 1, 0);

	// TODO BUG: OSPRay's side-by-side camera can't do proper stereo because it
	// uses the same look direction for both eyes
	std::array<OSPCamera, 2> cameras;
	for (size_t i = 0; i < cameras.size(); ++i) {
		auto eye_mat = vr_system->GetEyeToHeadTransform(i == 0 ? vr::Eye_Left : vr::Eye_Right);
		std::cout << "[\n";
		for (size_t r = 0; r < 3; ++r) {
			for (size_t c = 0; c < 4; ++c) {
				std::cout << eye_mat.m[r][c] << "  ";
			}
			std::cout << "\n";
		}
		std::cout << "]\n";
		cameras[i] = ospNewCamera("perspective");
		ospSetf(cameras[i], "aspect", image_size.x / static_cast<float>(image_size.y));
		// TODO: How to query the HMD IPD?
		//ospSet1i(cameras[i], "stereoMode", 0);
		//ospSet1f(camera, "interpupillaryDistance", 0.0635);
		vec3f eye_pos = cam_pos;
		if (i == 0) {
			eye_pos = eye_pos - vec3f(0.0318, 0, 0);
		} else {
			eye_pos = eye_pos + vec3f(0.0318, 0, 0);
		}
		vec3f eye_dir = cam_target - eye_pos;
		ospSetVec3f(cameras[i], "pos", (osp::vec3f&)eye_pos);
		ospSetVec3f(cameras[i], "dir", (osp::vec3f&)eye_dir);
		ospSetVec3f(cameras[i], "up",  (osp::vec3f&)cam_up);
		ospCommit(cameras[i]);
	}

	// Load the model w/ tinyobjloader
	tinyobj::attrib_t attrib;
	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> materials;
	std::string err;
	bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, model_file.c_str(),
			nullptr, true);
	if (!err.empty()) {
		std::cerr << "Error loading model: " << err << "\n";
	}
	if (!ret) {
		return 1;
	}

	OSPModel world = ospNewModel();

	// Load all the objects into ospray
	OSPData pos_data = ospNewData(attrib.vertices.size() / 3, OSP_FLOAT3,
			attrib.vertices.data(), OSP_DATA_SHARED_BUFFER);
	ospCommit(pos_data);

	for (size_t s = 0; s < shapes.size(); ++s) {
		std::cout << "Loading mesh " << shapes[s].name
			<< ", has " << shapes[s].mesh.indices.size() << " vertices\n";
		const tinyobj::mesh_t &mesh = shapes[s].mesh;
		std::vector<int32_t> indices;
		indices.reserve(mesh.indices.size());
		for (const auto &idx : mesh.indices) {
			indices.push_back(idx.vertex_index);
		}
		OSPData idx_data = ospNewData(indices.size() / 3, OSP_INT3, indices.data());
		ospCommit(idx_data);
		OSPGeometry geom = ospNewGeometry("triangles");
		ospSetObject(geom, "vertex", pos_data);
		ospSetObject(geom, "index", idx_data);
		ospCommit(geom);
		ospAddGeometry(world, geom);
	}
	ospCommit(world);

	OSPRenderer renderer = ospNewRenderer("ao");
	ospSetObject(renderer, "model", world);
	ospSetObject(renderer, "camera", cameras[0]);
	ospSetVec3f(renderer, "bgColor", (osp::vec3f&)vec3f(0.05));
	ospCommit(renderer);

	std::array<OSPFrameBuffer, 2> framebuffers;
	for (size_t i = 0; i < framebuffers.size(); ++i) {
		framebuffers[i] = ospNewFrameBuffer((osp::vec2i&)image_size, OSP_FB_SRGBA,
				OSP_FB_COLOR | OSP_FB_ACCUM);
		ospFrameBufferClear(framebuffers[i], OSP_FB_COLOR | OSP_FB_ACCUM);
	}

	std::array<vr::TrackedDevicePose_t, vr::k_unMaxTrackedDeviceCount> tracked_device_poses;
	bool quit = false;
	uint32_t prev_time = SDL_GetTicks();
	const std::string win_title = "OSPRay + Vive - frame time ";
	while (!quit) {
		vr::VRCompositor()->WaitGetPoses(tracked_device_poses.data(), tracked_device_poses.size(), NULL, 0);
		// TODO: update camera based on HMD position

		const uint32_t cur_time = SDL_GetTicks();
		const float elapsed = (cur_time - prev_time) / 1000.f;
		prev_time = cur_time;
		SDL_Event e;
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)){
				quit = true;
				break;
			}
		}

		// Render each eye and upload them
		for (size_t i = 0; i < framebuffers.size(); ++i) {
			ospSetObject(renderer, "camera", cameras[i]);
			// Debugging test
#if 1
			if (i == 0) {
				ospSetVec3f(renderer, "bgColor", (osp::vec3f&)vec3f(0.1, 0, 0));
			} else {
				ospSetVec3f(renderer, "bgColor", (osp::vec3f&)vec3f(0, 0, 0.1));
			}
#endif

			ospCommit(renderer);
			ospFrameBufferClear(framebuffers[i], OSP_FB_COLOR);
			ospRenderFrame(framebuffers[i], renderer, OSP_FB_COLOR | OSP_FB_ACCUM);
			const uint32_t *fb = static_cast<const uint32_t*>(ospMapFrameBuffer(framebuffers[i], OSP_FB_COLOR));
			glBindTexture(GL_TEXTURE_2D, texture);
			glTexSubImage2D(GL_TEXTURE_2D, 0, vr_render_dims[0] * i, 0, vr_render_dims[0], vr_render_dims[1],
					GL_RGBA, GL_UNSIGNED_BYTE, fb);
			ospUnmapFrameBuffer(fb, framebuffers[i]);
		}
		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);

		// Blit the left/right eye halves of the ospray framebuffer to the left/right resolve targets
		// and submit them
		for (size_t i = 0; i < eye_targets.size(); ++i) {
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, eye_targets[i].resolve_fb);
			glBlitFramebuffer(vr_render_dims[0] * i, 0, vr_render_dims[0] * i + vr_render_dims[0], vr_render_dims[1],
					0, 0, vr_render_dims[0], vr_render_dims[1], GL_COLOR_BUFFER_BIT, GL_NEAREST);
		}
		vr::Texture_t left_eye = {};
		left_eye.handle = reinterpret_cast<void*>(eye_targets[0].resolve_texture);
		left_eye.eType = vr::TextureType_OpenGL;
		left_eye.eColorSpace = vr::ColorSpace_Gamma;

		vr::Texture_t right_eye = {};
		right_eye.handle = reinterpret_cast<void*>(eye_targets[1].resolve_texture);
		right_eye.eType = vr::TextureType_OpenGL;
		right_eye.eColorSpace = vr::ColorSpace_Gamma;

		vr::VRCompositor()->Submit(vr::Eye_Left, &left_eye);
		vr::VRCompositor()->Submit(vr::Eye_Right, &right_eye);

		// Blit the app window display
#if 1
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
		glBlitFramebuffer(0, 0, vr_render_dims[0] * 2, vr_render_dims[1], 0, 0, WIN_WIDTH, WIN_HEIGHT,
				GL_COLOR_BUFFER_BIT, GL_NEAREST);
#endif
		SDL_GL_SwapWindow(win);

#if 1
		const std::string title = win_title + std::to_string(elapsed) + "ms";
		SDL_SetWindowTitle(win, title.c_str());
#endif
	}

	vr::VR_Shutdown();
	SDL_GL_DeleteContext(ctx);
	SDL_DestroyWindow(win);
	SDL_Quit();
	return 0;
}

<|endoftext|>


<commit_before>#include "model.hxx"
#include "3DView.hxx"
#include "GameUpdater.hxx"
#include "Cam.hxx"
#include "Hand.hxx"
#include "HistogramHand.hxx"
#include "NetGame.hxx"
#include "NetCam.hxx"
#include "HandToModel.hxx"

static const int redBalls = 3;
static const int yellowBalls = 12;

volatile bool running;

void camLoop(Cam_ c, NetCam_ nc, Hand_ h, HandToModel_ htm) {
    do {
        c->grabImage();
        nc->push(c->jpeg());
        h->update(c->frame());
        htm->update(h);
    } while (running);
}

int main(int argc, char * argv[]) {
    try {
        if (argc < 2) {
            std::cout << "Usage: " << argv[0] << " <cam id> [server]" << std::endl;
            return -1;
        }

        NetGame_ ng;
        NetCam_ nc;
        int ballof;
        if (argc < 3) {
            ng.reset(new NetGame());
            nc.reset(new NetCam());
            ballof = 0;
        } else {
            ng.reset(new NetGame(argv[2]));
            nc.reset(new NetCam(argv[2]));
            ballof = 0xffff;
        }

        Cam_ c = Cam::create(atoi(argv[1]));
        Hand_ hh(new HistogramHand(0.2, 0.1));

        hh->calibrate(c);

        Tube tube;
        tube.halfSize = cv::Size2f(1.6, 1.2);
        tube.goal = 3;
        tube.separator = 13;
        tube.opponentGoal = 23;
        tube.handMovement = 5;
        tube.handMax = 8;
        tube.spawnArea = 4;

        ThreeDView view(cv::Size(1366, 768), tube);
        HandToModel_ htm = HandToModel::create(tube);

        GameState gs;
        gs.own_lives = 12;
        gs.opponent_lives = 12;

        GameUpdater game(tube);

        Balls balls;
        Ball b;
        b.owner = ballOwnerLocal;
        b.type = 0;
        for (int i = 0; i < yellowBalls; ++i) {
            game.randomizeBall(b);
            balls[ballof + i] = b;
        }
        b.type = 1;
        for (int i = 0; i < redBalls; ++i) {
            game.randomizeBall(b);
            balls[ballof + yellowBalls + i] = b;
        }

        running = true;

        boost::thread camThread(boost::bind(&camLoop, c, nc, hh, htm));

        do {
            ng->sync(balls, gs, tube);
            nc->grabImage();

            glfwSetTime(0.0);
            view.render(balls, htm, gs, nc->frame(), c->frame());
            glfwSwapBuffers();
            glfwSleep(0.01);
            game.tick(glfwGetTime(), balls, gs, htm);
            running = !glfwGetKey(GLFW_KEY_ESC) && (gs.own_lives > 0) && (gs.opponent_lives > 0);
        } while (running);

        int ret;
        if (gs.opponent_lives <= 0) {
            if (gs.own_lives <= 0) {
                std::cout << "\n\aTIE! Play another round?\n";
                ret = 2;
            } else {
                std::cout << "\n\aOU WON! Congratulations.\n";
                ret = 0;
            }
        } else if (gs.own_lives <= 0) {
            std::cout << "\n\aGAME OVER! Better luck next time.\n";
            ret = 3;
        } else {
            std::cout << "\n\aGame terminated before conclusion.\n";
            ret = 1;
        }
        std::cout << gs.own_ratio * 100 << "% of the balls were still in your court." << std::endl;

        camThread.join();
        return ret;
    } catch (const std::string& str) {
        std::cerr << "exception: " << str << std::endl;
        return -1;
    }
}
<commit_msg>Sync oups<commit_after>#include "model.hxx"
#include "3DView.hxx"
#include "GameUpdater.hxx"
#include "Cam.hxx"
#include "Hand.hxx"
#include "HistogramHand.hxx"
#include "NetGame.hxx"
#include "NetCam.hxx"
#include "HandToModel.hxx"

static const int redBalls = 3;
static const int yellowBalls = 12;

volatile bool running;

void camLoop(Cam_ c, NetCam_ nc, Hand_ h, HandToModel_ htm) {
    do {
        c->grabImage();
        nc->push(c->jpeg());
        h->update(c->frame());
        htm->update(h);
    } while (running);
}

int main(int argc, char * argv[]) {
    try {
        if (argc < 2) {
            std::cout << "Usage: " << argv[0] << " <cam id> [server]" << std::endl;
            return -1;
        }

        NetGame_ ng;
        NetCam_ nc;
        int ballof;
        if (argc < 3) {
            ng.reset(new NetGame());
            nc.reset(new NetCam());
            ballof = 0;
        } else {
            ng.reset(new NetGame(argv[2]));
            nc.reset(new NetCam(argv[2]));
            ballof = 0xffff;
        }

        Cam_ c = Cam::create(atoi(argv[1]));
        Hand_ hh(new HistogramHand(0.2, 0.1));

        hh->calibrate(c);

        Tube tube;
        tube.halfSize = cv::Size2f(1.6, 1.2);
        tube.goal = 3;
        tube.separator = 13;
        tube.opponentGoal = 23;
        tube.handMovement = 5;
        tube.handMax = 8;
        tube.spawnArea = 4;

        ThreeDView view(cv::Size(1366, 768), tube);
        HandToModel_ htm = HandToModel::create(tube);

        GameState gs;
        gs.own_lives = 12;
        gs.opponent_lives = 12;

        GameUpdater game(tube);

        Balls balls;
        Ball b;
        b.owner = ballOwnerLocal;
        b.type = 0;
        for (int i = 0; i < yellowBalls; ++i) {
            game.randomizeBall(b);
            balls[ballof + i] = b;
        }
        b.type = 1;
        for (int i = 0; i < redBalls; ++i) {
            game.randomizeBall(b);
            balls[ballof + yellowBalls + i] = b;
        }

        running = true;

        boost::thread camThread(boost::bind(&camLoop, c, nc, hh, htm));

        do {
            glfwSetTime(0.0);
            view.render(balls, htm, gs, nc->frame(), c->frame());
            glfwSwapBuffers();
            glfwSleep(0.01);
            game.tick(glfwGetTime(), balls, gs, htm);
            ng->sync(balls, gs, tube);
            nc->grabImage();
            running = !glfwGetKey(GLFW_KEY_ESC) && (gs.own_lives > 0) && (gs.opponent_lives > 0);
        } while (running);

        int ret;
        if (gs.opponent_lives <= 0) {
            if (gs.own_lives <= 0) {
                std::cout << "\n\aTIE! Play another round?\n";
                ret = 2;
            } else {
                std::cout << "\n\aOU WON! Congratulations.\n";
                ret = 0;
            }
        } else if (gs.own_lives <= 0) {
            std::cout << "\n\aGAME OVER! Better luck next time.\n";
            ret = 3;
        } else {
            std::cout << "\n\aGame terminated before conclusion.\n";
            ret = 1;
        }
        std::cout << gs.own_ratio * 100 << "% of the balls were still in your court." << std::endl;

        camThread.join();
        return ret;
    } catch (const std::string& str) {
        std::cerr << "exception: " << str << std::endl;
        return -1;
    }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include "PO8e.h"

#define SRATE_HZ	(24414.0625)
#define SRATE_KHZ	(24.4140625)
#define NCHAN		96

bool			g_die = false;
long double g_startTime = 0.0;
long double gettime()  //in seconds!
{
	timespec pt ;
	clock_gettime(CLOCK_MONOTONIC, &pt);
	long double ret = (long double)(pt.tv_sec) ;
	ret += (long double)(pt.tv_nsec) / 1e9 ;
	return ret - g_startTime;
}

// service the po8e buffer
// 96 channels of spike/lfp, followed by time (ticks) split across two chans
// if there is no po8e card, simulate data with sines

void *po8_thread(void *)
{
	PO8e *card = NULL;
	bool simulate = false;
	int bufmax = 10000;	// must be >= 10000

	while (!g_die) {
		int totalcards = PO8e::cardCount();
		int conn_cards = 0;
		printf("Found %d PO8e card(s) in the system.\n", totalcards);
		if (totalcards < 1) {
			printf("  simulating instead.\n");
			simulate = true;
		}
		if (!simulate) {
			printf("Connecting to card 0\n");
			card = PO8e::connectToCard(0);
			if (card == NULL)
				printf("  connection failed to card0 \n");
			else {
				// todo: connect to multiple cards
				printf("  connection established to card0 at %p\n", (void *)card);
				if (!card->startCollecting()) {
					printf("  startCollecting() failed with: %d\n",
					       card->getLastError());
					card->stopCollecting();
					printf("  releasing card0\n");
					PO8e::releaseCard(card);
					card = NULL;
				} else {
					printf("  card is collecting incoming data.\n");
					conn_cards++;
					printf("Waiting for the stream to start on card0 ... ");
					card->waitForDataReady(); // waits ~ 1200 hours ;-)
					printf("started\n");
				}
			}
		}
		// start the timer used to compute the speed and set the collected bytes to 0
		long double starttime = gettime();
		long double totalSamples = 0.0; //for simulation.
		double		sinSamples = 0.0; // for driving the sinusoids; resets every 4e4.
		long long bytes = 0;
		unsigned int frame = 0;
		unsigned int nchan = NCHAN;
		unsigned int bps = 2; //bytes/sample
		if (!simulate) {
			nchan = card->numChannels();
			bps = card->dataSampleSize();
			printf("  %d channels @ %d bytes/sample\n", nchan, bps);
		}
		short *temp = new short[bufmax*(nchan+2)];  // 10000 samples * 2 bytes/sample * (nChannels+time)
		short *temptemp = new short[bufmax];
		while ((simulate || conn_cards > 0) && !g_die) {
			if (!card->waitForDataReady()) { // waits ~ 1200 hours ;-)
				// this occurs when the rpvdsex circuit is idled.
				// and potentially when a glitch happens
				printf("  waitForDataReady() failed with: %d\n",
				       card->getLastError());
				card->stopCollecting();
				conn_cards--;
				printf("  releasing card0\n");
				PO8e::releaseCard(card);
				card = NULL;
				break;
			}
			bool stopped = false;
			int numSamples = 0;
			if (!simulate) {
				numSamples = (int)card->samplesReady(&stopped);
				if (stopped) {
					printf("  stopped collecting data\n");
					card->stopCollecting();
					conn_cards--;
					printf("  releasing card0\n");
					PO8e::releaseCard(card);
					card = NULL;
					break;
				}
				if (numSamples > 0) {
					if (numSamples > bufmax) {
						printf("samplesReady() returned too many samples for buffer (buffer wrap?): %d\n",
						       numSamples);
						numSamples = bufmax;
					}
					card->readBlock(temp, numSamples);
					card->flushBufferedData(numSamples);
					totalSamples += numSamples;
				}
			} else { //simulate!
				long double now = gettime();
				numSamples = (int)((now - starttime)*SRATE_HZ - totalSamples);
				if (numSamples >= 250) {
					numSamples = 250;
					totalSamples = (now - starttime)*SRATE_HZ;
				}
				float scale = sin(sinSamples/4e4);
				for (int i=0; i<numSamples; i++) {
					temptemp[i] =  (short)(sinf((float)
					                            ((sinSamples + i)/6.0))*32768.f*scale);
				}
				for (int k=0; k<96; k++) {
					for (int i=0; i<numSamples; i++) {
						temp[k*numSamples +i] = temptemp[i];
					}
				}
				//last part of the buffer is just TDT ticks (most recent -> least delay?)
				for (int i=0; i<numSamples; i++) {
					int r = (int)(sinSamples +i);
					temp[NCHAN*numSamples     +i] = r       & 0xffff;
					temp[(NCHAN+1)*numSamples +i] = (r>>16) & 0xffff;
				}
				totalSamples += numSamples;
				sinSamples += numSamples;
				if (sinSamples > 4e4*2*3.1415926) sinSamples -= 4e4*2*3.1415926;
				usleep(70);
			}
			printf("frame: %d\t", frame);
			if (numSamples > 0 && numSamples <= bufmax) {
				bytes += numSamples * nchan * bps;
				if (frame %200 == 0) { //need to move this to the UI.
					int ticks = (unsigned short)(temp[NCHAN*numSamples + numSamples -1]);
					ticks += (unsigned short)(temp[(NCHAN+1)*numSamples + numSamples -1]) << 16;
					fprintf(stderr, "%d samples at %d Bps of %d chan: %Lf MB/sec | %d ticks\n",
					        numSamples,
					        bps,
					        nchan,
					        ((long double)bytes) / ((gettime() - starttime)*(1024.0*1024.0)),
					        ticks
					       );
				}
			}
			frame++;
		}
		//delete buffers since we have dynamically allocated;
		delete[] temp;
		delete[] temptemp;
		printf("\n");
		sleep(1);
	}
	return 0;
}

int main(void)
{
	printf("press enter to quit.\n");
	usleep(4e5);
	pthread_t thread1;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_create( &thread1, &attr, po8_thread, 0 );
	getchar(); // wait for enter
	g_die = true;
	usleep(4e5);
}
<commit_msg>comment<commit_after>#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include "PO8e.h"

#define SRATE_HZ	(24414.0625)
#define SRATE_KHZ	(24.4140625)
//#define SRATE_HZ	(48828.1250)
//#define SRATE_KHZ	(48.8281250)
#define NCHAN		96

bool			g_die = false;
long double g_startTime = 0.0;
long double gettime()  //in seconds!
{
	timespec pt ;
	clock_gettime(CLOCK_MONOTONIC, &pt);
	long double ret = (long double)(pt.tv_sec) ;
	ret += (long double)(pt.tv_nsec) / 1e9 ;
	return ret - g_startTime;
}

// service the po8e buffer
// 96 channels of spike/lfp, followed by time (ticks) split across two chans
// if there is no po8e card, simulate data with sines

void *po8_thread(void *)
{
	PO8e *card = NULL;
	bool simulate = false;
	int bufmax = 10000;	// must be >= 10000

	while (!g_die) {
		int totalcards = PO8e::cardCount();
		int conn_cards = 0;
		printf("Found %d PO8e card(s) in the system.\n", totalcards);
		if (totalcards < 1) {
			printf("  simulating instead.\n");
			simulate = true;
		}
		if (!simulate) {
			printf("Connecting to card 0\n");
			card = PO8e::connectToCard(0);
			if (card == NULL)
				printf("  connection failed to card0 \n");
			else {
				// todo: connect to multiple cards
				printf("  connection established to card0 at %p\n", (void *)card);
				if (!card->startCollecting()) {
					printf("  startCollecting() failed with: %d\n",
					       card->getLastError());
					card->stopCollecting();
					printf("  releasing card0\n");
					PO8e::releaseCard(card);
					card = NULL;
				} else {
					printf("  card is collecting incoming data.\n");
					conn_cards++;
					printf("Waiting for the stream to start on card0 ... ");
					card->waitForDataReady(); // waits ~ 1200 hours ;-)
					printf("started\n");
				}
			}
		}
		// start the timer used to compute the speed and set the collected bytes to 0
		long double starttime = gettime();
		long double totalSamples = 0.0; //for simulation.
		double		sinSamples = 0.0; // for driving the sinusoids; resets every 4e4.
		long long bytes = 0;
		unsigned int frame = 0;
		unsigned int nchan = NCHAN;
		unsigned int bps = 2; //bytes/sample
		if (!simulate) {
			nchan = card->numChannels();
			bps = card->dataSampleSize();
			printf("  %d channels @ %d bytes/sample\n", nchan, bps);
		}
		short *temp = new short[bufmax*(nchan+2)];  // 10000 samples * 2 bytes/sample * (nChannels+time)
		short *temptemp = new short[bufmax];
		while ((simulate || conn_cards > 0) && !g_die) {
			if (!card->waitForDataReady()) { // waits ~ 1200 hours ;-)
				// this occurs when the rpvdsex circuit is idled.
				// and potentially when a glitch happens
				printf("  waitForDataReady() failed with: %d\n",
				       card->getLastError());
				card->stopCollecting();
				conn_cards--;
				printf("  releasing card0\n");
				PO8e::releaseCard(card);
				card = NULL;
				break;
			}
			bool stopped = false;
			int numSamples = 0;
			if (!simulate) {
				numSamples = (int)card->samplesReady(&stopped);
				if (stopped) {
					printf("  stopped collecting data\n");
					card->stopCollecting();
					conn_cards--;
					printf("  releasing card0\n");
					PO8e::releaseCard(card);
					card = NULL;
					break;
				}
				if (numSamples > 0) {
					if (numSamples > bufmax) {
						printf("samplesReady() returned too many samples for buffer (buffer wrap?): %d\n",
						       numSamples);
						numSamples = bufmax;
					}
					card->readBlock(temp, numSamples);
					card->flushBufferedData(numSamples);
					totalSamples += numSamples;
				}
			} else { //simulate!
				long double now = gettime();
				numSamples = (int)((now - starttime)*SRATE_HZ - totalSamples);
				if (numSamples >= 250) {
					numSamples = 250;
					totalSamples = (now - starttime)*SRATE_HZ;
				}
				float scale = sin(sinSamples/4e4);
				for (int i=0; i<numSamples; i++) {
					temptemp[i] =  (short)(sinf((float)
					                            ((sinSamples + i)/6.0))*32768.f*scale);
				}
				for (int k=0; k<96; k++) {
					for (int i=0; i<numSamples; i++) {
						temp[k*numSamples +i] = temptemp[i];
					}
				}
				//last part of the buffer is just TDT ticks (most recent -> least delay?)
				for (int i=0; i<numSamples; i++) {
					int r = (int)(sinSamples +i);
					temp[NCHAN*numSamples     +i] = r       & 0xffff;
					temp[(NCHAN+1)*numSamples +i] = (r>>16) & 0xffff;
				}
				totalSamples += numSamples;
				sinSamples += numSamples;
				if (sinSamples > 4e4*2*3.1415926) sinSamples -= 4e4*2*3.1415926;
				usleep(70);
			}
			printf("frame: %d\t", frame);
			if (numSamples > 0 && numSamples <= bufmax) {
				bytes += numSamples * nchan * bps;
				if (frame %200 == 0) { //need to move this to the UI.
					int ticks = (unsigned short)(temp[NCHAN*numSamples + numSamples -1]);
					ticks += (unsigned short)(temp[(NCHAN+1)*numSamples + numSamples -1]) << 16;
					fprintf(stderr, "%d samples at %d Bps of %d chan: %Lf MB/sec | %d ticks\n",
					        numSamples,
					        bps,
					        nchan,
					        ((long double)bytes) / ((gettime() - starttime)*(1024.0*1024.0)),
					        ticks
					       );
				}
			}
			frame++;
		}
		//delete buffers since we have dynamically allocated;
		delete[] temp;
		delete[] temptemp;
		printf("\n");
		sleep(1);
	}
	return 0;
}

int main(void)
{
	printf("press enter to quit.\n");
	usleep(4e5);
	pthread_t thread1;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_create( &thread1, &attr, po8_thread, 0 );
	getchar(); // wait for enter
	g_die = true;
	usleep(4e5);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "print.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "session.h"
#include "report.h"

namespace ledger {

namespace {
  void print_note(std::ostream&     out,
                  const string&     note,
                  const std::size_t columns,
                  const std::size_t prior_width)
  {
    // The 4 is for four leading spaces at the beginning of the posting, and
    // the 3 is for two spaces and a semi-colon before the note.
    if (columns > 0 && note.length() > columns - (prior_width + 3))
      out << "\n    ;";
    else
      out << "  ;";

    bool need_separator = false;
    for (const char * p = note.c_str(); *p; p++) {
      if (*p == '\n') {
        need_separator = true;
      } else {
        if (need_separator) {
          out << "\n    ;";
          need_separator = false;
        }
        out << *p;
      }
    }
  }

  void print_xact(report_t& report, std::ostream& out, xact_t& xact)
  {
    format_type_t          format_type = FMT_WRITTEN;
    optional<const char *> format;

    if (report.HANDLED(date_format_)) {
      format_type = FMT_CUSTOM;
      format      = report.HANDLER(date_format_).str().c_str();
    }

    std::ostringstream buf;

    buf << format_date(item_t::use_effective_date ?
                       xact.date() : xact.actual_date(),
                       format_type, format);
    if (! item_t::use_effective_date && xact.effective_date())
      buf << '=' << format_date(*xact.effective_date(),
                                format_type, format);
    buf << ' ';

    buf << (xact.state() == item_t::CLEARED ? "* " :
            (xact.state() == item_t::PENDING ? "! " : ""));

    if (xact.code)
      buf << '(' << *xact.code << ") ";

    buf << xact.payee;

    string leader = buf.str();
    out << leader;

    std::size_t columns = (report.HANDLED(columns_) ?
                           report.HANDLER(columns_).value.to_long() : 80);

    if (xact.note)
      print_note(out, *xact.note, columns, unistring(leader).length());
    out << '\n';

    if (xact.metadata) {
      foreach (const item_t::string_map::value_type& data, *xact.metadata) {
        if (! data.second.second) {
          out << "    ; ";
          if (data.second.first)
            out << data.first << ": " << *data.second.first;
          else
            out << ':' << data.first << ":";
          out << '\n';
        }
      }
    }

    foreach (post_t * post, xact.posts) {
      if (! report.HANDLED(generated) &&
          (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
           ! post->has_flags(POST_ANONYMIZED)))
        continue;

      out << "    ";

      std::ostringstream buf;

      if (xact.state() == item_t::UNCLEARED)
        buf << (post->state() == item_t::CLEARED ? "* " :
                (post->state() == item_t::PENDING ? "! " : ""));

      if (post->has_flags(POST_VIRTUAL)) {
        if (post->has_flags(POST_MUST_BALANCE))
          buf << '[';
        else
          buf << '(';
      }

      buf << post->account->fullname();

      if (post->has_flags(POST_VIRTUAL)) {
        if (post->has_flags(POST_MUST_BALANCE))
          buf << ']';
        else
          buf << ')';
      }

      unistring name(buf.str());

      std::size_t account_width =
        (report.HANDLER(account_width_).specified ?
         report.HANDLER(account_width_).value.to_long() : 36);

      if (account_width < name.length())
        account_width = name.length();

      if (! post->has_flags(POST_CALCULATED) || report.HANDLED(generated)) {
        out << name.extract();
        int slip = (static_cast<int>(account_width) -
                    static_cast<int>(name.length()));
        if (slip > 0) {
          out.width(slip);
          out << ' ';
        }

        std::ostringstream amtbuf;

        string amt;
        if (post->amount_expr) {
          amt = post->amount_expr->text();
        } else {
          int amount_width =
            (report.HANDLER(amount_width_).specified ?
             report.HANDLER(amount_width_).value.to_int() : 12);

          std::ostringstream amt_str;
          value_t(post->amount).print(amt_str, amount_width, -1,
                                      AMOUNT_PRINT_RIGHT_JUSTIFY |
                                      AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
          amt = amt_str.str();
        }

        string trimmed_amt(amt);
        trim_left(trimmed_amt);
        int amt_slip = (static_cast<int>(amt.length()) -
                        static_cast<int>(trimmed_amt.length()));
        if (slip + amt_slip < 2)
          amtbuf << string(2 - (slip + amt_slip), ' ');
        amtbuf << amt;

        if (post->cost &&
            ! post->has_flags(POST_CALCULATED | POST_COST_CALCULATED)) {
          if (post->has_flags(POST_COST_IN_FULL))
            amtbuf << " @@ " << post->cost->abs();
          else
            amtbuf << " @ "
                   << (*post->cost / post->amount).abs();
        }

        if (post->assigned_amount)
          amtbuf << " = " << *post->assigned_amount;

        string trailer = amtbuf.str();
        out << trailer;

        account_width += unistring(trailer).length();
      } else {
        out << buf.str();
      }

      if (post->note)
        print_note(out, *post->note, columns, 4 + account_width);
      out << '\n';
    }
  }
}

void print_xacts::title(const string&)
{
  if (first_title) {
    first_title = false;
  } else {
    std::ostream& out(report.output_stream);
    out << '\n';
  }
}

void print_xacts::flush()
{
  std::ostream& out(report.output_stream);

  bool first = true;
  foreach (xact_t * xact, xacts) {
    if (first)
      first = false;
    else
      out << '\n';

    if (print_raw) {
      print_item(out, *xact);
      out << '\n';
    } else {
      print_xact(report, out, *xact);
    }
  }

  out.flush();
}

void print_xacts::operator()(post_t& post)
{
  if (! post.has_xdata() ||
      ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
    if (xacts_present.find(post.xact) == xacts_present.end()) {
      xacts_present.insert(xacts_present_map::value_type(post.xact, true));
      xacts.push_back(post.xact);
    }
    post.xdata().add_flags(POST_EXT_DISPLAYED);
  }
}

} // namespace ledger
<commit_msg>Fixes for variable shadowing (22/28)<commit_after>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "print.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "session.h"
#include "report.h"

namespace ledger {

namespace {
  void print_note(std::ostream&     out,
                  const string&     note,
                  const std::size_t columns,
                  const std::size_t prior_width)
  {
    // The 4 is for four leading spaces at the beginning of the posting, and
    // the 3 is for two spaces and a semi-colon before the note.
    if (columns > 0 && note.length() > columns - (prior_width + 3))
      out << "\n    ;";
    else
      out << "  ;";

    bool need_separator = false;
    for (const char * p = note.c_str(); *p; p++) {
      if (*p == '\n') {
        need_separator = true;
      } else {
        if (need_separator) {
          out << "\n    ;";
          need_separator = false;
        }
        out << *p;
      }
    }
  }

  void print_xact(report_t& report, std::ostream& out, xact_t& xact)
  {
    format_type_t          format_type = FMT_WRITTEN;
    optional<const char *> format;

    if (report.HANDLED(date_format_)) {
      format_type = FMT_CUSTOM;
      format      = report.HANDLER(date_format_).str().c_str();
    }

    std::ostringstream buf;

    buf << format_date(item_t::use_effective_date ?
                       xact.date() : xact.actual_date(),
                       format_type, format);
    if (! item_t::use_effective_date && xact.effective_date())
      buf << '=' << format_date(*xact.effective_date(),
                                format_type, format);
    buf << ' ';

    buf << (xact.state() == item_t::CLEARED ? "* " :
            (xact.state() == item_t::PENDING ? "! " : ""));

    if (xact.code)
      buf << '(' << *xact.code << ") ";

    buf << xact.payee;

    string leader = buf.str();
    out << leader;

    std::size_t columns = (report.HANDLED(columns_) ?
                           report.HANDLER(columns_).value.to_long() : 80);

    if (xact.note)
      print_note(out, *xact.note, columns, unistring(leader).length());
    out << '\n';

    if (xact.metadata) {
      foreach (const item_t::string_map::value_type& data, *xact.metadata) {
        if (! data.second.second) {
          out << "    ; ";
          if (data.second.first)
            out << data.first << ": " << *data.second.first;
          else
            out << ':' << data.first << ":";
          out << '\n';
        }
      }
    }

    foreach (post_t * post, xact.posts) {
      if (! report.HANDLED(generated) &&
          (post->has_flags(ITEM_TEMP | ITEM_GENERATED) &&
           ! post->has_flags(POST_ANONYMIZED)))
        continue;

      out << "    ";

      std::ostringstream pbuf;

      if (xact.state() == item_t::UNCLEARED)
        pbuf << (post->state() == item_t::CLEARED ? "* " :
                (post->state() == item_t::PENDING ? "! " : ""));

      if (post->has_flags(POST_VIRTUAL)) {
        if (post->has_flags(POST_MUST_BALANCE))
          pbuf << '[';
        else
          pbuf << '(';
      }

      pbuf << post->account->fullname();

      if (post->has_flags(POST_VIRTUAL)) {
        if (post->has_flags(POST_MUST_BALANCE))
          pbuf << ']';
        else
          pbuf << ')';
      }

      unistring name(pbuf.str());

      std::size_t account_width =
        (report.HANDLER(account_width_).specified ?
         report.HANDLER(account_width_).value.to_long() : 36);

      if (account_width < name.length())
        account_width = name.length();

      if (! post->has_flags(POST_CALCULATED) || report.HANDLED(generated)) {
        out << name.extract();
        int slip = (static_cast<int>(account_width) -
                    static_cast<int>(name.length()));
        if (slip > 0) {
          out.width(slip);
          out << ' ';
        }

        std::ostringstream amtbuf;

        string amt;
        if (post->amount_expr) {
          amt = post->amount_expr->text();
        } else {
          int amount_width =
            (report.HANDLER(amount_width_).specified ?
             report.HANDLER(amount_width_).value.to_int() : 12);

          std::ostringstream amt_str;
          value_t(post->amount).print(amt_str, amount_width, -1,
                                      AMOUNT_PRINT_RIGHT_JUSTIFY |
                                      AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS);
          amt = amt_str.str();
        }

        string trimmed_amt(amt);
        trim_left(trimmed_amt);
        int amt_slip = (static_cast<int>(amt.length()) -
                        static_cast<int>(trimmed_amt.length()));
        if (slip + amt_slip < 2)
          amtbuf << string(2 - (slip + amt_slip), ' ');
        amtbuf << amt;

        if (post->cost &&
            ! post->has_flags(POST_CALCULATED | POST_COST_CALCULATED)) {
          if (post->has_flags(POST_COST_IN_FULL))
            amtbuf << " @@ " << post->cost->abs();
          else
            amtbuf << " @ "
                   << (*post->cost / post->amount).abs();
        }

        if (post->assigned_amount)
          amtbuf << " = " << *post->assigned_amount;

        string trailer = amtbuf.str();
        out << trailer;

        account_width += unistring(trailer).length();
      } else {
        out << pbuf.str();
      }

      if (post->note)
        print_note(out, *post->note, columns, 4 + account_width);
      out << '\n';
    }
  }
}

void print_xacts::title(const string&)
{
  if (first_title) {
    first_title = false;
  } else {
    std::ostream& out(report.output_stream);
    out << '\n';
  }
}

void print_xacts::flush()
{
  std::ostream& out(report.output_stream);

  bool first = true;
  foreach (xact_t * xact, xacts) {
    if (first)
      first = false;
    else
      out << '\n';

    if (print_raw) {
      print_item(out, *xact);
      out << '\n';
    } else {
      print_xact(report, out, *xact);
    }
  }

  out.flush();
}

void print_xacts::operator()(post_t& post)
{
  if (! post.has_xdata() ||
      ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
    if (xacts_present.find(post.xact) == xacts_present.end()) {
      xacts_present.insert(xacts_present_map::value_type(post.xact, true));
      xacts.push_back(post.xact);
    }
    post.xdata().add_flags(POST_EXT_DISPLAYED);
  }
}

} // namespace ledger
<|endoftext|>


<commit_before>#include <iostream>

#include <3pp/mpc/mpc.h>

int main(int argc, char **argv)
{
    if (argc <= 1) {
        std::cout << "Usage: " << argv[0] << "file\n";
        return 1;
    }
    mpc_parser_t* Comment   = mpc_new("comment");
    mpc_parser_t* Indent   = mpc_new("indent");
    mpc_parser_t* Newline   = mpc_new("newline");
    mpc_parser_t* WhiteSpace = mpc_new("ws");
    mpc_parser_t* OptionalWhiteSpace = mpc_new("ows");
    mpc_parser_t* Number   = mpc_new("number");
    mpc_parser_t* Operator = mpc_new("operator");
    mpc_parser_t* FactorOperator = mpc_new("factorop");
    mpc_parser_t* TermOperator = mpc_new("termop");
    mpc_parser_t* Expr     = mpc_new("expr");
    mpc_parser_t* Body     = mpc_new("body");
    mpc_parser_t* Identifier = mpc_new("identifier");
    mpc_parser_t* TypeIdent = mpc_new("typeident");
    mpc_parser_t* Import = mpc_new("import");
    mpc_parser_t* MethodRet = mpc_new("methodret");
    mpc_parser_t* MethodDef = mpc_new("methoddef");
    mpc_parser_t* ParamDef = mpc_new("paramdef");
    mpc_parser_t* String = mpc_new("string");
    mpc_parser_t* Args = mpc_new("args");
    mpc_parser_t* Lexp = mpc_new("lexp");
    mpc_parser_t* Factor = mpc_new("factor");
    mpc_parser_t* MethodCall = mpc_new("methodcall");
    mpc_parser_t* MapIndex = mpc_new("mapindex");
    mpc_parser_t* ListItem = mpc_new("listitem");
    mpc_parser_t* MapItem = mpc_new("mapitem");
    mpc_parser_t* TupleMap = mpc_new("tuplemap");
    mpc_parser_t* MapItems = mpc_new("mapitems");
    mpc_parser_t* ListItems = mpc_new("listitems");
    mpc_parser_t* List = mpc_new("list");
    mpc_parser_t* Namespacedef = mpc_new("namespacedef");
    mpc_parser_t* MatchCase = mpc_new("matchcase");
    mpc_parser_t* Match = mpc_new("match");
    mpc_parser_t* Assignment = mpc_new("assignment");
    mpc_parser_t* Stmt = mpc_new("stmt");
    mpc_parser_t* Term = mpc_new("term");
    mpc_parser_t* Const = mpc_new("const");
    mpc_parser_t* Pure = mpc_new("pure");
    mpc_parser_t* TopLevel = mpc_new("toplevel");
    mpc_parser_t* NolangPure = mpc_new("nolangpure");

    mpc_err_t* err = mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
        "comment    : /(#|\\/\\/)[^\\r\\n]*/"
        "           | /\\/\\*[^\\*]*(\\*[^\\/][^\\*]*)*\\*\\// ;"
        "indent     : ' ' ' '+ ;"
        "newline    : '\\n';"
        "ws         : /[' ']+/ ;"
        "ows        : /[' '\\t]*/ ;"
        "identifier : /[A-Za-z_][A-Za-z0-9_-]*/ ;"
        "typeident  : <identifier> <ows> ':' <ows> <identifier> ;"
        "number     : /[0-9]+/ ;"
        "string     : /\"(\\\\.|[^\"])*\"/ "
        "           | /\'(\\\\.|[^\'])*\'/ ; "
        "operator   : '+' | '-' | '*' | '/' ;"
        "factorop   : '*'"
        "           | '/'"
        "           | \"div\""
        "           | \"mod\""
        "           | \"rem\";"
        "termop     : '+'"
        "           | '-';"
        "import     : \"import\" <ws> <identifier> <newline>;"
        "const      : \"const\" <ws> <assignment> <newline>;"
        "methodret  : <ows> ':' <ows> <identifier> ;"
        "methoddef  : (<pure> <ws>)? <identifier> <ows> <args>? <methodret>? <ows> \"=>\" (<newline>|<ws>) <body> ;"
        "paramdef   : <typeident>? <ows> (',' <ows> <typeident>)*; "
        "args       : '(' <paramdef>? ')'; "
        "factor     : <namespacedef>"
        "           | '(' <lexp> ')'"
        "           | <number>"
        "           | <string>"
        "           | <identifier>; "
        "term       : <factor> (<ows> <factorop> <ows> <factor>)*;"
        "lexp       : <term> (<ows> <termop> <ows> <term>)* ; "
        "expr       : <list>"
        "           | <lexp>;"
        "methodcall : '(' (<expr> (',' <ows> <expr>)*)? ')';"
        "mapindex   : '[' <expr> ']';"
        "listitem   : <expr>;"
        "mapitem    : <string> <ows> ':' <ows> <expr> ;"
        "tuplemap   : '(' <string> <ows> ',' <ows> <lexp> ')';"
        "mapitems   : (<tuplemap> | <mapitem>) <ows> (',' <ows> (<tuplemap> | <mapitem>)) *;"
        "listitems  : <listitem> (<ows> ',' <ows> <listitem>) *;"
        "list       : '[' <ows> (<mapitems> | <listitems>)? <ows> ']' ;"
        "namespacedef : <identifier> ('.' <identifier>)* (<methodcall> | <mapindex>)?;"
        "assignment : <typeident> <ws> '=' <ws> <expr>;"
        "matchcase  : <indent> (<identifier> | <number> | <string> | '?') <ows> ':' <ows> <stmt>;"
        //"match      : \"match\" <ws> (<identifier> | <namespacedef>) <ows> \"=>\" <newline> <matchcase>+;"
        "match      : \"match\" <ws> <stmt> <ows> \"=>\" <newline> <matchcase>+;"
        "stmt       : <match>"
        "           | <assignment>"
        "           | <namespacedef>"
        "           | <list>"
        "           | <expr>"
        "           | <comment>;"
        "body       : ((<indent>+ <stmt>)? <newline>)* ;"
        "pure       : \"pure\" ;"
        "toplevel   : <import>"
        "           | <const>"
        "           | <comment>"
        "           | <methoddef>"
        "           | <newline>;"
        "nolangpure : /^/ <toplevel>* /$/;"
      ,
        Comment, Indent, Newline, WhiteSpace, OptionalWhiteSpace,
        Identifier, TypeIdent,
        Number, String,
        Operator, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Assignment, MatchCase, Match,
        Stmt,
        Body, Pure,
        TopLevel, NolangPure, NULL);
    // expr       : <number> | '(' <operator> <expr>+ ')' ;

    if (err != NULL) {
        mpc_err_print(err);
        mpc_err_delete(err);
        exit(1);
    }

    mpc_result_t r;
    if (mpc_parse_contents(argv[1], NolangPure, &r)) {
      /* On Success Print the AST */
      mpc_ast_print(static_cast<mpc_ast_t*>(r.output));
      mpc_ast_delete(static_cast<mpc_ast_t*>(r.output));
    } else {
      /* Otherwise Print the Error */
      mpc_err_print(r.error);
      mpc_err_delete(r.error);
    }

    mpc_cleanup(15,
        Identifier, TypeIdent, Number, String,
        Operator, FactorOperator, TermOperator,
        MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, Body, Pure,
        NolangPure);

    return 0;
}
<commit_msg>Kludge to add newline at end to proper match case<commit_after>#include <iostream>
#include <fstream>
#include <streambuf>

#include <3pp/mpc/mpc.h>

std::string readFile(char *fname)
{
    std::ifstream is(fname, std::ifstream::in);
    std::string str(
        (std::istreambuf_iterator<char>(is)),
        std::istreambuf_iterator<char>()
    );
    return str + '\n';
}

int main(int argc, char **argv)
{
    if (argc <= 1) {
        std::cout << "Usage: " << argv[0] << "file\n";
        return 1;
    }
    mpc_parser_t* Comment   = mpc_new("comment");
    mpc_parser_t* Indent   = mpc_new("indent");
    mpc_parser_t* Newline   = mpc_new("newline");
    mpc_parser_t* WhiteSpace = mpc_new("ws");
    mpc_parser_t* OptionalWhiteSpace = mpc_new("ows");
    mpc_parser_t* Number   = mpc_new("number");
    mpc_parser_t* Operator = mpc_new("operator");
    mpc_parser_t* FactorOperator = mpc_new("factorop");
    mpc_parser_t* TermOperator = mpc_new("termop");
    mpc_parser_t* Expr     = mpc_new("expr");
    mpc_parser_t* Body     = mpc_new("body");
    mpc_parser_t* Identifier = mpc_new("identifier");
    mpc_parser_t* TypeIdent = mpc_new("typeident");
    mpc_parser_t* Import = mpc_new("import");
    mpc_parser_t* MethodRet = mpc_new("methodret");
    mpc_parser_t* MethodDef = mpc_new("methoddef");
    mpc_parser_t* ParamDef = mpc_new("paramdef");
    mpc_parser_t* String = mpc_new("string");
    mpc_parser_t* Args = mpc_new("args");
    mpc_parser_t* Lexp = mpc_new("lexp");
    mpc_parser_t* Factor = mpc_new("factor");
    mpc_parser_t* MethodCall = mpc_new("methodcall");
    mpc_parser_t* MapIndex = mpc_new("mapindex");
    mpc_parser_t* ListItem = mpc_new("listitem");
    mpc_parser_t* MapItem = mpc_new("mapitem");
    mpc_parser_t* TupleMap = mpc_new("tuplemap");
    mpc_parser_t* MapItems = mpc_new("mapitems");
    mpc_parser_t* ListItems = mpc_new("listitems");
    mpc_parser_t* List = mpc_new("list");
    mpc_parser_t* Namespacedef = mpc_new("namespacedef");
    mpc_parser_t* MatchCase = mpc_new("matchcase");
    mpc_parser_t* Match = mpc_new("match");
    mpc_parser_t* Assignment = mpc_new("assignment");
    mpc_parser_t* Stmt = mpc_new("stmt");
    mpc_parser_t* Term = mpc_new("term");
    mpc_parser_t* Const = mpc_new("const");
    mpc_parser_t* Pure = mpc_new("pure");
    mpc_parser_t* TopLevel = mpc_new("toplevel");
    mpc_parser_t* NolangPure = mpc_new("nolangpure");

    mpc_err_t* err = mpca_lang(MPCA_LANG_WHITESPACE_SENSITIVE,
        "comment    : /(#|\\/\\/)[^\\r\\n]*/"
        "           | /\\/\\*[^\\*]*(\\*[^\\/][^\\*]*)*\\*\\// ;"
        "indent     : ' ' ' '+ ;"
        "newline    : '\\n';"
        "ws         : /[' ']+/ ;"
        "ows        : /[' '\\t]*/ ;"
        "identifier : /[A-Za-z_][A-Za-z0-9_-]*/ ;"
        "typeident  : <identifier> <ows> ':' <ows> <identifier> ;"
        "number     : /[0-9]+/ ;"
        "string     : /\"(\\\\.|[^\"])*\"/ "
        "           | /\'(\\\\.|[^\'])*\'/ ; "
        "operator   : '+' | '-' | '*' | '/' ;"
        "factorop   : '*'"
        "           | '/'"
        "           | \"div\""
        "           | \"mod\""
        "           | \"rem\";"
        "termop     : '+'"
        "           | '-';"
        "import     : \"import\" <ws> <identifier> <newline>;"
        "const      : \"const\" <ws> <assignment> <newline>;"
        "methodret  : <ows> ':' <ows> <identifier> ;"
        "methoddef  : (<pure> <ws>)? <identifier> <ows> <args>? <methodret>? <ows> \"=>\" (<newline>|<ws>) <body> ;"
        "paramdef   : <typeident>? <ows> (',' <ows> <typeident>)*; "
        "args       : '(' <paramdef>? ')'; "
        "factor     : <namespacedef>"
        "           | '(' <lexp> ')'"
        "           | <number>"
        "           | <string>"
        "           | <identifier>; "
        "term       : <factor> (<ows> <factorop> <ows> <factor>)*;"
        "lexp       : <term> (<ows> <termop> <ows> <term>)* ; "
        "expr       : <list>"
        "           | <lexp>;"
        "methodcall : '(' (<expr> (',' <ows> <expr>)*)? ')';"
        "mapindex   : '[' <expr> ']';"
        "listitem   : <expr>;"
        "mapitem    : <string> <ows> ':' <ows> <expr> ;"
        "tuplemap   : '(' <string> <ows> ',' <ows> <lexp> ')';"
        "mapitems   : (<tuplemap> | <mapitem>) <ows> (',' <ows> (<tuplemap> | <mapitem>)) *;"
        "listitems  : <listitem> (<ows> ',' <ows> <listitem>) *;"
        "list       : '[' <ows> (<mapitems> | <listitems>)? <ows> ']' ;"
        "namespacedef : <identifier> ('.' <identifier>)* (<methodcall> | <mapindex>)?;"
        "assignment : <typeident> <ws> '=' <ws> <expr>;"
        "matchcase  : <indent> (<identifier> | <number> | <string> | '?') <ows> ':' <ows> <stmt> <newline>;"
        //"match      : \"match\" <ws> (<identifier> | <namespacedef>) <ows> \"=>\" <newline> <matchcase>+;"
        "match      : \"match\" <ws> <stmt> <ows> \"=>\" <newline> <matchcase>+;"
        "stmt       : <match>"
        "           | <assignment>"
        "           | <namespacedef>"
        "           | <list>"
        "           | <expr>"
        "           | <comment>;"
        "body       : ((<indent>+ <stmt>)? <newline>)* ;"
        "pure       : \"pure\" ;"
        "toplevel   : <import>"
        "           | <const>"
        "           | <comment>"
        "           | <methoddef>"
        "           | <newline>;"
        "nolangpure : /^/ <toplevel>* /$/;"
      ,
        Comment, Indent, Newline, WhiteSpace, OptionalWhiteSpace,
        Identifier, TypeIdent,
        Number, String,
        Operator, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Assignment, MatchCase, Match,
        Stmt,
        Body, Pure,
        TopLevel, NolangPure, NULL);

    if (err != NULL) {
        mpc_err_print(err);
        mpc_err_delete(err);
        exit(1);
    }

    mpc_result_t r;
    std::string data = readFile(argv[1]);
    if (mpc_parse(argv[1], data.c_str(), NolangPure, &r)) {
      mpc_ast_print(static_cast<mpc_ast_t*>(r.output));
      mpc_ast_delete(static_cast<mpc_ast_t*>(r.output));
    } else {
      mpc_err_print(r.error);
      mpc_err_delete(r.error);
    }

    mpc_cleanup(39,
        Comment, Indent, Newline, WhiteSpace, OptionalWhiteSpace,
        Identifier, TypeIdent,
        Number, String,
        Operator, FactorOperator, TermOperator,
        Import, Const,
        MethodRet, MethodDef, ParamDef, Args,
        Factor, Term, Lexp,
        Expr, MethodCall,
        MapIndex, ListItem, MapItem, TupleMap, MapItems, ListItems, List,
        Namespacedef,
        Assignment, MatchCase, Match,
        Stmt,
        Body, Pure,
        TopLevel, NolangPure);

    return 0;
}
<|endoftext|>