<commit_before>#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>

using namespace std;

const int cap = 1000; // the capacity of the 2-D array

// split a line by the delim and store to a 2-D array
void split(char *arr[], char str[], const char *delim);

// get command block between connectors
int getCommand(char **, const string&, int&, int);

int main(int argc, char *argv[]) {
    char origStr[cap]; // store the user input line
    char *save_1, *save_2; // save value using in strtok_r
    int i = 0;

    // always in my rshell
    while (1) {
        cout << "$ ";
        char *cmd[cap]; // declare a 2-D 1000*1000 array
        // pre-allocate cmd
        for(i = 0; i < cap; ++i) {
            cmd[i] = new char[cap];
        }

        bool isExecuted = true;
        char *effectStr;
        char errcmd[cap];
        string userStr; // change a cstring into string
        int flag = 4;
        int index = 0;
        int status;

        memset(origStr, 0, cap); // initialize origStr to an empty string
        cin.getline(origStr, cap); // get the user input line

        if (origStr[0] == '\0') {
            continue;
        }

        effectStr = strtok(origStr, "#"); // any command after the "#" is comment
        userStr = effectStr;

        while (flag != 0 && isExecuted) {
            if ( (flag = getCommand(cmd, userStr, index, flag)) == -1 ) {
                cout << "Error: Cannot start with connectors \"|| && ;\"." << endl;
                break;
            }

            if ( (strcmp(cmd[0], "exit") == 0) && cmd[1] == NULL) {
                return 0;
            }

            int pid = fork(); // create a child process to call execvp()

            // fork’s return value for an error is -1
            if (pid == -1) {
                perror("fork");
                exit(1); //there was an error with fork so exit the program and go back and fix it
            }

            // this is in child process
            else if (pid == 0) {
                // run execvp in child process in order not to exit the whole program
                if (execvp(cmd[0], cmd) == -1) {
                    strcpy(errcmd, cmd[0]);
                    perror(errcmd);
                    exit(EXIT_FAILURE);
                }

                exit(EXIT_SUCCESS); // kill the child process when it's done
            }

            // this is in parent process
            else {
                // wait for child process to finish executing
                if (wait(&status) == -1) {
                    perror("wait()");
                    exit(1);
                }
                // if the command fails and the connector is &&, do not execute the next command
                if (WEXITSTATUS(status) == EXIT_FAILURE && flag == 2) {
                    isExecuted = false;
                }
                // if the command is executed and the connector is ||, do not execute the next command
                else if (WEXITSTATUS(status) == EXIT_SUCCESS && flag == 1) {
                    isExecuted = false;
                }
                // execute the next command if it's not the situations above
                else {
                    isExecuted = true;
                }
          }
        }
    }

    return 0;
}

void split(char *arr[], char str[], const char *delim) {
    int i = 0; // initialize i to 0 before the loop

    // split the whole line by delim
    arr[i] = strtok(str, delim);
    while (arr[i] != NULL) {
        ++i;
        arr[i] = strtok(NULL, delim);
    }

    return;
}

int getCommand(char *cmd[], const string& str, int& index, int iFlag) {
    string substring;
    const int size = 3;
    int flag[size] = {0};
    char cstr[cap];
    int min;
    int mFlag;
    int i;
    int begin;
    int leng;

    // get the begin point of the substring according to the iFlag
    if (iFlag == 4) {  // 4 represents the first call
        begin = index;
    }
    else if (iFlag == 3) {
        begin = index + 1;
    }
    else {
        begin = index + 2;
    }

    // initialize pos[] to str's length
    int pos[size] = {(str.size() - 1), (str.size() - 1), (str.size() - 1)};

    // find each connector, 1 represents "||", 2 represents "&&",
    // 3 represents ";", 0 represents no connector
    if ((pos[0] = str.find("||", begin)) != string::npos) {
        flag[0] = 1;
    }
    if ((pos[1] = str.find("&&", begin)) != string::npos) {
        flag[1] = 2;
    }
    if ((pos[2] = str.find(";", begin)) != string::npos) {
        flag[2] = 3;
    }

    // find the first occurrence of any connector
    min = str.size() - 1;

    mFlag = 0;
    for (i = 0; i < size; ++i) {
        if (min > pos[i] && pos[i] != string::npos) {
            min = pos[i];
            mFlag = flag[i];
        }
    }

    // if the string begins with connectors, an error message -1 will return
    if (min == index) {
        return -1;
    }
    // get the length of substring
    if (mFlag == 0) {
        leng = min - begin + 1;
    }
    else {
        leng = min - begin;
    }
    // get the first command block
    substring = str.substr(begin, leng);

    // do toking
    strcpy(cstr, substring.c_str());

    i = 0;
    cmd[i] = strtok(cstr, " ");
    while (cmd[i] != NULL) {
        ++i;
        cmd[i] = strtok(NULL, " ");
    }

    index = min; // update the index to the first occurrence of any connector
    return mFlag;
}

<commit_msg>Now can handle multiple versions of input<commit_after>#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <algorithm>

using namespace std;

const int cap = 1000; // the capacity of the 2-D array

// split a line by the delim and store to a 2-D array
void split(char *arr[], char str[], const char *delim);
// get command block between connectors
int getCommand(char **, string&, int&, int);
// check if the string has syntax error
int strValid(const string&);

int main(int argc, char *argv[]) {
    char origStr[cap]; // store the user input line
    int i = 0;

    // always in my rshell
    while (1) {
    mylabel:
        cout << "$ ";
        char *cmd[cap]; // declare a 2-D 1000*1000 array
        // pre-allocate cmd
        for(i = 0; i < cap; ++i) {
            cmd[i] = new char[cap];
        }

        bool isExecuted = true;
        char *effectStr;
        char *spaceStr;
        char errcmd[cap];
        string userStr; // change a cstring into string
        string tempStr;
        int flag = 4;
        int index = 0;
        int status; // store the status of child exit

        memset(origStr, 0, cap); // initialize origStr to an empty string
        cin.getline(origStr, cap); // get the user input line

        // if the user just hit enter or enter several spaces, go to the next loop
        spaceStr = strtok(origStr, " ");
        if (origStr[0] == '\0' || spaceStr == NULL) {
            continue;
        }

        effectStr = strtok(origStr, "#"); // any command after the "#" is comment
        userStr = effectStr;

        if (strValid(userStr) == -1) {
            cout << "syntax error using connectors \"|| && ;\"" << endl;
            continue;
        }

        // if the string ended with any connectors, ask the user to input other commands
        bool isConnector = true;
        while (isConnector) {
            isConnector = (userStr.find("||", userStr.size() - 2) != string::npos) ||
            (userStr.find("&&", userStr.size() - 2) != string::npos) ||
            (userStr.find(";", userStr.size() - 1) != string::npos);
            if (isConnector) {
                cout << "<command>: ";
                getline(cin, tempStr);
                userStr = userStr + tempStr;
            }
            if (strValid(userStr) == -1) {
                cout << "syntax error using connectors \"|| && ;\"" << endl;
                goto mylabel;
            }
        }

        while (flag != 0 && isExecuted) {
            if ( (flag = getCommand(cmd, userStr, index, flag)) == -1 ) {
                cout << "Error: Cannot start with connectors \"|| && ;\"." << endl;
                break;
            }

            if ( (strcmp(cmd[0], "exit") == 0) ) {
                return 0;
            }

            int pid = fork(); // create a child process to call execvp()

            // fork’s return value for an error is -1
            if (pid == -1) {
                perror("fork");
                exit(1); //there was an error with fork so exit the program and go back and fix it
            }

            // this is in child process
            else if (pid == 0) {
                // run execvp in child process in order not to exit the whole program
                if (execvp(cmd[0], cmd) == -1) {
                    strcpy(errcmd, cmd[0]);
                    perror(errcmd);
                    exit(EXIT_FAILURE);
                }

                exit(EXIT_SUCCESS); // kill the child process when it's done
            }

            // this is in parent process
            else {
                // wait for child process to finish executing
                if (wait(&status) == -1) {
                    perror("wait()");
                    exit(1);
                }
                // if the command fails and the connector is &&, do not execute the next command
                if (WEXITSTATUS(status) == EXIT_FAILURE && flag == 2) {
                    isExecuted = false;
                }
                // if the command is executed and the connector is ||, do not execute the next command
                else if (WEXITSTATUS(status) == EXIT_SUCCESS && flag == 1) {
                    isExecuted = false;
                }
                // execute the next command if it's not the situations above
                else {
                    isExecuted = true;
                }
          }
        }
    }

    return 0;
}

void split(char *arr[], char str[], const char *delim) {
    int i = 0; // initialize i to 0 before the loop

    // split the whole line by delim
    arr[i] = strtok(str, delim);
    while (arr[i] != NULL) {
        ++i;
        arr[i] = strtok(NULL, delim);
    }

    return;
}

int getCommand(char *cmd[], string& str, int& index, int iFlag) {
    string substring;
    const int size = 3;
    int flag[size] = {0};
    char cstr[cap];
    int min;
    int mFlag;
    int i;
    int begin;
    int leng;

    // get the begin point of the substring according to the iFlag
    if (iFlag == 4) {  // 4 represents the first call
        begin = index;
    }
    else if (iFlag == 3) {
        begin = index + 1;
    }
    else {
        begin = index + 2;
    }

    // initialize pos[] to str's length
    int pos[size] = {(str.size() - 1), (str.size() - 1), (str.size() - 1)};

    // find each connector, 1 represents "||", 2 represents "&&",
    // 3 represents ";", 0 represents no connector
    if ((pos[0] = str.find("||", begin)) != string::npos) {
        flag[0] = 1;
    }
    if ((pos[1] = str.find("&&", begin)) != string::npos) {
        flag[1] = 2;
    }
    if ((pos[2] = str.find(";", begin)) != string::npos) {
        flag[2] = 3;
    }

    // find the first occurrence of any connector
    min = str.size() - 1;
    mFlag = 0;
    for (i = 0; i < size; ++i) {
        if (min > pos[i] && pos[i] != string::npos) {
            min = pos[i];
            mFlag = flag[i];
        }
    }

    // if the string begins with connectors, an error message -1 will return
    if (min == begin) {
        return -1;
    }

    // get the length of substring
    if (mFlag == 0) {
        leng = min - begin + 1;
    }
    else {
        leng = min - begin;
    }
    // get the first command block
    substring = str.substr(begin, leng);

    // do toking
    strcpy(cstr, substring.c_str());

    i = 0;
    cmd[i] = strtok(cstr, " ");

    while (cmd[i] != NULL) {
        ++i;
        cmd[i] = strtok(NULL, " ");
    }

    index = min; // update the index to the first occurrence of any connector
    return mFlag;
}

