stateScript for Nucleo-F401RE board

Dependencies:   SOMO_II mbed

Revision:
0:ecf80f0172d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/behave.cpp	Mon Feb 08 18:56:09 2016 +0000
@@ -0,0 +1,5592 @@
+#include "behave.h"
+#include "hardwareInterface.h"
+#include <ctype.h>
+#include <sstream>
+//#include <string.h>
+//#include <cstdlib>
+
+using namespace std;
+
+int16_t randomSeedCounter;  //used for seeding random numbers
+
+//digitalPort* portVector[NUMPORTS+1]; //a list of pointers to the digital ports
+
+//Main event queue
+eventQueue mainQueue;
+
+//The script parser
+//scriptStream parser(portVector, NUMPORTS, &mainQueue);
+
+//globals defined in hardwareInterface.cpp
+extern uint32_t timeKeeper; //the master clock
+extern bool resetTimer;
+extern bool clockSlave;
+extern bool changeToSlave;
+extern bool changeToStandAlone;
+extern outputStream textDisplay;
+
+//extern int currentDIOstate[2];
+bool broadCastStateChanges;
+bool textStreaming;
+
+
+
+//These items may be placed in hardware-specific parts of memory
+
+#ifdef MBEDHARDWARE
+//__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512);
+__attribute((section("AHBSRAM0"),aligned)) char buffer[256];
+__attribute((section("AHBSRAM1"),aligned)) event eventBlock[NUMEVENTS];
+__attribute((section("AHBSRAM1"),aligned)) condition conditionBlock[NUMCONDITIONS];
+__attribute((section("AHBSRAM1"),aligned)) intCompare intCompareBlock[NUMINTCOMPARE];
+__attribute((section("AHBSRAM0"),aligned)) action actionBlock[NUMACTIONS];
+__attribute((section("AHBSRAM0"),aligned)) portMessage portMessageBlock[NUMPORTMESSAGES];
+//__attribute((section("AHBSRAM1"),aligned)) intVariable intVariableBlock[10];
+__attribute((section("AHBSRAM0"),aligned)) intOperation intOperationBlock[NUMINTOPERATIONS];
+__attribute((section("AHBSRAM0"),aligned)) displayAction displayActionBlock[NUMDISPLAYACTIONS];
+__attribute((section("AHBSRAM0"),aligned)) triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
+#endif
+
+#if defined(FPGAHARDWARE) || defined(NUCLEOHARDWARE)
+
+char buffer[256];
+event eventBlock[NUMEVENTS];
+condition conditionBlock[NUMCONDITIONS];
+intCompare intCompareBlock[NUMINTCOMPARE];
+action actionBlock[NUMACTIONS];
+portMessage portMessageBlock[NUMPORTMESSAGES];
+intOperation intOperationBlock[NUMINTOPERATIONS];
+displayAction displayActionBlock[NUMDISPLAYACTIONS];
+triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
+#endif
+
+
+
+
+event* functionEventArray[NUMFUNCTIONS];
+bool   functionSpotTaken[NUMFUNCTIONS];
+
+
+//-----------------------------------------------
+//This is the main loop of the program
+mainLoop::mainLoop(){
+
+
+}
+
+void mainLoop::init() {
+    currentDIOstate[0] = 0;
+    currentDIOstate[1] = 0;
+    digitalInChanged = false;
+    digitalOutChanged = false;
+    textStreaming = true;
+    eraseBuffer();
+    broadCastStateChanges = true;
+
+
+
+//section for MBED hardware
+#ifdef MBEDHARDWARE
+    hardware = new MBEDSystem();
+    hardware->timerinit();
+    pc = new MBEDSerialPort();
+    pc->init();
+    textDisplay.setSerial(pc);
+
+#endif
+
+#ifdef FPGAHARDWARE
+       pc = new FPGASerialPort();
+       pc->init();
+
+       hardware = new FPGASystem();
+       hardware->timerinit();
+
+       textDisplay.setSerial(pc);
+
+       DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
+#endif
+
+#ifdef FPGAHARDWARE
+       pc = new NUCLEOSerialPort();
+       pc->init();
+
+       hardware = new MBEDSystem();
+       Ticker keeptime;
+       keeptime.attach_us(&hardware,&MBEDSystem::tick,1000);
+
+       textDisplay.setSerial(pc);
+
+       DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
+#endif
+
+    for (int i = 0; i < NUMPORTS; i++) {
+        //Set up the ports.  Each has two pointers to the harware implementations
+        //of a digital out and digital in.
+        ports[i].init(hardware->getDigitalOutPtr(i),hardware->getDigitalInPtr(i));
+    }
+
+
+    parser = new scriptStream(ports, NUMPORTS, &mainQueue, hardware);
+
+}
+
+void mainLoop::exec() {
+    bool digitalInChanged = false;
+    bool digitalOutChanged = false;
+    bool *ignoreUpdatePorts = hardware->getIgnoreUpdates();
+    uint32_t changeTime;
+    timeKeeper = 0; //set main clock to 0;
+
+    int bufferPos = 0;
+
+    //ostringstream timeConvert;   // stream used for the conversion
+    //ostringstream stateConvert;
+    int tmpChar;
+    int junkChar;
+
+    uint16_t shortcutTriggers[PENDINGTRIGGERBUFFERSIZE];
+    int numTriggersToProcess;
+
+    while (pc->readable()) {
+        junkChar = pc->readChar();
+    }
+
+#ifdef MBEDHARDWARE
+    LocalFileSystem local("local");
+
+    FILE *fp = fopen("/local/STARTUP.TXT", "r");
+    if (fp != NULL) {
+
+        textDisplay.send("Executing startup script...\r\n");
+
+        do {
+            tmpChar = fgetc(fp);
+            if ((tmpChar >= 32) && (tmpChar <= 126)) {
+                buffer[bufferPos] = tmpChar;
+                bufferPos++;
+            }
+            if ((tmpChar == 13) || (tmpChar == 10)) { //carrriage return
+                parser->addLineToCurrentBlock(buffer);
+                bufferPos = 0;
+                eraseBuffer();
+            }
+            //pc.putc(tmpChar);
+        } while (tmpChar != EOF);
+
+        buffer[bufferPos] = 59;
+        parser->addLineToCurrentBlock(buffer);
+        eraseBuffer();
+        fclose(fp);
+    } else {
+        textDisplay.send("No startup script found.\r\n");
+    }
+#endif
+
+    //Get the initial state of all input pins
+    for (int i = 0; i < NUMPORTS; i++) {
+
+        if (ports[i].getDigitalIn() == 1) {
+            currentDIOstate[0] |= (1 << i);
+        } else {
+            currentDIOstate[0] &= ~(1 << i);
+        }
+    }
+
+
+    //main loop
+    while(1) {
+        //check the main event queue to see if anything needs to be done
+
+        mainQueue.check();
+
+        //check if anything has been written to the serial input
+        while (pc->readable()) {
+
+            buffer[bufferPos] = pc->readChar();
+            bufferPos++;
+
+
+            //'Return' key pressed
+            if ((buffer[bufferPos-1] == 13) || (buffer[bufferPos-1] == 10)) {
+
+                buffer[bufferPos-1] = '\0';
+
+                parser->addLineToCurrentBlock(buffer);
+                bufferPos = 0;
+                eraseBuffer();
+
+            } else {
+
+                //Backspace was pressed
+                if (((buffer[bufferPos-1] == 127)||(buffer[bufferPos-1] == 8))) {
+                    if (bufferPos > 1) {
+                        bufferPos = bufferPos-2; //erase the backspace char plus the one before
+                    } else {
+                        bufferPos = bufferPos-1; //beginning of line, so nothing to erase
+                    }
+                }
+            }
+        }
+
+        //Check all the digital ports to see if anything has changed. In the update routine, the port's
+        //script callbacks are called if the port was triggered
+        digitalInChanged = false;
+        digitalOutChanged = false;
+        changeTime = timeKeeper;
+
+        for (int i = 0; i < NUMPORTS; i++) {
+
+            if (ports[i].update()) {
+
+                if (!ignoreUpdatePorts[i]) {
+                    //Only trigger an output update to the serial port if ignore is false
+                    digitalInChanged = true;
+                }
+                changeTime = min(changeTime,ports[i].lastChangeTime);
+
+
+                //The input state of all the ports in condensed into one number (each bit contains the info)
+                if (ports[i].getLastChangeState() == 1) {
+                    currentDIOstate[0] |= (1 << i);
+                } else {
+                    currentDIOstate[0] &= ~(1 << i);
+                }
+            }
+            if (ports[i].outStateChanged) {
+                if (!ignoreUpdatePorts[i]) {
+                     //Only trigger an output update to the serial port if ignore is false
+                    digitalOutChanged = true;
+                }
+                changeTime = min(changeTime,ports[i].lastOutChangeTime);
+                //The out state of all the ports is condensed into one number (each bit contains the info)
+                if (ports[i].outState == 1) {
+                    currentDIOstate[1] |= (1 << i);
+                } else {
+                    currentDIOstate[1] &= ~(1 << i);
+                }
+                ports[i].outStateChanged = false;
+            }
+        }
+
+        //If anything changed, we write the new values to the serial port (this can be turned off
+        //with broadCastStateChanges)
+        if ( (digitalInChanged||digitalOutChanged) && broadCastStateChanges) {
+            textDisplay << changeTime << " " << currentDIOstate[0] << " " << currentDIOstate[1] << "\r\n";
+
+            /*
+            timeConvert << changeTime; //broadcast the earliest timestamp when a change occured
+            //stateConvert << currentDIOstate[0] << " " << currentDIOstate[1];
+            stateConvert << currentDIOstate[0] << " " << currentDIOstate[1] << "       ";
+
+            textDisplay.send(timeConvert.str() + " " + stateConvert.str() + "\r\n");
+            timeConvert.clear();
+            timeConvert.seekp(0);
+            stateConvert.clear();
+            stateConvert.seekp(0);
+            */
+            digitalInChanged = false;
+            digitalOutChanged = false;
+        }
+
+        //We use a buffer to send text via the serial port.  For every loop
+        //in the main loop, we send one character if there is enything to send.
+        //This way, outputting text to serial does not hold up other time-sensitive
+        //things in the event queue
+        if ((textDisplay.unsentData) && (textStreaming)) {
+            pc->writeChar(textDisplay.getNextChar());
+        }
+
+        //Here is how we toggle between standalone and slave mode for the clock updating.
+        if (changeToSlave) {
+            hardware->setSlaveClock();
+        } else if (changeToStandAlone) {
+           hardware->setStandAloneClock();
+        }
+
+        //anything extra to do, defined by the hardware
+        hardware->mainLoopToDo();
+
+        //check for shortcut triggers
+        numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers);
+        for (int i = 0; i < numTriggersToProcess; i++) {
+            textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n";
+            if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]] && functionEventArray[i]->isUsed) {
+                //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n";
+                functionEventArray[shortcutTriggers[i]]->execute();
+            }
+        }
+
+    }
+
+}
+
+void mainLoop::eraseBuffer() {
+    for (int i = 0; i < 256; i++) {
+        buffer[i] = NULL;
+    }
+}
+
+//-------------------------------------------------
+
+//used to find the first available object in the staticly defined pools of memory
+template<class T> T* findFirstUnUsed(T a[], const int arrayLength) {
+
+    T* returnPtr = NULL;
+    for (int i = 0; i < arrayLength; i++) {
+        if (!a[i].isUsed) {
+            returnPtr = &a[i];
+            break;
+        }
+    }
+    return returnPtr;
+}
+
+//used to count the number of available objects in the memory pool
+template<class T> int countUnUsed(T a[], const int arrayLength) {
+
+    int count = 0;
+    for (int i = 0; i < arrayLength; i++) {
+        if (!a[i].isUsed) {
+            count++;
+        }
+    }
+    return count;
+}
+
+
+void displayMemoryLeft(void) {
+    textDisplay << "Available slots left in memory\r\n";
+    textDisplay << "  Blocks: " << countUnUsed(eventBlock, NUMEVENTS) << "\r\n";
+    textDisplay << "  Condition containers: " << countUnUsed(conditionBlock, NUMCONDITIONS) << "\r\n";
+    textDisplay << "  Int compare conditions: " << countUnUsed(intCompareBlock, NUMINTCOMPARE) << "\r\n";
+    textDisplay << "  Command containers: " << countUnUsed(actionBlock, NUMACTIONS) << "\r\n";
+    textDisplay << "  Port commands: "<< countUnUsed(portMessageBlock, NUMPORTMESSAGES) << "\r\n";
+    textDisplay << "  Integer operater commands: " << countUnUsed(intOperationBlock, NUMINTOPERATIONS) << "\r\n";
+    textDisplay << "  Text display commands: " << countUnUsed(displayActionBlock, NUMDISPLAYACTIONS) << "\r\n";
+}
+
+bool isNumber(const std::string& s) {
+    std::string::const_iterator it = s.begin();
+    while (it != s.end() && isdigit(*it)) ++it;
+    return !s.empty() && it == s.end();
+}
+
+void tokenize(const string& str,
+              vector<string>& tokens,
+              const string& delimiters = " ")
+{
+    // Skip delimiters at beginning.
+    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+    // Find first "non-delimiter".
+    string::size_type pos     = str.find_first_of(delimiters, lastPos);
+
+    while (string::npos != pos || string::npos != lastPos)
+    {
+        // Found a token, add it to the vector.
+        tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // Skip delimiters.  Note the "not_of"
+        lastPos = str.find_first_not_of(delimiters, pos);
+        // Find next "non-delimiter"
+        pos = str.find_first_of(delimiters, lastPos);
+    }
+}
+
+
+digitalPort::digitalPort():
+outPin(NULL),
+inPin(NULL),
+outState(0){
+
+}
+
+void digitalPort::init(sDigitalOut *DOP, sDigitalIn *DIP) {
+    outPin = DOP;
+    inPin = DIP;
+    lastInState = getDigitalIn();
+    inState = getDigitalIn();
+    lastChangeTime = 0;
+    lastOutChangeTime = 0;
+    lastChangeInterval = 0;
+    triggerUpEventPtr = NULL;
+    triggerDownEventPtr = NULL;
+    outStateChanged = false;
+
+}
+
+
+void digitalPort::setTriggerUpEvent(event* eventInput) {
+    if (triggerUpEventPtr != NULL) {
+        //delete triggerUpEventPtr;
+        triggerUpEventPtr->release();
+    }
+    triggerUpEventPtr = eventInput;
+}
+
+void digitalPort::setTriggerDownEvent(event* eventInput) {
+    if (triggerDownEventPtr != NULL) {
+        //delete triggerDownEventPtr;
+        triggerDownEventPtr->release();
+
+    }
+    triggerDownEventPtr = eventInput;
+}
+
+
+int digitalPort::getDigitalIn() {
+    return inPin->read();
+}
+
+
+void digitalPort::setDigitalOut(int outVal) {
+    if (outVal == -1) {
+        outVal = 1-outState;
+    }
+    outPin->write(outVal);
+    if (outState != outVal) {
+        outStateChanged = true;
+        lastOutChangeTime = timeKeeper;
+    }
+    outState = outVal;
+}
+
+//called when a digital in gets triggered
+/*
+void digitalPort::addStateChange(int newState, uint32_t timeStamp) {
+
+    if ((newState == 0) && (!lastDownEvent.triggered)){
+        lastDownEvent.timeStamp = timeStamp;
+        lastDownEvent.triggered = true;
+    } else if ((newState == 1) && (!lastUpEvent.triggered)) {
+        lastUpEvent.timeStamp = timeStamp;
+        lastUpEvent.triggered = true;
+    }
+}*/
+
+bool digitalPort::update() {
+
+    bool changed = false;
+    bool execUp = false;
+    bool execDown = false;
+    if ((timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
+
+        //changed = (lastInState != inState);
+
+        changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered);
+        if (changed) {
+            inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking
+
+            inState = getDigitalIn();
+
+            //We need to ignore flutter when levers/beam breaks are triggered. So
+            //if the current state if different than the last logged state, we only
+            //consider the first edge that brough us to the current state
+            if (lastInState != inState) {
+
+                if (inState == 1) {
+
+                    lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
+                    lastChangeTime = inPin->lastUpEvent.timeStamp;
+
+                    /*
+                    if (inPin->lastUpEvent.triggered) {
+                        //there were hardware triggers since the last main loop.  We use that time
+                        lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
+                        lastChangeTime = inPin->lastUpEvent.timeStamp;
+                    } else {
+                        //otherwise we use the current time
+                        lastChangeInterval = timeKeeper - lastChangeTime;
+                        lastChangeTime = timeKeeper;
+                    }
+                    */
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                } else if (inState == 0) {
+
+                    lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
+                    lastChangeTime = inPin->lastDownEvent.timeStamp;
+
+                    /*
+                    if (inPin->lastDownEvent.triggered) {
+                        lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
+                        lastChangeTime = inPin->lastDownEvent.timeStamp;
+                    } else {
+                        lastChangeInterval = timeKeeper - lastChangeTime;
+                        lastChangeTime = timeKeeper;
+                    }*/
+
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed){triggerDownEventPtr->execute();}
+                }
+            } else if (lastInState == inState) {
+
+                //Both up and down triggers must have happened, so we consider both
+                if (inState == 1) {
+
+                    lastChangeInterval = inPin->lastUpEvent.timeStamp - inPin->lastDownEvent.timeStamp;
+                    lastChangeTime = inPin->lastUpEvent.timeStamp;
+
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                } else if (inState == 0) {
+
+                    lastChangeInterval = inPin->lastDownEvent.timeStamp - inPin->lastUpEvent.timeStamp;
+                    lastChangeTime = inPin->lastDownEvent.timeStamp;
+
+                    if (triggerUpEventPtr != NULL && triggerUpEventPtr->isUsed) {triggerUpEventPtr->execute();}
+                    if (triggerDownEventPtr != NULL && triggerDownEventPtr->isUsed) {triggerDownEventPtr->execute();}
+                }
+            }
+
+            lastInState = inState;
+            inPin->lastUpEvent.triggered = false;
+            inPin->lastDownEvent.triggered = false;
+
+            inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
+
+
+        }
+
+
+
+    }
+
+    return changed;
+}
+
+int digitalPort::getLastChangeState() {
+    return lastInState;
+}
+uint32_t digitalPort::getTimeSinceLastChange() {
+    return lastChangeInterval;
+
+}
+
+intVariable::intVariable():
+value(0) {
+    isUsed = false;
+}
+
+intVariable::intVariable(std::string& tagInput, int initialValue):
+value(initialValue)
+{
+    strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
+    isUsed = true;
+}
+
+void intVariable::set(std::string& tagInput, int initialValue) {
+    value = initialValue;
+    //tag = string(tagInput);
+    strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
+    isUsed = true;
+}
+
+displayAction::displayAction():
+dText(string("--------------------------------------------------")){
+    dVariable = NULL;
+    isUsed = false;
+}
+
+void displayAction::release() {
+    dText = "--------------------------------------------------";
+    dVariable = NULL;
+    isUsed = false;
+}
+
+
+void displayAction::set(int* variable, string varNameInput) {
+    dVariable = variable;
+    dText = varNameInput;
+    isUsed = true;
+
+}
+
+void displayAction::set(string text) {
+    dText = text;
+    dVariable = NULL;
+    isUsed = true;
+}
+
+void displayAction::execute() {
+
+    if (dVariable != NULL) {
+        textDisplay << timeKeeper << " " << dText.c_str() << " = " << *dVariable << "\r\n";
+    } else {
+        textDisplay << timeKeeper << " " << dText.c_str() << "\r\n";
+    }
+}
+
+triggerFunctionAction::triggerFunctionAction():
+functionNum(0) {
+    isUsed = false;
+}
+
+triggerFunctionAction::triggerFunctionAction(int funcNum):
+functionNum(funcNum) {
+
+    isUsed = true;
+
+}
+
+void triggerFunctionAction::set(int funcNum) {
+    functionNum = funcNum;
+    isUsed = true;
+}
+
+void triggerFunctionAction::execute() {
+
+    if (functionSpotTaken[functionNum] && functionEventArray[functionNum]->isUsed) {
+        functionEventArray[functionNum]->execute();
+    }
+
+}
+
+void triggerFunctionAction::release() {
+    isUsed = false;
+}
+
+
+
+intCompare::intCompare():
+port(NULL) {
+    cmpVal = NULL;
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = false;
+
+}
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse):
+port(portInput) {
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse):
+port(portInput),
+cmpVal(cmpIntVarInput) {
+    cmpValGlobal = true;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
+cmpVal(cmpIntVarInput),
+intVal(intVarInput) {
+    cmpValGlobal = true;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = true;
+    setPointer(cmpString);
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, int cmpValInput):
+intVal(intVarInput){
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = true;
+    setPointer(cmpString);
+}
+
+intCompare::intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput):
+intVal(intVarInput) {
+    cmpVal = NULL;
+    port = NULL;
+    portValPtr = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    isUsed = true;
+    setPointer_operation(cmpString);
+}
+
+intCompare::intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse):
+port(portInput) {
+    cmpVal = NULL;
+    intVal = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) {
+    port = portInput;
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) {
+    port = portInput;
+    cmpVal = cmpIntVarInput;
+    cmpValGlobal = true;
+    intVal = NULL;
+    intOp = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
+    cmpVal = cmpIntVarInput;
+    intVal = intVarInput;
+    cmpValGlobal = true;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, int cmpValInput) {
+    intVal = intVarInput;
+    cmpVal = new int(cmpValInput);
+    cmpValGlobal = false;
+    port = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    setPointer(cmpString);
+    isUsed = true;
+}
+
+void intCompare::set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput) {
+    intVal = intVarInput;
+    cmpVal = NULL;
+    port = NULL;
+    portValPtr = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true;
+}
+
+void intCompare::set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) {
+    port = portInput;
+    cmpVal = NULL;
+    intVal = NULL;
+    cmpValGlobal = true;
+    intOp = cmpIntOpInput;
+    setPointer_operation(cmpString);
+    isUsed = true;
+    if (whichToUse == 1) {
+        portValPtr = &port->inState;
+    } else {
+        portValPtr = &port->outState;
+    }
+}
+
+
+
+intCompare::~intCompare() {
+    if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally
+    delete intOp;
+}
+
+void intCompare::release() {
+    if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally
+    if (intOp != NULL) {
+        intOp->release();
+    }
+    port = NULL;
+    cmpVal = NULL;
+    cmpValGlobal = false;
+    intVal = NULL;
+    intOp = NULL;
+    portValPtr = NULL;
+    isUsed = false;
+}
+
+
+void intCompare::setPointer(const char* cmpString) {
+    if (strcmp(cmpString, ">") == 0) {
+        isTruePtr = &intCompare::greaterThan;
+    }else if (strcmp(cmpString, ">=") == 0) {
+        isTruePtr = &intCompare::greaterOrEqual;
+    }else if (strcmp(cmpString, "<") == 0) {
+        isTruePtr = &intCompare::lessThan;
+    }else if (strcmp(cmpString, "<=") == 0) {
+        isTruePtr = &intCompare::lessOrEqual;
+    }else if (strcmp(cmpString, "==") == 0) {
+        isTruePtr = &intCompare::equal;
+    }else if (strcmp(cmpString, "!=") == 0) {
+        isTruePtr = &intCompare::notEqual;
+    }
+}
+
+void intCompare::setPointer_operation(const char* cmpString) {
+    if (strcmp(cmpString, ">") == 0) {
+        isTruePtr = &intCompare::greaterThan_op;
+    }else if (strcmp(cmpString, ">=") == 0) {
+        isTruePtr = &intCompare::greaterOrEqual_op;
+    }else if (strcmp(cmpString, "<") == 0) {
+        isTruePtr = &intCompare::lessThan_op;
+    }else if (strcmp(cmpString, "<=") == 0) {
+        isTruePtr = &intCompare::lessOrEqual_op;
+    }else if (strcmp(cmpString, "==") == 0) {
+        isTruePtr = &intCompare::equal_op;
+    }else if (strcmp(cmpString, "!=") == 0) {
+        isTruePtr = &intCompare::notEqual_op;
+    }
+}
+
+bool intCompare::isTrue() {
+    return (this->*isTruePtr)();
+
+}
+
+bool intCompare::notEqual() {
+    if (intVal != NULL) {
+        return (*intVal != *cmpVal);
+    } else {
+        return (*portValPtr != *cmpVal);
+    }
+}
+
+bool intCompare::greaterThan() {
+    if (intVal != NULL) {
+        return (*intVal > *cmpVal);
+    } else {
+        return (*portValPtr > *cmpVal);
+    }
+}
+
+bool intCompare::greaterOrEqual() {
+    if (intVal != NULL) {
+        return (*intVal >= *cmpVal);
+    } else {
+        return (*portValPtr >= *cmpVal);
+    }
+}
+
+bool intCompare::lessThan() {
+    if (intVal != NULL) {
+        return (*intVal < *cmpVal);
+    } else {
+        return (*portValPtr < *cmpVal);
+    }
+}
+
+bool intCompare::lessOrEqual() {
+    if (intVal != NULL) {
+        return (*intVal <= *cmpVal);
+    } else {
+        return (*portValPtr <= *cmpVal);
+    }
+}
+
+bool intCompare::equal() {
+    if (intVal != NULL) {
+        return (*intVal == *cmpVal);
+    } else {
+        return (*portValPtr == *cmpVal);
+    }
+}
+
+bool intCompare::notEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal != intOp->execute());
+    } else {
+        return (*portValPtr != intOp->execute());
+    }
+}
+
+bool intCompare::greaterThan_op() {
+    if (intVal != NULL) {
+        return (*intVal > intOp->execute());
+    } else {
+        return (*portValPtr > intOp->execute());
+    }
+}
+
+bool intCompare::greaterOrEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal >= intOp->execute());
+    } else {
+        return (*portValPtr >= intOp->execute());
+    }
+}
+
+bool intCompare::lessThan_op() {
+    if (intVal != NULL) {
+        return (*intVal < intOp->execute());
+    } else {
+        return (*portValPtr < intOp->execute());
+    }
+}
+
+bool intCompare::lessOrEqual_op() {
+    if (intVal != NULL) {
+        return (*intVal <= intOp->execute());
+    } else {
+        return (*portValPtr <= intOp->execute());
+    }
+}
+
+bool intCompare::equal_op() {
+    if (intVal != NULL) {
+        return (*intVal == intOp->execute());
+    } else {
+        return (*portValPtr == intOp->execute());
+    }
+}
+
+intOperation::intOperation():
+randHigh(-1) {
+    cmpVal = NULL;
+    intVal = NULL;
+    opPtr = NULL;
+    executePtr = NULL;
+    cmpValGlobal = false;
+    isUsed = false;
+    isClockAssign = false;
+    inputsFlipped = false;
+
+}
+
+/*
+ intOperation::intOperation(int randParam, const char* cmpString, int cmpValInput):
+ randHigh(randParam) {
+ cmpVal = new int(cmpValInput);
+ intVal = NULL;
+ opPtr = NULL;
+ cmpValGlobal = false;
+ isUsed = true;
+ if (strcmp(cmpString, "+") == 0) {
+ executePtr = &intOperation::add;
+ }else if (strcmp(cmpString, "-") == 0) {
+ executePtr = &intOperation::subtract;
+ }else if (strcmp(cmpString, "+=") == 0) {
+ executePtr = &intOperation::addAndStore;
+ }else if (strcmp(cmpString, "-=") == 0) {
+ executePtr = &intOperation::subtractAndStore;
+ }else if (strcmp(cmpString, "=") == 0) {
+ executePtr = &intOperation::equals;
+ }
+
+ }
+
+ intOperation::intOperation(int randParam, const char* cmpString, int* cmpIntVarInput):
+ randHigh(randParam),
+ cmpVal(cmpIntVarInput) {
+ intVal = NULL;
+ opPtr = NULL;
+ cmpValGlobal = true;
+ isUsed = true;
+ if (strcmp(cmpString, "+") == 0) {
+ executePtr = &intOperation::add;
+ }else if (strcmp(cmpString, "-") == 0) {
+ executePtr = &intOperation::subtract;
+ }else if (strcmp(cmpString, "+=") == 0) {
+ executePtr = &intOperation::addAndStore;
+ }else if (strcmp(cmpString, "-=") == 0) {
+ executePtr = &intOperation::subtractAndStore;
+ }else if (strcmp(cmpString, "=") == 0) {
+ executePtr = &intOperation::equals;
+ }
+ }
+
+ intOperation::intOperation(int* intVarInput, const char* cmpString, int cmpValInput):
+ intVal(intVarInput) {
+ cmpVal = new int(cmpValInput);
+ randHigh = -1;
+ opPtr = NULL;
+ cmpValGlobal = false;
+ isUsed = true;
+ if (strcmp(cmpString, "+") == 0) {
+ executePtr = &intOperation::add;
+ }else if (strcmp(cmpString, "-") == 0) {
+ executePtr = &intOperation::subtract;
+ }else if (strcmp(cmpString, "+=") == 0) {
+ executePtr = &intOperation::addAndStore;
+ }else if (strcmp(cmpString, "-=") == 0) {
+ executePtr = &intOperation::subtractAndStore;
+ }else if (strcmp(cmpString, "=") == 0) {
+ executePtr = &intOperation::equals;
+ }
+ }
+
+ intOperation::intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
+ cmpVal(cmpIntVarInput),
+ intVal(intVarInput) {
+ randHigh = -1;
+ opPtr = NULL;
+ cmpValGlobal = true;
+ isUsed = true;
+ if (strcmp(cmpString, "+") == 0) {
+ executePtr = &intOperation::add;
+ }else if (strcmp(cmpString, "-") == 0) {
+ executePtr = &intOperation::subtract;
+ }else if (strcmp(cmpString, "+=") == 0) {
+ executePtr = &intOperation::addAndStore;
+ }else if (strcmp(cmpString, "-=") == 0) {
+ executePtr = &intOperation::subtractAndStore;
+ }else if (strcmp(cmpString, "=") == 0) {
+ executePtr = &intOperation::equals;
+ }
+ }
+
+ intOperation::intOperation(int* intVarInput, intOperation* operationInput):
+ intVal(intVarInput) {
+ cmpVal = NULL;
+ randHigh = -1;
+ opPtr = operationInput;
+ executePtr = &intOperation::equals;
+ isUsed = true;
+ }
+ */
+
+void intOperation::setRandOp(int randParam, const char* cmpString, int cmpValInput, bool flipped) {
+    randHigh = randParam;
+    cmpVal = new int(cmpValInput);
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    inputsFlipped = flipped;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+
+}
+
+void intOperation::setRandOp(int randParam, const char* cmpString, int* cmpIntVarInput, bool flipped) {
+    randHigh = randParam;
+    cmpVal = cmpIntVarInput;
+    intVal = NULL;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true;
+    inputsFlipped = flipped;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, const char* cmpString, int cmpValInput) {
+
+    intVal = intVarInput;
+    cmpVal = new int(cmpValInput);
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
+    cmpVal = cmpIntVarInput;
+    intVal =intVarInput;
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = true;
+    isUsed = true;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }else if (strcmp(cmpString, "+=") == 0) {
+        executePtr = &intOperation::addAndStore;
+    }else if (strcmp(cmpString, "-=") == 0) {
+        executePtr = &intOperation::subtractAndStore;
+    }else if (strcmp(cmpString, "=") == 0) {
+        executePtr = &intOperation::equals;
+    }
+}
+
+void intOperation::set(int* intVarInput, intOperation* operationInput) {
+
+    intVal = intVarInput;
+    cmpVal = NULL;
+    randHigh = -1;
+    opPtr = operationInput;
+    executePtr = &intOperation::equals;
+    isUsed = true;
+
+}
+
+void intOperation::setClockOp(int* intVarInput) {
+    //used to assign current clock to variable
+    intVal = intVarInput;
+    cmpVal = NULL;
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    isClockAssign = true;
+    executePtr = &intOperation::equals;
+
+}
+
+void intOperation::setClockOp(const char* cmpString, int cmpValInput, bool flip) {
+    //used to add an integer to the current clock value
+
+    intVal = NULL;
+    cmpVal = new int(cmpValInput);
+    randHigh = -1;
+    opPtr = NULL;
+    cmpValGlobal = false;
+    isUsed = true;
+    isClockAssign = true;
+    inputsFlipped = flip;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }
+}
+
+void intOperation::setClockOp(const char* cmpString, int* cmpIntVarInput, bool flip) {
+    //used to add a variable to the current clock value
+
+    cmpVal = cmpIntVarInput;
+    intVal = NULL;
+    randHigh = -1;
+    opPtr = NULL;
+    isClockAssign = true;
+    cmpValGlobal = true;
+    isUsed = true;
+    inputsFlipped = flip;
+    if (strcmp(cmpString, "+") == 0) {
+        executePtr = &intOperation::add;
+    }else if (strcmp(cmpString, "-") == 0) {
+        executePtr = &intOperation::subtract;
+    }
+}
+
+
+intOperation::~intOperation() {
+    if (!cmpValGlobal) delete cmpVal;
+    delete opPtr;
+}
+
+void intOperation::release() {
+    if (!cmpValGlobal) delete cmpVal;
+    if (opPtr != NULL) {
+        opPtr->release();
+    }
+    randHigh = -1;
+    cmpVal = NULL;
+    intVal = NULL;
+    opPtr = NULL;
+    executePtr = NULL;
+    isClockAssign = false;
+    cmpValGlobal = false;
+    isUsed = false;
+}
+
+
+int intOperation::execute() {
+
+    return (this->*executePtr)();
+
+
+}
+
+int intOperation::add() {
+
+    if ((intVal != NULL) && (!isClockAssign)) {
+        return (*intVal + *cmpVal);
+    } else if ((intVal == NULL) && (isClockAssign)) {
+        return (timeKeeper + *cmpVal);
+    } else {
+        //srand(time(NULL));
+        srand(timeKeeper);
+        return (rand() % (randHigh+1)) + *cmpVal;
+        //return (port->getState() + *cmpVal);
+    }
+}
+
+int intOperation::subtract() {
+    if ((intVal != NULL) && (!isClockAssign)) {
+        return (*intVal - *cmpVal);
+    } else if ((intVal == NULL) && (isClockAssign)) {
+        if (inputsFlipped) {
+            return (*cmpVal-timeKeeper);
+        } else {
+            return (timeKeeper - *cmpVal);
+        }
+    } else {
+        srand(timeKeeper);
+        if (inputsFlipped) {
+            return (*cmpVal-(rand() % (randHigh+1)));
+        } else {
+            return (rand() % (randHigh+1)) - *cmpVal;
+        }
+        //return (port->getState() - *cmpVal);
+    }
+}
+
+int intOperation::addAndStore() {
+    if (intVal != NULL) {
+        *intVal = *intVal + *cmpVal;
+        return *intVal;
+    }
+    else {
+
+        //Doesn't happen
+        return 0;
+        //port->setState(port->getState() + *cmpVal);
+        //return port->getState();
+    }
+
+}
+
+int intOperation::subtractAndStore() {
+    if (intVal != NULL) {
+        *intVal = *intVal - *cmpVal;
+        return *intVal;
+    } else {
+        //doesn't happen
+        return 0;
+        //port->setState(port->getState() - *cmpVal);
+        //return port->getState();
+    }
+}
+
+int intOperation::equals() {
+    if ((intVal != NULL) && (opPtr == NULL) && (!isClockAssign)) {
+        *intVal = *cmpVal;
+        return *intVal;
+    } else if ((intVal != NULL) && (opPtr != NULL)) {
+
+        *intVal = opPtr->execute();
+        return *intVal;
+    } else if ((intVal != NULL) && (opPtr == NULL) && (isClockAssign)) {
+        *intVal = timeKeeper; //assign the current time to the variable
+        return *intVal;
+    } else if ((cmpVal != NULL)&& (!isClockAssign)){
+
+        srand(timeKeeper+randomSeedCounter);
+        randomSeedCounter++; //for seeding the next rand call, just in case it happens before the clock advances
+        *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable
+        return *cmpVal;
+
+    }
+    return -1;
+}
+
+condition::condition() {
+    intCmp = NULL;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+    isUsed = false;
+    conditionType = ARITHMATIC_CONDITION;
+}
+
+condition::condition(intCompare* compareInput) {
+
+    intCmp = compareInput;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+
+    isUsed = true;
+    conditionType = ARITHMATIC_CONDITION;
+
+}
+
+condition::condition(condition* condition1, char condType, condition* condition2) {
+    intCmp = NULL;
+    conditionPtrs[0] = condition1;
+    conditionPtrs[1] = condition2;
+    isUsed = true;
+    conditionType = condType;
+}
+
+condition::~condition() {
+    if (intCmp != NULL) {
+        delete intCmp;
+    }
+}
+
+void condition::release() {
+    if (intCmp != NULL) {
+        intCmp->release();
+        intCmp=NULL;
+    }
+    if (conditionPtrs[0] != NULL) {
+        conditionPtrs[0]->release();
+        conditionPtrs[1]->release();
+        conditionPtrs[0]=NULL;
+        conditionPtrs[1]=NULL;
+    }
+    isUsed = false;
+}
+
+void condition::set(intCompare* compareInput) {
+    release();
+    intCmp = compareInput;
+    conditionPtrs[0] = NULL;
+    conditionPtrs[1] = NULL;
+    isUsed = true;
+    conditionType = ARITHMATIC_CONDITION;
+}
+
+void condition::set(condition* condition1, char condType, condition* condition2) {
+    release();
+    intCmp = NULL;
+    conditionPtrs[0] = condition1;
+    conditionPtrs[1] = condition2;
+    isUsed = true;
+    conditionType = condType;
+}
+
+bool condition::isTrue() {
+
+
+    bool result = true;
+    if (conditionType == ARITHMATIC_CONDITION) {
+
+        result = (intCmp->isTrue)();
+    } else if (conditionType == AND_CONDITION) {
+
+        result = conditionPtrs[0]->isTrue() && conditionPtrs[1]->isTrue();
+    } else if (conditionType == OR_CONDITION) {
+
+        result = conditionPtrs[0]->isTrue() || conditionPtrs[1]->isTrue();
+    }
+    return result;
+
+}
+
+portMessage::portMessage():
+whichToSet(0),
+value(0),
+port(NULL) {
+    isUsed = false;
+}
+
+void portMessage::release() {
+
+    whichToSet = 0;
+    value = 0;
+    port = NULL;
+    isUsed = false;
+}
+
+/*
+ portMessage::portMessage(digitalPort* portIn, int whichToSetIn, int valueIn):
+ whichToSet(whichToSetIn),
+ value(valueIn),
+ port(portIn) {
+ isUsed = true;
+ }
+
+ void portMessage::setMessage(digitalPort* portIn, int whichToSetIn, int valueIn) {
+ whichToSet = whichToSetIn;
+ value = valueIn;
+ port = portIn;
+ isUsed = true;
+ }*/
+
+/*
+portMessage::portMessage(int* portIn, int whichToSetIn, int valueIn):
+whichToSet(whichToSetIn),
+value(valueIn),
+port(portIn) {
+    isUsed = true;
+}*/
+
+void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn, digitalPort* portVectorIn) {
+    whichToSet = whichToSetIn;
+    value = valueIn;
+    port = portIn;
+    portVector = portVectorIn;
+    isUsed = true;
+}
+
+void portMessage::execute() {
+
+    if (port != NULL) {
+        if ((*port > 0) && (*port <= NUMPORTS)) {
+            portVector[*port-1].setDigitalOut(value);
+        } else {
+            textDisplay << "Error: port index assigned by variable does not exist.\r\n";
+        }
+    } else {
+        portVector[whichToSet-1].setDigitalOut(value);
+    }
+
+}
+
+action::action():
+actionType(0) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = false;
+
+}
+
+action::~action() {
+    if (eventToCreate != NULL) delete eventToCreate;
+    if (op != NULL) delete op;
+    if (message != NULL) delete message;
+    delete displayActionPtr;
+    delete sound;
+}
+
+void action::release() {
+    if (eventToCreate != NULL) eventToCreate->release();
+    if (op != NULL) op->release();
+    if (message != NULL) message->release();
+    if (displayActionPtr != NULL) displayActionPtr->release();
+    if (triggerFunc != NULL) triggerFunc->release();
+    delete sound; //still need to make a static soundControl array
+
+    actionType = 0;
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = false;
+}
+
+action::action(intOperation* opInput):
+actionType(1) {
+    op = opInput;
+    message = NULL;
+    eventToCreate = NULL;
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(portMessage* messageInput):
+actionType(2) {
+    op = NULL;
+    eventToCreate = NULL;
+    message = messageInput;
+    displayActionPtr= NULL;
+    //eventDelay = 0;
+    sound = NULL;
+    triggerFunc = NULL;
+    sysCommand = -1;
+    isUsed = true;
+
+}
+
+action::action(event* eventInput):
+actionType(3) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = eventInput;
+    displayActionPtr= NULL;
+    sound = NULL;
+    triggerFunc = NULL;
+
+    //eventDelay = eventInput->timeLag;
+
+
+    sysCommand = -1;
+    isUsed = true;
+}
+
+/*
+ action::action(event* eventInput, uint32_t delay):
+ actionType(3) {
+ op = NULL;
+ message = NULL;
+ eventToCreate = eventInput;
+ displayActionPtr= NULL;
+ sound = NULL;
+ eventDelay = delay;
+ sysCommand = -1;
+ isUsed = true;
+
+ }*/
+
+
+
+action::action(displayAction* displayInput):
+actionType(4) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    triggerFunc = NULL;
+    displayActionPtr = displayInput;
+    //eventDelay = 0;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(sSound* soundInput):
+actionType(5) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = soundInput;
+    triggerFunc = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(triggerFunctionAction* triggerFuncInput):
+actionType(7) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    triggerFunc = triggerFuncInput;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = -1;
+    isUsed = true;
+}
+
+action::action(int8_t sysCommandInput):
+actionType(6) {
+    op = NULL;
+    message = NULL;
+    eventToCreate = NULL;
+    sound = NULL;
+    displayActionPtr = NULL;
+    //eventDelay = 0;
+    sysCommand = sysCommandInput;
+    isUsed = true;
+}
+
+void action::set(intOperation* opInput) {
+    actionType = 1;
+    op = opInput;
+    //eventDelay = 0;
+    isUsed = true;
+
+}
+
+void action::set(portMessage* messageInput) {
+    actionType = 2;
+    message = messageInput;
+    //eventDelay = 0;
+    isUsed = true;
+
+}
+
+void action::set(event* eventInput) {
+    actionType = 3;
+    eventToCreate = eventInput;
+    //eventDelay = eventInput->timeLag;
+
+    isUsed = true;
+
+}
+
+/*
+ void action::set(event* eventInput, uint32_t delay) {
+ actionType = 3;
+ eventToCreate = eventInput;
+ eventDelay = delay;
+ isUsed = true;
+
+ }*/
+
+
+
+void action::set(displayAction* displayInput) {
+    actionType = 4;
+    displayActionPtr = displayInput;
+    isUsed = true;
+}
+
+void action::set(sSound* soundInput) {
+    actionType = 5;
+    sound = soundInput;
+    isUsed = true;
+}
+
+void action::set(triggerFunctionAction* triggerFuncInput) {
+
+    actionType = 7;
+    triggerFunc = triggerFuncInput;
+    isUsed = true;
+}
+
+void action::set(int8_t sysCommandInput) {
+    actionType = 6;
+    sysCommand = sysCommandInput;
+    isUsed = true;
+}
+
+void action::execute() {
+
+    if (actionType == 1) {
+        op->execute();
+    } else if (actionType == 2) {
+        message->execute();
+    } else if (actionType == 3) {
+        this->execute(timeKeeper); //route to the other overloaded method
+    } else if (actionType == 4) {
+        displayActionPtr->execute(); //send text via serial
+    } else if (actionType == 5) {
+        sound->execute(); //operate sound device
+    } else if (actionType == 6) {
+        switch(sysCommand) {
+            case 0:
+                mainQueue.eraseQueue();
+                break;
+            case 1:
+                textStreaming = true;
+                break;
+            case 2:
+                textStreaming = false;
+                break;
+            case 3:
+                broadCastStateChanges = true;
+                break;
+            case 4:
+                broadCastStateChanges = false;
+                break;
+        }
+
+    } else if (actionType == 7) {
+        triggerFunc->execute(); //execute function
+    }
+}
+
+void action::execute(uint32_t blockExecTime) {
+
+    if (actionType == 1) {
+        op->execute();
+    } else if (actionType == 2) {
+        message->execute();
+    } else if (actionType == 3) { //an event block
+        //Because time will pass from the begining of the block, any defined delays should be updated
+
+        //int newDelay = eventDelay-(*globalTimeKeeperPtr-blockExecTime);
+        int newDelay;
+        if (eventToCreate->timeLagIsConstant) {
+            newDelay = eventToCreate->timeLag - (timeKeeper-blockExecTime);
+        } else {
+            newDelay = *eventToCreate->timeLagVar - (timeKeeper-blockExecTime);
+        }
+        if (newDelay < 0) {newDelay = 0;}
+        eventToCreate->addToQueue(newDelay); //add the event to the queue to be executed later
+
+        if (eventToCreate->hasWhileLoop) { //this is a while loop
+            if (eventToCreate->isConditionTrue()) {
+                //newDelay = (blockExecTime + eventToCreate->whileLoopPeriod) - *globalTimeKeeperPtr;
+                int tmpPeriod;
+                if (eventToCreate->whileLoopPeriodIsConstant) { //constant while loop period
+                    newDelay = (blockExecTime + eventToCreate->whileLoopPeriod);
+                    tmpPeriod = eventToCreate->whileLoopPeriod;
+                } else {
+                    tmpPeriod = *eventToCreate->whileLoopPeriodVar;
+                    if (tmpPeriod < 0) {
+                        tmpPeriod = 0;
+                    }
+                    newDelay = (blockExecTime + tmpPeriod);
+                }
+                while ( (newDelay-timeKeeper < 0) && (eventToCreate->isConditionTrue()) ) {
+                    eventToCreate->execute();
+                    newDelay = newDelay + tmpPeriod;
+
+                }
+                newDelay = newDelay-timeKeeper;
+                if (newDelay > 0) {
+                    eventToCreate->addToQueue(newDelay);
+                } else {
+                    eventToCreate->addToQueue(1);
+                }
+            } else if (eventToCreate->nextElseEventPtr != NULL) {
+                eventToCreate->nextElseEventPtr->addToQueue();
+
+            }
+        }
+    } else if (actionType == 4) {
+        displayActionPtr->execute(); //send text via serial
+    } else if (actionType == 5) {
+        sound->execute(); //operate sound device
+    } else if (actionType == 6) {
+        switch(sysCommand) {
+            case 0:
+                mainQueue.eraseQueue();
+                break;
+            case 1:
+                textStreaming = true;
+                break;
+            case 2:
+                textStreaming = false;
+                break;
+            case 3:
+                broadCastStateChanges = true;
+                break;
+            case 4:
+                broadCastStateChanges = false;
+                break;
+        }
+    } else if (actionType == 7) {
+
+        textDisplay.flush();
+        triggerFunc->execute(); //operate sound device
+    }
+}
+
+eventQueue::eventQueue() {
+
+    queueItem blankEvent;
+    blankEvent.timeToExecute = 0;
+    blankEvent.eventPtr = NULL;
+    queueSize = 100;
+    events.resize(queueSize,blankEvent);
+
+
+}
+
+void eventQueue::addEventToQueue(event* eventInput, uint32_t delay) {
+    //*updateSlavePtr = false;
+    uint32_t eventTime = timeKeeper + delay;
+    //*updateSlavePtr = true;
+    //std::vector<queueItem>::size_type sz = events.size();
+    //Look for the first empty slot in the queue and place the event there.
+    //This means that the events in the queue are out of order, but
+    //it prevents us from having to push_pack and pop off all the time.
+    for (unsigned i = 0; i < queueSize; i++) {
+        if (events[i].eventPtr == NULL) {
+            events[i].eventPtr = eventInput;
+            events[i].timeToExecute = eventTime;
+            break;
+        }
+    }
+}
+
+void eventQueue::eraseQueue() {
+    //Erase all events in the queue
+    std::vector<queueItem>::size_type sz = events.size();
+    for (unsigned i = 0; i < sz; i++) {
+        events[i].eventPtr = NULL;
+
+    }
+}
+
+
+//check if any of the events in the queue are up for execution
+void eventQueue::check(void) {
+
+    //*updateSlavePtr = false;
+    uint32_t currentTime = timeKeeper;
+    //*updateSlavePtr = true;
+    //std::vector<queueItem>::size_type sz = events.size();
+    for (unsigned i = 0; i < queueSize; i++) {
+        if (events[i].eventPtr != NULL) {
+            if(events[i].timeToExecute <= currentTime) {
+                if (!events[i].eventPtr->hasWhileLoop) {
+                    //this is not a while loop, so no need to check if the condition is still true
+                    events[i].eventPtr->execute();
+                } else if (events[i].eventPtr->isConditionTrue()){
+                    //The event is part of a while loop, so recheck the condition before executing
+                    events[i].eventPtr->execute();
+                    //if (events[i].eventPtr->isConditionTrue()) { //is the condition still true?
+                    int nextTime;
+                    int tmpPeriod;
+                    if (events[i].eventPtr->whileLoopPeriodIsConstant) {
+                        nextTime = (events[i].timeToExecute + events[i].eventPtr->whileLoopPeriod);
+                        tmpPeriod = events[i].eventPtr->whileLoopPeriod;
+                    } else {
+                        tmpPeriod = *events[i].eventPtr->whileLoopPeriodVar;
+                        if (tmpPeriod < 0) {
+                            tmpPeriod = 0;
+                        }
+                        nextTime = (events[i].timeToExecute + tmpPeriod);
+
+                    }
+                    //Just in case we are not keeping up, execute the event until we have cought up
+                    while ((nextTime-timeKeeper <= 0) && (events[i].eventPtr->isConditionTrue())) {
+                        events[i].eventPtr->execute();
+                        nextTime = nextTime+tmpPeriod;
+
+                    }
+                    nextTime = nextTime - timeKeeper;
+                    if (nextTime > 0) {
+                        //we add the event to the queue (but the condition is rechecked first)
+                        //if the condition is false, the 'then' statement is added to the queue instead
+                        events[i].eventPtr->addToQueue(nextTime);
+                    } else {
+                        //if we are having trouble keeping up, just add the next event in 1 ms
+                        events[i].eventPtr->addToQueue(1);
+                    }
+                    /*
+                     } else {
+                     if (events[i].eventPtr->nextElseEventPtr != NULL) {
+                     events[i].eventPtr->nextElseEventPtr->addToQueue();
+                     }
+                     }*/
+
+                } else {
+                    if (events[i].eventPtr->nextElseEventPtr != NULL) {
+                        events[i].eventPtr->nextElseEventPtr->addToQueue();
+                    }
+                }
+                events[i].eventPtr = NULL;
+            }
+        }
+    }
+}
+
+
+event::event():
+    timeLag(0),
+    queuePtr(&mainQueue) {
+
+    nextElseEventPtr = NULL;
+    conditionToCheck = NULL;
+    blockType = 0;
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = false;
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+
+}
+
+event::event(eventQueue* queueInput):
+    timeLag(0),
+    queuePtr(&mainQueue) {
+
+    nextElseEventPtr = NULL;
+    conditionToCheck = NULL;
+    blockType = 0;
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = true;
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+
+}
+
+event::~event() {
+    /*
+     while (!conditionArray.empty())
+     {
+     delete conditionArray.back();
+     conditionArray.pop_back();
+     }
+
+     while (!actionArray.empty())
+     {
+     delete actionArray.back();
+     actionArray.pop_back();
+     }
+
+     delete nextElseEventPtr;
+     */
+
+}
+
+void event::release() {
+
+    for (int i = 0; i < numActions; i++) {
+        actionArray[i]->release();
+    }
+
+    if (conditionToCheck != NULL) {
+        conditionToCheck->release();
+        conditionToCheck = NULL;
+    }
+
+    if (nextElseEventPtr != NULL) {
+        nextElseEventPtr->release();
+    }
+    timeLag = 0;
+    nextElseEventPtr = NULL;
+    blockType = 0;
+    whileLoopPeriod = 0;
+    numConditions = 0;
+    numActions = 0;
+    isUsed = false;
+    timeLagVar = NULL;
+    timeLagIsConstant = true;
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = false;
+    whileLoopPeriodVar = NULL;
+}
+
+void event::setTimeLag(uint32_t timeLagInput) {
+    timeLag = timeLagInput;
+    timeLagIsConstant = true;
+}
+
+void event::setTimeLag(int* timeLagInput) {
+    timeLagVar = timeLagInput;
+    timeLagIsConstant = false; //time lag is not defined by a constant
+}
+
+void event::setWhileLoopPeriod(uint32_t period) {
+    whileLoopPeriodIsConstant = true;
+    hasWhileLoop = true;
+    whileLoopPeriod = period;
+
+}
+
+void event::setWhileLoopPeriod(int* period) {
+    whileLoopPeriodIsConstant = false;
+    hasWhileLoop = true;
+    whileLoopPeriodVar = period;
+
+}
+
+void event::addCondition(condition* conditionInput) {
+    if (conditionToCheck != NULL) {
+        conditionToCheck->release();
+    }
+    conditionToCheck = conditionInput;
+
+    //conditionArray.push_back(conditionInput);
+}
+
+void event::addAction(action* actionInput) {
+    actionArray[numActions] = actionInput;
+    numActions++;
+    //actionArray.push_back(actionInput);
+}
+
+bool event::isConditionTrue(void) {
+    //if statement (can be left empty, which is interpreted as 'true')
+    bool result = true;
+
+    if ((conditionToCheck!=NULL)&&(!conditionToCheck->isTrue())) {
+        result = false;
+    }
+
+    return result;
+}
+
+void event::execute(void) {
+    //called from the event queue.  The condition is bypassed because it was already checked
+
+    uint32_t timeAtStartExec = timeKeeper;
+    for (unsigned i = 0; i < numActions; i++) {
+        actionArray[i]->execute(timeAtStartExec);
+
+    }
+
+}
+
+//Attach an 'else' statement to the event
+void event::setNextElseEvent(event* eventInput) {
+    nextElseEventPtr = eventInput;
+}
+
+
+//When we we call addToQueue() the condition is checked.  If true, the event is added
+//to the queue, otherwise we check if there was an 'else' statement attached to the event.
+void event::addToQueue(void) {
+    if (isConditionTrue()) {
+        if ((timeLagIsConstant)&&(timeLag == 0)) {
+            execute();
+
+        } else if (timeLagIsConstant) {
+            queuePtr->addEventToQueue(this, this->timeLag);
+        } else if ((!timeLagIsConstant)&&(*timeLagVar <= 0)) {
+            execute();
+        } else {
+            queuePtr->addEventToQueue(this, *timeLagVar);
+        }
+    } else if ((this->nextElseEventPtr != NULL)&&(whileLoopPeriod == 0)) {
+        this->nextElseEventPtr->addToQueue();
+    }
+}
+
+//We can override the timeLag field and use another delay
+void event::addToQueue(uint32_t delay) {
+    if (this->isConditionTrue()) {
+        //if ((delay == 0) && (whileLoopPeriod == 0)) {
+        if ((delay == 0)) {
+            this->execute();
+        } else {
+            queuePtr->addEventToQueue(this, delay);
+        }
+    } else if ((this->nextElseEventPtr != NULL)) { //&&(!hasWhileLoop)) {
+        this->nextElseEventPtr->addToQueue();
+    }
+}
+
+
+
+functionItem::functionItem(action* actionInput, string tagInput):
+tag(tagInput),
+actionPtr(actionInput) {
+}
+
+functionItem::~functionItem() {
+    delete actionPtr;
+}
+
+blockBuffer::blockBuffer() {
+    bufferWritePos = 0;
+    bufferReadPos = 0;
+    _linesAvailable = 0;
+
+}
+
+bool blockBuffer::addLine(char *input, int numChars) {
+
+    if (bufferWritePos+numChars >= INPUTCHARBUFFERSIZE) {
+        return false;
+    }
+    for(int i=0;i<numChars;i++) {
+        charBuffer[bufferWritePos] = input[i];
+        bufferWritePos++;
+    }
+    _linesAvailable++;
+    return true;
+}
+
+string blockBuffer::getNextLine() {
+
+    string outputLine;
+    int endOfLinePos = bufferReadPos;
+    bool endOfLineFound = false;
+
+    if (_linesAvailable > 0) {
+        //Find the end of the next line
+
+        while (endOfLinePos < INPUTCHARBUFFERSIZE) {
+
+            if (charBuffer[endOfLinePos] == '\0') {
+                endOfLineFound = true;
+                break;
+            }
+            endOfLinePos++;
+        }
+
+        //If the end was found, copy to output string
+        if (endOfLineFound) {
+
+            outputLine.append(charBuffer+bufferReadPos,endOfLinePos-bufferReadPos);
+            bufferReadPos = endOfLinePos+1;
+            _linesAvailable--;
+        } else {
+            textDisplay << "Error: No end of line found!";
+            textDisplay.flush();
+        }
+    }
+    if (_linesAvailable == 0) {
+        //we have read out all of the lines, so reset the buffer for the next block.
+        resetBuffer();
+    }
+    return outputLine;
+
+}
+
+int16_t blockBuffer::linesAvailable() {
+    return _linesAvailable;
+}
+
+void blockBuffer::resetBuffer() {
+    _linesAvailable = 0;
+    bufferReadPos = 0;
+    bufferWritePos = 0;
+}
+
+bool blockBuffer::empty() {
+    return (_linesAvailable == 0);
+}
+
+
+scriptStream::scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem *system):
+    portVector(portVectorInput),
+    numPorts(numPortsInput),
+    queuePtr(queueInput),
+    system(system) {
+
+    currentPort = -1;
+    currentTriggerPort = -1;
+    currentTriggerDir = 1;
+    currentFunction = -1;
+
+    randomSeedCounter = 0;  //used for seeding random numbers
+
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    expectingDoStatement = false;
+    elseFlag = false;
+    thenFlag = false;
+    currentDelay = 0;
+
+    for (int i = 0; i < NUMFUNCTIONS; i++) {
+        functionSpotTaken[i] = false;
+        functionEventArray[i] = NULL;
+    }
+
+
+}
+
+
+void scriptStream::addLineToCurrentBlock(char* lineInput) {
+
+    bool compile = false;
+    bool keep = false;
+    int numCharInLine = 0;
+    //A line ending with ';' then carriage return initiates the compile sequence
+    //Otherwise, add the line to the buffer and compile later
+    for (int i = 0; i < 256; i++) {
+        numCharInLine++;
+        if (lineInput[i] == ';') {
+            compile = true;
+        } else if (lineInput[i] == ' ') {
+            continue;
+        } else if (lineInput[i] == '\0') {
+            break;
+        } else {
+            keep = true;
+            compile = false;
+        }
+
+    }
+
+    //if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput));
+    if (keep) {
+        if (!currentBlock.addLine(lineInput,numCharInLine)) {
+            textDisplay << "Error: script input buffer full. The block is too long.\r\n";
+            currentBlock.resetBuffer();
+            compile = false;
+        }
+    }
+    if (compile) {
+        parseBlock();
+    }
+
+}
+
+
+//SCRIPT PARSING - all script commands are defined here.
+//-------------------------------------------------------
+void scriptStream::parseBlock() {
+
+    tmpEvent = NULL;
+    lineError = false;
+    blockDepth = 0;
+    ifBlockInit = false;
+    whileBlockInit = false;
+    expectingDoStatement = false;
+    elseFlag = false;
+    thenFlag = false;
+    currentDelay = 0;
+
+
+    std::size_t stringInd = 0;
+
+    bool wholeLineEvaluated = false;
+
+    while (!currentBlock.empty()) {
+
+        wholeLineEvaluated = false;
+        //tmpLine = currentBlock.back();
+        tmpLine = currentBlock.getNextLine();
+
+        lineError = false;
+        //remove tabs
+        std::size_t found = tmpLine.find_first_of(9); //tab
+        while (found!=std::string::npos) {
+            tmpLine[found]= ' ';
+            found=tmpLine.find_first_of(9,found+1);
+        }
+
+        found = tmpLine.find_first_of(37); //% for commenting
+        if (found!=std::string::npos) {
+            for (int p=found; p<tmpLine.size() ;p++) {
+                tmpLine[p]= ' ';
+            }
+        }
+
+        //break up the line into tokens separated by spaces
+        tokenize(tmpLine,tokens," ;");
+
+        std::vector<string>::size_type sz = tokens.size();
+
+        for (unsigned i = 0; i < sz; i++) {
+
+
+
+            //end statement signals the end of a block-----------------------------------------
+            if (tokens[i].compare("end") == 0) { //ends the current block
+
+                if (ifBlockInit || whileBlockInit || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                ifBlockInit = false;
+                whileBlockInit = false;
+                expectingDoStatement = false;
+                elseFlag = false;
+
+                if (blockDepth > 0) {
+                    textDisplay.debug("End statement\r\n");
+                    if (blockDepth == 1) {
+
+
+                        currentTriggerPort = -1;
+                        currentFunction = -1;
+
+
+
+                        blockDepth = 0;
+                    } else if (blockDepth > 1) {
+                        blockDepth = blockDepth - 1;
+                    }
+
+                    while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4) || (tmpEventPtrArray.back()->blockType == 6) || (tmpEventPtrArray.back()->blockType == 7) || (tmpEventPtrArray.back()->blockType == 8)){
+                        tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks
+                    }
+                    tmpEventPtrArray.pop_back(); //remove the pointer to the finished block
+
+                } else {
+                    textDisplay << "Error: End statement without block\r\n";
+                    lineError = true;
+                }
+
+
+
+                //sound statement used to play wave files------------------------------------------------
+                //example: sound('soundfile')
+                //         sound(stop)
+                //         sound(s03)
+            } else if (tokens[i].find("sound(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("sound(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+                    int* tmpVar = findIntVariable(dispVar);
+                    bool isText = false;
+                    bool stopSignal = false;
+                    bool resetSignal = false;
+                    unsigned char sendTrack = 0;
+                    if (tmpVar == NULL) {
+                        if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
+                            isText = true;
+//                            textDisplay <<"command= "<<tmpLine.substr(pos1+1,pos2-pos1-2)<<"\r\n";
+                        } else if (tmpLine.compare(pos1,1,"s")==0 && dispVar.length()==3) {
+                            sendTrack = (dispVar[1]-48)*10 + dispVar[2]-48;
+                        } else if (dispVar.compare("stop") == 0) {
+                            stopSignal = true;
+                        } else if (dispVar.compare("reset") == 0) {
+                            resetSignal = true;
+                        } else {
+                            textDisplay << "Error: variable input to sound() does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                    if (tmpAction == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so play sound now
+                        if (stopSignal) {
+                            sSound* S = system->createNewSoundAction();
+                            S->setPlayback(false);
+                            S->execute();
+                            delete S;
+                        } else if (resetSignal) {
+                            sSound* S = system->createNewSoundAction();
+                            S->setReset();
+                            S->execute();
+                            delete S;
+                        } else if (sendTrack>0 && sendTrack<100){ //track number must be 1-99
+                            sSound* S = system->createNewSoundAction();
+//                            textDisplay<<"sent:"<<sendTrack;
+                            S->setFile(sendTrack);
+                            S->execute();
+                            delete S;                            
+                        } else if (isText) {
+                            if (pos2-pos1-2 <= 20) {
+                                sSound* S = system->createNewSoundAction();
+                                S->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                                S->execute();
+                                delete S;
+                            } else {
+                                textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n";
+                            lineError = true;
+                        }
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the disp function was put inside a block
+                        textDisplay.debug("Sound statement\r\n");
+                        if (stopSignal) {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setPlayback(false);
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (resetSignal) {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setReset();
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (sendTrack>0 && sendTrack<100){
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setFile(sendTrack);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }else if (isText) {
+                            if (pos2-pos1-2 <= 20) {
+                                sSound* sPtr = system->createNewSoundAction();
+                                sPtr->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
+                                //action* tmpAction = new action(sPtr);
+                                tmpAction->set(sPtr);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            } else {
+                                textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n";
+                            lineError = true;
+                        }
+                    }
+                }
+
+            } else if (tokens[i].find("volume(") != std::string::npos) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("volume(")+7;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+
+                    int* tmpVar = findIntVariable(dispVar);
+                    bool isText = false;
+                    if (tmpVar == NULL) {
+                        if (isNumber(dispVar)) {
+                            isText = true;
+                        } else {
+                            textDisplay << "Error: variable input to volume() does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                    if (tmpAction == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so play sound now
+                        if (isText) {
+                            int newVolume = atoi(dispVar.data());
+                            if ((newVolume >=0)&&(newVolume <= 255)) { // for SOMO II it should be between 0 and 30, but I'm not sure how to let this code know whether the SOMO or the smartWAV is being used
+                                sSound* S = system->createNewSoundAction();
+//                                textDisplay << "new vol=" <<newVolume;
+                                S->setVolume(newVolume);
+                                S->execute();
+                                delete S;
+                            } else {
+                                textDisplay << "Error: sound volume must be between 0 and 255 .\r\n"; 
+                                lineError = true;
+                            }
+                        } else {
+                            sSound* S = system->createNewSoundAction();
+                            S->setVolume(tmpVar);
+                            S->execute();
+                            delete S;
+                        }
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the disp function was put inside a block
+                        textDisplay.debug("Volume statement\r\n");
+                        if (isText) {
+                            int newVolume = atoi(dispVar.data());
+
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setVolume(newVolume);
+
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+
+                        } else {
+                            sSound* sPtr = system->createNewSoundAction();
+                            sPtr->setVolume(tmpVar);
+                            //action* tmpAction = new action(sPtr);
+                            tmpAction->set(sPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+
+                    }
+                }
+                //clock statement used to is used to control the clock-------------------------
+                //example: clock(reset); clock(slave); clock(standalone)
+            } else if (tokens[i].find("clock(") != std::string::npos) { //clock commands
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth > 0) {
+                    textDisplay << "Error: clock commands only allowed outside of block structure\r\n";
+                    lineError = true;
+                }
+                int pos1 = tmpLine.find("clock(")+6;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax Error: expected a ')'\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    //int pos1 = tmpLine.find("clock(")+6;
+                    //int pos2 = tmpLine.find_first_of(")",pos1);
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+
+
+                    if (blockDepth == 0) {
+                        if (dispVar.compare("reset") == 0) {
+                            resetTimer = true;
+                            queuePtr->eraseQueue();
+                            textDisplay.send(string("Clock reset to 0\r\n"));
+
+                        } else if (dispVar.compare("slave") == 0) {
+                            if (!clockSlave) {
+                                changeToSlave = true;
+                                textDisplay.send(string("Slave mode\r\n"));
+
+                            }
+                        } else if (dispVar.compare("standalone") == 0) {
+                            if (clockSlave) {
+                                changeToStandAlone = true;
+                                textDisplay.send(string("Standalone mode\r\n"));
+
+                            }
+                        } else if (dispVar.compare("") == 0) {
+                            //The user needs the current time displayed.
+
+                            //textDisplay.send(string("Current Clock\r\n"));
+                            textDisplay << timeKeeper << " current time\r\n";
+                        } else {
+                            textDisplay << "Error: Clock control statement not understood\r\n";
+                            lineError = true;
+                        }
+                    }
+                }
+
+                //disp command used to display text via serial---------------------------------------
+                //example: disp('hello'); disp(myVar)
+            } else if (tokens[i].find("disp(") != std::string::npos) { //display value of variable
+
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay <<"Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                //int pos1 = tokens[i].find("disp(")+5;
+                //int pos2 = tokens[i].find_first_of(")",pos1);
+                //string dispVar = tokens[i].substr(pos1,pos2-pos1);
+
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("disp(")+5;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay <<"Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    string dispVar = tmpLine.substr(pos1,pos2-pos1);
+
+                    int* tmpVar = findIntVariable(dispVar);
+                    bool isText = false;
+                    if (tmpVar == NULL) {
+                        if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
+                            isText = true;
+                        } else {
+                            textDisplay << "Error: variable to display does not exist\r\n";
+                            lineError = true;
+                        }
+                    }
+                    displayAction* dPtr = findFirstUnUsed(displayActionBlock, NUMDISPLAYACTIONS);
+                    if (dPtr == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so display now
+
+                        if (isText) {
+                            //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
+                            dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2));
+                            dPtr->execute();
+                            //delete dPtr;
+                            dPtr->release();
+                        } else {
+                            //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
+                            dPtr->set(tmpVar, dispVar);
+                            dPtr->execute();
+                            //delete dPtr;
+                            dPtr->release();
+                        }
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the disp function was put inside a block
+                        textDisplay.debug("Display statement\r\n");
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay <<"Error: no memory slots available.\r\n";
+                            lineError = true;
+                        }
+                        if (!lineError && isText) {
+                            //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
+                            dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2));
+                            tmpAction->set(dPtr);
+                            //action* tmpAction = new action(dPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        } else if (!lineError) {
+                            //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
+                            dPtr->set(tmpVar, dispVar);
+                            tmpAction->set(dPtr);
+                            //action* tmpAction = new action(dPtr);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+
+                    }
+                }
+                //----------------------------------------------
+                //The trigger command is used like this:
+                //trigger(n)
+                //Where n is an integer corresponding to a "function n" block
+                //When "trigger" is called, the corresponding function is executed.
+            } else if (tokens[i].find("trigger(") != std::string::npos) { //trigger a function
+
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+
+                wholeLineEvaluated = true;
+                int pos1 = tmpLine.find("trigger(")+8;
+                int pos2 = tmpLine.find_first_of(")",pos1);
+                if (pos2 == std::string::npos) {
+                    textDisplay << "Syntax error: expected a ')'\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
+                    if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
+                        if (functionSpotTaken[funcNum-1] && functionEventArray[funcNum-1]->isUsed) {
+
+
+                        } else {
+                            textDisplay << "Error: function number does not exist\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: not a valid function number\r\n";
+                        lineError = true;
+                    }
+
+                    funcNum--;  //change to 0-based index
+                    if (!lineError && (blockDepth == 0)) {
+                        //we are not inside a block structure, so execute function now
+                        //textDisplay << "Exectuting function";
+                        //textDisplay.flush();
+
+                        functionEventArray[funcNum]->execute();
+
+                    } else if (!lineError && (blockDepth > 0) ){
+                        //the trigger function was put inside a block, so we need to create a new action
+                        textDisplay.debug("Trigger statement\r\n");
+                        triggerFunctionAction* tPtr = findFirstUnUsed(triggerFunctionActionBlock, NUMTRIGGERACTIONS);
+                        if (tPtr == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        }
+
+                        if (!lineError) {
+                            //we only give provide it the function number, instead
+                            //of a pointer to the event.  That way, if the user modifies
+                            //the function (which would change the pointer), all callbacks
+                            //still using that function number will use the new function.
+                            tPtr->set(funcNum);
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                            if (tmpAction == NULL) {
+                                textDisplay << "Error: no memory slots available.\r\n";
+                                lineError = true;
+                            }
+                            if (!lineError) {
+
+                                tmpAction->set(tPtr);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            }
+                        }
+
+
+                    }
+
+                }
+
+
+                //int is used to decalar new variables.  Only allowed outside of callbacks-------------------
+                //example: int a;  int b = 9
+            }else if(tokens[i].compare("kaboom") == 0){//send "kaboom;" to reset mbed
+//                mbed_reset();            
+            }else if (tokens[i].compare("int") == 0) { //define a new integer variable
+                textDisplay.debug("Int statement\r\n");
+                if (ifBlockInit || whileBlockInit || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                tmpString = "";
+                wholeLineEvaluated = true;
+                int spacesBeforeEqualSign = 0;
+                bool countSpaces = true;
+                //combine the tokens without whitespaces
+                for (unsigned j = i+1; j < sz; j++) {
+                    tmpString.append(tokens[j]);
+                    if (tokens[j].find_first_of("=") != std::string::npos) {
+                        if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
+                        countSpaces = false;
+                    } else if (countSpaces) {
+                        spacesBeforeEqualSign++;
+                    }
+                }
+
+                if (blockDepth > 0) {
+                    textDisplay << "Error: Variables can only be first declared outside of callbacks.\r\n";
+                    lineError = true;
+                }
+
+                if ((!lineError) && (spacesBeforeEqualSign > 1)) {
+                    textDisplay << "Error: Variable can't have a space in it.\r\n";
+                    lineError = true;
+                }
+                stringInd = tmpString.find_first_of("=");
+
+                bool variableCreated = false;
+                if (!lineError) {
+                    if (((stringInd == std::string::npos) && (sz == 2)) || (stringInd != std::string::npos)) {
+
+                        if ((stringInd != std::string::npos) && (stringInd > MAXVARNAMESIZE)) {
+                            textDisplay << "Error: variable names must be under 30 characters.\r\n";
+                            lineError = true;
+                        } else if (createIntVariable(tmpString.substr(0,stringInd))) {
+                            textDisplay.debug("Created new variable\r\n");
+                            variableCreated = true;
+                        } else {
+                            textDisplay.debug("Attempting to use existing variable\r\n");
+                            int* tmpVar = findIntVariable(tmpString.substr(0,stringInd));
+                            *tmpVar = 0;
+                            //lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: variable declaration not understood.\r\n";
+                        lineError = true;
+                    }
+                }
+                if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression
+                    //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                    action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+                    if (tmpAction != NULL) {
+                        tmpAction->execute();
+                        //delete tmpAction;
+                        tmpAction->release();
+                    } else {
+                        lineError = true;
+                        if (variableCreated) {
+                            delete globalVariables.back();
+                            globalVariables.pop_back();
+                        }
+                    }
+                }
+
+                //serial command is used to toggle whether or not to buffer up output text----------------
+                //examples: serial buffer; serial send
+            } else if (tokens[i].compare("serial") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                bool stream = true;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("buffer") == 0) {
+                        stream = false;
+                    } else if (tokens[i+1].compare("send") == 0) {
+                        stream = true;
+                    } else {
+                        textDisplay << "Error: 'serial' useage: 'serial buffer' or 'serial send'\r\n";
+                        lineError = true;
+                    }
+                }
+                i++;
+                if ((!lineError) && (blockDepth == 0)) {
+                    if (stream) {
+                        textStreaming = true;
+                    } else {
+                        textStreaming = false;
+                    }
+                } else if ((!lineError) && (blockDepth > 0)) {
+                    if (stream) {
+                        //action* tmpAction = new action(1); //code 1 = turn on text streaming
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        } else {
+                            tmpAction->set(1);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+                    } else {
+                        //action* tmpAction = new action(2); //code 2 = turn on text buffering
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        } else {
+                            tmpAction->set(2);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                    }
+                }
+
+                //updates command toggles the DIO update messages upon a change------------------
+                //examples: updates on; updates off
+                //examples: updates on 3; updates off 3
+            } else if (tokens[i].compare("updates") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                bool stream = true;
+                int specifiedPort = -1;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("on") == 0) {
+                        stream = true;
+                    } else if (tokens[i+1].compare("off") == 0) {
+                        stream = false;
+                    } else {
+                        textDisplay << "Error: 'updates' useage: 'updates on' or 'updates off'\r\n";
+                        lineError = true;
+                    }
+                }
+                if ((!lineError) && (i+2 < sz)) {
+                    //There is a port specified
+                    //int pos1 = tmpLine.find("trigger(")+8;
+                    //int pos2 = tmpLine.find_first_of(")",pos1);
+                    int tempPort = atoi(tokens[i+2].data());
+                    if (tempPort > 0) {
+                        specifiedPort = tempPort-1;
+                    } else {
+                        textDisplay << "Error: 'updates' useage: 'updates on [port]' or 'updates off [port]'\r\n";
+                        lineError = true;
+                    }
+                    i++;
+                }
+                i++;
+                if ((!lineError) && (blockDepth == 0)) {
+                    if (stream) {
+                        //applies to all;
+                        broadCastStateChanges = true;
+                        if (specifiedPort > -1) {
+                            system->setPortUpdatesOn(specifiedPort);
+                        } else {
+                            for (int i=0;i<NUMPORTS;i++) {
+                                system->setPortUpdatesOn(i);
+                            }
+                        }
+                    } else {
+                        if (specifiedPort > -1) {
+                            system->setPortUpdatesOff(specifiedPort);
+                        } else {
+                            //applies to all
+                            //broadCastStateChanges = false;
+                            for (int i=0;i<NUMPORTS;i++) {
+                                system->setPortUpdatesOff(i);
+                            }
+                        }
+
+                    }
+                } else if ((!lineError) && (blockDepth > 0)) {
+                    //Inside a block-- current no support here to specify a port
+
+                    if (stream) {
+                        //action* tmpAction = new action(3); //code 3 = turn on updates
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        } else {
+                            tmpAction->set(3);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+                    } else {
+                        //action* tmpAction = new action(4); //code 4 = turn off updates
+                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                        if (tmpAction == NULL) {
+                            textDisplay << "Error: no memory slots available.\r\n";
+                            lineError = true;
+                        } else {
+                            tmpAction->set(4);
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+                        }
+
+                    }
+                }
+
+            } else if (tokens[i].compare("memory") == 0) {
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if ((!lineError) && (blockDepth > 0)) {
+                    textDisplay << "Error: memory statement is not allowed inside a block.\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    displayMemoryLeft();
+                }
+
+
+            //clear is used to clear things from memory---------------------------------
+            //examples: clear all; clear callbacks; clear queue
+
+            } else if (tokens[i].compare("clear") == 0) { //delete all created events and variables
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                int clearMode = 0;
+                if ((!lineError)&&(i+1 < sz)){
+                    if (tokens[i+1].compare("all") == 0) {
+                        clearMode = 1;
+                    } else if (tokens[i+1].compare("blocks") == 0) {
+                        clearMode = 2;
+                    } else if (tokens[i+1].compare("queue") == 0) {
+                        clearMode = 3;
+                    } else {
+                        textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
+                        lineError = true;
+                    }
+                } else {
+                    textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
+                    lineError = true;
+                }
+
+
+                if ((!lineError) && (clearMode < 3) && (blockDepth > 0)) {
+                    textDisplay << "Error: 'clear all' and 'clear blocks' only allowed outside of block structures\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    //i++;
+                    //clear variables
+
+                    if (clearMode == 1) {
+                        //Clears everything
+                        int sendClearMode = 0;
+                        sendClearMode |= BLOCKMEMORYTYPES;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        sendClearMode |= ENVSETTINGSMEMORYTYPES;
+
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if  (clearMode == 2) {
+                        //Clear just varaibles
+                        int sendClearMode = 0;
+                        sendClearMode |= VARIABLEMEMORYTYPES;
+                        clearEnvironmentVariables(sendClearMode);
+
+                    } else if (clearMode == 3) {
+                        //Clear the current event queue (can itself be a queued action)
+                        if (blockDepth > 0) { //we are inside a block
+                            action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                            if (tmpAction == NULL) {
+                                textDisplay << "Error: no memory slots available.\r\n";
+                                lineError = true;
+                            } else {
+
+                                int8_t code = 0;
+                                tmpAction->set(code);
+                                //action* tmpAction = new action(code); //code 0 = clear queue
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                            }
+                        } else {
+                            //clear queue now
+                            queuePtr->eraseQueue();
+                        }
+                    }
+                    wholeLineEvaluated = true;
+
+
+                }
+
+                //do starts a block---------------------------------------------------------
+                //example:  do in 500
+                //              ...
+                //          end
+
+            } else if (tokens[i].compare("do") == 0) { //the start of a block
+
+                if (!ifBlockInit && !whileBlockInit) {
+
+                    if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+
+
+                    } else {
+                        textDisplay << "Error: a statement block must be placed inside a callback or function.\r\n";
+                        lineError = true;
+                    }
+
+                }
+                expectingDoStatement = false;
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                bool eventReserved = false;
+                if ((tmpEvent == NULL)||(tmpAction == NULL)) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    lineError = true;
+
+                } else {
+
+
+                }
+
+                if (i+2 < sz) { //a time delay in the block
+
+                    if ((!lineError) && (tokens[i+1].compare("in") == 0) && (isNumber(tokens[i+2]))) {
+                        textDisplay.debug("Do in number statement\r\n");
+                        currentDelay = atoi(tokens[i+2].data());
+                        if (currentDelay < 0) {
+                            textDisplay <<"Error: block delay time must be a positive integer\r\n";
+                            lineError = true;
+                        } else if (!ifBlockInit) { //a standalone do block
+                            //tmpEvent = new event(queuePtr);
+                            tmpEvent->isUsed = true;
+                            eventReserved = true;
+                            tmpEvent->setTimeLag(currentDelay);
+
+                            if ((!elseFlag) && ((!thenFlag))) {
+                                //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                tmpAction->set(tmpEvent);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 2; //this is a do block
+                                blockDepth = blockDepth+1;
+                            } else if (elseFlag) {
+                                tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 4; //an else block
+                            } else if (thenFlag) {
+
+                                tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 8; //a then block
+                            }
+
+                        } else { //an if block
+                            tmpEventPtrArray.back()->setTimeLag(currentDelay);
+
+                            if (!elseFlag && !thenFlag) {
+                                if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
+                                    tmpAction->set(tmpEventPtrArray.back());
+                                    tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                                    //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
+                                }
+                            } else if (elseFlag){
+                                tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                            } else if (thenFlag){
+                                tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+
+                            }
+
+
+                        }
+
+                    } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) {
+                        textDisplay.debug("Do in VAR statement\r\n");
+                        int* delayVar = findIntVariable(tokens[i+2]);
+                        //currentDelay = atoi(tokens[i+2].data());
+                        if (!ifBlockInit) { //a standalone do block
+                            //tmpEvent = new event(queuePtr);
+                            tmpEvent->isUsed = true;
+                            eventReserved = true;
+                            tmpEvent->setTimeLag(delayVar);
+
+                            if ((!elseFlag) && ((!thenFlag))) {
+                                //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                tmpAction->set(tmpEvent);
+                                tmpEventPtrArray.back()->addAction(tmpAction);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 2; //this is a do block
+                                blockDepth = blockDepth+1;
+                            } else if (elseFlag) {
+                                tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 4; //an else block
+                            } else if (thenFlag) {
+
+                                tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                tmpEventPtrArray.push_back(tmpEvent);
+                                tmpEventPtrArray.back()->blockType = 8; //a then block
+                            }
+
+                        } else { //an if block
+                            tmpEventPtrArray.back()->setTimeLag(delayVar);
+
+                            if (!elseFlag && !thenFlag) {
+                                if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
+                                    tmpAction->set(tmpEventPtrArray.back());
+                                    tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                                    //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
+                                }
+                            } else if (elseFlag){
+                                tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                            } else if (thenFlag){
+                                tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+
+                            }
+
+
+                        }
+
+                    } else {
+                        textDisplay << "Error: block delay time must be a positive integer or a variable\r\n";
+                        lineError = true;
+                    }
+                } else if (!lineError && !ifBlockInit) { //no time delay given, standalone do
+                    textDisplay.debug("Do statement\r\n");
+                    currentDelay = 0;
+                    //tmpEvent = new event(queuePtr);
+                    tmpEvent->isUsed = true;
+                    eventReserved = true;
+                    tmpEvent->setTimeLag(currentDelay);
+                    if (!elseFlag && !thenFlag) {
+                        tmpAction->set(tmpEvent);
+                        tmpEventPtrArray.back()->addAction(tmpAction);
+                        //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                        tmpEventPtrArray.push_back(tmpEvent);
+                        blockDepth = blockDepth+1;
+                    } else if (elseFlag) {
+                        tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                        tmpEventPtrArray.push_back(tmpEvent);
+                        tmpEventPtrArray.back()->blockType = 4; //an else block
+                    } else if (thenFlag) {
+                        tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                        tmpEventPtrArray.push_back(tmpEvent);
+                        tmpEventPtrArray.back()->blockType = 8; //a then block
+                    }
+
+                } else if (!lineError) { //no time delay, if block
+
+                    currentDelay = 0;
+                    tmpEventPtrArray.back()->setTimeLag(currentDelay);
+
+
+                    if (!elseFlag && !thenFlag) {
+                        if (blockDepth > 1) {
+                            tmpAction->set(tmpEventPtrArray.back());
+                            tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
+                            //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
+                        }
+                    } else {
+                        tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
+                    }
+
+                }
+                if (lineError && eventReserved) {
+                    tmpEvent->release();
+                }
+                //close block initiation
+                ifBlockInit = false;
+                whileBlockInit = false;
+                wholeLineEvaluated = true;
+                elseFlag = false;
+                thenFlag = false;
+
+                //currently, there are two types of root-level blocks: functions and callbacks
+                //
+                //A function can be triggered with a command, a callback is tied to a hardware event
+            } else if (tokens[i].compare("function") == 0) { //a new function block
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth != 0)  {
+                    textDisplay <<"Error: Can't declare a function block within another block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("Function statement\r\n");
+                    wholeLineEvaluated = true;
+                    if (i+1 < sz) {
+                        int tempFuncNum = atoi(tokens[i+1].data());
+                        if ((tempFuncNum > 0) && (tempFuncNum < NUMFUNCTIONS+1)) {
+                            currentFunction = tempFuncNum-1;
+                        } else {
+                            textDisplay << "Error: not a valid function number\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        if (!lineError) textDisplay << "Error: Not enough arguments for function statement\r\n";
+                        lineError = true;
+                    }
+                    if (sz > 2) {
+                        if (!((sz == 3) && (tokens[i+2].compare("do") == 0))) {
+                            textDisplay << "Error: Too many arguments in function statement\r\n";
+                            lineError = true;
+                        }
+                    }
+
+                    tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                    if (tmpEvent != NULL) {
+                        tmpEvent->isUsed = true;
+
+                    } else {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError) {
+
+                        blockDepth = 1;
+                        i = i+2;
+                        //create new event and attach it to the port
+                        //tmpEventPtrArray.push_back(new event(queuePtr));
+                        tmpEventPtrArray.push_back(tmpEvent);
+
+                        if (functionSpotTaken[currentFunction]) {
+                            functionEventArray[currentFunction]->release();
+                        }
+                        functionEventArray[currentFunction] = tmpEvent;
+                        functionSpotTaken[currentFunction] = true;
+
+                    }
+                }
+
+
+                //callback starts a callback block------------------------------------------
+                //exmaple: callback portin(1) down
+                //              ...
+                //         end
+            } else if (tokens[i].compare("callback") == 0) { //a new callback block
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                if (blockDepth != 0)  {
+                    textDisplay << "Error: Can't declare a callback block within another block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("Callback statement\r\n");
+                    wholeLineEvaluated = true;
+                    if (i+2 < sz) {
+                        if ((tokens[i+1].find("portin[") != std::string::npos) && (tokens[i+1].size() > 8) ) { //callback for a digital port
+                            int pos1 = tokens[i+1].find("portin[")+7;
+                            int pos2 = tokens[i+1].find_first_of("]",pos1);
+                            currentTriggerPort = atoi(tokens[i+1].substr(pos1,pos2-pos1).data());
+
+                            if (currentTriggerPort <= 0) {
+                                currentTriggerPort = -1;
+                                textDisplay << "Error: Not a valid port number\r\n";
+                                lineError = true;
+                            }
+                        } else {
+                            textDisplay << "Error: Not a valid callback input\r\n";
+                            lineError = true;
+                        }
+                        if (tokens[i+2].compare("up") == 0) {
+                            currentTriggerDir = 1;
+                        } else if (tokens[i+2].compare("down") == 0) {
+                            currentTriggerDir = -1;
+                        } else {
+                            textDisplay << "Error: No trigger direction given\r\n";
+                            lineError = true;
+                        }
+
+                    } else {
+                        if (!lineError) textDisplay << "Error: Not enough arguments for callback statement\r\n";
+                        lineError = true;
+                    }
+                    if (sz > 3) {
+                        if (!((sz == 4) && (tokens[i+3].compare("do") == 0))) {
+                            textDisplay << "Error: Too many arguments in callback statement\r\n";
+                            lineError = true;
+                        }
+                    }
+
+                    tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                    if (tmpEvent != NULL) {
+                        tmpEvent->isUsed = true;
+
+                    } else {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        lineError = true;
+                    }
+                    if (!lineError) {
+
+                        blockDepth = 1;
+                        i = i+2;
+                        //create new event and attach it to the port
+                        //tmpEventPtrArray.push_back(new event(queuePtr));
+                        tmpEventPtrArray.push_back(tmpEvent);
+                        if (currentTriggerDir == 1) {
+
+                            portVector[currentTriggerPort-1].setTriggerUpEvent(tmpEventPtrArray.back());
+                        } else {
+
+                            portVector[currentTriggerPort-1].setTriggerDownEvent(tmpEventPtrArray.back());
+                        }
+
+                    }
+                }
+
+                //if starts an if block----------------------------------------------
+                //examples: if x < 10 && y == 1 do;  if a==1 do in 1000
+            } else if (tokens[i].compare("if") == 0) { //a new if block
+                if (ifBlockInit || whileBlockInit) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                ifBlockInit = true;
+                currentDelay = 0;
+                bool eventDefined = false;
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                if (tmpEvent != NULL) {
+                    tmpEvent->isUsed = true;
+                    eventDefined = true;
+                } else {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    textDisplay.debug("If statement\r\n");
+                    //this is a regular event
+                    //tmpEventPtrArray.push_back(new event(queuePtr));
+                    tmpEventPtrArray.push_back(tmpEvent);
+
+                    if ((!elseFlag) && ((!thenFlag))) {
+                        tmpEventPtrArray.back()->blockType = 1; //this is an if block
+                        blockDepth = blockDepth + 1;
+                    } else if (elseFlag) {
+                        tmpEventPtrArray.back()->blockType = 3; //this is an else if block
+                    } else if (thenFlag) {
+                        tmpEventPtrArray.back()->blockType = 7; //this is a then if block
+                    }
+                }
+
+                if (!lineError) {
+                    //combine the condition tokens without whitespaces
+                    tmpString = "";
+                    for (unsigned j = i+1; j < sz; j++) {
+                        if (tokens[j].compare("do") != 0) {
+                            i++;
+                            tmpString.append(tokens[j]);
+                        } else {
+                            break;
+                        }
+                    }
+                    //adds the conditions to the current event
+
+                    if (!evaluateConditions(tmpString, tmpEventPtrArray.back())) lineError = true;
+                }
+
+                if (lineError && eventDefined) {
+                    tmpEvent->release();
+                }
+
+
+                //else starts an else block-------------------------------------
+                //examples:  else do in 500;  else if x==7 do
+            } else if (tokens[i].compare("else") == 0) { //an else block
+                if (ifBlockInit || whileBlockInit || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                textDisplay.debug("Else statement\r\n");
+                //callbacks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && ((currentTriggerPort > -1)||(currentFunction > -1))) {
+                    textDisplay << "Error: else statement can not occur after a trigger block or outside a block\r\n";
+                    lineError = true;
+                }
+
+                //check to make sure we are in an 'if' block
+                if ((!lineError) && (tmpEventPtrArray.back()->blockType != 1) && (tmpEventPtrArray.back()->blockType != 3)) { //not currently in an 'if' or 'else if' block
+                    textDisplay << "Error: else statement can only occur in an 'if' block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    elseFlag = true;
+                    expectingDoStatement = true;
+
+                }
+            } else if (tokens[i].compare("then") == 0) { //a then block
+                if (ifBlockInit || whileBlockInit) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                //trigger blocks can't have else conditions
+                if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) {
+                    textDisplay << "Error: 'then' statement can only occur after a 'while' block\r\n";
+                    lineError = true;
+                }
+
+                //check to make sure we are in a 'while' block
+                if ((!lineError) && (tmpEventPtrArray.back()->blockType != 5)) { //not currently in a while block
+                    textDisplay << "Error: 'then' statement can only occur in a 'while' block\r\n";
+                    lineError = true;
+                }
+                if (!lineError) {
+                    thenFlag = true;
+                    expectingDoStatement = true;
+
+                }
+                //while starts a while block----------------------------------------
+                //example:  while x<10 do every 100
+                //              ...
+                //          end
+            } else if (tokens[i].compare("while") == 0) { //a new while block
+                if (ifBlockInit || whileBlockInit) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+                textDisplay.debug("While statement\r\n");
+
+                if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
+
+
+                } else {
+                    textDisplay << "Error: a statement block must be placed inside a callback or function.\r\n";
+                    lineError = true;
+                }
+                //whileBlockInit = true;
+                currentDelay = 0;
+
+                tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
+                if (tmpEvent != NULL) {
+                    tmpEvent->isUsed = true;
+                    tmpEvent->setTimeLag(currentDelay);
+                } else {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    lineError = true;
+                }
+
+                //tmpEvent = new event(queuePtr);
+
+
+                if (!lineError) {
+                    //combine the condition tokens without whitespaces
+                    tmpString = "";
+                    for (unsigned j = i+1; j < sz; j++) {
+                        if (tokens[j].compare("do") != 0) {
+                            i++;
+                            tmpString.append(tokens[j]);
+                        } else {
+                            break;
+                        }
+                    }
+                    //adds the conditions to the current event
+                    if (!evaluateConditions(tmpString, tmpEvent)) lineError = true;
+                }
+
+                if (!lineError) {
+                    if ((i+3) < sz) {
+                        if ((tokens[i+1].compare("do") == 0) && (tokens[i+2].compare("every") == 0)) {
+
+                            if (isNumber(tokens[i+3])) {
+                                uint32_t period = atoi(tokens[i+3].data());
+                                if (period > 0) {
+
+
+                                    //tmpEvent->whileLoopPeriod = period;
+                                    tmpEvent->setWhileLoopPeriod(period);
+                                    if (!elseFlag) {
+                                        tmpEvent->blockType = 5; //this is a while block
+
+                                        action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                                        if (tmpAction == NULL) {
+                                            textDisplay << "Error: no memory slots available.\r\n";
+                                            lineError = true;
+                                        } else {
+                                            tmpAction->set(tmpEvent);
+                                        }
+                                        //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                        tmpEventPtrArray.back()->addAction(tmpAction);
+
+                                        tmpEventPtrArray.push_back(tmpEvent);
+                                        blockDepth = blockDepth+1;
+                                    } else {
+                                        tmpEvent->blockType = 6; //this is an else while block
+                                        tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                        tmpEventPtrArray.push_back(tmpEvent);
+                                    }
+                                    wholeLineEvaluated = true;
+                                } else {
+                                    textDisplay << "Error: loop period must be a positive integer.\r\n";
+                                    lineError = true;
+                                }
+                            } else if (findIntVariable(tokens[i+3])!=NULL) {
+
+                                int* period = findIntVariable(tokens[i+3]);
+                                //tmpEvent->whileLoopPeriodVar = period;
+                                tmpEvent->setWhileLoopPeriod(period);
+                                if (!elseFlag) {
+                                    tmpEvent->blockType = 5; //this is a while block
+
+                                    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+                                    if (tmpAction == NULL) {
+                                        textDisplay << "Error: no memory slots available.\r\n";
+                                        lineError = true;
+                                    } else {
+                                        tmpAction->set(tmpEvent);
+                                    }
+                                    //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
+                                    tmpEventPtrArray.back()->addAction(tmpAction);
+
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                    blockDepth = blockDepth+1;
+                                } else {
+                                    tmpEvent->blockType = 6; //this is an else while block
+                                    tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
+                                    tmpEventPtrArray.push_back(tmpEvent);
+                                }
+                                wholeLineEvaluated = true;
+                            }
+                        } else {
+                            textDisplay << "Error: expected a 'do every' statement\r\n";
+                            lineError = true;
+                        }
+                    } else {
+                        textDisplay << "Error: expected a 'do every' statement\r\n";
+                        lineError = true;
+                    }
+                }
+
+                //if the line contains an '=' sign,the equality is evaulated-------------------------
+                //examples:  a = 1;  a = b + 5; a = random(100); portout[2] = 1; portout[2] = flip
+            } else if ((tmpLine.find_first_of("=") != std::string::npos) ) { //an expression
+                if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
+                    textDisplay << "Error: expected a 'do' statement\r\n";
+                    lineError = true;
+                }
+
+                wholeLineEvaluated = true;
+                tmpString = "";
+                int spacesBeforeEqualSign = 0;
+                bool countSpaces = true;
+                //combine the tokens without whitespaces
+                for (unsigned j = i; j < sz; j++) {
+                    tmpString.append(tokens[j]);
+                    if (tokens[j].find_first_of("=") != std::string::npos) {
+                        if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
+                        countSpaces = false;
+                    } else if (countSpaces) {
+                        spacesBeforeEqualSign++;
+                    }
+                }
+                if (!lineError && spacesBeforeEqualSign > 1) {
+                    textDisplay << "Error: Variable can't have a space in it.\r\n";
+                    lineError = true;
+                }
+
+                if (!lineError) {
+                    if (blockDepth > 0) {
+                        textDisplay.debug("Variable assignment statement\r\n");
+                        //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+                        if (tmpAction != NULL) {
+                            tmpEventPtrArray.back()->addAction(tmpAction);
+
+                        } else {
+                            lineError = true;
+                        }
+
+                    } else { //assignment was written outside of any block structure, so execute now
+
+
+                        //action* tmpAction = evaluateAssignmentForAction(tmpString);
+                        action* tmpAction = evaluateAssignmentForAction(tmpString.data());
+
+                        if (tmpAction != NULL) {
+                            tmpAction->execute();
+
+                            //delete tmpAction;
+                            tmpAction->release();
+                        } else {
+                            lineError = true;
+                        }
+                    }
+                }
+            } else {
+                //if there was no match to any of the above, an error is given
+                textDisplay << "Error: statement not understood.\r\n";
+                lineError = true;
+            }
+
+            if (lineError) {
+                 textDisplay.flush();
+                 break; //stop parsing the rest of the line if an error was detected
+            }
+            if (wholeLineEvaluated) { //some of the tokens forces the whole line to be avaluated at once
+                i = sz; //skip ahead to end of the line
+            }
+
+        }
+
+        //if there was an error, we quit compiling the code
+        if (lineError) {
+
+            textDisplay << "Line text: ";
+            /*
+            while (!tokens.empty()) {
+                textDisplay << tokens.front()<< " ";
+                //tokens.erase(tokens.begin());
+            }*/
+
+            //Display the line with the syntax error
+            for (int tokInd = 0; tokInd < tokens.size(); tokInd++) {
+                textDisplay << tokens.at(tokInd) << " ";
+            }
+            textDisplay << "\r\n";
+            textDisplay.flush();
+
+            currentBlock.resetBuffer();
+
+            //Clear the line tokens
+            while (!tokens.empty()) {
+                tokens.pop_back();
+            }
+
+            if (tmpEventPtrArray.size() > 0) {
+                tmpEventPtrArray.at(0)->release(); //release the unfinished block (and all children)
+            }
+            while (tmpEventPtrArray.size() > 0){
+                tmpEventPtrArray.pop_back();
+            }
+
+
+            //delete tmpEvent;
+            /*
+            if (tmpEvent != NULL) {
+                tmpEvent->release();
+            }
+            */
+        } else {
+
+            //Clear the line tokens
+            while (!tokens.empty()) {
+                tokens.pop_back();
+            }
+            //currentBlock.pop_back();
+
+        }
+
+    }
+
+    //make sure that all blocks have a matching end statement
+
+
+    if ((!lineError)&&(blockDepth > 0)) {
+        textDisplay << "Error: Missing 1 or more end statements\r\n";
+        lineError = true;
+        currentBlock.resetBuffer();
+    }
+
+    if ((!lineError)&&(blockDepth == 0)) {
+        textDisplay.send("~~~\r\n");
+    }
+
+    //displayMemoryLeft();
+    //DisplayRAMBanks();
+
+}
+
+
+//used to return a pointer to a variable, if it exists
+int* scriptStream::findIntVariable(string nameInput) {
+
+    textDisplay.debug("Finding variable: ");
+    textDisplay.debug(nameInput.data());
+    int* outPtr = NULL;
+    bool foundIt = false;
+    if (nameInput.find("portout") != std::string::npos) {
+        int pos1 = nameInput.find("portout[")+8;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[portnum-1].outState;
+            foundIt = true;
+        }
+    } else if (nameInput.find("portin") != std::string::npos) {
+        int pos1 = nameInput.find("portin[")+7;
+        int pos2 = nameInput.find_first_of("]",pos1);
+        int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        int portVal = 0;
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[portnum-1].inState;
+            foundIt = true;
+        }
+    }
+
+    if (!foundIt) {
+        std::vector<intVariable*>::size_type sz = globalVariables.size();
+        int start = 0;
+        int end = nameInput.length()-1;
+
+        for (unsigned i = 0; i < sz; i++) {
+
+
+            if ((findStringLoc(nameInput.data(),globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }
+            /*
+            if (nameInput.compare(globalVariables[i]->tag) == 0) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }*/
+        }
+    }
+    textDisplay.debug("...done\r\n");
+
+    return outPtr;
+}
+
+
+//used to return a pointer to a variable, if it exists
+int* scriptStream::findIntVariable(const char* nameInput, int start, int end) {
+
+    textDisplay.debug("Finding variable...");
+    int* outPtr = NULL;
+    bool foundIt = false;
+
+    if (findStringLoc(nameInput,"portout[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"portout[",start,end)+8;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+
+        //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[(int)portnum-1].outState;
+            foundIt = true;
+        }
+    } else if (findStringLoc(nameInput,"portin[",start,end) != -1) {
+        int pos1 = findStringLoc(nameInput,"portin[",start,end)+7;
+        int pos2 = findStringLoc(nameInput, "]",pos1,end);
+        if ((pos1 == -1)||(pos2 == -1)) {
+            //syntax error
+            return NULL;
+        }
+        long int portnum = strtol(nameInput+pos1,NULL,10);
+
+        if ((portnum > 0) && (portnum <= numPorts)) {
+            outPtr = &portVector[(int)portnum-1].inState;
+            foundIt = true;
+        }
+    }
+
+    if (!foundIt) {
+        std::vector<intVariable*>::size_type sz = globalVariables.size();
+        for (unsigned i = 0; i < sz; i++) {
+            //const char* varName = globalVariables[i]->tag.data();
+            if ((findStringLoc(nameInput,globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
+                outPtr = &globalVariables[i]->value;
+                break;
+            }
+        }
+    }
+    textDisplay.debug("done\r\n");
+
+    return outPtr;
+}
+
+bool scriptStream::createIntVariable(string nameInput) {
+    if (findIntVariable(nameInput) == NULL) {
+        globalVariables.push_back(new intVariable(nameInput, 0));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+action* scriptStream::evaluateAssignmentForAction(const char* expression) {
+
+    //action* tmpAction = new action(); //create a new action
+    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+    if (tmpAction == NULL) {
+        textDisplay << "Error: no action memory slots available.\r\n";
+        return NULL;
+    }
+    int stringInd;
+    int stringInd2;
+    int afterEqualLoc;
+    int beforeEqualLoc;
+    int lastCharLoc = strlen(expression)-1;
+    int multiplierInt = 1;
+    //string afterEqual;
+    //string beforeEqual;
+    //The expression might have up to three variables
+    int* tmpVar;
+    int* tmpVar2;
+    int* tmpVar3;
+
+    stringInd = findStringLoc(expression,"=",0,strlen(expression)-1); //location of = sign, if it exists
+    if (stringInd == -1) {
+        //Make sure there is an equal sign
+        return NULL;
+    }
+
+    beforeEqualLoc = stringInd-1;
+    afterEqualLoc = stringInd+1;
+
+    //location of +/- sign (only one allowed)
+    stringInd2 = findStringLoc(expression,"+",afterEqualLoc,strlen(expression)-1);
+    if (stringInd2 == -1) {
+        stringInd2 = findStringLoc(expression,"-",afterEqualLoc,strlen(expression)-1);
+        multiplierInt = -1;
+
+    }
+
+    tmpVar = findIntVariable(expression,0,beforeEqualLoc); //returns pointer to the variable
+    if (findStringLoc(expression,"portout[",0,beforeEqualLoc) != -1) {  //set the output of a digital port
+        textDisplay.debug("Portout assignment\r\n");
+        int pos1 = findStringLoc(expression,"portout[",0,beforeEqualLoc)+8;
+        int pos2 = findStringLoc(expression,"]",pos1,beforeEqualLoc)-1;
+        if (pos2 < pos1) {
+            textDisplay << "Error: expected a ] character\r\n";
+            return NULL;
+        }
+
+        int portnum = -1;
+        if (isNum(expression,pos1,pos2)) {
+            portnum = atoi(expression+pos1);
+        }
+        int* tmpVar = findIntVariable(expression, pos1,pos2); //returns pointer to the variable, if given
+        int portVal = 0;
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
+            if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
+                portVal = atoi(expression+afterEqualLoc);
+                if ((portVal == 0) || (portVal == 1)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        //tmpMessage->setMessage(portVector[portnum],1,portVal);
+                        if (tmpVar == NULL) { //a constant port number was given
+                            tmpMessage->setMessage(NULL,portnum,portVal,portVector);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n";
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if (findStringLoc(expression,"flip",afterEqualLoc,lastCharLoc)!=-1) {
+                //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
+                portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                if (tmpMessage == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    //tmpMessage->setMessage(portVector[portnum],1,-1);
+                    if (tmpVar == NULL) { //a constant port number was given
+                        tmpMessage->setMessage(NULL,portnum,-1,portVector);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                    }
+                }
+                tmpAction->set(tmpMessage);
+            } else {
+                textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (findStringLoc(expression,"portin",0,stringInd)!=-1) {
+        textDisplay << "Error: portins can not be set\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    } else if (tmpVar != NULL) {
+        intOperation* tmpOp;
+        intOperation* tmpOp2;
+        if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
+            textDisplay.debug("Numeric assignment\r\n");
+            //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc));
+            }
+            tmpAction->set(tmpOp);
+
+        } else if ((stringInd2 == -1)&&(findStringLoc(expression,"random",afterEqualLoc,lastCharLoc)!=-1)) {
+            //assign random number
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Random number assignment\r\n");
+            int highVal = getRandomParam(expression,afterEqualLoc,lastCharLoc);
+
+            if (highVal > 0) {
+                //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->setRandOp(highVal, "=", tmpVar, false);
+                }
+                tmpAction->set(tmpOp);
+
+            } else {
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else if ((stringInd2 == -1)&&(findStringLoc(expression,"clock()",afterEqualLoc,lastCharLoc)!=-1)) {
+            //assign clock value
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Clock assignment to variable\r\n");
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
+            }
+            tmpAction->set(tmpOp);
+
+        } else if (stringInd2 != -1) { //a +/- operation is there
+            textDisplay.debug("equation assignment\r\n");
+            //string multiplier("+");
+            char multiplier[3];
+            if (multiplierInt==1) {
+                strcpy(multiplier,"+");
+            } else {
+                strcpy(multiplier,"-");
+            }
+
+            /*
+            if (afterEqual[stringInd2] == '-') {
+                multiplier = "-";
+                multiplierInt = -1;
+            }*/
+            tmpVar2 = findIntVariable(expression,afterEqualLoc,stringInd2-1); //before the +/- sign
+            tmpVar3 = findIntVariable(expression,stringInd2+1,lastCharLoc); //after the +/- sign
+
+            if ((tmpVar2 != NULL) && isNum(expression,stringInd2+1,lastCharLoc)) { //variable +/- number
+                if (tmpVar2 == tmpVar) {
+                    //final sign is += or -=
+                    if (multiplierInt==1) {
+                        strcpy(multiplier,"+=");
+                    } else {
+                        strcpy(multiplier,"-=");
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier, atoi(expression+stringInd2+1));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->set(tmpVar2,multiplier, atoi(expression+stringInd2+1));
+                        //tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar3 != NULL) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- variable
+                if (tmpVar3 == tmpVar) {
+                    //final sign is += or -=
+                    if (multiplierInt==1) {
+                        strcpy(multiplier,"+=");
+                    } else {
+                        strcpy(multiplier,"-=");
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier, atoi(expression+afterEqualLoc));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(tmpVar3, multiplier, atoi(expression+afterEqualLoc));
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->set(tmpVar2, multiplier, tmpVar3);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ( isNum(expression,stringInd2+1,lastCharLoc) && isNum(expression,afterEqualLoc,stringInd2-1) ) { //number +/- number
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc) + (multiplierInt * atoi(expression+stringInd2+1)) );
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ((findStringLoc(expression,"random", afterEqualLoc,stringInd2-1)!=-1)  && isNum(expression,stringInd2+1,lastCharLoc)) { //random +/- number
+                int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier, atoi(expression+stringInd2+1),false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((findStringLoc(expression,"random",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //random +/- variable
+                int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier, tmpVar3, false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+
+
+            } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- random
+                int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier, atoi(expression+afterEqualLoc),true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- random
+                int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier, tmpVar2, true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            }
+
+
+            else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && isNum(expression,stringInd2+1,lastCharLoc)) { //clock() +/- number
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier, atoi(expression+stringInd2+1),false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //clock() +/- variable
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier, tmpVar3, false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,lastCharLoc)) { //number +/- clock()
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier, atoi(expression+afterEqualLoc), true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- clock()
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier, tmpVar2, true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            }
+
+            else {
+                textDisplay << "Expression not understood: " << expression << "\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+
+        } else if (findIntVariable(expression,afterEqualLoc,lastCharLoc) != NULL) { //assign value of another variable
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", findIntVariable(expression,afterEqualLoc,lastCharLoc));
+            }
+            tmpAction->set(tmpOp);
+
+        } else {
+            textDisplay << "Variable not found: " << expression+afterEqualLoc << "\r\n";
+            tmpAction->release();
+            return NULL;
+        }
+
+    } else {
+        textDisplay << "Variable not found\r\n";
+        tmpAction->release();
+        return NULL;
+    }
+    textDisplay.debug("Assignment successful\r\n");
+    return tmpAction;
+}
+
+action* scriptStream::evaluateAssignmentForAction(string expression) {
+
+    //action* tmpAction = new action(); //create a new action
+    action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
+    if (tmpAction == NULL) {
+        textDisplay << "Error: no action memory slots available.\r\n";
+        return NULL;
+    }
+    std::size_t stringInd;
+    std::size_t stringInd2;
+    string afterEqual;
+    string beforeEqual;
+    //The expression might have up to three variables
+    int* tmpVar;
+    int* tmpVar2;
+    int* tmpVar3;
+    stringInd = expression.find_first_of("="); //location of = sign, if it exists
+    beforeEqual = expression.substr(0,stringInd); // the string after the = sign
+    afterEqual = expression.substr(stringInd+1,std::string::npos); // the string after the = sign
+    stringInd2 = afterEqual.find_first_of("+-"); //location of +/- sign (only one allowed)
+    tmpVar = findIntVariable(expression.substr(0,stringInd)); //returns pointer to the variable
+
+    if (beforeEqual.find("portout[") != std::string::npos) { //set the output of a digital port
+        textDisplay.debug("Portout assignment\r\n");
+        int pos1 = beforeEqual.find("portout[")+8;
+        int pos2 = beforeEqual.find_first_of("]",pos1);
+        int portnum = atoi(beforeEqual.substr(pos1,pos2-pos1).data());
+        int* tmpVar = findIntVariable(beforeEqual.substr(pos1,pos2-pos1)); //returns pointer to the variable, if given
+        int portVal = 0;
+        if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
+            if (isNumber(afterEqual)) { //a simple numeric assign
+                portVal = atoi(afterEqual.data());
+                if ((portVal == 0) || (portVal == 1)) {
+                    //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
+                    portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                    if (tmpMessage == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        //tmpMessage->setMessage(portVector[portnum],1,portVal);
+                        if (tmpVar == NULL) { //a constant port number was given
+                            tmpMessage->setMessage(NULL,portnum,portVal,portVector);
+                        } else {
+                            tmpMessage->setMessage(tmpVar,0,portVal,portVector);
+                        }
+                    }
+
+
+                    tmpAction->set(tmpMessage);
+
+                } else {
+                    textDisplay << "Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n";
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if (afterEqual.compare("flip") == 0) {
+                //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
+                portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
+                if (tmpMessage == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    //tmpMessage->setMessage(portVector[portnum],1,-1);
+                    if (tmpVar == NULL) { //a constant port number was given
+                        tmpMessage->setMessage(NULL,portnum,-1,portVector);
+                    } else {
+                        tmpMessage->setMessage(tmpVar,0,-1,portVector);
+                    }
+                }
+                tmpAction->set(tmpMessage);
+            } else {
+                textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else {
+            textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+    } else if (beforeEqual.find("portin") != std::string::npos) {
+        textDisplay << "Error: portins can not be set\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    } else if (tmpVar != NULL) {
+        intOperation* tmpOp;
+        intOperation* tmpOp2;
+        if (isNumber(afterEqual)) { //a simple numeric assign
+            textDisplay.debug("Numeric assignment\r\n");
+            //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", atoi(afterEqual.data()));
+            }
+            tmpAction->set(tmpOp);
+
+        } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("random") != std::string::npos)) {
+            //assign random number
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Random number assignment\r\n");
+            int highVal = getRandomParam(afterEqual);
+
+            if (highVal > 0) {
+                //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->setRandOp(highVal, "=", tmpVar, false);
+                }
+                tmpAction->set(tmpOp);
+
+            } else {
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+        } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("clock()") != std::string::npos)) {
+            //assign clock value
+            //no +/- detected, so its a simple assign
+            textDisplay.debug("Clock assignment to variable\r\n");
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
+            }
+            tmpAction->set(tmpOp);
+
+        } else if (stringInd2 != std::string::npos) { //a +/- operation is there
+            textDisplay.debug("equation assignment\r\n");
+            string multiplier("+");
+            int multiplierInt = 1;
+            if (afterEqual[stringInd2] == '-') {
+                multiplier = "-";
+                multiplierInt = -1;
+            }
+            tmpVar2 = findIntVariable(afterEqual.substr(0,stringInd2)); //before the +/- sign
+            tmpVar3 = findIntVariable(afterEqual.substr(stringInd2+1,std::string::npos)); //after the +/- sign
+
+            if ((tmpVar2 != NULL) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //variable +/- number
+                if (tmpVar2 == tmpVar) {
+                    multiplier.append("="); //final sign is += or -=
+                    //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->set(tmpVar2,multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
+                        //tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar3 != NULL) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- variable
+                if (tmpVar3 == tmpVar) {
+                    multiplier.append("="); //makes "+=" or "-="
+                    //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->set(tmpVar3, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                }
+
+            } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->set(tmpVar2, multiplier.data(), tmpVar3);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ( isNumber(afterEqual.substr(stringInd2+1,std::string::npos)) && isNumber(afterEqual.substr(0,stringInd2)) ) { //number +/- number
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())));
+                }
+                tmpAction->set(tmpOp);
+
+            } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //random +/- number
+                int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && (tmpVar3 != NULL)) { //random +/- variable
+                int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar3, false);
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+
+
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- random
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- random
+                int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
+
+                if (highVal > 0) {
+
+
+                    tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp2 == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+
+                        tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar2, true); //the "true" signifies that the rand value came last
+                    }
+                    tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                    if (tmpOp == NULL) {
+                        textDisplay << "Error: no memory slots available.\r\n";
+                        tmpOp2->release();
+                        tmpAction->release();
+                        return NULL;
+                    } else {
+                        tmpOp->set(tmpVar, tmpOp2);
+                    }
+                    tmpAction->set(tmpOp);
+
+                } else {
+                    //delete tmpAction;
+                    tmpAction->release();
+                    return NULL;
+                }
+            }
+
+
+
+
+
+            else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //clock() +/- number
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && (tmpVar3 != NULL)) { //clock() +/- variable
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp2->setClockOp(multiplier.data(), tmpVar3, false);
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+
+
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- clock()
+
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- clock()
+
+
+                tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp2 == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpAction->release();
+                    return NULL;
+                } else {
+
+                    tmpOp2->setClockOp(multiplier.data(), tmpVar2, true); //the "true" signifies that clock() came last
+                }
+                tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+                if (tmpOp == NULL) {
+                    textDisplay << "Error: no memory slots available.\r\n";
+                    tmpOp2->release();
+                    tmpAction->release();
+                    return NULL;
+                } else {
+                    tmpOp->set(tmpVar, tmpOp2);
+                }
+                tmpAction->set(tmpOp);
+
+
+            }
+
+            else {
+                textDisplay << "Expression not understood: " << afterEqual << "\r\n";
+                //delete tmpAction;
+                tmpAction->release();
+                return NULL;
+            }
+
+        } else if (findIntVariable(afterEqual) != NULL) { //assign value of another variable
+            //tmpOp = new intOperation(tmpVar, "=", findIntVariable(afterEqual));
+            tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
+            if (tmpOp == NULL) {
+                textDisplay << "Error: no memory slots available.\r\n";
+                tmpAction->release();
+                return NULL;
+            } else {
+                tmpOp->set(tmpVar, "=", findIntVariable(afterEqual));
+            }
+            tmpAction->set(tmpOp);
+
+        } else {
+            textDisplay << "Variable not found: " << afterEqual << "\r\n";
+            //delete tmpAction;
+            tmpAction->release();
+            return NULL;
+        }
+
+    } else {
+        textDisplay << "Variable not found\r\n";
+        //delete tmpAction;
+        tmpAction->release();
+        return NULL;
+    }
+    textDisplay.debug("Assignment successful\r\n");
+    return tmpAction;
+}
+
+/*
+bool scriptStream::isOutsideParenth(string& expression,std::size_t foundItem) {
+
+    int pDepth = 0;  // How many nested parentheses
+
+    if (foundItem < expression.length()) {
+        for (int i = 0; i <= foundItem; i++) {
+            if (expression[i] == '(') {
+                pDepth++;
+            } else if (expression[i] == ')') {
+                pDepth--;
+            }
+        }
+        if (pDepth<=0) {
+
+            return true;
+        } else {
+
+            return false;
+        }
+    } else {
+        return true;
+    }
+
+}
+
+std::size_t scriptStream::findFirstOrOutsideParenth(string& expression) {
+
+    std::size_t foundItem = expression.find("||");
+    while (foundItem != std::string::npos) {
+        if (isOutsideParenth(expression,foundItem)) {
+            break;
+        }
+        foundItem = expression.find("||",foundItem+1);
+    }
+    return foundItem;
+}
+
+std::size_t scriptStream::findFirstAndOutsideParenth(string& expression) {
+
+    std::size_t foundItem = expression.find("&&");
+    while (foundItem != std::string::npos) {
+        if (isOutsideParenth(expression,foundItem)){
+            break;
+        }
+        foundItem = expression.find("&&",foundItem+1);
+    }
+    return foundItem;
+}
+
+condition* scriptStream::parseConditions(string& expression) {
+    //This function is used to parse a condition string
+    //such as (x < y && x != z) || (y == 2)
+    //This function first identifies the root node of the logic tree
+    //based on operator precedence ( () > && > || ), and then recursively calls itself
+    //to find the nodes of the branches. The basic building blocks of
+    //the final condition object are arithmatic comparitors (a > b) and
+    //other condition objects.
+
+
+
+    condition* newCondition = NULL;
+    bool singleCondition = false; //no compound conditions
+    string afterComparator;
+    string beforeComparator;
+
+    std::size_t found;
+
+    //To make a parse tree, we start by looking for operators with the lowest precendence
+    //so we look for OR conditions first
+    char currentOperator = OR_CONDITION;
+
+    found = findFirstOrOutsideParenth(expression);
+    if (found==std::string::npos) { //no or conditions outside parentheses found, so we look for AND conditions
+        currentOperator = AND_CONDITION;
+
+        found = findFirstAndOutsideParenth(expression);
+    }
+    if (found==std::string::npos) { //no or/and conditions outside parentheses found
+        //if the expression is encapsulated in parentheses, remove the parentheses
+        bool removedParenth = false;
+        if ((expression[0] == '(') && (expression[expression.length()-1] == ')')) {
+
+            expression = expression.substr(1,expression.length()-2);
+            removedParenth = true;
+        }
+        if (removedParenth) { //we removed parentheses, so try again
+            textDisplay.debug("Condition: parenth removed\r\n");
+            return parseConditions(expression);
+        } else {
+            singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
+        }
+    }
+
+    if (singleCondition) { //no compound conditions found
+        textDisplay.debug("Single condition: ");
+        std::size_t equalStringInd;
+        std::size_t greaterOrEqualStringInd;
+        std::size_t lessThanOrEqualStringInd;
+        std::size_t notEqualStringInd;
+        std::size_t greaterThanStringInd;
+        std::size_t lessThanStringInd;
+        std::size_t generalCompareStringInd;
+
+
+        string tmpCondition = expression;
+        string compareString;
+        //The expression might have up to three variables
+        int* tmpVar;
+        int* tmpVar2;
+        int* tmpVar3;
+
+        int offset = 0;
+        equalStringInd = tmpCondition.find("=="); //location of comparator
+        greaterOrEqualStringInd = tmpCondition.find(">="); //location of comparator
+        lessThanOrEqualStringInd = tmpCondition.find("<="); //location of comparator
+        notEqualStringInd = tmpCondition.find("!="); //location of comparator
+        greaterThanStringInd = tmpCondition.find_first_of(">"); //location of comparator
+        lessThanStringInd = tmpCondition.find_first_of("<"); //location of comparator
+
+        if ((equalStringInd != std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+            (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
+
+            generalCompareStringInd = equalStringInd;
+            compareString = "==";
+            textDisplay.debug("==\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd != std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
+
+            generalCompareStringInd = greaterOrEqualStringInd;
+            compareString = ">=";
+            textDisplay.debug(">=\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd != std::string::npos) && (notEqualStringInd == std::string::npos)){
+
+            generalCompareStringInd = lessThanOrEqualStringInd;
+            compareString = "<=";
+            textDisplay.debug("<=\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd != std::string::npos)){
+
+            generalCompareStringInd = notEqualStringInd;
+            compareString = "!=";
+            textDisplay.debug("!=\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
+                   (greaterThanStringInd != std::string::npos) && (lessThanStringInd == std::string::npos)){
+
+            generalCompareStringInd = greaterThanStringInd;
+            compareString = ">";
+            offset = 1;
+            textDisplay.debug(">\r\n");
+        } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
+                   (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
+                   (greaterThanStringInd == std::string::npos) && (lessThanStringInd != std::string::npos)){
+
+            generalCompareStringInd = lessThanStringInd;
+            compareString = "<";
+            offset = 1;
+            textDisplay.debug("<\r\n");
+
+        }else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+            return 0;
+        }
+        textDisplay.debug("Allocating memory for condition...");
+        intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
+
+        if (newCompare == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        textDisplay.debug("success.\r\n");
+        beforeComparator.reserve(tmpCondition.length());
+        textDisplay << beforeComparator.capacity();
+        textDisplay.flush();
+
+        afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
+
+        beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
+
+        tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable
+        if (tmpVar != NULL) { //before the comparator is a single variable
+            tmpVar2 = findIntVariable(afterComparator); //returns pointer to the variable
+            if (tmpVar2 != NULL) { //we are comapring a single variable to another
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2);
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to variable\r\n");
+                newCompare->set(tmpVar,compareString.data(),tmpVar2);
+                newCondition->set(newCompare);
+
+
+            } else if (isNumber(afterComparator)) {
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to number\r\n");
+                newCompare->set(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                newCondition->set(newCompare);
+
+
+            } //more here
+
+        } else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+
+            return NULL;
+        }
+
+    } else { //this is a compound condition (with either && or ||)
+        textDisplay.debug("Compound condition\r\n");
+        afterComparator = expression.substr(found+2,std::string::npos);
+        beforeComparator = expression.substr(0,found);
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        } else {
+            newCondition->isUsed = true; //reserve the condition slot;
+        }
+        //recursively call this function to parse the sub conditions
+        condition* cond1 = parseConditions(beforeComparator);
+        if (cond1 == NULL) {
+            newCondition->release();
+            return NULL;
+        }
+        condition* cond2 = parseConditions(afterComparator);
+        if (cond2 == NULL) {
+            newCondition->release();
+            cond1->release();
+            return NULL;
+        }
+        newCondition->set(cond1,currentOperator, cond2);
+
+    }
+
+    return newCondition; //all went well, so return the newly made condition
+
+}*/
+
+
+bool scriptStream::isOutsideParenth(const char* expression,int foundItem,int start, int end) {
+
+    int pDepth = 0;  // How many nested parentheses
+
+    if ((foundItem >= start)&&(foundItem<=end)&&(foundItem < strlen(expression))&&(end < strlen(expression))&&(start <= end)&&(start>=0)) {
+        for (int i = start; i <= foundItem; i++) {
+            if (expression[i] == '(') {
+                pDepth++;
+            } else if (expression[i] == ')') {
+                pDepth--;
+            }
+        }
+        if (pDepth<=0) {
+
+            return true;
+        } else {
+
+            return false;
+        }
+    } else {
+        //error handling defaults in a true condition
+        return true;
+    }
+
+}
+
+int scriptStream::findFirstOrOutsideParenth(const char* expression,int start, int end) {
+
+    int foundItem = findStringLoc(expression,"||",start,end);
+    while (foundItem != -1) {
+        if (isOutsideParenth(expression,foundItem,start,end)) {
+            //it's out side of ()
+            break;
+        }
+        //not outside ()
+        foundItem = findStringLoc(expression,"||",foundItem+1,end);
+    }
+    return foundItem;
+}
+
+int scriptStream::findFirstAndOutsideParenth(const char* expression,int start, int end) {
+
+    int foundItem = findStringLoc(expression,"&&",start,end);
+    while (foundItem != -1) {
+        if (isOutsideParenth(expression,foundItem,start,end)){
+            break;
+        }
+        foundItem = findStringLoc(expression,"||",foundItem+1,end);
+    }
+    return foundItem;
+}
+
+
+condition* scriptStream::parseConditions(const char* expression,int start, int end) {
+
+
+    //This function is used to parse a condition string
+    //such as (x < y && x != z) || (y == 2)
+    //This function first identifies the root node of the logic tree
+    //based on operator precedence ( () > && > || ), and then recursively calls itself
+    //to find the nodes of the branches. The basic building blocks of
+    //the final condition object are arithmatic comparitors (a > b) and
+    //other condition objects.
+
+
+
+    condition* newCondition = NULL;
+    bool singleCondition = false; //no compound conditions
+    //string afterComparator;
+    //string beforeComparator;
+    int afterComparatorLoc;
+    int beforeComparatorLoc;
+
+
+
+    int found;
+
+    //To make a parse tree, we start by looking for operators with the lowest precendence
+    //so we look for OR conditions first
+    char currentOperator = OR_CONDITION;
+
+    found = findFirstOrOutsideParenth(expression,start,end);
+    if (found==-1) { //no or conditions outside parentheses found, so we look for AND conditions
+        currentOperator = AND_CONDITION;
+
+        found = findFirstAndOutsideParenth(expression,start,end);
+    }
+    if (found==-1) { //no or/and conditions outside parentheses found
+        //if the expression is encapsulated in parentheses, remove the parentheses
+        bool removedParenth = false;
+        if ((expression[start] == '(') && (expression[end] == ')')) {
+
+            start++;
+            end--;
+
+            //expression = expression.substr(1,expression.length()-2);
+            removedParenth = true;
+        }
+        if (removedParenth) { //we removed parentheses, so try again
+            textDisplay.debug("Condition: parenth removed\r\n");
+            return parseConditions(expression,start,end);
+        } else {
+            singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
+        }
+    }
+
+    if (singleCondition) { //no compound conditions found
+        textDisplay.debug("Single condition: ");
+        int equalStringInd;
+        int greaterOrEqualStringInd;
+        int lessThanOrEqualStringInd;
+        int notEqualStringInd;
+        int greaterThanStringInd;
+        int lessThanStringInd;
+        int generalCompareStringInd;
+
+
+        //string tmpCondition = expression;
+        char compareString[3];
+        //The expression might have up to three variables
+        int* tmpVar;
+        int* tmpVar2;
+        //int* tmpVar3;
+
+        int offset = 0;
+        equalStringInd = findStringLoc(expression,"==",start,end);  //location of comparator
+        greaterOrEqualStringInd = findStringLoc(expression,">=",start,end); //location of comparator
+        lessThanOrEqualStringInd = findStringLoc(expression,"<=",start,end); //location of comparator
+        notEqualStringInd = findStringLoc(expression,"!=",start,end); //location of comparator
+        greaterThanStringInd = findStringLoc(expression,">",start,end); //location of comparator
+        lessThanStringInd = findStringLoc(expression,"<",start,end); //location of comparator
+
+        if ((equalStringInd != -1) && (greaterOrEqualStringInd == -1) &&
+            (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = equalStringInd;
+            strcpy(compareString,"==");
+            //compareString = "==";
+            textDisplay.debug("==\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd != -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = greaterOrEqualStringInd;
+            strcpy(compareString,">=");
+            //compareString = ">=";
+            textDisplay.debug(">=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd != -1) && (notEqualStringInd == -1)){
+
+            generalCompareStringInd = lessThanOrEqualStringInd;
+            strcpy(compareString,"<=");
+            //compareString = "<=";
+            textDisplay.debug("<=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd != -1)){
+
+            generalCompareStringInd = notEqualStringInd;
+            strcpy(compareString,"!=");
+            //compareString = "!=";
+            textDisplay.debug("!=\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
+                   (greaterThanStringInd != -1) && (lessThanStringInd == -1)){
+
+            generalCompareStringInd = greaterThanStringInd;
+            strcpy(compareString,">");
+            //compareString = ">";
+            offset = 1;
+            textDisplay.debug(">\r\n");
+        } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
+                   (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
+                   (greaterThanStringInd == -1) && (lessThanStringInd != -1)){
+
+            generalCompareStringInd = lessThanStringInd;
+            strcpy(compareString,"<");
+            //compareString = "<";
+            offset = 1;
+            textDisplay.debug("<\r\n");
+
+        }else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+            return 0;
+        }
+        textDisplay.debug("Allocating memory for condition...");
+        intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
+
+        if (newCompare == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        }
+        textDisplay.debug("success.\r\n");
+        //beforeComparator.reserve(tmpCondition.length());
+        //textDisplay << beforeComparator.capacity();
+        //textDisplay.flush();
+
+        afterComparatorLoc = generalCompareStringInd+2-offset;
+        beforeComparatorLoc = generalCompareStringInd-1;
+
+        //afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
+        //beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
+
+        //tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable
+        tmpVar = findIntVariable(expression,start,beforeComparatorLoc);
+
+        if (tmpVar != NULL) { //before the comparator is a single variable
+            tmpVar2 = findIntVariable(expression, afterComparatorLoc, end); //returns pointer to the variable
+            if (tmpVar2 != NULL) { //we are comapring a single variable to another
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2);
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to variable\r\n");
+                newCompare->set(tmpVar,compareString,tmpVar2);
+                newCondition->set(newCompare);
+
+
+            } else if (isNum(expression, afterComparatorLoc, end)) {
+                //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
+                //currentEvent->addCondition(new condition(newCompare));
+                textDisplay.debug("Compare variable to number\r\n");
+                newCompare->set(tmpVar,compareString,atoi(expression+afterComparatorLoc));
+                newCondition->set(newCompare);
+
+
+            } else {
+                textDisplay << "Condition not understood: " << expression << "\r\n";
+                return NULL;
+            }//more here
+
+        } else {
+            textDisplay << "Condition not understood: " << expression << "\r\n";
+
+            return NULL;
+        }
+
+    } else { //this is a compound condition (with either && or ||)
+        textDisplay.debug("Compound condition\r\n");
+        afterComparatorLoc = found+2;
+        beforeComparatorLoc = found-1;
+        //afterComparator = expression.substr(found+2,std::string::npos);
+        //beforeComparator = expression.substr(0,found);
+        newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
+        if (newCondition == NULL) {
+            textDisplay << "Error: No memory slots available.";
+            return NULL;
+        } else {
+            newCondition->isUsed = true; //reserve the condition slot;
+        }
+        //recursively call this function to parse the sub conditions
+        condition* cond1 = parseConditions(expression,start,beforeComparatorLoc);
+        if (cond1 == NULL) {
+            newCondition->release();
+            return NULL;
+        }
+        condition* cond2 = parseConditions(expression,afterComparatorLoc,end);
+        if (cond2 == NULL) {
+            newCondition->release();
+            cond1->release();
+            return NULL;
+        }
+        newCondition->set(cond1,currentOperator, cond2);
+
+    }
+
+    return newCondition; //all went well, so return the newly made condition
+
+
+}
+
+
+
+
+bool scriptStream::evaluateConditions(string& expression, event* currentEvent) {
+    //calls the function to parse the condition string.  The condition pointer is then
+    //attached to the event
+
+    condition* newCondition = NULL;
+    //newCondition = parseConditions(expression);
+    newCondition = parseConditions(expression.data(),0,expression.length()-1);
+    if (newCondition == NULL) {
+        return false;
+    } else {
+        currentEvent->addCondition(newCondition);
+        return true;
+    }
+}
+
+int scriptStream::getRandomParam(const char* expression,int start, int end) {
+
+    int pos1 = findStringLoc(expression,"random(",start,end)+7;
+    int pos2 = findStringLoc(expression,")",pos1,end);
+    if (pos2 == -1) {
+        textDisplay << "Error: bad syntax\r\n";
+        return 0;
+    }
+
+    int highVal = atoi(expression+pos1);
+
+    if ((highVal > 0)) {
+        return highVal;
+    } else {
+        textDisplay << "Error: random parameter must be 1 or more\r\n";
+        return 0;
+    }
+}
+
+int scriptStream::getRandomParam(string expression) {
+
+    int pos1 = expression.find("random(")+7;
+    int pos2 = expression.find_first_of(")",pos1);
+    int highVal = atoi(expression.substr(pos1,pos2-pos1).data());
+
+    if ((highVal > 0)) {
+        return highVal;
+    } else {
+        textDisplay << "Error: random parameter must be 1 or more\r\n";
+        return 0;
+    }
+}
+
+int scriptStream::findStringLoc(const char *refString, const char *findString,int start,int end) {
+    //look for 'findString' inside 'refString', only considering characters in between 'start' and 'end'
+    //return -1 if not found
+
+    if ((start < strlen(refString))&&(end < strlen(refString))&&(end >= start)) {
+        const char* charPtr = strstr(refString+start,findString);
+        //if found, make sure it was containted within the start and end bounds
+        if ((charPtr != NULL) && ((int)(charPtr-refString) <= (end-strlen(findString)+1))) {
+            return (int)(charPtr-refString);
+        }
+    }
+    return -1;
+}
+
+bool scriptStream::isNum(const char *expression, int start, int end) {
+
+    if ((start>0)&&(end<strlen(expression))&&(start<=end)) {
+
+        bool outcome = true;
+        while (start <= end) {
+            //look for any digit, or a - sign
+            if (!((expression[start] >= 45) && (expression[start] <= 57) && (expression[start] != 46) && (expression[start] != 47))) {
+                outcome = false;
+                break;
+            }
+            start++;
+        }
+        return outcome;
+    }
+    return false;
+}
+
+bool scriptStream::areStringsSame(const char *str1, const char *str2, int start, int end) {
+    if ((findStringLoc(str1,str2,start,end) != -1) && (strlen(str2)==(end-start+1))) {
+        return true;
+    } else {
+        return false;
+    }
+
+
+}
+
+void scriptStream::clearEnvironmentVariables(int clearMode) {
+    //Modes:
+
+    //clear callbacks, functions, and queue
+    if (clearMode & BLOCKMEMORYTYPES) {
+        for (int pNum = 0; pNum < NUMPORTS; pNum++) {
+            //delete portVector[pNum]->triggerUpEventPtr;
+            if (portVector[pNum].triggerUpEventPtr != NULL) {
+                portVector[pNum].triggerUpEventPtr->release();
+            }
+            portVector[pNum].triggerUpEventPtr = NULL;
+
+            //delete portVector[pNum]->triggerDownEventPtr;
+            if (portVector[pNum].triggerDownEventPtr != NULL) {
+                portVector[pNum].triggerDownEventPtr->release();
+            }
+            portVector[pNum].triggerDownEventPtr = NULL;
+
+        }
+        for (int i = 0; i < NUMFUNCTIONS; i++) {
+            functionSpotTaken[i] = false;
+            functionEventArray[i] = NULL;
+        }
+        for (int i = 0; i < NUMEVENTS; i++) {
+            eventBlock[i].release();
+        }
+        for (int i = 0; i < NUMCONDITIONS; i++) {
+            conditionBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTCOMPARE; i++) {
+            intCompareBlock[i].release();
+        }
+        for (int i = 0; i < NUMACTIONS; i++) {
+            actionBlock[i].release();
+        }
+        for (int i = 0; i < NUMPORTMESSAGES; i++) {
+            portMessageBlock[i].release();
+        }
+        for (int i = 0; i < NUMINTOPERATIONS; i++) {
+            intOperationBlock[i].release();
+        }
+        for (int i = 0; i < NUMDISPLAYACTIONS; i++) {
+            displayActionBlock[i].release();
+        }
+        for (int i = 0; i <NUMTRIGGERACTIONS; i++) {
+            triggerFunctionActionBlock[i].release();
+        }
+
+        queuePtr->eraseQueue();
+    }
+
+    if (clearMode & VARIABLEMEMORYTYPES) {
+        while (!globalVariables.empty()) {
+            delete globalVariables.back();
+            globalVariables.pop_back();
+        }
+    }
+
+    if (clearMode & ENVSETTINGSMEMORYTYPES) {
+        //set all environment settings to default values
+        broadCastStateChanges = true;
+        for (int i=0;i<NUMPORTS;i++) {
+            system->setPortUpdatesOn(i);
+        }
+    }
+
+
+
+}
+