int strValid(const string& str) {
    int i;
    int pos;
    string temp = str;

    for (i = 0; i < temp.size() - 1; ++i) {
        if (temp.at(i) == ' ') {
            temp.erase(i, 1);
        }
    }
    // if the character after any connector is either of "| & ;",
    // despite white spaces, then it's a syntax error
    pos = temp.find_first_of("|&");
    while (pos != string::npos) {
        // if string is ended with "| &", return -1
        if (pos == temp.size() - 1) {
            return -1;
        }
        // if string only has one of "| &" or has different combinations "like |&", return -1
        else if (temp.at(pos + 1) != temp.at(pos)) {
            return -1;
        }
        // if string end with "||" or "&&", return 1 indicates valid
        else if (pos == temp.size() - 2) {
            return 1;
        }
        // if string has more than 2 of "| & ;", return -1
        else if (temp.at(pos + 2) == '|' || temp.at(pos + 2) == '&' || temp.at(pos + 2) == ';') {
            return -1;
        }
        pos = temp.find_first_of("|&", pos + 2);
    }

    pos = temp.find(";");
    while (pos != string::npos) {
        // if string is ended with ";", return 1 indicates valid
        if (pos == temp.size() - 1) {
            return 1;
        }
        // if string has more than 1 of ";" or something like ";|", return -1
        else if (temp.at(pos + 1) == '|' || temp.at(pos + 1) == '&' || temp.at(pos + 1) == ';') {
            return -1;
        }
        pos = temp.find(";", pos + 1);
    }

    return 1;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string.h>
#include <boost/tokenizer.hpp>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <algorithm>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>

using namespace std;
using namespace boost;

class Connector
{
    public:
        Connector();
        ~Connector();
        bool run;
        int type;
        bool runNext();
        bool precedence;

};

Connector::Connector()
{
    // the semicolon connector allows the next command to be execute always
    run = true;
    type = 0; // semicolon connector set to 0
    precedence = false;
}

Connector::~Connector()
{
}
bool Connector::runNext()
{
    if (type == 1) // && connector
    {
        if (!run) // if the first command doesn't succeed  it wont run the next command
        {
            return false;
        }
    }
    else if (type == 2) // || connector
    {
        if (run) // if the first command succeed it wont run the next command
        {
            return false;
        }
    }
    return true;
}
void parseinator(vector<string> input, string& command, string& argument, int& position, Connector& connect, string& flag);
void commandifier(string command, string argument, Connector& connect, string flag);
void test_function(string command, string flag, string argument, Connector& connect);
int main()
{
    string flag;
    string str;
    string command;
    string argument;
    Connector connect;
    char hostname[100];
    int position = 0;
    while (true)
    {
        printf("%s",getlogin()); // returns string containing name of user logged in
        gethostname(hostname, sizeof hostname); // returns the standard host name for the current machine
        cout << "@" << hostname << "$ ";
        getline(cin, str);
        if (str == "exit") // special command of exit
        {
            break;
        }
        vector<string> instruction; // vector of strings
        typedef tokenizer<boost::char_separator<char> > Tok;
        char_separator<char> sep; // default constructed
        Tok tok(str, sep);;
        for (Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) // parses the input into a command and argument
        {
	    instruction.push_back(*tok_iter);

	}
	if (instruction[0] != "#") // checks for user input except for comments (#)
        {
            parseinator(instruction, command, argument, position, connect, flag); // parses the input into a command and argument
            commandifier(command, argument, connect, flag); // runs a command with a given argument
            command = "";
            argument = "";
            int vector_size = instruction.size();
            for (; position < vector_size;) // run until the end of the instruction
            {
                parseinator(instruction, command, argument, position, connect, flag);
                if (connect.runNext() && command != "") // checks connector to see if the next command should be ran
	        {
                    commandifier(command, argument, connect, flag);
                }
	        else
	        {
	            while(connect.precedence && position < vector_size)
		        {
		            if(instruction[position] == ")")
		            {
		                connect.precedence = false;
		            }
		            position++;
		        }
	            connect.run = true;
	            command = "";
	        }
	        command = "";
                argument = "";
            }
            position = 0;
        }
    }
    return 0;
}
void parseinator(vector<string> input, string& command, string& argument, int& position, Connector& connect, string& flag)
{
    if (input[position] == "&") // check if string is equal to & connector
    {
        connect.type = 1; // set & connector to 1
        position += 2; // +=2 in order to take && connect
    }
    if (input[position] == "|")
    {
        connect.type = 2; // set | connector to 2
        position += 2; // +=2 in order to take || connector
    }
    if (input[position] == ";")
    {
        connect.type = 0; // set ; connector to 0
        position ++;
    }
    if (input[position] == "(")
    {
        connect.precedence = true;
        position++;
    }
    if (input[position] != "#")
    {
        command = input[position];
        position++;
    }
    if (command == "test")
    {
        if(input[position] == "-")
        {
            position++;
	    if (input[position] == "f")
            {
		flag = "-e";
		position++;
	    }
	    else if (input[position] == "d")
	    {
		flag = "-d";
		position++;
	    }
	    else // DEFAULT E
	    {
		flag = "-e";
		position++;
            }
        }
    }

    int input_size = input.size();
    for (; position < input_size; position++)
    {
        if (input[position] == ")")
        {
            connect.precedence = false;
            position++;
            break;
        }
        if(command == "echo" && input[position] == "\"")
        {
            position++;
            while(input[position] != "\"" && position <= input_size)
            {

                argument += input[position];
                if(!isalnum(input[position].at(0)) && !isalnum(input[position+1].at(0)))
                {

                }
                else
		{
                    argument += " ";
                }
		position++;
            }
            position++;
            break;
        }
        if (input[position] == "#")
        {
            position = input.size();
            break;
        }
        if (input[position] == "&" || input[position] == "|" || input[position] == ";")
	    {
            break;
    	}

        argument += input[position];
        int input_size1 = input.size();
        if (position+1 != input_size1 && command == "echo")
	{
	    //adds spaces when echoing
            argument += " ";
	}
    }
}
void commandifier(string command, string argument, Connector& connect, string flag)
{
    const char * const_command = command.c_str();
    char * char_command = new char[command.size()];
    const char * const_argument = argument.c_str();
    char * char_argument = new char[argument.size()];
    strcpy (char_command, const_command);
    strcpy (char_argument, const_argument);
    char * args[2]; // char pointer array that holds command, and NULL
    char * args1[3]; // char pointer array that holds command, argument, and NULL
    bool no_arg = true;
    bool failed = false;

    if(command == "test" || command == "[")
    {
	test_function(command,flag,argument,connect);
	return;
    }
    // exit command
    if(command == "exit" || argument == "exit")
    {
	exit(1);
    }

    if (argument.size() == 0) // no arguments
    {
        args[0] = char_command; // args will contain the command
        args[1] = NULL;
    }
    else
    {
	no_arg = false; // sets bool no_arg to false
	args1[0] = char_command; // args1 contains command and argument
        args1[1] = char_argument;
        args1[2] = NULL;
    }
    pid_t c_pid, pid; // data type to reporesent process ID's
    int status;
    c_pid = fork(); // create our fork

    if (c_pid < 0) // indicates the fork has fail if its less than 0
    {
        perror("fork failed");
        exit(1);
    }
    else if (c_pid == 0) // in child process
    {
 	if (no_arg) // no argument
	{
        	execvp( args[0], args); // execvp the char pointer array that holds the command only
        	if (execvp(args[0], args) == -1) // if it returns -1 it failed
                {
                    perror("execvp failed");
                    connect.run = false;
                    failed = true;
                }
		exit(3);
	}
	else // with command and argument
	{
		execvp(args1[0], args1); // execvp the char pointer array that holds the command, and argument
		if (execvp(args1[0], args1) == -1) // if it returns -1 it failed
                {
                    perror("execvp failed");
                    connect.run = false;
                    failed = true;
                }
		exit(3);
	}
    }
    else if (c_pid > 0) // parent process
    {
        if((pid = wait(&status)) < 0 )
        {
            perror("wait");
	    exit(3);
        }
        if (WIFEXITED(status))  //Evaluates to a non-zero value if status was returned for a child process that terminated normally.

        {
            if (WEXITSTATUS(status) != 0)
            {
                connect.run = false;
            }
	    else
	    {
		connect.run = true;
            }
        }
       else
        {
            connect.run = true;
        }
     }
}
void test_function(string command, string flag, string argument, Connector &connect)
{
   const char * arg = argument.c_str();
   struct stat sb; // struct for the stat function
   if(flag == "-f")
   {
 	switch (sb.st_mode & S_IFMT){
	case S_IFREG:   connect.run = true;  // checks if the input is a regular file
	}
   }
   if(flag == "-d")
   {
	switch(sb.st_mode & S_IFMT){
	case S_IFDIR: connect.run = true; // check if the input is a directory
	}

   }
   if(stat(arg,&sb)==0) // checks if file/directory exists
   {
        connect.run = true;
   }
   else
   {
   	connect.run = false;
   }
}

<commit_msg>Update rshell.cpp<commit_after>#include <iostream>
#include <string.h>
#include <boost/tokenizer.hpp>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <algorithm>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>

using namespace std;
using namespace boost;

class Connector
{
    public:
        Connector();
        ~Connector();
        bool run;
        int type;
        bool runNext();
        bool precedence;

};

Connector::Connector()
{
    // the semicolon connector allows the next command to be execute always
    run = true;
    type = 0; // semicolon connector set to 0
    precedence = false;
}

Connector::~Connector()
{
}
bool Connector::runNext()
{
    if (type == 1) // && connector
    {
        if (!run) // if the first command doesn't succeed  it wont run the next command
        {
            return false;
        }
    }
    else if (type == 2) // || connector
    {
        if (run) // if the first command succeed it wont run the next command
        {
            return false;
        }
    }
    return true;
}
void parseinator(vector<string> input, string& command, string& argument, int& position, Connector& connect, string& flag);
void commandifier(string command, string argument, Connector& connect, string flag);
void test_function(string command, string flag, string argument, Connector& connect);
int main()
{
    string flag;
    string str;
    string command;
    string argument;
    Connector connect;
    char hostname[100];
    int position = 0;
    while (true)
    {
        printf("%s",getlogin()); // returns string containing name of user logged in
        gethostname(hostname, sizeof hostname); // returns the standard host name for the current machine
        cout << "@" << hostname << "$ ";
        getline(cin, str);
        if (str == "exit") // special command of exit
        {
            break;
        }
        vector<string> instruction; // vector of strings
        typedef tokenizer<boost::char_separator<char> > Tok;
        char_separator<char> sep; // default constructed
        Tok tok(str, sep);;
        for (Tok::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok_iter) // parses the input into a command and argument
        {
	    instruction.push_back(*tok_iter);

	}
	if (instruction[0] != "#") // checks for user input except for comments (#)
        {
            parseinator(instruction, command, argument, position, connect, flag); // parses the input into a command and argument
            commandifier(command, argument, connect, flag); // runs a command with a given argument
            command = "";
            argument = "";
            int vector_size = instruction.size();
            for (; position < vector_size;) // run until the end of the instruction
            {
                parseinator(instruction, command, argument, position, connect, flag);
                if (connect.runNext() && command != "") // checks connector to see if the next command should be ran
	        {
                    commandifier(command, argument, connect, flag);
                }
	        else
	        {
	            while(connect.precedence && position < vector_size)
		        {
		            if(instruction[position] == ")")
		            {
		                connect.precedence = false;
		            }
		            position++;
		        }
	            connect.run = true;
	            command = "";
	        }
	        command = "";
                argument = "";
            }
            position = 0;
        }
    }
    return 0;
}
void parseinator(vector<string> input, string& command, string& argument, int& position, Connector& connect, string& flag)
{
    if (input[position] == "&") // check if string is equal to & connector
    {
        connect.type = 1; // set & connector to 1
        position += 2; // +=2 in order to take && connect
    }
    if (input[position] == "|")
    {
        connect.type = 2; // set | connector to 2
        position += 2; // +=2 in order to take || connector
    }
    if (input[position] == ";")
    {
        connect.type = 0; // set ; connector to 0
        position ++;
    }
    if (input[position] == "(")
    {
        connect.precedence = true;
        position++;
    }
    if (input[position] != "#")
    {
        command = input[position];
        position++;
    }
    if (command == "test")
    {
        if(input[position] == "-")
        {
            position++;
	    if (input[position] == "f")
            {
		flag = "-f";
		position++;
	    }
	    else if (input[position] == "d")
	    {
		flag = "-d";
		position++;
	    }
	    else // DEFAULT E
	    {
		flag = "-e";
		position++;
            }
        }
    }

    int input_size = input.size();
    for (; position < input_size; position++)
    {
        if (input[position] == ")")
        {
            connect.precedence = false;
            position++;
            break;
        }
        if(command == "echo" && input[position] == "\"")
        {
            position++;
            while(input[position] != "\"" && position <= input_size)
            {

                argument += input[position];
                if(!isalnum(input[position].at(0)) && !isalnum(input[position+1].at(0)))
                {

                }
                else
		{
                    argument += " ";
                }
		position++;
            }
            position++;
            break;
        }
        if (input[position] == "#")
        {
            position = input.size();
            break;
        }
        if (input[position] == "&" || input[position] == "|" || input[position] == ";")
	    {
            break;
    	}

        argument += input[position];
        int input_size1 = input.size();
        if (position+1 != input_size1 && command == "echo")
	{
	    //adds spaces when echoing
            argument += " ";
	}
    }
}
void commandifier(string command, string argument, Connector& connect, string flag)
{
    const char * const_command = command.c_str();
    char * char_command = new char[command.size()];
    const char * const_argument = argument.c_str();
    char * char_argument = new char[argument.size()];
    strcpy (char_command, const_command);
    strcpy (char_argument, const_argument);
    char * args[2]; // char pointer array that holds command, and NULL
    char * args1[3]; // char pointer array that holds command, argument, and NULL
    bool no_arg = true;
    bool failed = false;

    if(command == "test" || command == "[")
    {
	test_function(command,flag,argument,connect);
	return;
    }
    // exit command
    if(command == "exit" || argument == "exit")
    {
	exit(1);
    }

    if (argument.size() == 0) // no arguments
    {
        args[0] = char_command; // args will contain the command
        args[1] = NULL;
    }
    else
    {
	no_arg = false; // sets bool no_arg to false
	args1[0] = char_command; // args1 contains command and argument
        args1[1] = char_argument;
        args1[2] = NULL;
    }
    pid_t c_pid, pid; // data type to reporesent process ID's
    int status;
    c_pid = fork(); // create our fork

    if (c_pid < 0) // indicates the fork has fail if its less than 0
    {
        perror("fork failed");
        exit(1);
    }
    else if (c_pid == 0) // in child process
    {
 	if (no_arg) // no argument
	{
        	execvp( args[0], args); // execvp the char pointer array that holds the command only
        	if (execvp(args[0], args) == -1) // if it returns -1 it failed
                {
                    perror("execvp failed");
                    connect.run = false;
                    failed = true;
                }
		exit(3);
	}
	else // with command and argument
	{
		execvp(args1[0], args1); // execvp the char pointer array that holds the command, and argument
		if (execvp(args1[0], args1) == -1) // if it returns -1 it failed
                {
                    perror("execvp failed");
                    connect.run = false;
                    failed = true;
                }
		exit(3);
	}
    }
    else if (c_pid > 0) // parent process
    {
        if((pid = wait(&status)) < 0 )
        {
            perror("wait");
	    exit(3);
        }
        if (WIFEXITED(status))  //Evaluates to a non-zero value if status was returned for a child process that terminated normally.

        {
            if (WEXITSTATUS(status) != 0)
            {
                connect.run = false;
            }
	    else
	    {
		connect.run = true;
            }
        }
       else
        {
            connect.run = true;
        }
     }
}
void test_function(string command, string& flag, string argument, Connector &connect)
{
   const char * arg = argument.c_str();
   struct stat sb; // struct for the stat function
   cout<<flag<<endl;
   if(flag == "-f")
   {
        if(stat(arg,&sb) == 0)
        {
            connect.run = true;
	    if(S_ISREG(sb.st_mode))
	    {
 		connect.run = true;
	    }
	    else
	    {
		connect.run = false;
	    }
        }
        else
        {
            connect.run = false;
        }
   }
   else if(flag == "-d")
   {
        if(stat(arg,&sb) == 0)
        {
            connect.run = true;
            if(S_ISDIR(sb.st_mode))
            {
            	connect.run = true;
            }
            else
       	    {
             	connect.run = false;
            }
        }
        else
        {
            connect.run = false;
        }

   }
   else
   {
	if(stat(arg,&sb) == 0)
	{
	    connect.run = true;
 	}
	else
	{
	    connect.run = false;
	}
   }
}
<|endoftext|>


<commit_before>#include <queue>
#include <cstring>
#include <iostream>
#include <vector>
#include <string.h>
#include <unistd.h>
#include <boost/tokenizer.hpp>
#include <sys/utsname.h>

using namespace std;
using namespace boost;

// Cases to test:
// cd Desktop&&ls -a
// cd Desktop&[ENTER] ls -a
// cd Desktop;ls -a
// cd Desktop;ls
// ls;ls;ls;ls
// cd Desktop & ls -a
// cd Desktop;
// ls;
// cd Desktop||ls -a;vim touch.cpp&&[ENTER] ls -a
// cd Desktop
// ; clear
// && ls
// || ls -a
// NOTE: cd will NOT be tested or used!
// Re-read specs if unsure!!

void pcmd_prompt() {
    string login(getlogin());
    struct utsname hostname;
    uname(&hostname);
    string sysName(hostname.sysname);
    string machineName(hostname.machine);
    string nodeName(hostname.nodename);
    cout << login << "@" << nodeName << "$ ";
    // <sys/utsname.h> defines the struct utsname which includes info such as:
    // sysname, nodename, release, version, and machine
    // uname returns the struct with the wanted information
}

void parse_into_queue(queue<string> &l, const string &s) {
    char_separator<char> delim(" ", ";&|#") ;
    tokenizer<char_separator<char>> mytok(s, delim);

    for (auto i = mytok.begin(); i != mytok.end(); ++i) {
        l.push(*i);
    }
}

void init_cmd_queues(queue<string> &arg, queue<string> &con, queue<string> &l) {
     while (!l.empty()) {
         while (l.front() == "&" || l.front() == "|" || l.front() == ";") {
              con.push(l.front());
              l.pop();
         }
         arg.push(l.front());
         l.pop();
    }
}

void print_queue (queue<string> q) {
    while (!q.empty()) {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;
}

int main(int argc, char* argv[]) {
    // needs to be in while loop -- loop until "exit"
    string cmd_input;
    queue<string> list;
    pcmd_prompt();
    getline(cin, cmd_input);

    parse_into_queue(list, cmd_input);

    print_queue(list);

    // while list is NOT empty
        // get executable -- check if "exit"
            // if "exit" -- exit the ENTIRE program!!
            // else place into exec cstring
        // if valid connector -- "&&", "||", ";"
            // begin execution of exec and flags
            // return any errors
            // check logic to see if we continue through list -- break if needed
        // else if flag
            // place into flags cstrings
        // continue through list

    return 0;
}
<commit_msg>made rshell.cpp skeleton<commit_after>#include <queue>
#include <cstring>
#include <iostream>
#include <vector>
#include <string.h>
#include <unistd.h>
#include <boost/tokenizer.hpp>
#include <sys/utsname.h>

using namespace std;
using namespace boost;

// Cases to test:
// cd Desktop&&ls -a
// cd Desktop&[ENTER] ls -a
// cd Desktop;ls -a
// cd Desktop;ls
// ls;ls;ls;ls
// cd Desktop & ls -a
// cd Desktop;
// ls;
// cd Desktop||ls -a;vim touch.cpp&&[ENTER] ls -a
// cd Desktop
// ; clear
// && ls
// || ls -a
// NOTE: cd will NOT be tested or used!
// Re-read specs if unsure!!

// prints user and machine info
void pcmd_prompt() {
    // <sys/utsname.h> defines the struct utsname which includes info such as:
    // sysname, nodename, release, version, and machine
    // uname returns the struct with the wanted information

    string login(getlogin());
    struct utsname hostname;
    uname(&hostname);
    string nodeName(hostname.nodename);
    cout << login << "@" << nodeName << "$ ";
}

// parses input into queue for execution
void parse_into_queue(queue<string> &l, const string &s) {
    char_separator<char> delim(" ", ";&|#") ;
    tokenizer<char_separator<char>> mytok(s, delim);

    for (auto i = mytok.begin(); i != mytok.end(); ++i) {
        l.push(*i);
    }
}

// for testing purposes
void print_queue (queue<string> q) {
    if (q.empty()) {
        return;
    }
    while (!q.empty()) {
        cout << "[" << q.front() << "] ";
        q.pop();
    }
    cout << endl;
}

int main(int argc, char* argv[]) {
    // needs to be in while loop -- loop until "exit"
    string cmd_input;
    queue<string> list;
    pcmd_prompt();
    getline(cin, cmd_input);

    parse_into_queue(list, cmd_input);

    print_queue(list);

    cout << "init size: " << list.size() << endl;

    vector<string> cmd;
    while (!list.empty()) {
       while (!list.empty() && list.front() != "&" && list.front() != "|" && list.front() != ";") {
         cmd.push_back(list.front());
         list.pop();
       }

       if (cmd.size() == 0) {
           cout << "syntax error!" << endl;
           return 1;
       }
       else if (cmd.at(0) == "exit") {
         cout << "Exiting RShell" << endl;
         return 0;
       }
       else {
         // begin exec
         // return error flag
         // check logic to see if we continue
         // NOTE: cmd.at(0) = executable, everything else is flag
         if (cmd.size() == 1) {
             cout << "performing executable [" <<  cmd.at(0) << "] with NO flags";
         }
         else {
            cout << "performing executable [" <<  cmd.at(0) << "] with flags: ";
            for (int i = 1; i < cmd.size(); ++i) {
            cout << cmd.at(i) << " ";
            }
         }
         cout << endl;
       }

       cout << "queue size after processing cmd: " << list.size() << endl;
       print_queue(list);

       if (!list.empty() && list.front() == "&") {
         list.pop();
         if (list.front() == "&") {
             // check logic
             list.pop();
         }
         else {
             cout << "&" << list.front() << " is not a connector!" << endl;
             return 1;
         }
         cout << "queue size after processing connector: " << list.size() << endl;
         print_queue(list);
       }
       else if (!list.empty() && list.front() == "|") {
         list.pop();
         if (list.front() == "|") {
             // check logic
             list.pop();
          }
          else {
             cout << "|" << list.front() << " is not a connector!" << endl;
             return 1;
          }
          cout << "queue size after processing connector: " << list.size() << endl;
          print_queue(list);
       }
       else if (!list.empty() && list.front() == ";") {
         // go onto next
         list.pop();
         cout << "queue size after processing connector: " << list.size() << endl;
         print_queue(list);
       }
       else if (!list.empty())  {
         cout << list.front() <<  " is not a connector!" << endl;
         return 1;
       }
       else {
         cout << "queue size after processing connector: " << list.size() << endl;
         print_queue(list);
       }
       cmd.clear();
    }

    // while list is NOT empty
        // get executable -- check if "exit"
            // if "exit" -- exit the ENTIRE program!!
            // else place into exec cstring
        // if valid connector -- "&&", "||", ";"
            // begin execution of exec and flags
            // return any errors
            // check logic to see if we continue through list -- break if needed
        // else if flag
            // place into flags cstrings
        // continue through list

    return 0;
}
<|endoftext|>


<commit_before>#include<iostream>
#include<fcntl.h>
#include<pwd.h>
#include<sstream>
#include<stdio.h>
#include<boost/tokenizer.hpp>
#include<errno.h>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/unistd.h>

using namespace std;
using namespace boost;

typedef tokenizer<char_separator<char> > Tok;

void readCommands(string str);
int conjunct(int n, stringstream& ss, const Tok::iterator &it);
void skipCommand(Tok::iterator &it, Tok &tokens);
void splitString(char** args, stringstream& ss, int n);
void ioRedir(const Tok::iterator &it, bool inRedir, bool append);
void resetIO(int in0, int out1);
void pipeRedir(int fd[], int fdLoop[], bool pipeOut, bool isFirst, bool isLast, int n, stringstream& ss, const Tok::iterator &it, bool didRedir);

int main(){

    cout << endl;
    string str = "";
    struct passwd *pass;

    pass = getpwuid(getuid());
    if(pass == NULL){
        perror("getpwuid()");
    }

    char* usrname = pass->pw_name;
    char hostname[128];

    int success = gethostname(hostname, sizeof hostname);
    if(success == -1){
        perror("gethostname()");
    }

    string userinfo = "";
    string username = "";

    if(usrname != NULL && success == 0){
        username = usrname;
        userinfo = username + "@" + hostname;
    }

    bool notExited = true;

    while(notExited){
        cout << userinfo << "$ ";
        getline(cin, str);
        readCommands(str);
    }

    return 0;
}

void readCommands(string str){

    char_separator<char> sep("\" ", ";#|&<>");

    Tok tokens(str, sep);
    stringstream ss;
    int in0;
    int out1;
    int fd[2];
    int fdLoop[2];
    bool pipeOut = false; bool isFirst = true;
    bool didRedir = false;
    bool didPipe = false;
    int n = 0;

    if((in0 = dup(0)) == -1){
        perror("input-0");
        exit(-1);
    }

    if((out1 = dup(1)) == -1){
        perror("output-1");
        exit(-1);
    }

    if((pipe(fd)) == -1){
        perror("pipe");
        exit(-1);
    }

    for(Tok::iterator it = tokens.begin(); it != tokens.end(); it++){

        if(*it == ";"){
            conjunct(n, ss, it);
            n = 0;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it ==  "&"){
            if(conjunct(n, ss, it) == -1){
                skipCommand(it, tokens);
            }
            n = 0;
            if(it == tokens.end()) break;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it == "|"){
            Tok::iterator copy = it;
            copy++;

            if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                conjunct(0, ss, it);
                skipCommand(it, tokens);
                return;
            }

            if(*copy == "|"){
                copy++;
                if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                    conjunct(0, ss, it);
                    skipCommand(it, tokens);
                    return;
                }

                if(conjunct(n, ss, it) != -1){
                    skipCommand(it, tokens);
                }
            }
            else{
//TODO piping
                didPipe = true;

                (!pipeOut) ? pipeOut = true : pipeOut = false;

                pipeRedir(fd, fdLoop, pipeOut, isFirst, false, n, ss, it, didRedir);
                sFirst = false;

                n = 0;
                continue;
            }

            n = 0;
            if(it == tokens.end()) break;
            it++;
        }
        else if(*it == "<" || *it == ">"){

            another:

            bool inRedir = false;
            bool append = false;

            if(*it == "<") inRedir = true;

            it++;

            here:

            if(it == tokens.end()){
                cerr << "Bash: syntax error near unexpected token \'newline\'" << endl;
                exit(-1);
            }

            if(*it == ">"){
                append = true;
                it++;
                goto here;
            }

            ioRedir(it, inRedir, append);

            didRedir = true;

            Tok::iterator copy = it;
            copy++;

            if(copy == tokens.end()) break;

            if(*copy == ">" || *copy == "<"){
                goto another;
                it++;
            }
        }

        if(*it == "#"){
            conjunct(n, ss, it);
            return;
        }

        if(*it != "&" && *it != "|"){
            ss << *it;
            ss << " ";
            n++;
        }
    }
//TODO piping
    if(n > 0){
        Tok::iterator it = tokens.begin();
        if(didPipe){
            (!pipeOut) ? pipeOut = true : pipeOut = false;
            pipeRedir(fd, fdLoop,  pipeOut, isFirst, true, n, ss, it, didRedir);
        }
        else{
            conjunct(n, ss, it);
        }
    }

    if(didRedir){
        resetIO(in0, out1);
    }
}

int conjunct(int n, stringstream& ss, const Tok::iterator &it){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return -1;
    }
    else if(n == 0 && *it == "#") return 0;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    int pid = fork();

    if(pid == -1){
        perror("There was an error with the fork().");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp((const char*) args[0], (char* const*) args)){
            perror(args[0]);
            exit(3);
        }
    }
    else if(pid > 0){

        if(-1 == wait(&status)){
            perror("There was an error with wait().");
            return -1;
        }

        if(WIFEXITED(status)){
            if(WEXITSTATUS(status) == 3){
                delete[] args;
                return -1;
            }
        }
    }

    delete[] args;

    return 0;
}

void ioRedir(const Tok::iterator &it, bool inRedir, bool append){

    if(*it == "&" || *it == "|" || *it == ";"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        exit(-1);
    }

    if(inRedir){
        string input = *it;

        int fdi;

        if((fdi = open((char*) input.c_str(), O_RDONLY)) == -1){
            perror("open input");
            exit(-1);
        }

        if(close(0) == -1){
            perror("close input");
            exit(-1);
        }

        if(dup(fdi) == -1){
            perror("dup input");
            exit(-1);
        }
        return;
    }
    else{
        string output = *it;

        int fdo;
        mode_t readWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

        if(append){
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_APPEND,  readWrite)) == -1){
                perror("open output");
                exit(-1);
            }
        }
        else{
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_TRUNC,  readWrite)) == -1){
                perror("open output append");
                exit(-1);
            }
        }

        if(close(1) == -1){
            perror("close output");
            exit(-1);
        }

        if(dup(fdo) == -1){
            perror("dup output");
            exit(-1);
        }
    }
}

void resetIO(int in0, int out1){

    if(dup2(in0, 0) == -1){
        perror("dup input - 0");
        exit(-1);
    }

    if(dup2(out1, 1) == -1){
        perror("dup output - 1");
        exit(-1);
    }
}

//TODO piping
void pipeRedir(int fd[], int fdLoop[], bool pipeOut, bool isFirst, bool isLast, int n, stringstream& ss, const Tok::iterator& it, bool didRedir){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return;
    }
    else if(n == 0 && *it == "#") return;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    if(pipeOut){
        int pid;

        if(!isFirst){
            if(pipe(fd) == -1){
                perror("repipe fd in input");
                exit(-1);
            }
        }

        if((pid = fork()) == -1){
            perror("fork in pipe");
            exit(-1);
        }

        if(pid == 0){
            if(isFirst){
                if(close(fd[0]) == -1){
                    perror("close in pipe");
                    exit(-1);
                }
            }

            if(!isFirst){
                if(dup2(fdLoop[0], 0) == -1){
                    perror("dup2 fdLoop in input");
                    exit(-1);
                }
            }

            if(!isLast){
                if(dup2(fd[1], 1) == -1){
                    perror("dup2 in pipe");
                    exit(-1);
                }
            }
            //TODO execute command here

            if(-1 == execvp((const char*) args[0], (char* const*) args)){
                perror("execvp in pipe");
                exit(-1);
            }
        }
        else{
            if(wait(&status) == -1){
                perror("wait in pipe");
                exit(-1);
            }

            if(close(fd[1]) == -1){
                perror("close in pipe parent");
                exit(-1);
            }

            if(!isFirst){
                if(close(fdLoop[0]) == -1){
                    perror("close fdLoop in input");
                    exit(-1);
                }
            }

            if(WIFEXITED(status)){
                if(WEXITSTATUS(status) == 3){
                    exit(-1);
                }
            }

        }
    }
    else{
        int pid;
        if(!isLast){
            if(pipe(fdLoop) == -1){
                    perror("fdLoop in output");
                    exit(-1);
            }
        }

        if((pid = fork()) == -1){
            perror("fork#2 in pipe");
            exit(-1);
        }

        if(pid == 0){

            if(dup2(fd[0], 0) == -1){
                perror("dup2 #2 in pipe");
                exit(-1);
            }

            //TODO execute command here

            if(!isLast){
                if(dup2(fdLoop[1], 1) == -1){
                    perror("dup2 loop in output");
                    exit(-1);
                }
            }

            if(-1 == execvp((const char*) args[0], (char* const*) args)){
                perror("execvp in pipe");
                exit(-1);
            }

        }
        else{

            if(wait(&status) == -1){
                perror("wait #2 in pipe");
                exit(-1);
            }

            if(close(fd[0]) == -1){
                perror("close #2 in pipe parent");
                exit(-1);
            }

            if(!isLast){
                if(close(fdLoop[1]) == -1){
                    perror("close fdLoop in output");
                    exit(-1);
                }
            }
            if(WIFEXITED(status)){
                if(WEXITSTATUS(status) == 3){
                    exit(-1);
                }
            }
        }
    }
}

void skipCommand(Tok::iterator &it, Tok &tokens){
    while(it != tokens.end() && *it != ";"){
        it++;
    }
}

void splitString(char** args, stringstream& ss, int n){

    string *str = new string[n];

    for(int i = 0; i < n; i++){

        ss >> str[i];

        args[i] = (char*) str[i].c_str();
    }

    args[n] = NULL;

    char exitC[] = "exit";

    if(strcmp(args[0], exitC) == 0){
        cout << endl;
        exit(0);
    }

    delete[] str;
}
<commit_msg>made some adjustments<commit_after>#include<iostream>
#include<fcntl.h>
#include<pwd.h>
#include<sstream>
#include<stdio.h>
#include<boost/tokenizer.hpp>
#include<errno.h>
#include<string>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/unistd.h>

using namespace std;
using namespace boost;

typedef tokenizer<char_separator<char> > Tok;

void readCommands(string str);
int conjunct(int n, stringstream& ss, const Tok::iterator &it);
void skipCommand(Tok::iterator &it, Tok &tokens);
void splitString(char** args, stringstream& ss, int n);
bool ioRedir(const Tok::iterator &it, bool inRedir, bool append);
void resetIO(int in0, int out1);
void pipeRedir(int fd[], int fdLoop[], bool pipeOut, bool isFirst, bool isLast, int n, stringstream& ss, const Tok::iterator &it, bool didRedir);

int main(){

    cout << endl;
    string str = "";
    struct passwd *pass;

    pass = getpwuid(getuid());
    if(pass == NULL){
        perror("getpwuid()");
    }

    char* usrname = pass->pw_name;
    char hostname[128];

    int success = gethostname(hostname, sizeof hostname);
    if(success == -1){
        perror("gethostname()");
    }

    string userinfo = "";
    string username = "";

    if(usrname != NULL && success == 0){
        username = usrname;
        userinfo = username + "@" + hostname;
    }

    bool notExited = true;

    while(notExited){
        cout << userinfo << "$ ";
        getline(cin, str);
        readCommands(str);
    }

    return 0;
}

void readCommands(string str){

    char_separator<char> sep("\" ", ";#|&<>");

    Tok tokens(str, sep);
    stringstream ss;
    int in0;
    int out1;
    int fd[2];
    int fdLoop[2];
    bool pipeOut = false; bool isFirst = true;
    bool didRedir = false;
    bool didPipe = false;
    int n = 0;

    if((in0 = dup(0)) == -1){
        perror("input-0");
        exit(-1);
    }

    if((out1 = dup(1)) == -1){
        perror("output-1");
        exit(-1);
    }

    if((pipe(fd)) == -1){
        perror("pipe");
        exit(-1);
    }

    for(Tok::iterator it = tokens.begin(); it != tokens.end(); it++){

        begin:

        if(*it == ";"){
            conjunct(n, ss, it);
            n = 0;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it ==  "&"){
            if(conjunct(n, ss, it) == -1){
                skipCommand(it, tokens);
            }
            n = 0;
            if(it == tokens.end()) break;
            it++;
            if(it == tokens.end()) break;
        }
        else if(*it == "|"){
            Tok::iterator copy = it;
            copy++;

            if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                conjunct(0, ss, it);
                skipCommand(it, tokens);
                return;
            }

            if(*copy == "|"){
                copy++;
                if(copy == tokens.end() || *copy == ";" || *copy == "&"){
                    conjunct(0, ss, it);
                    skipCommand(it, tokens);
                    return;
                }

                if(conjunct(n, ss, it) != -1){
                    skipCommand(it, tokens);
                }
            }
            else{
//TODO piping
                didPipe = true;

                (!pipeOut) ? pipeOut = true : pipeOut = false;

                pipeRedir(fd, fdLoop, pipeOut, isFirst, false, n, ss, it, didRedir);
                isFirst = false;

                n = 0;
                continue;
            }

            n = 0;
            if(it == tokens.end()) break;
            it++;
        }
        else if(*it == "<" || *it == ">"){
            bool append = false;

another:
            Tok::iterator check = it;
            check++;
            bool inRedir = false;
            bool stringRedir = false;

            if(check != tokens.end() && *check == ">"){
                append = true;
                it++;
                goto here;
            }

            if(*it == "<"){
                inRedir = true;
                Tok::iterator copy = it;
                int i;
                for(i = 0; i < 2; i++){
                    copy++;
                    if(copy == tokens.end() || *copy != "<") break;
                }

                if(i == 2 && copy != tokens.end() && *copy != ";" && *copy != "|" && *copy != "&"){
                    stringRedir = true;
                }
            }

            if(stringRedir){
                it++; it++; it++;
                string redirString = "";

                while(it != tokens.end() && *it != ";" && *it != "|" && *it != "&"){
                    redirString += (*it + " ");
                    it++;
                }

                if(write(0, (char*) redirString.c_str(), redirString.size() + 1) == -1){
                    perror("write to extra");
                    return;
                }

                if(it == tokens.end()){
                    break;
                }
                else{
                    goto begin;
                }

            }
here:
            it++;

            if(it == tokens.end()){
                cerr << "Bash: syntax error near unexpected token \'newline\'" << endl;
                exit(-1);
            }

            if(!ioRedir(it, inRedir, append)) return;

            didRedir = true;

            Tok::iterator copy = it;
            copy++;

            if(copy == tokens.end()) break;

            if(*copy == ">" || *copy == "<"){
                it++;
                goto another;
            }
        }

        if(*it == "#"){
            conjunct(n, ss, it);
            return;
        }

        if(*it != "&" && *it != "|"){
            ss << *it;
            ss << " ";
            n++;
        }
    }
    //TODO piping
    if(n > 0){
        Tok::iterator it = tokens.begin();
        if(didPipe){
            (!pipeOut) ? pipeOut = true : pipeOut = false;
            pipeRedir(fd, fdLoop,  pipeOut, isFirst, true, n, ss, it, didRedir);
        }
        else{
            conjunct(n, ss, it);
        }
    }

    if(didRedir){
        resetIO(in0, out1);
    }
}

int conjunct(int n, stringstream& ss, const Tok::iterator &it){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return -1;
    }
    else if(n == 0 && *it == "#") return 0;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    int pid = fork();

    if(pid == -1){
        perror("There was an error with the fork().");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp((const char*) args[0], (char* const*) args)){
            perror(args[0]);
            exit(3);
        }
    }
    else if(pid > 0){

        if(-1 == wait(&status)){
            perror("There was an error with wait().");
            return -1;
        }

        if(WIFEXITED(status)){
            if(WEXITSTATUS(status) == 3){
                delete[] args;
                return -1;
            }
        }
    }

    delete[] args;

    return 0;
}

bool ioRedir(const Tok::iterator &it, bool inRedir, bool append){

    if(*it == "&" || *it == "|" || *it == ";"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return false;
    }

    if(inRedir){
        string input = *it;

        int fdi;

        if((fdi = open((char*) input.c_str(), O_RDONLY)) == -1){
            perror("open input");
            return false;
        }

        if(close(0) == -1){
            perror("close input");
            exit(-1);
        }

        if(dup(fdi) == -1){
            perror("dup input");
            exit(-1);
        }
        return true;
    }
    else{
        string output = *it;

        int fdo;
        mode_t readWrite = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

        if(append){
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_APPEND,  readWrite)) == -1){
                perror("open output");
                exit(-1);
            }
        }
        else{
            if((fdo = open((char*) output.c_str(), O_RDWR | O_CREAT | O_TRUNC,  readWrite)) == -1){
                perror("open output append");
                exit(-1);
            }
        }

        if(close(1) == -1){
            perror("close output");
            exit(-1);
        }

        if(dup(fdo) == -1){
            perror("dup output");
            exit(-1);
        }
    }

    return true;
}

void resetIO(int in0, int out1){

    if(dup2(in0, 0) == -1){
        perror("dup input - 0");
        exit(-1);
    }

    if(dup2(out1, 1) == -1){
        perror("dup output - 1");
        exit(-1);
    }
}

//TODO piping
void pipeRedir(int fd[], int fdLoop[], bool pipeOut, bool isFirst, bool isLast, int n, stringstream& ss, const Tok::iterator& it, bool didRedir){

    int status;

    if(n == 0 && *it != "#"){
        cerr << "Bash: syntax error near unexpected token \'" << *it << "\'" << endl;
        return;
    }
    else if(n == 0 && *it == "#") return;
    char** args = new char*[n + 1];

    splitString(args, ss, n);

    if(pipeOut){
        int pid;

        if(!isFirst){
            if(pipe(fd) == -1){
                perror("repipe fd in input");
                exit(-1);
            }
        }

        if((pid = fork()) == -1){
            perror("fork in pipe");
            exit(-1);
        }

        if(pid == 0){
            if(isFirst){
                if(close(fd[0]) == -1){
                    perror("close in pipe");
                    exit(-1);
                }
            }

            if(!isFirst){
                if(dup2(fdLoop[0], 0) == -1){
                    perror("dup2 fdLoop in input");
                    exit(-1);
                }
            }

            if(!isLast){
                if(dup2(fd[1], 1) == -1){
                    perror("dup2 in pipe");
                    exit(-1);
                }
            }
            //TODO execute command here

            if(-1 == execvp((const char*) args[0], (char* const*) args)){
                perror("execvp in pipe");
                exit(-1);
            }
        }
        else{
            if(wait(&status) == -1){
                perror("wait in pipe");
                exit(-1);
            }

            if(close(fd[1]) == -1){
                perror("close in pipe parent");
                exit(-1);
            }

            if(!isFirst){
                if(close(fdLoop[0]) == -1){
                    perror("close fdLoop in input");
                    exit(-1);
                }
            }

            if(WIFEXITED(status)){
                if(WEXITSTATUS(status) == 3){
                    exit(-1);
                }
            }

        }
    }
    else{
        int pid;
        if(!isLast){
            if(pipe(fdLoop) == -1){
                perror("fdLoop in output");
                exit(-1);
            }
        }

        if((pid = fork()) == -1){
            perror("fork#2 in pipe");
            exit(-1);
        }

        if(pid == 0){

            if(dup2(fd[0], 0) == -1){
                perror("dup2 #2 in pipe");
                exit(-1);
            }

            //TODO execute command here

            if(!isLast){
                if(dup2(fdLoop[1], 1) == -1){
                    perror("dup2 loop in output");
                    exit(-1);
                }
            }

            if(-1 == execvp((const char*) args[0], (char* const*) args)){
                perror("execvp in pipe");
                exit(-1);
            }

        }
        else{

            if(wait(&status) == -1){
                perror("wait #2 in pipe");
                exit(-1);
            }

            if(close(fd[0]) == -1){
                perror("close #2 in pipe parent");
                exit(-1);
            }

            if(!isLast){
                if(close(fdLoop[1]) == -1){
                    perror("close fdLoop in output");
                    exit(-1);
                }
            }
            if(WIFEXITED(status)){
                if(WEXITSTATUS(status) == 3){
                    exit(-1);
                }
            }
        }
    }
}

void skipCommand(Tok::iterator &it, Tok &tokens){
    while(it != tokens.end() && *it != ";"){
        it++;
    }
}

void splitString(char** args, stringstream& ss, int n){

    string *str = new string[n];

    for(int i = 0; i < n; i++){

        ss >> str[i];

        args[i] = (char*) str[i].c_str();
    }

    args[n] = NULL;

    char exitC[] = "exit";

    if(strcmp(args[0], exitC) == 0){
        cout << endl;
        exit(0);
    }

    delete[] str;
}
<|endoftext|>


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: geom/prep/PreparedPolygonPredicate.java rev. 1.4 (JTS-1.10)
 * (2007-12-12)
 *
 **********************************************************************/

#include <geos/geom/prep/PreparedPolygonPredicate.h>
#include <geos/geom/prep/PreparedPolygon.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/util/ComponentCoordinateExtracter.h>
#include <geos/geom/Location.h>
#include <geos/algorithm/locate/PointOnGeometryLocator.h>
#include <geos/algorithm/locate/SimplePointInAreaLocator.h>
// std
#include <cstddef>

namespace geos {
namespace geom { // geos.geom
namespace prep { // geos.geom.prep
//
// private:
//

//
// protected:
//
bool
PreparedPolygonPredicate::isAllTestComponentsInTarget(const geom::Geometry* testGeom) const
{
    geom::Coordinate::ConstVect pts;
    geom::util::ComponentCoordinateExtracter::getCoordinates(*testGeom, pts);

    for(std::size_t i = 0, ni = pts.size(); i < ni; i++) {
        const geom::Coordinate* pt = pts[i];
        const int loc = prepPoly->getPointLocator()->locate(pt);
        if(geom::Location::EXTERIOR == loc) {
            return false;
        }
    }
    return true;
}

bool
PreparedPolygonPredicate::isAllTestComponentsInTargetInterior(
    const geom::Geometry* testGeom) const
{
    geom::Coordinate::ConstVect pts;
    geom::util::ComponentCoordinateExtracter::getCoordinates(*testGeom, pts);

    for(std::size_t i = 0, ni = pts.size(); i < ni; i++) {
        const geom::Coordinate* pt = pts[i];
        const int loc = prepPoly->getPointLocator()->locate(pt);
        if(geom::Location::INTERIOR != loc) {
            return false;
        }
    }
    return true;
}

bool
PreparedPolygonPredicate::isAnyTestComponentInTarget(
    const geom::Geometry* testGeom) const
{
    geom::Coordinate::ConstVect pts;
    geom::util::ComponentCoordinateExtracter::getCoordinates(*testGeom, pts);

    for(std::size_t i = 0, ni = pts.size(); i < ni; i++) {
        const Coordinate* pt = pts[i];
        const int loc = prepPoly->getPointLocator()->locate(pt);
        if(geom::Location::EXTERIOR != loc) {
            return true;
        }
    }
    return false;
}

bool
PreparedPolygonPredicate::isAnyTestComponentInTargetInterior(
    const geom::Geometry* testGeom) const
{
    if (testGeom->getGeometryTypeId() == GEOS_POINT) {
        // Avoid creating a vector to store a single point
        return prepPoly->getPointLocator()->locate(testGeom->getCoordinate()) == geom::Location::INTERIOR;
    }

    geom::Coordinate::ConstVect pts;
    geom::util::ComponentCoordinateExtracter::getCoordinates(*testGeom, pts);

    for(std::size_t i = 0, ni = pts.size(); i < ni; i++) {
        const Coordinate* pt = pts[i];
        const int loc = prepPoly->getPointLocator()->locate(pt);
        if(geom::Location::INTERIOR == loc) {
            return true;
        }
    }
    return false;
}

bool
PreparedPolygonPredicate::isAnyTargetComponentInAreaTest(
    const geom::Geometry* testGeom,
    const geom::Coordinate::ConstVect* targetRepPts) const
{
    algorithm::locate::SimplePointInAreaLocator piaLoc(testGeom);

    for(std::size_t i = 0, ni = targetRepPts->size(); i < ni; i++) {
        const geom::Coordinate* pt = (*targetRepPts)[i];
        const int loc = piaLoc.locate(pt);
        if(geom::Location::EXTERIOR != loc) {
            return true;
        }
    }

    return false;
}

//
// public:
//

} // namespace geos.geom.prep
} // namespace geos.geom
} // namespace geos
<commit_msg>Use custom GeometryComponentFilter in PreparedPolygonPredicate to avoid creating vectors<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: geom/prep/PreparedPolygonPredicate.java rev. 1.4 (JTS-1.10)
 * (2007-12-12)
 *
 **********************************************************************/

#include <geos/geom/prep/PreparedPolygonPredicate.h>
#include <geos/geom/prep/PreparedPolygon.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateFilter.h>
#include <geos/geom/util/ComponentCoordinateExtracter.h>
#include <geos/geom/Location.h>
#include <geos/algorithm/locate/PointOnGeometryLocator.h>
#include <geos/algorithm/locate/SimplePointInAreaLocator.h>
// std
#include <cstddef>

namespace geos {
namespace geom { // geos.geom
namespace prep { // geos.geom.prep
//
// private:
//

//
// protected:
//
struct AnyMatchingLocationFilter : public GeometryComponentFilter {
    explicit AnyMatchingLocationFilter(algorithm::locate::PointOnGeometryLocator* locator, int loc) :
        pt_locator(locator), test_loc(loc), found(false) {}

    algorithm::locate::PointOnGeometryLocator* pt_locator;
    const int test_loc;
    bool found;

    void filter_ro(const Geometry* g) override {
        auto pt = g->getCoordinate();
        if (!found) {
            const int loc = pt_locator->locate(pt);
            if (loc == test_loc) {
                found = true;
            }
        }
    }
};

struct AnyNotMatchingLocationFilter : public GeometryComponentFilter {
    explicit AnyNotMatchingLocationFilter(algorithm::locate::PointOnGeometryLocator* locator, int loc) :
            pt_locator(locator), test_loc(loc), found(false) {}

    algorithm::locate::PointOnGeometryLocator* pt_locator;
    const int test_loc;
    bool found;

    void filter_ro(const Geometry* g) override {
        auto pt = g->getCoordinate();
        if (!found) {
            const int loc = pt_locator->locate(pt);
            if (loc != test_loc) {
                found = true;
            }
        }
    }
};

bool
PreparedPolygonPredicate::isAllTestComponentsInTarget(const geom::Geometry* testGeom) const
{
    AnyMatchingLocationFilter filter(prepPoly->getPointLocator(), geom::Location::EXTERIOR);
    testGeom->apply_ro(&filter);

    return !filter.found;
}

bool
PreparedPolygonPredicate::isAllTestComponentsInTargetInterior(
    const geom::Geometry* testGeom) const
{
    AnyNotMatchingLocationFilter filter(prepPoly->getPointLocator(), geom::Location::INTERIOR);
    testGeom->apply_ro(&filter);

    return !filter.found;
}

bool
PreparedPolygonPredicate::isAnyTestComponentInTarget(
    const geom::Geometry* testGeom) const
{
    AnyNotMatchingLocationFilter filter(prepPoly->getPointLocator(), geom::Location::EXTERIOR);
    testGeom->apply_ro(&filter);

    return filter.found;
}

bool
PreparedPolygonPredicate::isAnyTestComponentInTargetInterior(
    const geom::Geometry* testGeom) const
{
    AnyMatchingLocationFilter filter(prepPoly->getPointLocator(), geom::Location::INTERIOR);
    testGeom->apply_ro(&filter);

    return filter.found;
}

bool
PreparedPolygonPredicate::isAnyTargetComponentInAreaTest(
    const geom::Geometry* testGeom,
    const geom::Coordinate::ConstVect* targetRepPts) const
{
    algorithm::locate::SimplePointInAreaLocator piaLoc(testGeom);

    for(std::size_t i = 0, ni = targetRepPts->size(); i < ni; i++) {
        const geom::Coordinate* pt = (*targetRepPts)[i];
        const int loc = piaLoc.locate(pt);
        if(geom::Location::EXTERIOR != loc) {
            return true;
        }
    }

    return false;
}

//
// public:
//

} // namespace geos.geom.prep
} // namespace geos.geom
} // namespace geos
<|endoftext|>


<commit_before><commit_msg>chromeos: Fix infinite recursion caused by typo<commit_after><|endoftext|>


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

/**
 * \file ir_expression_flattening.cpp
 *
 * Takes the leaves of expression trees and makes them dereferences of
 * assignments of the leaves to temporaries, according to a predicate.
 *
 * This is used for automatic function inlining, where we want to take
 * an expression containing a call and move the call out to its own
 * assignment so that we can inline it at the appropriate place in the
 * instruction stream.
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class ir_expression_flattening_visitor : public ir_visitor {
public:
   ir_expression_flattening_visitor(ir_instruction *base_ir,
				    bool (*predicate)(ir_instruction *ir))
   {
      this->base_ir = base_ir;
      this->predicate = predicate;

      /* empty */
   }

   virtual ~ir_expression_flattening_visitor()
   {
      /* empty */
   }

   /**
    * \name Visit methods
    *
    * As typical for the visitor pattern, there must be one \c visit method for
    * each concrete subclass of \c ir_instruction.  Virtual base classes within
    * the hierarchy should not have \c visit methods.
    */
   /*@{*/
   virtual void visit(ir_variable *);
   virtual void visit(ir_loop *);
   virtual void visit(ir_loop_jump *);
   virtual void visit(ir_function_signature *);
   virtual void visit(ir_function *);
   virtual void visit(ir_expression *);
   virtual void visit(ir_swizzle *);
   virtual void visit(ir_dereference_variable *);
   virtual void visit(ir_dereference_array *);
   virtual void visit(ir_dereference_record *);
   virtual void visit(ir_assignment *);
   virtual void visit(ir_constant *);
   virtual void visit(ir_call *);
   virtual void visit(ir_return *);
   virtual void visit(ir_if *);
   /*@}*/

   bool (*predicate)(ir_instruction *ir);
   ir_instruction *base_ir;
};

void
do_expression_flattening(exec_list *instructions,
			 bool (*predicate)(ir_instruction *ir))
{
   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();

      ir_expression_flattening_visitor v(ir, predicate);
      ir->accept(&v);
   }
}

void
ir_expression_flattening_visitor::visit(ir_variable *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_loop *ir)
{
   do_expression_flattening(&ir->body_instructions, this->predicate);
}

void
ir_expression_flattening_visitor::visit(ir_loop_jump *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_function_signature *ir)
{
   do_expression_flattening(&ir->body, this->predicate);
}

void
ir_expression_flattening_visitor::visit(ir_function *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_expression *ir)
{
   unsigned int operand;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      ir->operands[operand]->accept(this);

      /* If the operand matches the predicate, then we'll assign its
       * value to a temporary and deref the temporary as the operand.
       */
      if (this->predicate(ir->operands[operand])) {
	 ir_variable *var;
	 ir_assignment *assign;

	 var = new ir_variable(ir->operands[operand]->type, "flattening_tmp");
	 this->base_ir->insert_before(var);

	 assign = new ir_assignment(new ir_dereference_variable(var),
				    ir->operands[operand],
				    NULL);
	 this->base_ir->insert_before(assign);

	 ir->operands[operand] = new ir_dereference_variable(var);
      }
   }
}

void
ir_expression_flattening_visitor::visit(ir_swizzle *ir)
{
   ir->val->accept(this);
}

void
ir_expression_flattening_visitor::visit(ir_dereference_variable *ir)
{
   ir->var->accept(this);
}

void
ir_expression_flattening_visitor::visit(ir_dereference_array *ir)
{
   ir->array_index->accept(this);
   ir->array->accept(this);
}

void
ir_expression_flattening_visitor::visit(ir_dereference_record *ir)
{
   ir->record->accept(this);
}

void
ir_expression_flattening_visitor::visit(ir_assignment *ir)
{
   ir->rhs->accept(this);
}

void
ir_expression_flattening_visitor::visit(ir_constant *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_call *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_return *ir)
{
   (void) ir;
}

void
ir_expression_flattening_visitor::visit(ir_if *ir)
{
   ir->condition->accept(this);

   do_expression_flattening(&ir->then_instructions, this->predicate);
   do_expression_flattening(&ir->else_instructions, this->predicate);
}
<commit_msg>Reimplement ir_expression_flattening_visitor using ir_hierarchical_vistor<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file ir_expression_flattening.cpp
 *
 * Takes the leaves of expression trees and makes them dereferences of
 * assignments of the leaves to temporaries, according to a predicate.
 *
 * This is used for automatic function inlining, where we want to take
 * an expression containing a call and move the call out to its own
 * assignment so that we can inline it at the appropriate place in the
 * instruction stream.
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class ir_expression_flattening_visitor : public ir_hierarchical_visitor {
public:
   ir_expression_flattening_visitor(ir_instruction *base_ir,
				    bool (*predicate)(ir_instruction *ir))
   {
      this->base_ir = base_ir;
      this->predicate = predicate;
   }

   virtual ~ir_expression_flattening_visitor()
   {
      /* empty */
   }

   virtual ir_visitor_status visit_enter(ir_call *);
   virtual ir_visitor_status visit_enter(ir_return *);
   virtual ir_visitor_status visit_leave(ir_expression *);

   bool (*predicate)(ir_instruction *ir);
   ir_instruction *base_ir;
};

void
do_expression_flattening(exec_list *instructions,
			 bool (*predicate)(ir_instruction *ir))
{
   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();

      ir_expression_flattening_visitor v(ir, predicate);
      ir->accept(&v);
   }
}

ir_visitor_status
ir_expression_flattening_visitor::visit_leave(ir_expression *ir)
{
   unsigned int operand;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      /* If the operand matches the predicate, then we'll assign its
       * value to a temporary and deref the temporary as the operand.
       */
      if (this->predicate(ir->operands[operand])) {
	 ir_variable *var;
	 ir_assignment *assign;

	 var = new ir_variable(ir->operands[operand]->type, "flattening_tmp");
	 this->base_ir->insert_before(var);

	 assign = new ir_assignment(new ir_dereference_variable(var),
				    ir->operands[operand],
				    NULL);
	 this->base_ir->insert_before(assign);

	 ir->operands[operand] = new ir_dereference_variable(var);
      }
   }

   return visit_continue;
}

ir_visitor_status
ir_expression_flattening_visitor::visit_enter(ir_call *ir)
{
   /* FINISHME: Why not process the call parameters? (Same behavior as original
    * FINISHME: code.)
    */
   (void) ir;
   return visit_continue_with_parent;
}

ir_visitor_status
ir_expression_flattening_visitor::visit_enter(ir_return *ir)
{
   /* FINISHME: Why not process the return value? (Same behavior as original
    * FINISHME: code.)
    */
   (void) ir;
   return visit_continue_with_parent;
}
<|endoftext|>


<commit_before>//
// Created by Andrei Formiga on 2/3/17.
//

#include <string>
#include <cstdlib>
#include "lexer.h"

/// O token atual
Token tok;

/// O arquivo/stream de onde o lexer le caracteres
FILE *stream;

/// buffer de caracteres para o lexer
int buffer;
bool bufferValid = false;

int getNextChar() {
    if (!bufferValid)
        buffer = getc(stream);
    else
        bufferValid = false;
    return buffer;
}

void returnChar(int c) {
    buffer = c;
    bufferValid = true;
}

/// Inicializa o lexer
void initLexer(FILE *f) {
    bufferValid = false;
    stream = f;
}

void testLexer() {
    // TODO: testar o analisador lexico
}

char *palavrasChave[] = { "int", "printf", "printint", "return"};

int identificaPalavraChave(const char *s) {
    for (int i = 0; i < 4; ++i) {
        if (strcmp(s, palavrasChave[i]) == 0)
            return i;
    }

    return -1;
}

void lexerError(const char *err) {
    fprintf(stderr, "Erro lexico: %s\n", err);
    exit(1);
}

const char* printTokenType(Token &tok) {
    switch (tok.type) {
        case TokType::PalavraChave:
            return "PCHAVE";
        case TokType::Identificador:
            return "ID";
        case TokType::LiteralNum:
            return "NUM";
        case TokType::Operador:
            return "OP";
        case TokType::Eof:
            return "EOF";
        case TokType::Pontuacao:
            return "PONT";
    }
}

Token *getNextToken() {
    int c = getNextChar();

    // pula espaco em branco
    while (isspace(c))
        c = getNextChar();

    bool done = false;
    while (!done) {
        switch (c) {
            case '/':
                c = getNextChar();
                if (c != '/') {
                    lexerError("comentario esperado");
                    return nullptr;
                }
                while (c != '\n')
                    c = getNextChar();
                c = getNextChar();
                break;

            case '+':
                tok.type = TokType::Operador;
                tok.val = OpSoma;
                done = true;
                break;

            case '*':
                tok.type = TokType::Operador;
                tok.val = OpMult;
                done = true;
                break;

            case '<':
                tok.type = TokType::Operador;
                tok.val = OpLt;
                done = true;
                break;

            case '=':
                tok.type = TokType::Operador;
                c = getNextChar();
                if (c == '=')
                    tok.val = OpEq;
                else {
                    tok.val = OpAssign;
                    returnChar(c);
                }
                done = true;
                break;

            case '(':
                tok.type = TokType::Pontuacao;
                tok.val = LParen;
                done = true;
                break;

            case ')':
                tok.type = TokType::Pontuacao;
                tok.val = RParen;
                done = true;
                break;

            case '{':
                tok.type = TokType::Pontuacao;
                tok.val = LBrace;
                done = true;
                break;

            case '}':
                tok.type = TokType::Pontuacao;
                tok.val = RBrace;
                done = true;
                break;

            case ',':
                tok.type = TokType::Pontuacao;
                tok.val = Comma;
                done = true;
                break;

            case ';':
                tok.type = TokType::Pontuacao;
                tok.val = Semicolon;
                done = true;
                break;

            case EOF:
                tok.type = TokType::Eof;
                done = true;
                break;

            default:
                if (isdigit(c)) {
                    std::string num;

                    while (isdigit(c)) {
                        num += c;
                        c = getNextChar();
                    }
                    returnChar(c);
                    tok.type = TokType::LiteralNum;
                    tok.val = atoi(num.c_str());
                    done = true;
                } else if (isalpha(c)) {
                    std::string s;

                    while (isalnum(c)) {
                        s += c;
                        c = getNextChar();
                    }
                    returnChar(c);

                    int ix = identificaPalavraChave(s.c_str());
                    if (ix == -1) {
                        tok.type = TokType::Identificador;
                        tok.nome = s;
                    } else {
                        tok.type = TokType::PalavraChave;
                        tok.val = ix;
                    }
                    done = true;
                } else {
                    std::string error = "Caractere nao esperado: " + static_cast<char>(c);
                    lexerError(error.c_str());
                    return nullptr;
                }
                break;
        }
    }

    return &tok;
}
<commit_msg>Elimina alguns warnings do compilador<commit_after>//
// Created by Andrei Formiga on 2/3/17.
//

#include <string>
#include <cstdlib>
#include "lexer.h"

/// O token atual
Token tok;

/// O arquivo/stream de onde o lexer le caracteres
FILE *stream;

/// buffer de caracteres para o lexer
int buffer;
bool bufferValid = false;

int getNextChar() {
    if (!bufferValid)
        buffer = getc(stream);
    else
        bufferValid = false;
    return buffer;
}

void returnChar(int c) {
    buffer = c;
    bufferValid = true;
}

/// Inicializa o lexer
void initLexer(FILE *f) {
    bufferValid = false;
    stream = f;
}

void testLexer() {
    // TODO: testar o analisador lexico
}

std::string palavrasChave[] = { "int", "printf", "printint", "return"};

int identificaPalavraChave(std::string &s) {
    for (int i = 0; i < 4; ++i) {
        if (s == palavrasChave[i])
            return i;
    }

    return -1;
}

void lexerError(const char *err) {
    fprintf(stderr, "Erro lexico: %s\n", err);
    exit(1);
}

const char* printTokenType(Token &tok) {
    switch (tok.type) {
        case TokType::PalavraChave:
            return "PCHAVE";
        case TokType::Identificador:
            return "ID";
        case TokType::LiteralNum:
            return "NUM";
        case TokType::Operador:
            return "OP";
        case TokType::Eof:
            return "EOF";
        case TokType::Pontuacao:
            return "PONT";
    }
}

Token *getNextToken() {
    int c = getNextChar();

    // pula espaco em branco
    while (isspace(c))
        c = getNextChar();

    bool done = false;
    while (!done) {
        switch (c) {
            case '/':
                c = getNextChar();
                if (c != '/') {
                    lexerError("comentario esperado");
                    return nullptr;
                }
                while (c != '\n')
                    c = getNextChar();
                c = getNextChar();
                break;

            case '+':
                tok.type = TokType::Operador;
                tok.val = OpSoma;
                done = true;
                break;

            case '*':
                tok.type = TokType::Operador;
                tok.val = OpMult;
                done = true;
                break;

            case '<':
                tok.type = TokType::Operador;
                tok.val = OpLt;
                done = true;
                break;

            case '=':
                tok.type = TokType::Operador;
                c = getNextChar();
                if (c == '=')
                    tok.val = OpEq;
                else {
                    tok.val = OpAssign;
                    returnChar(c);
                }
                done = true;
                break;

            case '(':
                tok.type = TokType::Pontuacao;
                tok.val = LParen;
                done = true;
                break;

            case ')':
                tok.type = TokType::Pontuacao;
                tok.val = RParen;
                done = true;
                break;

            case '{':
                tok.type = TokType::Pontuacao;
                tok.val = LBrace;
                done = true;
                break;

            case '}':
                tok.type = TokType::Pontuacao;
                tok.val = RBrace;
                done = true;
                break;

            case ',':
                tok.type = TokType::Pontuacao;
                tok.val = Comma;
                done = true;
                break;

            case ';':
                tok.type = TokType::Pontuacao;
                tok.val = Semicolon;
                done = true;
                break;

            case EOF:
                tok.type = TokType::Eof;
                done = true;
                break;

            default:
                if (isdigit(c)) {
                    std::string num;

                    while (isdigit(c)) {
                        num += c;
                        c = getNextChar();
                    }
                    returnChar(c);
                    tok.type = TokType::LiteralNum;
                    tok.val = atoi(num.c_str());
                    done = true;
                } else if (isalpha(c)) {
                    std::string s;

                    while (isalnum(c)) {
                        s += c;
                        c = getNextChar();
                    }
                    returnChar(c);

                    int ix = identificaPalavraChave(s);
                    if (ix == -1) {
                        tok.type = TokType::Identificador;
                        tok.nome = s;
                    } else {
                        tok.type = TokType::PalavraChave;
                        tok.val = ix;
                    }
                    done = true;
                } else {
                    std::string error = "Caractere nao esperado: ";
                    error += static_cast<char>(c);
                    lexerError(error.c_str());
                    return nullptr;
                }
                break;
        }
    }

    return &tok;
}
<|endoftext|>