Andy Lustig / Mbed 2 deprecated stateScript_v2_karpova

Dependencies:   SMARTWAV mbed

Fork of stateScript_v2 by Mattias Karlsson

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers behave.cpp Source File

behave.cpp

00001 #include "behave.h"
00002 #include "hardwareInterface.h"
00003 #include <ctype.h>
00004 #include <sstream>
00005 //#include <string.h>
00006 //#include <cstdlib>
00007 
00008 using namespace std;
00009 
00010 int16_t randomSeedCounter;  //used for seeding random numbers
00011 
00012 //digitalPort* portVector[NUMPORTS+1]; //a list of pointers to the digital ports
00013 
00014 //Main event queue
00015 eventQueue mainQueue;
00016 
00017 //The script parser
00018 //scriptStream parser(portVector, NUMPORTS, &mainQueue);
00019 
00020 //globals defined in hardwareInterface.cpp
00021 extern uint32_t timeKeeper; //the master clock
00022 extern bool resetTimer;
00023 extern bool clockSlave;
00024 extern bool changeToSlave;
00025 extern bool changeToStandAlone;
00026 extern outputStream textDisplay;
00027 
00028 //extern int currentDIOstate[2];
00029 bool broadCastStateChanges;
00030 bool textStreaming;
00031 
00032 
00033 
00034 //These items may be placed in hardware-specific parts of memory
00035 
00036 #ifdef MBEDHARDWARE
00037 //__attribute((section("AHBSRAM0"),aligned)) outputStream textDisplay(512);
00038 __attribute((section("AHBSRAM0"),aligned)) char buffer[256];
00039 __attribute((section("AHBSRAM1"),aligned)) event eventBlock[NUMEVENTS];
00040 __attribute((section("AHBSRAM1"),aligned)) condition conditionBlock[NUMCONDITIONS];
00041 __attribute((section("AHBSRAM1"),aligned)) intCompare intCompareBlock[NUMINTCOMPARE];
00042 __attribute((section("AHBSRAM0"),aligned)) action actionBlock[NUMACTIONS];
00043 __attribute((section("AHBSRAM0"),aligned)) portMessage portMessageBlock[NUMPORTMESSAGES];
00044 //__attribute((section("AHBSRAM1"),aligned)) intVariable intVariableBlock[10];
00045 __attribute((section("AHBSRAM0"),aligned)) intOperation intOperationBlock[NUMINTOPERATIONS];
00046 __attribute((section("AHBSRAM0"),aligned)) displayAction displayActionBlock[NUMDISPLAYACTIONS];
00047 __attribute((section("AHBSRAM0"),aligned)) triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
00048 #endif
00049 
00050 #ifdef FPGAHARDWARE
00051 
00052 char buffer[256];
00053 event eventBlock[NUMEVENTS];
00054 condition conditionBlock[NUMCONDITIONS];
00055 intCompare intCompareBlock[NUMINTCOMPARE];
00056 action actionBlock[NUMACTIONS];
00057 portMessage portMessageBlock[NUMPORTMESSAGES];
00058 intOperation intOperationBlock[NUMINTOPERATIONS];
00059 displayAction displayActionBlock[NUMDISPLAYACTIONS];
00060 triggerFunctionAction triggerFunctionActionBlock[NUMTRIGGERACTIONS];
00061 #endif
00062 
00063 
00064 event* functionEventArray[NUMFUNCTIONS];
00065 bool   functionSpotTaken[NUMFUNCTIONS];
00066 
00067 
00068 //-----------------------------------------------
00069 //This is the main loop of the program
00070 mainLoop::mainLoop(){
00071 
00072 
00073 }
00074 
00075 void mainLoop::init() {
00076     currentDIOstate[0] = 0;
00077     currentDIOstate[1] = 0;
00078     digitalInChanged = false;
00079     digitalOutChanged = false;
00080     textStreaming = true;
00081     eraseBuffer();
00082     broadCastStateChanges = true;
00083 
00084 
00085 
00086 //section for MBED hardware
00087 #ifdef MBEDHARDWARE
00088     hardware = new MBEDSystem();
00089     hardware->timerinit();
00090     pc = new MBEDSerialPort();
00091     pc->init();
00092     textDisplay.setSerial(pc);
00093 
00094 #endif
00095 
00096 #ifdef FPGAHARDWARE
00097        pc = new FPGASerialPort();
00098        pc->init();
00099 
00100        hardware = new FPGASystem();
00101        hardware->timerinit();
00102 
00103        textDisplay.setSerial(pc);
00104 
00105        DIO_DCR = DIO_DCR_IE;       // enable DIO edge interrupts
00106 #endif
00107 
00108     for (int i = 0; i < NUMPORTS; i++) {
00109         //Set up the ports.  Each has two pointers to the harware implementations
00110         //of a digital out and digital in.
00111         ports[i].init(hardware->getDigitalOutPtr(i),hardware->getDigitalInPtr(i));
00112     }
00113 
00114 
00115     parser = new scriptStream(ports, NUMPORTS, &mainQueue, hardware);
00116 
00117 }
00118 
00119 void mainLoop::exec() {
00120     bool digitalInChanged = false;
00121     bool digitalOutChanged = false;
00122     bool *ignoreUpdatePorts = hardware->getIgnoreUpdates();
00123     uint32_t changeTime;
00124     timeKeeper = 0; //set main clock to 0;
00125 
00126     int bufferPos = 0;
00127 
00128     ostringstream timeConvert;   // stream used for the conversion
00129     ostringstream stateConvert;
00130     int tmpChar;
00131     int junkChar;
00132 
00133     uint16_t shortcutTriggers[PENDINGTRIGGERBUFFERSIZE];
00134     int numTriggersToProcess;
00135 
00136     while (pc->readable()) {
00137         junkChar = pc->readChar();
00138     }
00139 
00140 #ifdef MBEDHARDWARE
00141     LocalFileSystem local("local");
00142 
00143     FILE *fp = fopen("/local/STARTUP.TXT", "r");
00144     if (fp != NULL) {
00145 
00146         textDisplay.send("Executing startup script...\r\n");
00147 
00148         do {
00149             tmpChar = fgetc(fp);
00150             if ((tmpChar >= 32) && (tmpChar <= 126)) {
00151                 buffer[bufferPos] = tmpChar;
00152                 bufferPos++;
00153             }
00154             if ((tmpChar == 13) || (tmpChar == 10)) { //carrriage return
00155                 parser->addLineToCurrentBlock(buffer);
00156                 bufferPos = 0;
00157                 eraseBuffer();
00158             }
00159             //pc.putc(tmpChar);
00160         } while (tmpChar != EOF);
00161 
00162         buffer[bufferPos] = 59;
00163         parser->addLineToCurrentBlock(buffer);
00164         eraseBuffer();
00165         fclose(fp);
00166     } else {
00167         textDisplay.send("No startup script found.\r\n");
00168     }
00169 #endif
00170 
00171     //Get the initial state of all input pins
00172     for (int i = 0; i < NUMPORTS; i++) {
00173 
00174         if (ports[i].getDigitalIn() == 1) {
00175             currentDIOstate[0] |= (1 << i);
00176         } else {
00177             currentDIOstate[0] &= ~(1 << i);
00178         }
00179     }
00180 
00181 
00182     //main loop
00183     while(1) {
00184         //check the main event queue to see if anything needs to be done
00185 
00186         mainQueue.check();
00187 
00188         //check if anything has been written to the serial input
00189         while (pc->readable()) {
00190 
00191             buffer[bufferPos] = pc->readChar();
00192             bufferPos++;
00193 
00194 
00195             //'Return' key pressed
00196             if ((buffer[bufferPos-1] == 13) || (buffer[bufferPos-1] == 10)) {
00197 
00198                 buffer[bufferPos-1] = '\0';
00199 
00200                 parser->addLineToCurrentBlock(buffer);
00201                 bufferPos = 0;
00202                 eraseBuffer();
00203 
00204             } else {
00205 
00206                 //Backspace was pressed
00207                 if (((buffer[bufferPos-1] == 127)||(buffer[bufferPos-1] == 8))) {
00208                     if (bufferPos > 1) {
00209                         bufferPos = bufferPos-2; //erase the backspace char plus the one before
00210                     } else {
00211                         bufferPos = bufferPos-1; //beginning of line, so nothing to erase
00212                     }
00213                 }
00214             }
00215         }
00216 
00217         //Check all the digital ports to see if anything has changed. In the update routine, the port's
00218         //script callbacks are called if the port was triggered
00219         digitalInChanged = false;
00220         digitalOutChanged = false;
00221         changeTime = timeKeeper;
00222 
00223         for (int i = 0; i < NUMPORTS; i++) {
00224 
00225             if (ports[i].update()) {
00226 
00227                 if (!ignoreUpdatePorts[i]) {
00228                     //Only trigger an output update to the serial port if ignore is false
00229                     digitalInChanged = true;
00230                 }
00231                 changeTime = min(changeTime,ports[i].lastChangeTime);
00232 
00233 
00234                 //The input state of all the ports in condensed into one number (each bit contains the info)
00235                 if (ports[i].getLastChangeState() == 1) {
00236                     currentDIOstate[0] |= (1 << i);
00237                 } else {
00238                     currentDIOstate[0] &= ~(1 << i);
00239                 }
00240             }
00241             if (ports[i].outStateChanged) {
00242                 digitalOutChanged = true;
00243                 changeTime = min(changeTime,ports[i].lastOutChangeTime);
00244                 //The out state of all the ports is condensed into one number (each bit contains the info)
00245                 if (ports[i].outState == 1) {
00246                     currentDIOstate[1] |= (1 << i);
00247                 } else {
00248                     currentDIOstate[1] &= ~(1 << i);
00249                 }
00250                 ports[i].outStateChanged = false;
00251             }
00252         }
00253 
00254         //If anything changed, we write the new values to the serial port (this can be turned off
00255         //with broadCastStateChanges)
00256         if ( (digitalInChanged||digitalOutChanged) && broadCastStateChanges) {
00257             textDisplay << changeTime << " " << currentDIOstate[0] << " " << currentDIOstate[1] << "\r\n";
00258 
00259             /*
00260             timeConvert << changeTime; //broadcast the earliest timestamp when a change occured
00261             //stateConvert << currentDIOstate[0] << " " << currentDIOstate[1];
00262             stateConvert << currentDIOstate[0] << " " << currentDIOstate[1] << "       ";
00263 
00264             textDisplay.send(timeConvert.str() + " " + stateConvert.str() + "\r\n");
00265             timeConvert.clear();
00266             timeConvert.seekp(0);
00267             stateConvert.clear();
00268             stateConvert.seekp(0);
00269             */
00270             digitalInChanged = false;
00271             digitalOutChanged = false;
00272         }
00273 
00274         //We use a buffer to send text via the serial port.  For every loop
00275         //in the main loop, we send one character if there is enything to send.
00276         //This way, outputting text to serial does not hold up other time-sensitive
00277         //things in the event queue
00278         if ((textDisplay.unsentData) && (textStreaming)) {
00279             pc->writeChar(textDisplay.getNextChar());
00280         }
00281 
00282         //Here is how we toggle between standalone and slave mode for the clock updating.
00283         if (changeToSlave) {
00284             hardware->setSlaveClock();
00285         } else if (changeToStandAlone) {
00286            hardware->setStandAloneClock();
00287         }
00288 
00289         //anything extra to do, defined by the hardware
00290         hardware->mainLoopToDo();
00291 
00292         //check for shortcut triggers
00293         numTriggersToProcess = hardware->getPendingFunctionTriggers(shortcutTriggers);
00294         for (int i = 0; i < numTriggersToProcess; i++) {
00295             textDisplay << "Trigger function " << shortcutTriggers[i]+1 << "\r\n";
00296             if ((shortcutTriggers[i] < NUMTRIGGERACTIONS) && functionSpotTaken[shortcutTriggers[i]]) {
00297                 //textDisplay << "Executing function array index " << shortcutTriggers[i] << "\r\n";
00298                 functionEventArray[shortcutTriggers[i]]->execute();
00299             }
00300         }
00301 
00302     }
00303 
00304 }
00305 
00306 void mainLoop::eraseBuffer() {
00307     for (int i = 0; i < 256; i++) {
00308         buffer[i] = NULL;
00309     }
00310 }
00311 
00312 //-------------------------------------------------
00313 
00314 //used to find the first available object in the staticly defined pools of memory
00315 template<class T> T* findFirstUnUsed(T a[], const int arrayLength) {
00316 
00317     T* returnPtr = NULL;
00318     for (int i = 0; i < arrayLength; i++) {
00319         if (!a[i].isUsed) {
00320             returnPtr = &a[i];
00321             break;
00322         }
00323     }
00324     return returnPtr;
00325 }
00326 
00327 //used to count the number of available objects in the memory pool
00328 template<class T> int countUnUsed(T a[], const int arrayLength) {
00329 
00330     int count = 0;
00331     for (int i = 0; i < arrayLength; i++) {
00332         if (!a[i].isUsed) {
00333             count++;
00334         }
00335     }
00336     return count;
00337 }
00338 
00339 
00340 void displayMemoryLeft(void) {
00341     textDisplay << "Available slots left in memory\r\n";
00342     textDisplay << "  Blocks: " << countUnUsed(eventBlock, NUMEVENTS) << "\r\n";
00343     textDisplay << "  Condition containers: " << countUnUsed(conditionBlock, NUMCONDITIONS) << "\r\n";
00344     textDisplay << "  Int compare conditions: " << countUnUsed(intCompareBlock, NUMINTCOMPARE) << "\r\n";
00345     textDisplay << "  Command containers: " << countUnUsed(actionBlock, NUMACTIONS) << "\r\n";
00346     textDisplay << "  Port commands: "<< countUnUsed(portMessageBlock, NUMPORTMESSAGES) << "\r\n";
00347     textDisplay << "  Integer operater commands: " << countUnUsed(intOperationBlock, NUMINTOPERATIONS) << "\r\n";
00348     textDisplay << "  Text display commands: " << countUnUsed(displayActionBlock, NUMDISPLAYACTIONS) << "\r\n";
00349 }
00350 
00351 bool isNumber(const std::string& s) {
00352     std::string::const_iterator it = s.begin();
00353     while (it != s.end() && isdigit(*it)) ++it;
00354     return !s.empty() && it == s.end();
00355 }
00356 
00357 void tokenize(const string& str,
00358               vector<string>& tokens,
00359               const string& delimiters = " ")
00360 {
00361     // Skip delimiters at beginning.
00362     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
00363     // Find first "non-delimiter".
00364     string::size_type pos     = str.find_first_of(delimiters, lastPos);
00365 
00366     while (string::npos != pos || string::npos != lastPos)
00367     {
00368         // Found a token, add it to the vector.
00369         tokens.push_back(str.substr(lastPos, pos - lastPos));
00370         // Skip delimiters.  Note the "not_of"
00371         lastPos = str.find_first_not_of(delimiters, pos);
00372         // Find next "non-delimiter"
00373         pos = str.find_first_of(delimiters, lastPos);
00374     }
00375 }
00376 
00377 
00378 digitalPort::digitalPort():
00379 outPin(NULL),
00380 inPin(NULL),
00381 outState(0){
00382 
00383 }
00384 
00385 void digitalPort::init(sDigitalOut *DOP, sDigitalIn *DIP) {
00386     outPin = DOP;
00387     inPin = DIP;
00388     lastInState = getDigitalIn();
00389     inState = getDigitalIn();
00390     lastChangeTime = 0;
00391     lastOutChangeTime = 0;
00392     lastChangeInterval = 0;
00393     triggerUpEventPtr = NULL;
00394     triggerDownEventPtr = NULL;
00395     outStateChanged = false;
00396 
00397 }
00398 
00399 
00400 void digitalPort::setTriggerUpEvent(event* eventInput) {
00401     if (triggerUpEventPtr != NULL) {
00402         //delete triggerUpEventPtr;
00403         triggerUpEventPtr->release();
00404     }
00405     triggerUpEventPtr = eventInput;
00406 }
00407 
00408 void digitalPort::setTriggerDownEvent(event* eventInput) {
00409     if (triggerDownEventPtr != NULL) {
00410         //delete triggerDownEventPtr;
00411         triggerDownEventPtr->release();
00412 
00413     }
00414     triggerDownEventPtr = eventInput;
00415 }
00416 
00417 
00418 int digitalPort::getDigitalIn() {
00419     return inPin->read();
00420 }
00421 
00422 
00423 void digitalPort::setDigitalOut(int outVal) {
00424     if (outVal == -1) {
00425         outVal = 1-outState;
00426     }
00427     outPin->write(outVal);
00428     if (outState != outVal) {
00429         outStateChanged = true;
00430         lastOutChangeTime = timeKeeper;
00431     }
00432     outState = outVal;
00433 }
00434 
00435 //called when a digital in gets triggered
00436 /*
00437 void digitalPort::addStateChange(int newState, uint32_t timeStamp) {
00438 
00439     if ((newState == 0) && (!lastDownEvent.triggered)){
00440         lastDownEvent.timeStamp = timeStamp;
00441         lastDownEvent.triggered = true;
00442     } else if ((newState == 1) && (!lastUpEvent.triggered)) {
00443         lastUpEvent.timeStamp = timeStamp;
00444         lastUpEvent.triggered = true;
00445     }
00446 }*/
00447 
00448 bool digitalPort::update() {
00449 
00450     bool changed = false;
00451     bool execUp = false;
00452     bool execDown = false;
00453     if ((timeKeeper - lastChangeTime) > 1) { //prevents flutter triggers when button is pressed
00454 
00455         //changed = (lastInState != inState);
00456 
00457         changed = (inPin->lastUpEvent.triggered || inPin->lastDownEvent.triggered);
00458         if (changed) {
00459             inPin->setUpdate(true); //Once we get the state of the pin, we buffer any pin changes until we are done checking
00460 
00461             inState = getDigitalIn();
00462 
00463             //We need to ignore flutter when levers/beam breaks are triggered. So
00464             //if the current state if different than the last logged state, we only
00465             //consider the first edge that brough us to the current state
00466             if (lastInState != inState) {
00467 
00468                 if (inState == 1) {
00469 
00470                     lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
00471                     lastChangeTime = inPin->lastUpEvent.timeStamp;
00472 
00473                     /*
00474                     if (inPin->lastUpEvent.triggered) {
00475                         //there were hardware triggers since the last main loop.  We use that time
00476                         lastChangeInterval = inPin->lastUpEvent.timeStamp - lastChangeTime;
00477                         lastChangeTime = inPin->lastUpEvent.timeStamp;
00478                     } else {
00479                         //otherwise we use the current time
00480                         lastChangeInterval = timeKeeper - lastChangeTime;
00481                         lastChangeTime = timeKeeper;
00482                     }
00483                     */
00484                     if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
00485                 } else if (inState == 0) {
00486 
00487                     lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
00488                     lastChangeTime = inPin->lastDownEvent.timeStamp;
00489 
00490                     /*
00491                     if (inPin->lastDownEvent.triggered) {
00492                         lastChangeInterval = inPin->lastDownEvent.timeStamp - lastChangeTime;
00493                         lastChangeTime = inPin->lastDownEvent.timeStamp;
00494                     } else {
00495                         lastChangeInterval = timeKeeper - lastChangeTime;
00496                         lastChangeTime = timeKeeper;
00497                     }*/
00498 
00499                     if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
00500                 }
00501             } else if (lastInState == inState) {
00502 
00503                 //Both up and down triggers must have happened, so we consider both
00504                 if (inState == 1) {
00505 
00506                     lastChangeInterval = inPin->lastUpEvent.timeStamp - inPin->lastDownEvent.timeStamp;
00507                     lastChangeTime = inPin->lastUpEvent.timeStamp;
00508 
00509                     if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
00510                     if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
00511                 } else if (inState == 0) {
00512 
00513                     lastChangeInterval = inPin->lastDownEvent.timeStamp - inPin->lastUpEvent.timeStamp;
00514                     lastChangeTime = inPin->lastDownEvent.timeStamp;
00515 
00516                     if (triggerUpEventPtr != NULL) {triggerUpEventPtr->execute();}
00517                     if (triggerDownEventPtr != NULL) {triggerDownEventPtr->execute();}
00518                 }
00519             }
00520 
00521             lastInState = inState;
00522             inPin->lastUpEvent.triggered = false;
00523             inPin->lastDownEvent.triggered = false;
00524 
00525             inPin->setUpdate(false); //This also checks if there were any buffered changes that occured
00526 
00527 
00528         }
00529 
00530 
00531 
00532     }
00533 
00534     return changed;
00535 }
00536 
00537 int digitalPort::getLastChangeState() {
00538     return lastInState;
00539 }
00540 uint32_t digitalPort::getTimeSinceLastChange() {
00541     return lastChangeInterval;
00542 
00543 }
00544 
00545 intVariable::intVariable():
00546 value(0) {
00547     isUsed = false;
00548 }
00549 
00550 intVariable::intVariable(std::string& tagInput, int initialValue):
00551 value(initialValue)
00552 {
00553     strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
00554     isUsed = true;
00555 }
00556 
00557 void intVariable::set(std::string& tagInput, int initialValue) {
00558     value = initialValue;
00559     //tag = string(tagInput);
00560     strncpy(tag,tagInput.data(),MAXVARNAMESIZE);
00561     isUsed = true;
00562 }
00563 
00564 displayAction::displayAction():
00565 dText(string("--------------------------------------------------")){
00566     dVariable = NULL;
00567     isUsed = false;
00568 }
00569 
00570 void displayAction::release() {
00571     dText = "--------------------------------------------------";
00572     dVariable = NULL;
00573     isUsed = false;
00574 }
00575 
00576 
00577 void displayAction::set(int* variable, string varNameInput) {
00578     dVariable = variable;
00579     dText = varNameInput;
00580     isUsed = true;
00581 
00582 }
00583 
00584 void displayAction::set(string text) {
00585     dText = text;
00586     dVariable = NULL;
00587     isUsed = true;
00588 }
00589 
00590 void displayAction::execute() {
00591 
00592     if (dVariable != NULL) {
00593         textDisplay << timeKeeper << " " << dText.c_str() << " = " << *dVariable << "\r\n";
00594     } else {
00595         textDisplay << timeKeeper << " " << dText.c_str() << "\r\n";
00596     }
00597 }
00598 
00599 triggerFunctionAction::triggerFunctionAction():
00600 functionNum(0) {
00601     isUsed = false;
00602 }
00603 
00604 triggerFunctionAction::triggerFunctionAction(int funcNum):
00605 functionNum(funcNum) {
00606 
00607     isUsed = true;
00608 
00609 }
00610 
00611 void triggerFunctionAction::set(int funcNum) {
00612     functionNum = funcNum;
00613     isUsed = true;
00614 }
00615 
00616 void triggerFunctionAction::execute() {
00617 
00618     if (functionSpotTaken[functionNum]) {
00619         functionEventArray[functionNum]->execute();
00620     }
00621 
00622 }
00623 
00624 void triggerFunctionAction::release() {
00625     isUsed = false;
00626 }
00627 
00628 
00629 
00630 intCompare::intCompare():
00631 port(NULL) {
00632     cmpVal = NULL;
00633     cmpValGlobal = false;
00634     intVal = NULL;
00635     intOp = NULL;
00636     portValPtr = NULL;
00637     isUsed = false;
00638 
00639 }
00640 intCompare::intCompare(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse):
00641 port(portInput) {
00642     cmpVal = new int(cmpValInput);
00643     cmpValGlobal = false;
00644     intVal = NULL;
00645     intOp = NULL;
00646     setPointer(cmpString);
00647     isUsed = true;
00648     if (whichToUse == 1) {
00649         portValPtr = &port->inState;
00650     } else {
00651         portValPtr = &port->outState;
00652     }
00653 }
00654 
00655 intCompare::intCompare(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse):
00656 port(portInput),
00657 cmpVal(cmpIntVarInput) {
00658     cmpValGlobal = true;
00659     intVal = NULL;
00660     intOp = NULL;
00661     setPointer(cmpString);
00662     isUsed = true;
00663     if (whichToUse == 1) {
00664         portValPtr = &port->inState;
00665     } else {
00666         portValPtr = &port->outState;
00667     }
00668 }
00669 
00670 intCompare::intCompare(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
00671 cmpVal(cmpIntVarInput),
00672 intVal(intVarInput) {
00673     cmpValGlobal = true;
00674     port = NULL;
00675     intOp = NULL;
00676     portValPtr = NULL;
00677     isUsed = true;
00678     setPointer(cmpString);
00679 }
00680 
00681 intCompare::intCompare(int* intVarInput, const char* cmpString, int cmpValInput):
00682 intVal(intVarInput){
00683     cmpVal = new int(cmpValInput);
00684     cmpValGlobal = false;
00685     port = NULL;
00686     intOp = NULL;
00687     portValPtr = NULL;
00688     isUsed = true;
00689     setPointer(cmpString);
00690 }
00691 
00692 intCompare::intCompare(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput):
00693 intVal(intVarInput) {
00694     cmpVal = NULL;
00695     port = NULL;
00696     portValPtr = NULL;
00697     cmpValGlobal = true;
00698     intOp = cmpIntOpInput;
00699     isUsed = true;
00700     setPointer_operation(cmpString);
00701 }
00702 
00703 intCompare::intCompare(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse):
00704 port(portInput) {
00705     cmpVal = NULL;
00706     intVal = NULL;
00707     cmpValGlobal = true;
00708     intOp = cmpIntOpInput;
00709     setPointer_operation(cmpString);
00710     isUsed = true;
00711     if (whichToUse == 1) {
00712         portValPtr = &port->inState;
00713     } else {
00714         portValPtr = &port->outState;
00715     }
00716 }
00717 
00718 
00719 
00720 void intCompare::set(digitalPort* portInput, const char* cmpString, int cmpValInput, int whichToUse) {
00721     port = portInput;
00722     cmpVal = new int(cmpValInput);
00723     cmpValGlobal = false;
00724     intVal = NULL;
00725     intOp = NULL;
00726     setPointer(cmpString);
00727     isUsed = true;
00728     if (whichToUse == 1) {
00729         portValPtr = &port->inState;
00730     } else {
00731         portValPtr = &port->outState;
00732     }
00733 }
00734 
00735 void intCompare::set(digitalPort* portInput, const char* cmpString, int* cmpIntVarInput, int whichToUse) {
00736     port = portInput;
00737     cmpVal = cmpIntVarInput;
00738     cmpValGlobal = true;
00739     intVal = NULL;
00740     intOp = NULL;
00741     setPointer(cmpString);
00742     isUsed = true;
00743     if (whichToUse == 1) {
00744         portValPtr = &port->inState;
00745     } else {
00746         portValPtr = &port->outState;
00747     }
00748 }
00749 
00750 void intCompare::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
00751     cmpVal = cmpIntVarInput;
00752     intVal = intVarInput;
00753     cmpValGlobal = true;
00754     port = NULL;
00755     intOp = NULL;
00756     portValPtr = NULL;
00757     setPointer(cmpString);
00758     isUsed = true;
00759 }
00760 
00761 void intCompare::set(int* intVarInput, const char* cmpString, int cmpValInput) {
00762     intVal = intVarInput;
00763     cmpVal = new int(cmpValInput);
00764     cmpValGlobal = false;
00765     port = NULL;
00766     intOp = NULL;
00767     portValPtr = NULL;
00768     setPointer(cmpString);
00769     isUsed = true;
00770 }
00771 
00772 void intCompare::set(int* intVarInput, const char* cmpString, intOperation* cmpIntOpInput) {
00773     intVal = intVarInput;
00774     cmpVal = NULL;
00775     port = NULL;
00776     portValPtr = NULL;
00777     cmpValGlobal = true;
00778     intOp = cmpIntOpInput;
00779     setPointer_operation(cmpString);
00780     isUsed = true;
00781 }
00782 
00783 void intCompare::set(digitalPort* portInput, const char* cmpString, intOperation* cmpIntOpInput, int whichToUse) {
00784     port = portInput;
00785     cmpVal = NULL;
00786     intVal = NULL;
00787     cmpValGlobal = true;
00788     intOp = cmpIntOpInput;
00789     setPointer_operation(cmpString);
00790     isUsed = true;
00791     if (whichToUse == 1) {
00792         portValPtr = &port->inState;
00793     } else {
00794         portValPtr = &port->outState;
00795     }
00796 }
00797 
00798 
00799 
00800 intCompare::~intCompare() {
00801     if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally
00802     delete intOp;
00803 }
00804 
00805 void intCompare::release() {
00806     if (!cmpValGlobal) delete cmpVal; //we only delete the intCompare object if it was created locally
00807     if (intOp != NULL) {
00808         intOp->release();
00809     }
00810     port = NULL;
00811     cmpVal = NULL;
00812     cmpValGlobal = false;
00813     intVal = NULL;
00814     intOp = NULL;
00815     portValPtr = NULL;
00816     isUsed = false;
00817 }
00818 
00819 
00820 void intCompare::setPointer(const char* cmpString) {
00821     if (strcmp(cmpString, ">") == 0) {
00822         isTruePtr = &intCompare::greaterThan;
00823     }else if (strcmp(cmpString, ">=") == 0) {
00824         isTruePtr = &intCompare::greaterOrEqual;
00825     }else if (strcmp(cmpString, "<") == 0) {
00826         isTruePtr = &intCompare::lessThan;
00827     }else if (strcmp(cmpString, "<=") == 0) {
00828         isTruePtr = &intCompare::lessOrEqual;
00829     }else if (strcmp(cmpString, "==") == 0) {
00830         isTruePtr = &intCompare::equal;
00831     }else if (strcmp(cmpString, "!=") == 0) {
00832         isTruePtr = &intCompare::notEqual;
00833     }
00834 }
00835 
00836 void intCompare::setPointer_operation(const char* cmpString) {
00837     if (strcmp(cmpString, ">") == 0) {
00838         isTruePtr = &intCompare::greaterThan_op;
00839     }else if (strcmp(cmpString, ">=") == 0) {
00840         isTruePtr = &intCompare::greaterOrEqual_op;
00841     }else if (strcmp(cmpString, "<") == 0) {
00842         isTruePtr = &intCompare::lessThan_op;
00843     }else if (strcmp(cmpString, "<=") == 0) {
00844         isTruePtr = &intCompare::lessOrEqual_op;
00845     }else if (strcmp(cmpString, "==") == 0) {
00846         isTruePtr = &intCompare::equal_op;
00847     }else if (strcmp(cmpString, "!=") == 0) {
00848         isTruePtr = &intCompare::notEqual_op;
00849     }
00850 }
00851 
00852 bool intCompare::isTrue() {
00853     return (this->*isTruePtr)();
00854 
00855 }
00856 
00857 bool intCompare::notEqual() {
00858     if (intVal != NULL) {
00859         return (*intVal != *cmpVal);
00860     } else {
00861         return (*portValPtr != *cmpVal);
00862     }
00863 }
00864 
00865 bool intCompare::greaterThan() {
00866     if (intVal != NULL) {
00867         return (*intVal > *cmpVal);
00868     } else {
00869         return (*portValPtr > *cmpVal);
00870     }
00871 }
00872 
00873 bool intCompare::greaterOrEqual() {
00874     if (intVal != NULL) {
00875         return (*intVal >= *cmpVal);
00876     } else {
00877         return (*portValPtr >= *cmpVal);
00878     }
00879 }
00880 
00881 bool intCompare::lessThan() {
00882     if (intVal != NULL) {
00883         return (*intVal < *cmpVal);
00884     } else {
00885         return (*portValPtr < *cmpVal);
00886     }
00887 }
00888 
00889 bool intCompare::lessOrEqual() {
00890     if (intVal != NULL) {
00891         return (*intVal <= *cmpVal);
00892     } else {
00893         return (*portValPtr <= *cmpVal);
00894     }
00895 }
00896 
00897 bool intCompare::equal() {
00898     if (intVal != NULL) {
00899         return (*intVal == *cmpVal);
00900     } else {
00901         return (*portValPtr == *cmpVal);
00902     }
00903 }
00904 
00905 bool intCompare::notEqual_op() {
00906     if (intVal != NULL) {
00907         return (*intVal != intOp->execute());
00908     } else {
00909         return (*portValPtr != intOp->execute());
00910     }
00911 }
00912 
00913 bool intCompare::greaterThan_op() {
00914     if (intVal != NULL) {
00915         return (*intVal > intOp->execute());
00916     } else {
00917         return (*portValPtr > intOp->execute());
00918     }
00919 }
00920 
00921 bool intCompare::greaterOrEqual_op() {
00922     if (intVal != NULL) {
00923         return (*intVal >= intOp->execute());
00924     } else {
00925         return (*portValPtr >= intOp->execute());
00926     }
00927 }
00928 
00929 bool intCompare::lessThan_op() {
00930     if (intVal != NULL) {
00931         return (*intVal < intOp->execute());
00932     } else {
00933         return (*portValPtr < intOp->execute());
00934     }
00935 }
00936 
00937 bool intCompare::lessOrEqual_op() {
00938     if (intVal != NULL) {
00939         return (*intVal <= intOp->execute());
00940     } else {
00941         return (*portValPtr <= intOp->execute());
00942     }
00943 }
00944 
00945 bool intCompare::equal_op() {
00946     if (intVal != NULL) {
00947         return (*intVal == intOp->execute());
00948     } else {
00949         return (*portValPtr == intOp->execute());
00950     }
00951 }
00952 
00953 intOperation::intOperation():
00954 randHigh(-1) {
00955     cmpVal = NULL;
00956     intVal = NULL;
00957     opPtr = NULL;
00958     executePtr = NULL;
00959     cmpValGlobal = false;
00960     isUsed = false;
00961     isClockAssign = false;
00962     inputsFlipped = false;
00963 
00964 }
00965 
00966 /*
00967  intOperation::intOperation(int randParam, const char* cmpString, int cmpValInput):
00968  randHigh(randParam) {
00969  cmpVal = new int(cmpValInput);
00970  intVal = NULL;
00971  opPtr = NULL;
00972  cmpValGlobal = false;
00973  isUsed = true;
00974  if (strcmp(cmpString, "+") == 0) {
00975  executePtr = &intOperation::add;
00976  }else if (strcmp(cmpString, "-") == 0) {
00977  executePtr = &intOperation::subtract;
00978  }else if (strcmp(cmpString, "+=") == 0) {
00979  executePtr = &intOperation::addAndStore;
00980  }else if (strcmp(cmpString, "-=") == 0) {
00981  executePtr = &intOperation::subtractAndStore;
00982  }else if (strcmp(cmpString, "=") == 0) {
00983  executePtr = &intOperation::equals;
00984  }
00985 
00986  }
00987 
00988  intOperation::intOperation(int randParam, const char* cmpString, int* cmpIntVarInput):
00989  randHigh(randParam),
00990  cmpVal(cmpIntVarInput) {
00991  intVal = NULL;
00992  opPtr = NULL;
00993  cmpValGlobal = true;
00994  isUsed = true;
00995  if (strcmp(cmpString, "+") == 0) {
00996  executePtr = &intOperation::add;
00997  }else if (strcmp(cmpString, "-") == 0) {
00998  executePtr = &intOperation::subtract;
00999  }else if (strcmp(cmpString, "+=") == 0) {
01000  executePtr = &intOperation::addAndStore;
01001  }else if (strcmp(cmpString, "-=") == 0) {
01002  executePtr = &intOperation::subtractAndStore;
01003  }else if (strcmp(cmpString, "=") == 0) {
01004  executePtr = &intOperation::equals;
01005  }
01006  }
01007 
01008  intOperation::intOperation(int* intVarInput, const char* cmpString, int cmpValInput):
01009  intVal(intVarInput) {
01010  cmpVal = new int(cmpValInput);
01011  randHigh = -1;
01012  opPtr = NULL;
01013  cmpValGlobal = false;
01014  isUsed = true;
01015  if (strcmp(cmpString, "+") == 0) {
01016  executePtr = &intOperation::add;
01017  }else if (strcmp(cmpString, "-") == 0) {
01018  executePtr = &intOperation::subtract;
01019  }else if (strcmp(cmpString, "+=") == 0) {
01020  executePtr = &intOperation::addAndStore;
01021  }else if (strcmp(cmpString, "-=") == 0) {
01022  executePtr = &intOperation::subtractAndStore;
01023  }else if (strcmp(cmpString, "=") == 0) {
01024  executePtr = &intOperation::equals;
01025  }
01026  }
01027 
01028  intOperation::intOperation(int* intVarInput, const char* cmpString, int* cmpIntVarInput):
01029  cmpVal(cmpIntVarInput),
01030  intVal(intVarInput) {
01031  randHigh = -1;
01032  opPtr = NULL;
01033  cmpValGlobal = true;
01034  isUsed = true;
01035  if (strcmp(cmpString, "+") == 0) {
01036  executePtr = &intOperation::add;
01037  }else if (strcmp(cmpString, "-") == 0) {
01038  executePtr = &intOperation::subtract;
01039  }else if (strcmp(cmpString, "+=") == 0) {
01040  executePtr = &intOperation::addAndStore;
01041  }else if (strcmp(cmpString, "-=") == 0) {
01042  executePtr = &intOperation::subtractAndStore;
01043  }else if (strcmp(cmpString, "=") == 0) {
01044  executePtr = &intOperation::equals;
01045  }
01046  }
01047 
01048  intOperation::intOperation(int* intVarInput, intOperation* operationInput):
01049  intVal(intVarInput) {
01050  cmpVal = NULL;
01051  randHigh = -1;
01052  opPtr = operationInput;
01053  executePtr = &intOperation::equals;
01054  isUsed = true;
01055  }
01056  */
01057 
01058 void intOperation::setRandOp(int randParam, const char* cmpString, int cmpValInput, bool flipped) {
01059     randHigh = randParam;
01060     cmpVal = new int(cmpValInput);
01061     intVal = NULL;
01062     opPtr = NULL;
01063     cmpValGlobal = false;
01064     isUsed = true;
01065     inputsFlipped = flipped;
01066     if (strcmp(cmpString, "+") == 0) {
01067         executePtr = &intOperation::add;
01068     }else if (strcmp(cmpString, "-") == 0) {
01069         executePtr = &intOperation::subtract;
01070     }else if (strcmp(cmpString, "=") == 0) {
01071         executePtr = &intOperation::equals;
01072     }
01073 
01074 }
01075 
01076 void intOperation::setRandOp(int randParam, const char* cmpString, int* cmpIntVarInput, bool flipped) {
01077     randHigh = randParam;
01078     cmpVal = cmpIntVarInput;
01079     intVal = NULL;
01080     opPtr = NULL;
01081     cmpValGlobal = true;
01082     isUsed = true;
01083     inputsFlipped = flipped;
01084     if (strcmp(cmpString, "+") == 0) {
01085         executePtr = &intOperation::add;
01086     }else if (strcmp(cmpString, "-") == 0) {
01087         executePtr = &intOperation::subtract;
01088     }else if (strcmp(cmpString, "=") == 0) {
01089         executePtr = &intOperation::equals;
01090     }
01091 }
01092 
01093 void intOperation::set(int* intVarInput, const char* cmpString, int cmpValInput) {
01094 
01095     intVal = intVarInput;
01096     cmpVal = new int(cmpValInput);
01097     randHigh = -1;
01098     opPtr = NULL;
01099     cmpValGlobal = false;
01100     isUsed = true;
01101     if (strcmp(cmpString, "+") == 0) {
01102         executePtr = &intOperation::add;
01103     }else if (strcmp(cmpString, "-") == 0) {
01104         executePtr = &intOperation::subtract;
01105     }else if (strcmp(cmpString, "+=") == 0) {
01106         executePtr = &intOperation::addAndStore;
01107     }else if (strcmp(cmpString, "-=") == 0) {
01108         executePtr = &intOperation::subtractAndStore;
01109     }else if (strcmp(cmpString, "=") == 0) {
01110         executePtr = &intOperation::equals;
01111     }
01112 }
01113 
01114 void intOperation::set(int* intVarInput, const char* cmpString, int* cmpIntVarInput) {
01115     cmpVal = cmpIntVarInput;
01116     intVal =intVarInput;
01117     randHigh = -1;
01118     opPtr = NULL;
01119     cmpValGlobal = true;
01120     isUsed = true;
01121     if (strcmp(cmpString, "+") == 0) {
01122         executePtr = &intOperation::add;
01123     }else if (strcmp(cmpString, "-") == 0) {
01124         executePtr = &intOperation::subtract;
01125     }else if (strcmp(cmpString, "+=") == 0) {
01126         executePtr = &intOperation::addAndStore;
01127     }else if (strcmp(cmpString, "-=") == 0) {
01128         executePtr = &intOperation::subtractAndStore;
01129     }else if (strcmp(cmpString, "=") == 0) {
01130         executePtr = &intOperation::equals;
01131     }
01132 }
01133 
01134 void intOperation::set(int* intVarInput, intOperation* operationInput) {
01135 
01136     intVal = intVarInput;
01137     cmpVal = NULL;
01138     randHigh = -1;
01139     opPtr = operationInput;
01140     executePtr = &intOperation::equals;
01141     isUsed = true;
01142 
01143 }
01144 
01145 void intOperation::setClockOp(int* intVarInput) {
01146     //used to assign current clock to variable
01147     intVal = intVarInput;
01148     cmpVal = NULL;
01149     randHigh = -1;
01150     opPtr = NULL;
01151     cmpValGlobal = false;
01152     isUsed = true;
01153     isClockAssign = true;
01154     executePtr = &intOperation::equals;
01155 
01156 }
01157 
01158 void intOperation::setClockOp(const char* cmpString, int cmpValInput, bool flip) {
01159     //used to add an integer to the current clock value
01160 
01161     intVal = NULL;
01162     cmpVal = new int(cmpValInput);
01163     randHigh = -1;
01164     opPtr = NULL;
01165     cmpValGlobal = false;
01166     isUsed = true;
01167     isClockAssign = true;
01168     inputsFlipped = flip;
01169     if (strcmp(cmpString, "+") == 0) {
01170         executePtr = &intOperation::add;
01171     }else if (strcmp(cmpString, "-") == 0) {
01172         executePtr = &intOperation::subtract;
01173     }
01174 }
01175 
01176 void intOperation::setClockOp(const char* cmpString, int* cmpIntVarInput, bool flip) {
01177     //used to add a variable to the current clock value
01178 
01179     cmpVal = cmpIntVarInput;
01180     intVal = NULL;
01181     randHigh = -1;
01182     opPtr = NULL;
01183     isClockAssign = true;
01184     cmpValGlobal = true;
01185     isUsed = true;
01186     inputsFlipped = flip;
01187     if (strcmp(cmpString, "+") == 0) {
01188         executePtr = &intOperation::add;
01189     }else if (strcmp(cmpString, "-") == 0) {
01190         executePtr = &intOperation::subtract;
01191     }
01192 }
01193 
01194 
01195 intOperation::~intOperation() {
01196     if (!cmpValGlobal) delete cmpVal;
01197     delete opPtr;
01198 }
01199 
01200 void intOperation::release() {
01201     if (!cmpValGlobal) delete cmpVal;
01202     if (opPtr != NULL) {
01203         opPtr->release();
01204     }
01205     randHigh = -1;
01206     cmpVal = NULL;
01207     intVal = NULL;
01208     opPtr = NULL;
01209     executePtr = NULL;
01210     isClockAssign = false;
01211     cmpValGlobal = false;
01212     isUsed = false;
01213 }
01214 
01215 
01216 int intOperation::execute() {
01217 
01218     return (this->*executePtr)();
01219 
01220 
01221 }
01222 
01223 int intOperation::add() {
01224 
01225     if ((intVal != NULL) && (!isClockAssign)) {
01226         return (*intVal + *cmpVal);
01227     } else if ((intVal == NULL) && (isClockAssign)) {
01228         return (timeKeeper + *cmpVal);
01229     } else {
01230         //srand(time(NULL));
01231         srand(timeKeeper);
01232         return (rand() % (randHigh+1)) + *cmpVal;
01233         //return (port->getState() + *cmpVal);
01234     }
01235 }
01236 
01237 int intOperation::subtract() {
01238     if ((intVal != NULL) && (!isClockAssign)) {
01239         return (*intVal - *cmpVal);
01240     } else if ((intVal == NULL) && (isClockAssign)) {
01241         if (inputsFlipped) {
01242             return (*cmpVal-timeKeeper);
01243         } else {
01244             return (timeKeeper - *cmpVal);
01245         }
01246     } else {
01247         srand(timeKeeper);
01248         if (inputsFlipped) {
01249             return (*cmpVal-(rand() % (randHigh+1)));
01250         } else {
01251             return (rand() % (randHigh+1)) - *cmpVal;
01252         }
01253         //return (port->getState() - *cmpVal);
01254     }
01255 }
01256 
01257 int intOperation::addAndStore() {
01258     if (intVal != NULL) {
01259         *intVal = *intVal + *cmpVal;
01260         return *intVal;
01261     }
01262     else {
01263 
01264         //Doesn't happen
01265         return 0;
01266         //port->setState(port->getState() + *cmpVal);
01267         //return port->getState();
01268     }
01269 
01270 }
01271 
01272 int intOperation::subtractAndStore() {
01273     if (intVal != NULL) {
01274         *intVal = *intVal - *cmpVal;
01275         return *intVal;
01276     } else {
01277         //doesn't happen
01278         return 0;
01279         //port->setState(port->getState() - *cmpVal);
01280         //return port->getState();
01281     }
01282 }
01283 
01284 int intOperation::equals() {
01285     if ((intVal != NULL) && (opPtr == NULL) && (!isClockAssign)) {
01286         *intVal = *cmpVal;
01287         return *intVal;
01288     } else if ((intVal != NULL) && (opPtr != NULL)) {
01289 
01290         *intVal = opPtr->execute();
01291         return *intVal;
01292     } else if ((intVal != NULL) && (opPtr == NULL) && (isClockAssign)) {
01293         *intVal = timeKeeper; //assign the current time to the variable
01294         return *intVal;
01295     } else if ((cmpVal != NULL)&& (!isClockAssign)){
01296 
01297         srand(timeKeeper+randomSeedCounter);
01298         randomSeedCounter++; //for seeding the next rand call, just in case it happens before the clock advances
01299         *cmpVal = (rand() % (randHigh+1)); //this is how we assign a random number to variable
01300         return *cmpVal;
01301 
01302     }
01303     return -1;
01304 }
01305 
01306 condition::condition() {
01307     intCmp = NULL;
01308     conditionPtrs[0] = NULL;
01309     conditionPtrs[1] = NULL;
01310     isUsed = false;
01311     conditionType = ARITHMATIC_CONDITION;
01312 }
01313 
01314 condition::condition(intCompare* compareInput) {
01315 
01316     intCmp = compareInput;
01317     conditionPtrs[0] = NULL;
01318     conditionPtrs[1] = NULL;
01319 
01320     isUsed = true;
01321     conditionType = ARITHMATIC_CONDITION;
01322 
01323 }
01324 
01325 condition::condition(condition* condition1, char condType, condition* condition2) {
01326     intCmp = NULL;
01327     conditionPtrs[0] = condition1;
01328     conditionPtrs[1] = condition2;
01329     isUsed = true;
01330     conditionType = condType;
01331 }
01332 
01333 condition::~condition() {
01334     if (intCmp != NULL) {
01335         delete intCmp;
01336     }
01337 }
01338 
01339 void condition::release() {
01340     if (intCmp != NULL) {
01341         intCmp->release();
01342         intCmp=NULL;
01343     }
01344     if (conditionPtrs[0] != NULL) {
01345         conditionPtrs[0]->release();
01346         conditionPtrs[1]->release();
01347         conditionPtrs[0]=NULL;
01348         conditionPtrs[1]=NULL;
01349     }
01350     isUsed = false;
01351 }
01352 
01353 void condition::set(intCompare* compareInput) {
01354     release();
01355     intCmp = compareInput;
01356     conditionPtrs[0] = NULL;
01357     conditionPtrs[1] = NULL;
01358     isUsed = true;
01359     conditionType = ARITHMATIC_CONDITION;
01360 }
01361 
01362 void condition::set(condition* condition1, char condType, condition* condition2) {
01363     release();
01364     intCmp = NULL;
01365     conditionPtrs[0] = condition1;
01366     conditionPtrs[1] = condition2;
01367     isUsed = true;
01368     conditionType = condType;
01369 }
01370 
01371 bool condition::isTrue() {
01372 
01373 
01374     bool result = true;
01375     if (conditionType == ARITHMATIC_CONDITION) {
01376 
01377         result = (intCmp->isTrue)();
01378     } else if (conditionType == AND_CONDITION) {
01379 
01380         result = conditionPtrs[0]->isTrue() && conditionPtrs[1]->isTrue();
01381     } else if (conditionType == OR_CONDITION) {
01382 
01383         result = conditionPtrs[0]->isTrue() || conditionPtrs[1]->isTrue();
01384     }
01385     return result;
01386 
01387 }
01388 
01389 portMessage::portMessage():
01390 whichToSet(0),
01391 value(0),
01392 port(NULL) {
01393     isUsed = false;
01394 }
01395 
01396 void portMessage::release() {
01397 
01398     whichToSet = 0;
01399     value = 0;
01400     port = NULL;
01401     isUsed = false;
01402 }
01403 
01404 /*
01405  portMessage::portMessage(digitalPort* portIn, int whichToSetIn, int valueIn):
01406  whichToSet(whichToSetIn),
01407  value(valueIn),
01408  port(portIn) {
01409  isUsed = true;
01410  }
01411 
01412  void portMessage::setMessage(digitalPort* portIn, int whichToSetIn, int valueIn) {
01413  whichToSet = whichToSetIn;
01414  value = valueIn;
01415  port = portIn;
01416  isUsed = true;
01417  }*/
01418 
01419 /*
01420 portMessage::portMessage(int* portIn, int whichToSetIn, int valueIn):
01421 whichToSet(whichToSetIn),
01422 value(valueIn),
01423 port(portIn) {
01424     isUsed = true;
01425 }*/
01426 
01427 void portMessage::setMessage(int* portIn, int whichToSetIn, int valueIn, digitalPort* portVectorIn) {
01428     whichToSet = whichToSetIn;
01429     value = valueIn;
01430     port = portIn;
01431     portVector = portVectorIn;
01432     isUsed = true;
01433 }
01434 
01435 void portMessage::execute() {
01436 
01437     if (port != NULL) {
01438         if ((*port > 0) && (*port <= NUMPORTS)) {
01439             portVector[*port-1].setDigitalOut(value);
01440         } else {
01441             textDisplay << "Error: port index assigned by variable does not exist.\r\n";
01442         }
01443     } else {
01444         portVector[whichToSet-1].setDigitalOut(value);
01445     }
01446 
01447 }
01448 
01449 action::action():
01450 actionType(0) {
01451     op = NULL;
01452     message = NULL;
01453     eventToCreate = NULL;
01454     displayActionPtr = NULL;
01455     //eventDelay = 0;
01456     sound = NULL;
01457     triggerFunc = NULL;
01458     sysCommand = -1;
01459     isUsed = false;
01460 
01461 }
01462 
01463 action::~action() {
01464     if (eventToCreate != NULL) delete eventToCreate;
01465     if (op != NULL) delete op;
01466     if (message != NULL) delete message;
01467     delete displayActionPtr;
01468     delete sound;
01469 }
01470 
01471 void action::release() {
01472     if (eventToCreate != NULL) eventToCreate->release();
01473     if (op != NULL) op->release();
01474     if (message != NULL) message->release();
01475     if (displayActionPtr != NULL) displayActionPtr->release();
01476     if (triggerFunc != NULL) triggerFunc->release();
01477     delete sound; //still need to make a static soundControl array
01478 
01479     actionType = 0;
01480     op = NULL;
01481     message = NULL;
01482     eventToCreate = NULL;
01483     displayActionPtr = NULL;
01484     //eventDelay = 0;
01485     sound = NULL;
01486     triggerFunc = NULL;
01487     sysCommand = -1;
01488     isUsed = false;
01489 }
01490 
01491 action::action(intOperation* opInput):
01492 actionType(1) {
01493     op = opInput;
01494     message = NULL;
01495     eventToCreate = NULL;
01496     displayActionPtr= NULL;
01497     //eventDelay = 0;
01498     sound = NULL;
01499     triggerFunc = NULL;
01500     sysCommand = -1;
01501     isUsed = true;
01502 }
01503 
01504 action::action(portMessage* messageInput):
01505 actionType(2) {
01506     op = NULL;
01507     eventToCreate = NULL;
01508     message = messageInput;
01509     displayActionPtr= NULL;
01510     //eventDelay = 0;
01511     sound = NULL;
01512     triggerFunc = NULL;
01513     sysCommand = -1;
01514     isUsed = true;
01515 
01516 }
01517 
01518 action::action(event* eventInput):
01519 actionType(3) {
01520     op = NULL;
01521     message = NULL;
01522     eventToCreate = eventInput;
01523     displayActionPtr= NULL;
01524     sound = NULL;
01525     triggerFunc = NULL;
01526 
01527     //eventDelay = eventInput->timeLag;
01528 
01529 
01530     sysCommand = -1;
01531     isUsed = true;
01532 }
01533 
01534 /*
01535  action::action(event* eventInput, uint32_t delay):
01536  actionType(3) {
01537  op = NULL;
01538  message = NULL;
01539  eventToCreate = eventInput;
01540  displayActionPtr= NULL;
01541  sound = NULL;
01542  eventDelay = delay;
01543  sysCommand = -1;
01544  isUsed = true;
01545 
01546  }*/
01547 
01548 
01549 
01550 action::action(displayAction* displayInput):
01551 actionType(4) {
01552     op = NULL;
01553     message = NULL;
01554     eventToCreate = NULL;
01555     sound = NULL;
01556     triggerFunc = NULL;
01557     displayActionPtr = displayInput;
01558     //eventDelay = 0;
01559     sysCommand = -1;
01560     isUsed = true;
01561 }
01562 
01563 action::action(sSound* soundInput):
01564 actionType(5) {
01565     op = NULL;
01566     message = NULL;
01567     eventToCreate = NULL;
01568     sound = soundInput;
01569     triggerFunc = NULL;
01570     displayActionPtr = NULL;
01571     //eventDelay = 0;
01572     sysCommand = -1;
01573     isUsed = true;
01574 }
01575 
01576 action::action(triggerFunctionAction* triggerFuncInput):
01577 actionType(7) {
01578     op = NULL;
01579     message = NULL;
01580     eventToCreate = NULL;
01581     sound = NULL;
01582     triggerFunc = triggerFuncInput;
01583     displayActionPtr = NULL;
01584     //eventDelay = 0;
01585     sysCommand = -1;
01586     isUsed = true;
01587 }
01588 
01589 action::action(int8_t sysCommandInput):
01590 actionType(6) {
01591     op = NULL;
01592     message = NULL;
01593     eventToCreate = NULL;
01594     sound = NULL;
01595     displayActionPtr = NULL;
01596     //eventDelay = 0;
01597     sysCommand = sysCommandInput;
01598     isUsed = true;
01599 }
01600 
01601 void action::set(intOperation* opInput) {
01602     actionType = 1;
01603     op = opInput;
01604     //eventDelay = 0;
01605     isUsed = true;
01606 
01607 }
01608 
01609 void action::set(portMessage* messageInput) {
01610     actionType = 2;
01611     message = messageInput;
01612     //eventDelay = 0;
01613     isUsed = true;
01614 
01615 }
01616 
01617 void action::set(event* eventInput) {
01618     actionType = 3;
01619     eventToCreate = eventInput;
01620     //eventDelay = eventInput->timeLag;
01621 
01622     isUsed = true;
01623 
01624 }
01625 
01626 /*
01627  void action::set(event* eventInput, uint32_t delay) {
01628  actionType = 3;
01629  eventToCreate = eventInput;
01630  eventDelay = delay;
01631  isUsed = true;
01632 
01633  }*/
01634 
01635 
01636 
01637 void action::set(displayAction* displayInput) {
01638     actionType = 4;
01639     displayActionPtr = displayInput;
01640     isUsed = true;
01641 }
01642 
01643 void action::set(sSound* soundInput) {
01644     actionType = 5;
01645     sound = soundInput;
01646     isUsed = true;
01647 }
01648 
01649 void action::set(triggerFunctionAction* triggerFuncInput) {
01650 
01651     actionType = 7;
01652     triggerFunc = triggerFuncInput;
01653     isUsed = true;
01654 }
01655 
01656 void action::set(int8_t sysCommandInput) {
01657     actionType = 6;
01658     sysCommand = sysCommandInput;
01659     isUsed = true;
01660 }
01661 
01662 void action::execute() {
01663 
01664     if (actionType == 1) {
01665         op->execute();
01666     } else if (actionType == 2) {
01667         message->execute();
01668     } else if (actionType == 3) {
01669         this->execute(timeKeeper); //route to the other overloaded method
01670     } else if (actionType == 4) {
01671         displayActionPtr->execute(); //send text via serial
01672     } else if (actionType == 5) {
01673         sound->execute(); //operate sound device
01674     } else if (actionType == 6) {
01675         switch(sysCommand) {
01676             case 0:
01677                 mainQueue.eraseQueue();
01678                 break;
01679             case 1:
01680                 textStreaming = true;
01681                 break;
01682             case 2:
01683                 textStreaming = false;
01684                 break;
01685             case 3:
01686                 broadCastStateChanges = true;
01687                 break;
01688             case 4:
01689                 broadCastStateChanges = false;
01690                 break;
01691         }
01692 
01693     } else if (actionType == 7) {
01694         triggerFunc->execute(); //execute function
01695     }
01696 }
01697 
01698 void action::execute(uint32_t blockExecTime) {
01699 
01700     if (actionType == 1) {
01701         op->execute();
01702     } else if (actionType == 2) {
01703         message->execute();
01704     } else if (actionType == 3) { //an event block
01705         //Because time will pass from the begining of the block, any defined delays should be updated
01706 
01707         //int newDelay = eventDelay-(*globalTimeKeeperPtr-blockExecTime);
01708         int newDelay;
01709         if (eventToCreate->timeLagIsConstant) {
01710             newDelay = eventToCreate->timeLag - (timeKeeper-blockExecTime);
01711         } else {
01712             newDelay = *eventToCreate->timeLagVar - (timeKeeper-blockExecTime);
01713         }
01714         if (newDelay < 0) {newDelay = 0;}
01715         eventToCreate->addToQueue(newDelay); //add the event to the queue to be executed later
01716 
01717         if (eventToCreate->hasWhileLoop) { //this is a while loop
01718             if (eventToCreate->isConditionTrue()) {
01719                 //newDelay = (blockExecTime + eventToCreate->whileLoopPeriod) - *globalTimeKeeperPtr;
01720                 int tmpPeriod;
01721                 if (eventToCreate->whileLoopPeriodIsConstant) { //constant while loop period
01722                     newDelay = (blockExecTime + eventToCreate->whileLoopPeriod);
01723                     tmpPeriod = eventToCreate->whileLoopPeriod;
01724                 } else {
01725                     tmpPeriod = *eventToCreate->whileLoopPeriodVar;
01726                     if (tmpPeriod < 0) {
01727                         tmpPeriod = 0;
01728                     }
01729                     newDelay = (blockExecTime + tmpPeriod);
01730                 }
01731                 while ( (newDelay-timeKeeper < 0) && (eventToCreate->isConditionTrue()) ) {
01732                     eventToCreate->execute();
01733                     newDelay = newDelay + tmpPeriod;
01734 
01735                 }
01736                 newDelay = newDelay-timeKeeper;
01737                 if (newDelay > 0) {
01738                     eventToCreate->addToQueue(newDelay);
01739                 } else {
01740                     eventToCreate->addToQueue(1);
01741                 }
01742             } else if (eventToCreate->nextElseEventPtr != NULL) {
01743                 eventToCreate->nextElseEventPtr->addToQueue();
01744 
01745             }
01746         }
01747     } else if (actionType == 4) {
01748         displayActionPtr->execute(); //send text via serial
01749     } else if (actionType == 5) {
01750         sound->execute(); //operate sound device
01751     } else if (actionType == 6) {
01752         switch(sysCommand) {
01753             case 0:
01754                 mainQueue.eraseQueue();
01755                 break;
01756             case 1:
01757                 textStreaming = true;
01758                 break;
01759             case 2:
01760                 textStreaming = false;
01761                 break;
01762             case 3:
01763                 broadCastStateChanges = true;
01764                 break;
01765             case 4:
01766                 broadCastStateChanges = false;
01767                 break;
01768         }
01769     } else if (actionType == 7) {
01770 
01771         textDisplay.flush();
01772         triggerFunc->execute(); //operate sound device
01773     }
01774 }
01775 
01776 eventQueue::eventQueue() {
01777 
01778     queueItem blankEvent;
01779     blankEvent.timeToExecute = 0;
01780     blankEvent.eventPtr = NULL;
01781     queueSize = 100;
01782     events.resize(queueSize,blankEvent);
01783 
01784 
01785 }
01786 
01787 void eventQueue::addEventToQueue(event* eventInput, uint32_t delay) {
01788     //*updateSlavePtr = false;
01789     uint32_t eventTime = timeKeeper + delay;
01790     //*updateSlavePtr = true;
01791     //std::vector<queueItem>::size_type sz = events.size();
01792     //Look for the first empty slot in the queue and place the event there.
01793     //This means that the events in the queue are out of order, but
01794     //it prevents us from having to push_pack and pop off all the time.
01795     for (unsigned i = 0; i < queueSize; i++) {
01796         if (events[i].eventPtr == NULL) {
01797             events[i].eventPtr = eventInput;
01798             events[i].timeToExecute = eventTime;
01799             break;
01800         }
01801     }
01802 }
01803 
01804 void eventQueue::eraseQueue() {
01805     //Erase all events in the queue
01806     std::vector<queueItem>::size_type sz = events.size();
01807     for (unsigned i = 0; i < sz; i++) {
01808         events[i].eventPtr = NULL;
01809 
01810     }
01811 }
01812 
01813 
01814 //check if any of the events in the queue are up for execution
01815 void eventQueue::check(void) {
01816 
01817     //*updateSlavePtr = false;
01818     uint32_t currentTime = timeKeeper;
01819     //*updateSlavePtr = true;
01820     //std::vector<queueItem>::size_type sz = events.size();
01821     for (unsigned i = 0; i < queueSize; i++) {
01822         if (events[i].eventPtr != NULL) {
01823             if(events[i].timeToExecute <= currentTime) {
01824                 if (!events[i].eventPtr->hasWhileLoop) {
01825                     //this is not a while loop, so no need to check if the condition is still true
01826                     events[i].eventPtr->execute();
01827                 } else if (events[i].eventPtr->isConditionTrue()){
01828                     //The event is part of a while loop, so recheck the condition before executing
01829                     events[i].eventPtr->execute();
01830                     //if (events[i].eventPtr->isConditionTrue()) { //is the condition still true?
01831                     int nextTime;
01832                     int tmpPeriod;
01833                     if (events[i].eventPtr->whileLoopPeriodIsConstant) {
01834                         nextTime = (events[i].timeToExecute + events[i].eventPtr->whileLoopPeriod);
01835                         tmpPeriod = events[i].eventPtr->whileLoopPeriod;
01836                     } else {
01837                         tmpPeriod = *events[i].eventPtr->whileLoopPeriodVar;
01838                         if (tmpPeriod < 0) {
01839                             tmpPeriod = 0;
01840                         }
01841                         nextTime = (events[i].timeToExecute + tmpPeriod);
01842 
01843                     }
01844                     //Just in case we are not keeping up, execute the event until we have cought up
01845                     while ((nextTime-timeKeeper <= 0) && (events[i].eventPtr->isConditionTrue())) {
01846                         events[i].eventPtr->execute();
01847                         nextTime = nextTime+tmpPeriod;
01848 
01849                     }
01850                     nextTime = nextTime - timeKeeper;
01851                     if (nextTime > 0) {
01852                         //we add the event to the queue (but the condition is rechecked first)
01853                         //if the condition is false, the 'then' statement is added to the queue instead
01854                         events[i].eventPtr->addToQueue(nextTime);
01855                     } else {
01856                         //if we are having trouble keeping up, just add the next event in 1 ms
01857                         events[i].eventPtr->addToQueue(1);
01858                     }
01859                     /*
01860                      } else {
01861                      if (events[i].eventPtr->nextElseEventPtr != NULL) {
01862                      events[i].eventPtr->nextElseEventPtr->addToQueue();
01863                      }
01864                      }*/
01865 
01866                 } else {
01867                     if (events[i].eventPtr->nextElseEventPtr != NULL) {
01868                         events[i].eventPtr->nextElseEventPtr->addToQueue();
01869                     }
01870                 }
01871                 events[i].eventPtr = NULL;
01872             }
01873         }
01874     }
01875 }
01876 
01877 
01878 event::event():
01879     timeLag(0),
01880     queuePtr(&mainQueue) {
01881 
01882     nextElseEventPtr = NULL;
01883     conditionToCheck = NULL;
01884     blockType = 0;
01885     whileLoopPeriod = 0;
01886     numConditions = 0;
01887     numActions = 0;
01888     isUsed = false;
01889     timeLagVar = NULL;
01890     timeLagIsConstant = true;
01891     whileLoopPeriodIsConstant = true;
01892     hasWhileLoop = false;
01893     whileLoopPeriodVar = NULL;
01894 
01895 }
01896 
01897 event::event(eventQueue* queueInput):
01898     timeLag(0),
01899     queuePtr(&mainQueue) {
01900 
01901     nextElseEventPtr = NULL;
01902     conditionToCheck = NULL;
01903     blockType = 0;
01904     whileLoopPeriod = 0;
01905     numConditions = 0;
01906     numActions = 0;
01907     isUsed = true;
01908     timeLagVar = NULL;
01909     timeLagIsConstant = true;
01910     whileLoopPeriodIsConstant = true;
01911     hasWhileLoop = false;
01912     whileLoopPeriodVar = NULL;
01913 
01914 }
01915 
01916 event::~event() {
01917     /*
01918      while (!conditionArray.empty())
01919      {
01920      delete conditionArray.back();
01921      conditionArray.pop_back();
01922      }
01923 
01924      while (!actionArray.empty())
01925      {
01926      delete actionArray.back();
01927      actionArray.pop_back();
01928      }
01929 
01930      delete nextElseEventPtr;
01931      */
01932 
01933 }
01934 
01935 void event::release() {
01936 
01937     for (int i = 0; i < numActions; i++) {
01938         actionArray[i]->release();
01939     }
01940 
01941     if (conditionToCheck != NULL) {
01942         conditionToCheck->release();
01943         conditionToCheck = NULL;
01944     }
01945 
01946     if (nextElseEventPtr != NULL) {
01947         nextElseEventPtr->release();
01948     }
01949     timeLag = 0;
01950     nextElseEventPtr = NULL;
01951     blockType = 0;
01952     whileLoopPeriod = 0;
01953     numConditions = 0;
01954     numActions = 0;
01955     isUsed = false;
01956     timeLagVar = NULL;
01957     timeLagIsConstant = true;
01958     whileLoopPeriodIsConstant = true;
01959     hasWhileLoop = false;
01960     whileLoopPeriodVar = NULL;
01961 }
01962 
01963 void event::setTimeLag(uint32_t timeLagInput) {
01964     timeLag = timeLagInput;
01965     timeLagIsConstant = true;
01966 }
01967 
01968 void event::setTimeLag(int* timeLagInput) {
01969     timeLagVar = timeLagInput;
01970     timeLagIsConstant = false; //time lag is not defined by a constant
01971 }
01972 
01973 void event::setWhileLoopPeriod(uint32_t period) {
01974     whileLoopPeriodIsConstant = true;
01975     hasWhileLoop = true;
01976     whileLoopPeriod = period;
01977 
01978 }
01979 
01980 void event::setWhileLoopPeriod(int* period) {
01981     whileLoopPeriodIsConstant = false;
01982     hasWhileLoop = true;
01983     whileLoopPeriodVar = period;
01984 
01985 }
01986 
01987 void event::addCondition(condition* conditionInput) {
01988     if (conditionToCheck != NULL) {
01989         conditionToCheck->release();
01990     }
01991     conditionToCheck = conditionInput;
01992 
01993     //conditionArray.push_back(conditionInput);
01994 }
01995 
01996 void event::addAction(action* actionInput) {
01997     actionArray[numActions] = actionInput;
01998     numActions++;
01999     //actionArray.push_back(actionInput);
02000 }
02001 
02002 bool event::isConditionTrue(void) {
02003     //if statement (can be left empty, which is interpreted as 'true')
02004     bool result = true;
02005 
02006     if ((conditionToCheck!=NULL)&&(!conditionToCheck->isTrue())) {
02007         result = false;
02008     }
02009 
02010     return result;
02011 }
02012 
02013 void event::execute(void) {
02014     //called from the event queue.  The condition is bypassed because it was already checked
02015 
02016     uint32_t timeAtStartExec = timeKeeper;
02017     for (unsigned i = 0; i < numActions; i++) {
02018         actionArray[i]->execute(timeAtStartExec);
02019 
02020     }
02021 
02022 }
02023 
02024 //Attach an 'else' statement to the event
02025 void event::setNextElseEvent(event* eventInput) {
02026     nextElseEventPtr = eventInput;
02027 }
02028 
02029 
02030 //When we we call addToQueue() the condition is checked.  If true, the event is added
02031 //to the queue, otherwise we check if there was an 'else' statement attached to the event.
02032 void event::addToQueue(void) {
02033     if (isConditionTrue()) {
02034         if ((timeLagIsConstant)&&(timeLag == 0)) {
02035             execute();
02036 
02037         } else if (timeLagIsConstant) {
02038             queuePtr->addEventToQueue(this, this->timeLag);
02039         } else if ((!timeLagIsConstant)&&(*timeLagVar <= 0)) {
02040             execute();
02041         } else {
02042             queuePtr->addEventToQueue(this, *timeLagVar);
02043         }
02044     } else if ((this->nextElseEventPtr != NULL)&&(whileLoopPeriod == 0)) {
02045         this->nextElseEventPtr->addToQueue();
02046     }
02047 }
02048 
02049 //We can override the timeLag field and use another delay
02050 void event::addToQueue(uint32_t delay) {
02051     if (this->isConditionTrue()) {
02052         //if ((delay == 0) && (whileLoopPeriod == 0)) {
02053         if ((delay == 0)) {
02054             this->execute();
02055         } else {
02056             queuePtr->addEventToQueue(this, delay);
02057         }
02058     } else if ((this->nextElseEventPtr != NULL)) { //&&(!hasWhileLoop)) {
02059         this->nextElseEventPtr->addToQueue();
02060     }
02061 }
02062 
02063 
02064 
02065 functionItem::functionItem(action* actionInput, string tagInput):
02066 tag(tagInput),
02067 actionPtr(actionInput) {
02068 }
02069 
02070 functionItem::~functionItem() {
02071     delete actionPtr;
02072 }
02073 
02074 blockBuffer::blockBuffer() {
02075     bufferWritePos = 0;
02076     bufferReadPos = 0;
02077     _linesAvailable = 0;
02078 
02079 }
02080 
02081 bool blockBuffer::addLine(char *input, int numChars) {
02082 
02083     if (bufferWritePos+numChars >= INPUTCHARBUFFERSIZE) {
02084         return false;
02085     }
02086     for(int i=0;i<numChars;i++) {
02087         charBuffer[bufferWritePos] = input[i];
02088         bufferWritePos++;
02089     }
02090     _linesAvailable++;
02091     return true;
02092 }
02093 
02094 string blockBuffer::getNextLine() {
02095 
02096     string outputLine;
02097     int endOfLinePos = bufferReadPos;
02098     bool endOfLineFound = false;
02099 
02100     if (_linesAvailable > 0) {
02101         //Find the end of the next line
02102 
02103         while (endOfLinePos < INPUTCHARBUFFERSIZE) {
02104 
02105             if (charBuffer[endOfLinePos] == '\0') {
02106                 endOfLineFound = true;
02107                 break;
02108             }
02109             endOfLinePos++;
02110         }
02111 
02112         //If the end was found, copy to output string
02113         if (endOfLineFound) {
02114 
02115             outputLine.append(charBuffer+bufferReadPos,endOfLinePos-bufferReadPos);
02116             bufferReadPos = endOfLinePos+1;
02117             _linesAvailable--;
02118         } else {
02119             textDisplay << "Error: No end of line found!";
02120             textDisplay.flush();
02121         }
02122     }
02123     if (_linesAvailable == 0) {
02124         //we have read out all of the lines, so reset the buffer for the next block.
02125         resetBuffer();
02126     }
02127     return outputLine;
02128 
02129 }
02130 
02131 int16_t blockBuffer::linesAvailable() {
02132     return _linesAvailable;
02133 }
02134 
02135 void blockBuffer::resetBuffer() {
02136     _linesAvailable = 0;
02137     bufferReadPos = 0;
02138     bufferWritePos = 0;
02139 }
02140 
02141 bool blockBuffer::empty() {
02142     return (_linesAvailable == 0);
02143 }
02144 
02145 
02146 scriptStream::scriptStream(digitalPort* portVectorInput, int numPortsInput, eventQueue* queueInput, sSystem *system):
02147     portVector(portVectorInput),
02148     numPorts(numPortsInput),
02149     queuePtr(queueInput),
02150     system(system) {
02151 
02152     currentPort = -1;
02153     currentTriggerPort = -1;
02154     currentTriggerDir = 1;
02155     currentFunction = -1;
02156 
02157     randomSeedCounter = 0;  //used for seeding random numbers
02158 
02159     lineError = false;
02160     blockDepth = 0;
02161     ifBlockInit = false;
02162     whileBlockInit = false;
02163     expectingDoStatement = false;
02164     elseFlag = false;
02165     thenFlag = false;
02166     currentDelay = 0;
02167 
02168     for (int i = 0; i < NUMFUNCTIONS; i++) {
02169         functionSpotTaken[i] = false;
02170         functionEventArray[i] = NULL;
02171     }
02172 
02173 
02174 }
02175 
02176 
02177 void scriptStream::addLineToCurrentBlock(char* lineInput) {
02178 
02179     bool compile = false;
02180     bool keep = false;
02181     int numCharInLine = 0;
02182     //A line ending with ';' then carriage return initiates the compile sequence
02183     //Otherwise, add the line to the buffer and compile later
02184     for (int i = 0; i < 256; i++) {
02185         numCharInLine++;
02186         if (lineInput[i] == ';') {
02187             compile = true;
02188         } else if (lineInput[i] == ' ') {
02189             continue;
02190         } else if (lineInput[i] == '\0') {
02191             break;
02192         } else {
02193             keep = true;
02194             compile = false;
02195         }
02196 
02197     }
02198 
02199     //if (keep) currentBlock.insert(currentBlock.begin(),string(lineInput));
02200     if (keep) {
02201         if (!currentBlock.addLine(lineInput,numCharInLine)) {
02202             textDisplay << "Error: script input buffer full. The block is too long.\r\n";
02203             currentBlock.resetBuffer();
02204             compile = false;
02205         }
02206     }
02207     if (compile) {
02208         parseBlock();
02209     }
02210 
02211 }
02212 
02213 
02214 //SCRIPT PARSING - all script commands are defined here.
02215 //-------------------------------------------------------
02216 void scriptStream::parseBlock() {
02217 
02218 
02219     lineError = false;
02220     blockDepth = 0;
02221     ifBlockInit = false;
02222     whileBlockInit = false;
02223     expectingDoStatement = false;
02224     elseFlag = false;
02225     thenFlag = false;
02226     currentDelay = 0;
02227 
02228 
02229     std::size_t stringInd = 0;
02230 
02231     bool wholeLineEvaluated = false;
02232 
02233     while (!currentBlock.empty()) {
02234 
02235         wholeLineEvaluated = false;
02236         //tmpLine = currentBlock.back();
02237         tmpLine = currentBlock.getNextLine();
02238 
02239         lineError = false;
02240         //remove tabs
02241         std::size_t found = tmpLine.find_first_of(9); //tab
02242         while (found!=std::string::npos) {
02243             tmpLine[found]= ' ';
02244             found=tmpLine.find_first_of(9,found+1);
02245         }
02246 
02247         found = tmpLine.find_first_of(37); //% for commenting
02248         if (found!=std::string::npos) {
02249             for (int p=found; p<tmpLine.size() ;p++) {
02250                 tmpLine[p]= ' ';
02251             }
02252         }
02253 
02254         //break up the line into tokens separated by spaces
02255         tokenize(tmpLine,tokens," ;");
02256 
02257         std::vector<string>::size_type sz = tokens.size();
02258 
02259         for (unsigned i = 0; i < sz; i++) {
02260 
02261 
02262 
02263             //end statement signals the end of a block-----------------------------------------
02264             if (tokens[i].compare("end") == 0) { //ends the current block
02265 
02266                 if (ifBlockInit || whileBlockInit || expectingDoStatement) {
02267                     textDisplay << "Error: expected a 'do' statement\r\n";
02268                     lineError = true;
02269                 }
02270 
02271                 ifBlockInit = false;
02272                 whileBlockInit = false;
02273                 expectingDoStatement = false;
02274                 elseFlag = false;
02275 
02276                 if (blockDepth > 0) {
02277                     textDisplay.debug("End statement\r\n");
02278                     if (blockDepth == 1) {
02279 
02280 
02281                         currentTriggerPort = -1;
02282                         currentFunction = -1;
02283 
02284 
02285 
02286                         blockDepth = 0;
02287                     } else if (blockDepth > 1) {
02288                         blockDepth = blockDepth - 1;
02289                     }
02290 
02291                     while ((tmpEventPtrArray.back()->blockType == 3) || (tmpEventPtrArray.back()->blockType == 4) || (tmpEventPtrArray.back()->blockType == 6) || (tmpEventPtrArray.back()->blockType == 7) || (tmpEventPtrArray.back()->blockType == 8)){
02292                         tmpEventPtrArray.pop_back(); //recursively remove the pointers to all else blocks
02293                     }
02294                     tmpEventPtrArray.pop_back(); //remove the pointer to the finished block
02295 
02296                 } else {
02297                     textDisplay << "Error: End statement without block\r\n";
02298                     lineError = true;
02299                 }
02300 
02301 
02302 
02303                 //sound statement used to play wave files------------------------------------------------
02304                 //example: sound('soundfile')
02305                 //         sound(stop)
02306             } else if (tokens[i].find("sound(") != std::string::npos) {
02307                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02308                     textDisplay << "Error: expected a 'do' statement\r\n";
02309                     lineError = true;
02310                 }
02311                 wholeLineEvaluated = true;
02312                 int pos1 = tmpLine.find("sound(")+6;
02313                 int pos2 = tmpLine.find_first_of(")",pos1);
02314                 string dispVar = tmpLine.substr(pos1,pos2-pos1);
02315 
02316                 int* tmpVar = findIntVariable(dispVar);
02317                 bool isText = false;
02318                 bool stopSignal = false;
02319                 bool resetSignal = false;
02320                 if (tmpVar == NULL) {
02321                     if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
02322                         isText = true;
02323                     } else if (dispVar.compare("stop") == 0) {
02324                         stopSignal = true;
02325                     } else if (dispVar.compare("reset") == 0) {
02326                         resetSignal = true;
02327                     } else {
02328                         textDisplay << "Error: variable input to sound() does not exist\r\n";
02329                         lineError = true;
02330                     }
02331                 }
02332                 action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02333                 if (tmpAction == NULL) {
02334                     textDisplay << "Error: no memory slots available.\r\n";
02335                     lineError = true;
02336                 }
02337                 if (!lineError && (blockDepth == 0)) {
02338                     //we are not inside a block structure, so play sound now
02339                     if (stopSignal) {
02340                         sSound* S = system->createNewSoundAction();
02341                         S->setPlayback(false);
02342                         S->execute();
02343                         delete S;
02344                     } else if (resetSignal) {
02345                         sSound* S = system->createNewSoundAction();
02346                         S->setReset();
02347                         S->execute();
02348                         delete S;
02349                     } else if (isText) {
02350 
02351                         if (pos2-pos1-2 <= 20) {
02352 
02353                             sSound* S = system->createNewSoundAction();
02354                             S->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
02355                             S->execute();
02356                             delete S;
02357                         } else {
02358                             textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
02359                             lineError = true;
02360                         }
02361                     } else {
02362                         textDisplay << "Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n";
02363                         lineError = true;
02364                     }
02365 
02366                 } else if (!lineError && (blockDepth > 0) ){
02367                     //the disp function was put inside a block
02368                     textDisplay.debug("Sound statement\r\n");
02369                     if (stopSignal) {
02370                         sSound* sPtr = system->createNewSoundAction();
02371                         sPtr->setPlayback(false);
02372                         //action* tmpAction = new action(sPtr);
02373                         tmpAction->set(sPtr);
02374                         tmpEventPtrArray.back()->addAction(tmpAction);
02375                     } else if (resetSignal) {
02376                         sSound* sPtr = system->createNewSoundAction();
02377                         sPtr->setReset();
02378                         //action* tmpAction = new action(sPtr);
02379                         tmpAction->set(sPtr);
02380                         tmpEventPtrArray.back()->addAction(tmpAction);
02381                     } else if (isText) {
02382 
02383                         if (pos2-pos1-2 <= 20) {
02384                             sSound* sPtr = system->createNewSoundAction();
02385                             sPtr->setFile(tmpLine.substr(pos1+1,pos2-pos1-2));
02386                             //action* tmpAction = new action(sPtr);
02387                             tmpAction->set(sPtr);
02388                             tmpEventPtrArray.back()->addAction(tmpAction);
02389                         } else {
02390                             textDisplay << "Error: sound file names must be 20 characters or less.\r\n";
02391                             lineError = true;
02392                         }
02393                     } else {
02394                         textDisplay << "Error: variable input to sound() not yet supported.  Enter a string in single quotes.\r\n";
02395                         lineError = true;
02396                     }
02397 
02398 
02399                 }
02400 
02401             } else if (tokens[i].find("volume(") != std::string::npos) {
02402                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02403                     textDisplay << "Error: expected a 'do' statement\r\n";
02404                     lineError = true;
02405                 }
02406                 wholeLineEvaluated = true;
02407                 int pos1 = tmpLine.find("volume(")+7;
02408                 int pos2 = tmpLine.find_first_of(")",pos1);
02409                 string dispVar = tmpLine.substr(pos1,pos2-pos1);
02410 
02411                 int* tmpVar = findIntVariable(dispVar);
02412                 bool isText = false;
02413                 if (tmpVar == NULL) {
02414                     if (isNumber(dispVar)) {
02415                         isText = true;
02416                     } else {
02417                         textDisplay << "Error: variable input to volume() does not exist\r\n";
02418                         lineError = true;
02419                     }
02420                 }
02421                 action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02422                 if (tmpAction == NULL) {
02423                     textDisplay << "Error: no memory slots available.\r\n";
02424                     lineError = true;
02425                 }
02426                 if (!lineError && (blockDepth == 0)) {
02427                     //we are not inside a block structure, so play sound now
02428                     if (isText) {
02429                         int newVolume = atoi(dispVar.data());
02430                         if ((newVolume >=0)&&(newVolume <= 255)) {
02431                             sSound* S = system->createNewSoundAction();
02432                             S->setVolume(newVolume);
02433                             S->execute();
02434                             delete S;
02435                         } else {
02436                             textDisplay << "Error: sound volume must be between 0 and 255 .\r\n";
02437                             lineError = true;
02438                         }
02439                     } else {
02440                         sSound* S = system->createNewSoundAction();
02441                         S->setVolume(tmpVar);
02442                         S->execute();
02443                         delete S;
02444                     }
02445 
02446                 } else if (!lineError && (blockDepth > 0) ){
02447                     //the disp function was put inside a block
02448                     textDisplay.debug("Volume statement\r\n");
02449                     if (isText) {
02450                         int newVolume = atoi(dispVar.data());
02451 
02452                         sSound* sPtr = system->createNewSoundAction();
02453                         sPtr->setVolume(newVolume);
02454 
02455                         //action* tmpAction = new action(sPtr);
02456                         tmpAction->set(sPtr);
02457                         tmpEventPtrArray.back()->addAction(tmpAction);
02458 
02459                     } else {
02460                         sSound* sPtr = system->createNewSoundAction();
02461                         sPtr->setVolume(tmpVar);
02462                         //action* tmpAction = new action(sPtr);
02463                         tmpAction->set(sPtr);
02464                         tmpEventPtrArray.back()->addAction(tmpAction);
02465                     }
02466 
02467 
02468                 }
02469                 //clock statement used to is used to control the clock-------------------------
02470                 //example: clock(reset); clock(slave); clock(standalone)
02471             } else if (tokens[i].find("clock(") != std::string::npos) { //clock commands
02472                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02473                     textDisplay << "Error: expected a 'do' statement\r\n";
02474                     lineError = true;
02475                 }
02476                 if (blockDepth > 0) {
02477                     textDisplay << "Error: clock commands only allowed outside of block structure\r\n";
02478                     lineError = true;
02479                 }
02480 
02481                 if (!lineError) {
02482                     int pos1 = tmpLine.find("clock(")+6;
02483                     int pos2 = tmpLine.find_first_of(")",pos1);
02484                     string dispVar = tmpLine.substr(pos1,pos2-pos1);
02485 
02486 
02487                     if (blockDepth == 0) {
02488                         if (dispVar.compare("reset") == 0) {
02489                             resetTimer = true;
02490                             queuePtr->eraseQueue();
02491                             textDisplay.send(string("Clock reset to 0\r\n"));
02492 
02493                         } else if (dispVar.compare("slave") == 0) {
02494                             if (!clockSlave) {
02495                                 changeToSlave = true;
02496                                 textDisplay.send(string("Slave mode\r\n"));
02497 
02498                             }
02499                         } else if (dispVar.compare("standalone") == 0) {
02500                             if (clockSlave) {
02501                                 changeToStandAlone = true;
02502                                 textDisplay.send(string("Standalone mode\r\n"));
02503 
02504                             }
02505                         } else if (dispVar.compare("") == 0) {
02506                             //The user needs the current time displayed.
02507 
02508                             //textDisplay.send(string("Current Clock\r\n"));
02509                             textDisplay << timeKeeper << " current time\r\n";
02510                         } else {
02511                             textDisplay << "Error: Clock control statement not understood\r\n";
02512                             lineError = true;
02513                         }
02514                     }
02515                 }
02516 
02517                 //disp command used to display text via serial---------------------------------------
02518                 //example: disp('hello'); disp(myVar)
02519             } else if (tokens[i].find("disp(") != std::string::npos) { //display value of variable
02520 
02521                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02522                     textDisplay <<"Error: expected a 'do' statement\r\n";
02523                     lineError = true;
02524                 }
02525 
02526                 //int pos1 = tokens[i].find("disp(")+5;
02527                 //int pos2 = tokens[i].find_first_of(")",pos1);
02528                 //string dispVar = tokens[i].substr(pos1,pos2-pos1);
02529 
02530                 wholeLineEvaluated = true;
02531                 int pos1 = tmpLine.find("disp(")+5;
02532                 int pos2 = tmpLine.find_first_of(")",pos1);
02533                 if (pos2 == std::string::npos) {
02534                     textDisplay <<"Error: expected a ) character\r\n";
02535                     lineError = true;
02536                 }
02537 
02538                 if (!lineError) {
02539                     string dispVar = tmpLine.substr(pos1,pos2-pos1);
02540 
02541                     int* tmpVar = findIntVariable(dispVar);
02542                     bool isText = false;
02543                     if (tmpVar == NULL) {
02544                         if ((tmpLine.compare(pos1,1,"'")==0) && (tmpLine.compare(pos2-1,1,"'")==0)) {
02545                             isText = true;
02546                         } else {
02547                             textDisplay << "Error: variable to display does not exist\r\n";
02548                             lineError = true;
02549                         }
02550                     }
02551                     displayAction* dPtr = findFirstUnUsed(displayActionBlock, NUMDISPLAYACTIONS);
02552                     if (dPtr == NULL) {
02553                         textDisplay << "Error: no memory slots available.\r\n";
02554                         lineError = true;
02555                     }
02556 
02557                     if (!lineError && (blockDepth == 0)) {
02558                         //we are not inside a block structure, so display now
02559 
02560                         if (isText) {
02561                             //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
02562                             dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2));
02563                             dPtr->execute();
02564                             //delete dPtr;
02565                             dPtr->release();
02566                         } else {
02567                             //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
02568                             dPtr->set(tmpVar, dispVar);
02569                             dPtr->execute();
02570                             //delete dPtr;
02571                             dPtr->release();
02572                         }
02573 
02574                     } else if (!lineError && (blockDepth > 0) ){
02575                         //the disp function was put inside a block
02576                         textDisplay.debug("Display statement\r\n");
02577                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02578                         if (tmpAction == NULL) {
02579                             textDisplay <<"Error: no memory slots available.\r\n";
02580                             lineError = true;
02581                         }
02582                         if (!lineError && isText) {
02583                             //displayAction* dPtr = new displayAction(tmpLine.substr(pos1+1,pos2-pos1-2), pcPtr);
02584                             dPtr->set(tmpLine.substr(pos1+1,pos2-pos1-2));
02585                             tmpAction->set(dPtr);
02586                             //action* tmpAction = new action(dPtr);
02587                             tmpEventPtrArray.back()->addAction(tmpAction);
02588                         } else if (!lineError) {
02589                             //displayAction* dPtr = new displayAction(tmpVar, dispVar, pcPtr);
02590                             dPtr->set(tmpVar, dispVar);
02591                             tmpAction->set(dPtr);
02592                             //action* tmpAction = new action(dPtr);
02593                             tmpEventPtrArray.back()->addAction(tmpAction);
02594                         }
02595 
02596 
02597                     }
02598                 }
02599                 //----------------------------------------------
02600                 //The trigger command is used like this:
02601                 //trigger(n)
02602                 //Where n is an integer corresponding to a "function n" block
02603                 //When "trigger" is called, the corresponding function is executed.
02604             } else if (tokens[i].find("trigger(") != std::string::npos) { //trigger a function
02605 
02606                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02607                     textDisplay << "Error: expected a 'do' statement\r\n";
02608                     lineError = true;
02609                 }
02610 
02611 
02612                 wholeLineEvaluated = true;
02613                 int pos1 = tmpLine.find("trigger(")+8;
02614                 int pos2 = tmpLine.find_first_of(")",pos1);
02615                 int funcNum = atoi(tmpLine.substr(pos1,pos2-pos1).data());
02616                 if ((funcNum > 0) && (funcNum < NUMFUNCTIONS+1)) {
02617                     if (functionSpotTaken[funcNum-1]) {
02618 
02619 
02620                     } else {
02621                         textDisplay << "Error: function number does not exist\r\n";
02622                         lineError = true;
02623                     }
02624                 } else {
02625                     textDisplay << "Error: not a valid function number\r\n";
02626                     lineError = true;
02627                 }
02628 
02629                 funcNum--;  //change to 0-based index
02630                 if (!lineError && (blockDepth == 0)) {
02631                     //we are not inside a block structure, so execute function now
02632                     //textDisplay << "Exectuting function";
02633                     //textDisplay.flush();
02634 
02635                     functionEventArray[funcNum]->execute();
02636 
02637                 } else if (!lineError && (blockDepth > 0) ){
02638                     //the trigger function was put inside a block, so we need to create a new action
02639                     textDisplay.debug("Trigger statement\r\n");
02640                     triggerFunctionAction* tPtr = findFirstUnUsed(triggerFunctionActionBlock, NUMTRIGGERACTIONS);
02641                     if (tPtr == NULL) {
02642                         textDisplay << "Error: no memory slots available.\r\n";
02643                         lineError = true;
02644                     }
02645 
02646                     if (!lineError) {
02647                         //we only give provide it the function number, instead
02648                         //of a pointer to the event.  That way, if the user modifies
02649                         //the function (which would change the pointer), all callbacks
02650                         //still using that function number will use the new function.
02651                         tPtr->set(funcNum);
02652                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02653                         if (tmpAction == NULL) {
02654                             textDisplay << "Error: no memory slots available.\r\n";
02655                             lineError = true;
02656                         }
02657                         if (!lineError) {
02658 
02659                             tmpAction->set(tPtr);
02660                             tmpEventPtrArray.back()->addAction(tmpAction);
02661                         }
02662                     }
02663 
02664 
02665                 }
02666 
02667 
02668 
02669 
02670                 //int is used to decalar new variables.  Only allowed outside of callbacks-------------------
02671                 //example: int a;  int b = 9
02672             }else if(tokens[i].compare("kaboom") == 0){//send "kaboom;" to reset mbed
02673                 mbed_reset();            
02674             }else if (tokens[i].compare("int") == 0) { //define a new integer variable
02675                 textDisplay.debug("Int statement\r\n");
02676                 if (ifBlockInit || whileBlockInit || expectingDoStatement) {
02677                     textDisplay << "Error: expected a 'do' statement\r\n";
02678                     lineError = true;
02679                 }
02680                 tmpString = "";
02681                 wholeLineEvaluated = true;
02682                 int spacesBeforeEqualSign = 0;
02683                 bool countSpaces = true;
02684                 //combine the tokens without whitespaces
02685                 for (unsigned j = i+1; j < sz; j++) {
02686                     tmpString.append(tokens[j]);
02687                     if (tokens[j].find_first_of("=") != std::string::npos) {
02688                         if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
02689                         countSpaces = false;
02690                     } else if (countSpaces) {
02691                         spacesBeforeEqualSign++;
02692                     }
02693                 }
02694 
02695                 if (blockDepth > 0) {
02696                     textDisplay << "Error: Variables can only be first declared outside of callbacks.\r\n";
02697                     lineError = true;
02698                 }
02699 
02700                 if ((!lineError) && (spacesBeforeEqualSign > 1)) {
02701                     textDisplay << "Error: Variable can't have a space in it.\r\n";
02702                     lineError = true;
02703                 }
02704                 stringInd = tmpString.find_first_of("=");
02705 
02706                 bool variableCreated = false;
02707                 if (!lineError) {
02708                     if (((stringInd == std::string::npos) && (sz == 2)) || (stringInd != std::string::npos)) {
02709 
02710                         if ((stringInd != std::string::npos) && (stringInd > MAXVARNAMESIZE)) {
02711                             textDisplay << "Error: variable names must be under 30 characters.\r\n";
02712                             lineError = true;
02713                         } else if (createIntVariable(tmpString.substr(0,stringInd))) {
02714                             textDisplay.debug("Created new variable\r\n");
02715                             variableCreated = true;
02716                         } else {
02717                             textDisplay.debug("Attempting to use existing variable\r\n");
02718                             int* tmpVar = findIntVariable(tmpString.substr(0,stringInd));
02719                             *tmpVar = 0;
02720                             //lineError = true;
02721                         }
02722                     } else {
02723                         textDisplay << "Error: variable declaration not understood.\r\n";
02724                         lineError = true;
02725                     }
02726                 }
02727                 if ((!lineError) && (stringInd != std::string::npos)) { //evaluate the expression
02728                     //action* tmpAction = evaluateAssignmentForAction(tmpString);
02729                     action* tmpAction = evaluateAssignmentForAction(tmpString.data());
02730                     if (tmpAction != NULL) {
02731                         tmpAction->execute();
02732                         //delete tmpAction;
02733                         tmpAction->release();
02734                     } else {
02735                         lineError = true;
02736                         if (variableCreated) {
02737                             delete globalVariables.back();
02738                             globalVariables.pop_back();
02739                         }
02740                     }
02741                 }
02742 
02743                 //serial command is used to toggle whether or not to buffer up output text----------------
02744                 //examples: serial buffer; serial send
02745             } else if (tokens[i].compare("serial") == 0) {
02746                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02747                     textDisplay << "Error: expected a 'do' statement\r\n";
02748                     lineError = true;
02749                 }
02750                 bool stream = true;
02751                 if ((!lineError)&&(i+1 < sz)){
02752                     if (tokens[i+1].compare("buffer") == 0) {
02753                         stream = false;
02754                     } else if (tokens[i+1].compare("send") == 0) {
02755                         stream = true;
02756                     } else {
02757                         textDisplay << "Error: 'serial' useage: 'serial buffer' or 'serial send'\r\n";
02758                         lineError = true;
02759                     }
02760                 }
02761                 i++;
02762                 if ((!lineError) && (blockDepth == 0)) {
02763                     if (stream) {
02764                         textStreaming = true;
02765                     } else {
02766                         textStreaming = false;
02767                     }
02768                 } else if ((!lineError) && (blockDepth > 0)) {
02769                     if (stream) {
02770                         //action* tmpAction = new action(1); //code 1 = turn on text streaming
02771                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02772                         if (tmpAction == NULL) {
02773                             textDisplay << "Error: no memory slots available.\r\n";
02774                             lineError = true;
02775                         } else {
02776                             tmpAction->set(1);
02777                             tmpEventPtrArray.back()->addAction(tmpAction);
02778                         }
02779 
02780                     } else {
02781                         //action* tmpAction = new action(2); //code 2 = turn on text buffering
02782                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02783                         if (tmpAction == NULL) {
02784                             textDisplay << "Error: no memory slots available.\r\n";
02785                             lineError = true;
02786                         } else {
02787                             tmpAction->set(2);
02788                             tmpEventPtrArray.back()->addAction(tmpAction);
02789                         }
02790                     }
02791                 }
02792 
02793                 //updates command toggles the DIO update messages upon a change------------------
02794                 //examples: updates on; updates off
02795             } else if (tokens[i].compare("updates") == 0) {
02796                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02797                     textDisplay << "Error: expected a 'do' statement\r\n";
02798                     lineError = true;
02799                 }
02800                 bool stream = true;
02801                 int specifiedPort = -1;
02802                 if ((!lineError)&&(i+1 < sz)){
02803                     if (tokens[i+1].compare("on") == 0) {
02804                         stream = true;
02805                     } else if (tokens[i+1].compare("off") == 0) {
02806                         stream = false;
02807                     } else {
02808                         textDisplay << "Error: 'updates' useage: 'updates on' or 'updates off'\r\n";
02809                         lineError = true;
02810                     }
02811                 }
02812                 if ((!lineError) && (i+2 < sz)) {
02813                     //There is a port specified
02814                     //int pos1 = tmpLine.find("trigger(")+8;
02815                     //int pos2 = tmpLine.find_first_of(")",pos1);
02816                     int tempPort = atoi(tokens[i+2].data());
02817                     
02818                     if (tempPort > 0) {
02819                         specifiedPort = tempPort-1;
02820                     } else {
02821                         textDisplay << "Error: 'updates' useage: 'updates on [port]' or 'updates off [port]'\r\n";
02822                         lineError = true;
02823                     }
02824                     i++;
02825                 }
02826                 i++;
02827                 if ((!lineError) && (blockDepth == 0)) {
02828                     if (stream) {
02829                         //applies to all;
02830                         broadCastStateChanges = true;
02831                         if (specifiedPort > -1) {
02832                             system->setPortUpdatesOn(specifiedPort);
02833                         } else {
02834                             for (int i=0;i<NUMPORTS;i++) {
02835                                 system->setPortUpdatesOn(i);
02836                             }
02837                         }
02838                     } else {
02839                         if (specifiedPort > -1) {
02840                             system->setPortUpdatesOff(specifiedPort);
02841                         } else {
02842                             //applies to all
02843                             //broadCastStateChanges = false;
02844                             for (int i=0;i<NUMPORTS;i++) {
02845                                 system->setPortUpdatesOff(i);
02846                             }
02847                         }
02848 
02849                     }
02850                 } else if ((!lineError) && (blockDepth > 0)) {
02851                     //Inside a block-- current no support here to specify a port
02852 
02853                     if (stream) {
02854                         //action* tmpAction = new action(3); //code 3 = turn on updates
02855                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02856                         if (tmpAction == NULL) {
02857                             textDisplay << "Error: no memory slots available.\r\n";
02858                             lineError = true;
02859                         } else {
02860                             tmpAction->set(3);
02861                             tmpEventPtrArray.back()->addAction(tmpAction);
02862                         }
02863                     } else {
02864                         //action* tmpAction = new action(4); //code 4 = turn off updates
02865                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02866                         if (tmpAction == NULL) {
02867                             textDisplay << "Error: no memory slots available.\r\n";
02868                             lineError = true;
02869                         } else {
02870                             tmpAction->set(4);
02871                             tmpEventPtrArray.back()->addAction(tmpAction);
02872                         }
02873 
02874                     }
02875                 }
02876 
02877             } else if (tokens[i].compare("memory") == 0) {
02878                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02879                     textDisplay << "Error: expected a 'do' statement\r\n";
02880                     lineError = true;
02881                 }
02882                 if ((!lineError) && (blockDepth > 0)) {
02883                     textDisplay << "Error: memory statement is not allowed inside a block.\r\n";
02884                     lineError = true;
02885                 }
02886                 if (!lineError) {
02887                     displayMemoryLeft();
02888                 }
02889 
02890 
02891             //clear is used to clear things from memory---------------------------------
02892             //examples: clear all; clear callbacks; clear queue
02893 
02894             } else if (tokens[i].compare("clear") == 0) { //delete all created events and variables
02895                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
02896                     textDisplay << "Error: expected a 'do' statement\r\n";
02897                     lineError = true;
02898                 }
02899                 int clearMode = 0;
02900                 if ((!lineError)&&(i+1 < sz)){
02901                     if (tokens[i+1].compare("all") == 0) {
02902                         clearMode = 1;
02903                     } else if (tokens[i+1].compare("blocks") == 0) {
02904                         clearMode = 2;
02905                     } else if (tokens[i+1].compare("queue") == 0) {
02906                         clearMode = 3;
02907                     } else {
02908                         textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
02909                         lineError = true;
02910                     }
02911                 } else {
02912                     textDisplay << "Error: clear what: all, blocks, or queue? \r\n";
02913                     lineError = true;
02914                 }
02915 
02916 
02917                 if ((!lineError) && (clearMode < 3) && (blockDepth > 0)) {
02918                     textDisplay << "Error: 'clear all' and 'clear blocks' only allowed outside of block structures\r\n";
02919                     lineError = true;
02920                 }
02921                 if (!lineError) {
02922                     //i++;
02923                     //clear variables
02924                     if (clearMode == 1) {
02925                         while (!globalVariables.empty()) {
02926                             delete globalVariables.back();
02927                             globalVariables.pop_back();
02928                         }
02929                         broadCastStateChanges = true;
02930                         for (int i=0;i<NUMPORTS;i++) {
02931                             system->setPortUpdatesOn(i);
02932                         }
02933                     }
02934 
02935                     //clear callbacks, functions, and queue
02936                     if (clearMode < 3) {
02937                         for (int pNum = 0; pNum < NUMPORTS; pNum++) {
02938                             //delete portVector[pNum]->triggerUpEventPtr;
02939                             if (portVector[pNum].triggerUpEventPtr != NULL) {
02940                                 portVector[pNum].triggerUpEventPtr->release();
02941                             }
02942                             portVector[pNum].triggerUpEventPtr = NULL;
02943 
02944                             //delete portVector[pNum]->triggerDownEventPtr;
02945                             if (portVector[pNum].triggerDownEventPtr != NULL) {
02946                                 portVector[pNum].triggerDownEventPtr->release();
02947                             }
02948                             portVector[pNum].triggerDownEventPtr = NULL;
02949 
02950 
02951                             /*
02952                              while (!functionArray.empty()) {
02953                              delete functionArray.back();
02954                              functionArray.pop_back();
02955                              } */
02956                         }
02957                         for (int i = 0; i < NUMFUNCTIONS; i++) {
02958                             functionSpotTaken[i] = false;
02959                             functionEventArray[i] = NULL;
02960                         }
02961                         for (int i = 0; i < NUMEVENTS; i++) {
02962                             eventBlock[i].release();
02963                         }
02964                         for (int i = 0; i < NUMCONDITIONS; i++) {
02965                             conditionBlock[i].release();
02966                         }
02967                         for (int i = 0; i < NUMINTCOMPARE; i++) {
02968                             intCompareBlock[i].release();
02969                         }
02970                         for (int i = 0; i < NUMACTIONS; i++) {
02971                             actionBlock[i].release();
02972                         }
02973                         for (int i = 0; i < NUMPORTMESSAGES; i++) {
02974                             portMessageBlock[i].release();
02975                         }
02976                         for (int i = 0; i < NUMINTOPERATIONS; i++) {
02977                             intOperationBlock[i].release();
02978                         }
02979                         for (int i = 0; i < NUMDISPLAYACTIONS; i++) {
02980                             displayActionBlock[i].release();
02981                         }
02982                         for (int i = 0; i <NUMTRIGGERACTIONS; i++) {
02983                             triggerFunctionActionBlock[i].release();
02984                         }
02985 
02986                         queuePtr->eraseQueue();
02987                     }
02988 
02989                     if (clearMode == 4) {
02990                         if (blockDepth > 0) { //we are inside a block
02991                             action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
02992                             if (tmpAction == NULL) {
02993                                 textDisplay << "Error: no memory slots available.\r\n";
02994                                 lineError = true;
02995                             } else {
02996 
02997                                 int8_t code = 0;
02998                                 tmpAction->set(code);
02999                                 //action* tmpAction = new action(code); //code 0 = clear queue
03000                                 tmpEventPtrArray.back()->addAction(tmpAction);
03001                             }
03002                         } else {
03003                             //clear queue now
03004                             queuePtr->eraseQueue();
03005                         }
03006                     }
03007                     wholeLineEvaluated = true;
03008 
03009 
03010                 }
03011 
03012                 //do starts a block---------------------------------------------------------
03013                 //example:  do in 500
03014                 //              ...
03015                 //          end
03016 
03017             } else if (tokens[i].compare("do") == 0) { //the start of a block
03018 
03019                 if (!ifBlockInit && !whileBlockInit) {
03020 
03021                     if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
03022 
03023 
03024                     } else {
03025                         textDisplay << "Error: a statement block must be placed inside a callback or function.\r\n";
03026                         lineError = true;
03027                     }
03028 
03029                 }
03030                 expectingDoStatement = false;
03031                 tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
03032                 action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
03033                 bool eventReserved = false;
03034                 if ((tmpEvent == NULL)||(tmpAction == NULL)) {
03035                     textDisplay << "Error: no memory slots available.\r\n";
03036                     lineError = true;
03037 
03038                 } else {
03039 
03040 
03041                 }
03042 
03043                 if (i+2 < sz) { //a time delay in the block
03044 
03045                     if ((!lineError) && (tokens[i+1].compare("in") == 0) && (isNumber(tokens[i+2]))) {
03046                         textDisplay.debug("Do in number statement\r\n");
03047                         currentDelay = atoi(tokens[i+2].data());
03048                         if (currentDelay < 0) {
03049                             textDisplay <<"Error: block delay time must be a positive integer\r\n";
03050                             lineError = true;
03051                         } else if (!ifBlockInit) { //a standalone do block
03052                             //tmpEvent = new event(queuePtr);
03053                             tmpEvent->isUsed = true;
03054                             eventReserved = true;
03055                             tmpEvent->setTimeLag(currentDelay);
03056 
03057                             if ((!elseFlag) && ((!thenFlag))) {
03058                                 //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
03059                                 tmpAction->set(tmpEvent);
03060                                 tmpEventPtrArray.back()->addAction(tmpAction);
03061                                 tmpEventPtrArray.push_back(tmpEvent);
03062                                 tmpEventPtrArray.back()->blockType = 2; //this is a do block
03063                                 blockDepth = blockDepth+1;
03064                             } else if (elseFlag) {
03065                                 tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03066                                 tmpEventPtrArray.push_back(tmpEvent);
03067                                 tmpEventPtrArray.back()->blockType = 4; //an else block
03068                             } else if (thenFlag) {
03069 
03070                                 tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03071                                 tmpEventPtrArray.push_back(tmpEvent);
03072                                 tmpEventPtrArray.back()->blockType = 8; //a then block
03073                             }
03074 
03075                         } else { //an if block
03076                             tmpEventPtrArray.back()->setTimeLag(currentDelay);
03077 
03078                             if (!elseFlag && !thenFlag) {
03079                                 if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
03080                                     tmpAction->set(tmpEventPtrArray.back());
03081                                     tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
03082                                     //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
03083                                 }
03084                             } else if (elseFlag){
03085                                 tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
03086                             } else if (thenFlag){
03087                                 tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
03088 
03089                             }
03090 
03091 
03092                         }
03093 
03094                     } else if ((!lineError) && (tokens[i+1].compare("in") == 0) && (findIntVariable(tokens[i+2])!=NULL)) {
03095                         textDisplay.debug("Do in VAR statement\r\n");
03096                         int* delayVar = findIntVariable(tokens[i+2]);
03097                         //currentDelay = atoi(tokens[i+2].data());
03098                         if (!ifBlockInit) { //a standalone do block
03099                             //tmpEvent = new event(queuePtr);
03100                             tmpEvent->isUsed = true;
03101                             eventReserved = true;
03102                             tmpEvent->setTimeLag(delayVar);
03103 
03104                             if ((!elseFlag) && ((!thenFlag))) {
03105                                 //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
03106                                 tmpAction->set(tmpEvent);
03107                                 tmpEventPtrArray.back()->addAction(tmpAction);
03108                                 tmpEventPtrArray.push_back(tmpEvent);
03109                                 tmpEventPtrArray.back()->blockType = 2; //this is a do block
03110                                 blockDepth = blockDepth+1;
03111                             } else if (elseFlag) {
03112                                 tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03113                                 tmpEventPtrArray.push_back(tmpEvent);
03114                                 tmpEventPtrArray.back()->blockType = 4; //an else block
03115                             } else if (thenFlag) {
03116 
03117                                 tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03118                                 tmpEventPtrArray.push_back(tmpEvent);
03119                                 tmpEventPtrArray.back()->blockType = 8; //a then block
03120                             }
03121 
03122                         } else { //an if block
03123                             tmpEventPtrArray.back()->setTimeLag(delayVar);
03124 
03125                             if (!elseFlag && !thenFlag) {
03126                                 if (blockDepth > 1) { //this is a nested block, so add it as an action to the parent block
03127                                     tmpAction->set(tmpEventPtrArray.back());
03128                                     tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
03129                                     //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
03130                                 }
03131                             } else if (elseFlag){
03132                                 tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
03133                             } else if (thenFlag){
03134                                 tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
03135 
03136                             }
03137 
03138 
03139                         }
03140 
03141                     } else {
03142                         textDisplay << "Error: block delay time must be a positive integer or a variable\r\n";
03143                         lineError = true;
03144                     }
03145                 } else if (!lineError && !ifBlockInit) { //no time delay given, standalone do
03146                     textDisplay.debug("Do statement\r\n");
03147                     currentDelay = 0;
03148                     //tmpEvent = new event(queuePtr);
03149                     tmpEvent->isUsed = true;
03150                     eventReserved = true;
03151                     tmpEvent->setTimeLag(currentDelay);
03152                     if (!elseFlag && !thenFlag) {
03153                         tmpAction->set(tmpEvent);
03154                         tmpEventPtrArray.back()->addAction(tmpAction);
03155                         //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
03156                         tmpEventPtrArray.push_back(tmpEvent);
03157                         blockDepth = blockDepth+1;
03158                     } else if (elseFlag) {
03159                         tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03160                         tmpEventPtrArray.push_back(tmpEvent);
03161                         tmpEventPtrArray.back()->blockType = 4; //an else block
03162                     } else if (thenFlag) {
03163                         tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03164                         tmpEventPtrArray.push_back(tmpEvent);
03165                         tmpEventPtrArray.back()->blockType = 8; //a then block
03166                     }
03167 
03168                 } else if (!lineError) { //no time delay, if block
03169 
03170                     currentDelay = 0;
03171                     tmpEventPtrArray.back()->setTimeLag(currentDelay);
03172 
03173 
03174                     if (!elseFlag && !thenFlag) {
03175                         if (blockDepth > 1) {
03176                             tmpAction->set(tmpEventPtrArray.back());
03177                             tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(tmpAction);
03178                             //tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->addAction(new action(tmpEventPtrArray.back()));
03179                         }
03180                     } else {
03181                         tmpEventPtrArray.at(tmpEventPtrArray.size()-2)->setNextElseEvent(tmpEventPtrArray.back());
03182                     }
03183 
03184                 }
03185                 if (lineError && eventReserved) {
03186                     tmpEvent->release();
03187                 }
03188                 //close block initiation
03189                 ifBlockInit = false;
03190                 whileBlockInit = false;
03191                 wholeLineEvaluated = true;
03192                 elseFlag = false;
03193                 thenFlag = false;
03194 
03195                 //currently, there are two types of root-level blocks: functions and callbacks
03196                 //
03197                 //A function can be triggered with a command, a callback is tied to a hardware event
03198             } else if (tokens[i].compare("function") == 0) { //a new function block
03199                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
03200                     textDisplay << "Error: expected a 'do' statement\r\n";
03201                     lineError = true;
03202                 }
03203                 if (blockDepth != 0)  {
03204                     textDisplay <<"Error: Can't declare a function block within another block\r\n";
03205                     lineError = true;
03206                 }
03207                 if (!lineError) {
03208                     textDisplay.debug("Function statement\r\n");
03209                     wholeLineEvaluated = true;
03210                     if (i+1 < sz) {
03211                         int tempFuncNum = atoi(tokens[i+1].data());
03212                         if ((tempFuncNum > 0) && (tempFuncNum < NUMFUNCTIONS+1)) {
03213                             currentFunction = tempFuncNum-1;
03214                         } else {
03215                             textDisplay << "Error: not a valid function number\r\n";
03216                             lineError = true;
03217                         }
03218                     } else {
03219                         if (!lineError) textDisplay << "Error: Not enough arguments for function statement\r\n";
03220                         lineError = true;
03221                     }
03222                     if (sz > 2) {
03223                         if (!((sz == 3) && (tokens[i+2].compare("do") == 0))) {
03224                             textDisplay << "Error: Too many arguments in function statement\r\n";
03225                             lineError = true;
03226                         }
03227                     }
03228 
03229                     tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
03230                     if (tmpEvent != NULL) {
03231                         tmpEvent->isUsed = true;
03232 
03233                     } else {
03234                         textDisplay << "Error: no memory slots available.\r\n";
03235                         lineError = true;
03236                     }
03237                     if (!lineError) {
03238 
03239                         blockDepth = 1;
03240                         i = i+2;
03241                         //create new event and attach it to the port
03242                         //tmpEventPtrArray.push_back(new event(queuePtr));
03243                         tmpEventPtrArray.push_back(tmpEvent);
03244 
03245                         if (functionSpotTaken[currentFunction]) {
03246                             functionEventArray[currentFunction]->release();
03247                         }
03248                         functionEventArray[currentFunction] = tmpEvent;
03249                         functionSpotTaken[currentFunction] = true;
03250 
03251                     }
03252                 }
03253 
03254 
03255                 //callback starts a callback block------------------------------------------
03256                 //exmaple: callback portin(1) down
03257                 //              ...
03258                 //         end
03259             } else if (tokens[i].compare("callback") == 0) { //a new callback block
03260                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
03261                     textDisplay << "Error: expected a 'do' statement\r\n";
03262                     lineError = true;
03263                 }
03264                 if (blockDepth != 0)  {
03265                     textDisplay << "Error: Can't declare a callback block within another block\r\n";
03266                     lineError = true;
03267                 }
03268                 if (!lineError) {
03269                     textDisplay.debug("Callback statement\r\n");
03270                     wholeLineEvaluated = true;
03271                     if (i+2 < sz) {
03272                         if ((tokens[i+1].find("portin[") != std::string::npos) && (tokens[i+1].size() > 8) ) { //callback for a digital port
03273                             int pos1 = tokens[i+1].find("portin[")+7;
03274                             int pos2 = tokens[i+1].find_first_of("]",pos1);
03275                             currentTriggerPort = atoi(tokens[i+1].substr(pos1,pos2-pos1).data());
03276 
03277                             if (currentTriggerPort <= 0) {
03278                                 currentTriggerPort = -1;
03279                                 textDisplay << "Error: Not a valid port number\r\n";
03280                                 lineError = true;
03281                             }
03282                         } else {
03283                             textDisplay << "Error: Not a valid callback input\r\n";
03284                             lineError = true;
03285                         }
03286                         if (tokens[i+2].compare("up") == 0) {
03287                             currentTriggerDir = 1;
03288                         } else if (tokens[i+2].compare("down") == 0) {
03289                             currentTriggerDir = -1;
03290                         } else {
03291                             textDisplay << "Error: No trigger direction given\r\n";
03292                             lineError = true;
03293                         }
03294 
03295                     } else {
03296                         if (!lineError) textDisplay << "Error: Not enough arguments for callback statement\r\n";
03297                         lineError = true;
03298                     }
03299                     if (sz > 3) {
03300                         if (!((sz == 4) && (tokens[i+3].compare("do") == 0))) {
03301                             textDisplay << "Error: Too many arguments in callback statement\r\n";
03302                             lineError = true;
03303                         }
03304                     }
03305 
03306                     tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
03307                     if (tmpEvent != NULL) {
03308                         tmpEvent->isUsed = true;
03309 
03310                     } else {
03311                         textDisplay << "Error: no memory slots available.\r\n";
03312                         lineError = true;
03313                     }
03314                     if (!lineError) {
03315 
03316                         blockDepth = 1;
03317                         i = i+2;
03318                         //create new event and attach it to the port
03319                         //tmpEventPtrArray.push_back(new event(queuePtr));
03320                         tmpEventPtrArray.push_back(tmpEvent);
03321                         if (currentTriggerDir == 1) {
03322 
03323                             portVector[currentTriggerPort-1].setTriggerUpEvent(tmpEventPtrArray.back());
03324                         } else {
03325 
03326                             portVector[currentTriggerPort-1].setTriggerDownEvent(tmpEventPtrArray.back());
03327                         }
03328 
03329                     }
03330                 }
03331 
03332                 //if starts an if block----------------------------------------------
03333                 //examples: if x < 10 && y == 1 do;  if a==1 do in 1000
03334             } else if (tokens[i].compare("if") == 0) { //a new if block
03335                 if (ifBlockInit || whileBlockInit) {
03336                     textDisplay << "Error: expected a 'do' statement\r\n";
03337                     lineError = true;
03338                 }
03339 
03340                 ifBlockInit = true;
03341                 currentDelay = 0;
03342                 bool eventDefined = false;
03343                 tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
03344                 if (tmpEvent != NULL) {
03345                     tmpEvent->isUsed = true;
03346                     eventDefined = true;
03347                 } else {
03348                     textDisplay << "Error: no memory slots available.\r\n";
03349                     lineError = true;
03350                 }
03351                 if (!lineError) {
03352                     textDisplay.debug("If statement\r\n");
03353                     //this is a regular event
03354                     //tmpEventPtrArray.push_back(new event(queuePtr));
03355                     tmpEventPtrArray.push_back(tmpEvent);
03356 
03357                     if ((!elseFlag) && ((!thenFlag))) {
03358                         tmpEventPtrArray.back()->blockType = 1; //this is an if block
03359                         blockDepth = blockDepth + 1;
03360                     } else if (elseFlag) {
03361                         tmpEventPtrArray.back()->blockType = 3; //this is an else if block
03362                     } else if (thenFlag) {
03363                         tmpEventPtrArray.back()->blockType = 7; //this is a then if block
03364                     }
03365                 }
03366 
03367                 if (!lineError) {
03368                     //combine the condition tokens without whitespaces
03369                     tmpString = "";
03370                     for (unsigned j = i+1; j < sz; j++) {
03371                         if (tokens[j].compare("do") != 0) {
03372                             i++;
03373                             tmpString.append(tokens[j]);
03374                         } else {
03375                             break;
03376                         }
03377                     }
03378                     //adds the conditions to the current event
03379 
03380                     if (!evaluateConditions(tmpString, tmpEventPtrArray.back())) lineError = true;
03381                 }
03382 
03383                 if (lineError && eventDefined) {
03384                     tmpEvent->release();
03385                 }
03386 
03387 
03388                 //else starts an else block-------------------------------------
03389                 //examples:  else do in 500;  else if x==7 do
03390             } else if (tokens[i].compare("else") == 0) { //an else block
03391                 if (ifBlockInit || whileBlockInit || expectingDoStatement) {
03392                     textDisplay << "Error: expected a 'do' statement\r\n";
03393                     lineError = true;
03394                 }
03395                 textDisplay.debug("Else statement\r\n");
03396                 //callbacks can't have else conditions
03397                 if ((!lineError) && (blockDepth < 2) && ((currentTriggerPort > -1)||(currentFunction > -1))) {
03398                     textDisplay << "Error: else statement can not occur after a trigger block or outside a block\r\n";
03399                     lineError = true;
03400                 }
03401 
03402                 //check to make sure we are in an 'if' block
03403                 if ((!lineError) && (tmpEventPtrArray.back()->blockType != 1) && (tmpEventPtrArray.back()->blockType != 3)) { //not currently in an 'if' or 'else if' block
03404                     textDisplay << "Error: else statement can only occur in an 'if' block\r\n";
03405                     lineError = true;
03406                 }
03407                 if (!lineError) {
03408                     elseFlag = true;
03409                     expectingDoStatement = true;
03410 
03411                 }
03412             } else if (tokens[i].compare("then") == 0) { //a then block
03413                 if (ifBlockInit || whileBlockInit) {
03414                     textDisplay << "Error: expected a 'do' statement\r\n";
03415                     lineError = true;
03416                 }
03417 
03418                 //trigger blocks can't have else conditions
03419                 if ((!lineError) && (blockDepth < 2) && (currentTriggerPort > -1)) {
03420                     textDisplay << "Error: 'then' statement can only occur after a 'while' block\r\n";
03421                     lineError = true;
03422                 }
03423 
03424                 //check to make sure we are in a 'while' block
03425                 if ((!lineError) && (tmpEventPtrArray.back()->blockType != 5)) { //not currently in a while block
03426                     textDisplay << "Error: 'then' statement can only occur in a 'while' block\r\n";
03427                     lineError = true;
03428                 }
03429                 if (!lineError) {
03430                     thenFlag = true;
03431                     expectingDoStatement = true;
03432 
03433                 }
03434                 //while starts a while block----------------------------------------
03435                 //example:  while x<10 do every 100
03436                 //              ...
03437                 //          end
03438             } else if (tokens[i].compare("while") == 0) { //a new while block
03439                 if (ifBlockInit || whileBlockInit) {
03440                     textDisplay << "Error: expected a 'do' statement\r\n";
03441                     lineError = true;
03442                 }
03443                 textDisplay.debug("While statement\r\n");
03444 
03445                 if ((currentTriggerPort > 0) || (currentFunction > -1)) { //check to make sure we are inside a trigger block
03446 
03447 
03448                 } else {
03449                     textDisplay << "Error: a statement block must be placed inside a callback or function.\r\n";
03450                     lineError = true;
03451                 }
03452                 //whileBlockInit = true;
03453                 currentDelay = 0;
03454 
03455                 tmpEvent = findFirstUnUsed(eventBlock, NUMEVENTS);
03456                 if (tmpEvent != NULL) {
03457                     tmpEvent->isUsed = true;
03458                     tmpEvent->setTimeLag(currentDelay);
03459                 } else {
03460                     textDisplay << "Error: no memory slots available.\r\n";
03461                     lineError = true;
03462                 }
03463 
03464                 //tmpEvent = new event(queuePtr);
03465 
03466 
03467                 if (!lineError) {
03468                     //combine the condition tokens without whitespaces
03469                     tmpString = "";
03470                     for (unsigned j = i+1; j < sz; j++) {
03471                         if (tokens[j].compare("do") != 0) {
03472                             i++;
03473                             tmpString.append(tokens[j]);
03474                         } else {
03475                             break;
03476                         }
03477                     }
03478                     //adds the conditions to the current event
03479                     if (!evaluateConditions(tmpString, tmpEvent)) lineError = true;
03480                 }
03481 
03482                 if (!lineError) {
03483                     if ((i+3) < sz) {
03484                         if ((tokens[i+1].compare("do") == 0) && (tokens[i+2].compare("every") == 0)) {
03485 
03486                             if (isNumber(tokens[i+3])) {
03487                                 uint32_t period = atoi(tokens[i+3].data());
03488                                 if (period > 0) {
03489 
03490 
03491                                     //tmpEvent->whileLoopPeriod = period;
03492                                     tmpEvent->setWhileLoopPeriod(period);
03493                                     if (!elseFlag) {
03494                                         tmpEvent->blockType = 5; //this is a while block
03495 
03496                                         action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
03497                                         if (tmpAction == NULL) {
03498                                             textDisplay << "Error: no memory slots available.\r\n";
03499                                             lineError = true;
03500                                         } else {
03501                                             tmpAction->set(tmpEvent);
03502                                         }
03503                                         //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
03504                                         tmpEventPtrArray.back()->addAction(tmpAction);
03505 
03506                                         tmpEventPtrArray.push_back(tmpEvent);
03507                                         blockDepth = blockDepth+1;
03508                                     } else {
03509                                         tmpEvent->blockType = 6; //this is an else while block
03510                                         tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03511                                         tmpEventPtrArray.push_back(tmpEvent);
03512                                     }
03513                                     wholeLineEvaluated = true;
03514                                 } else {
03515                                     textDisplay << "Error: loop period must be a positive integer.\r\n";
03516                                     lineError = true;
03517                                 }
03518                             } else if (findIntVariable(tokens[i+3])!=NULL) {
03519 
03520                                 int* period = findIntVariable(tokens[i+3]);
03521                                 //tmpEvent->whileLoopPeriodVar = period;
03522                                 tmpEvent->setWhileLoopPeriod(period);
03523                                 if (!elseFlag) {
03524                                     tmpEvent->blockType = 5; //this is a while block
03525 
03526                                     action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
03527                                     if (tmpAction == NULL) {
03528                                         textDisplay << "Error: no memory slots available.\r\n";
03529                                         lineError = true;
03530                                     } else {
03531                                         tmpAction->set(tmpEvent);
03532                                     }
03533                                     //tmpEventPtrArray.back()->addAction(new action(tmpEvent));
03534                                     tmpEventPtrArray.back()->addAction(tmpAction);
03535 
03536                                     tmpEventPtrArray.push_back(tmpEvent);
03537                                     blockDepth = blockDepth+1;
03538                                 } else {
03539                                     tmpEvent->blockType = 6; //this is an else while block
03540                                     tmpEventPtrArray.back()->setNextElseEvent(tmpEvent);
03541                                     tmpEventPtrArray.push_back(tmpEvent);
03542                                 }
03543                                 wholeLineEvaluated = true;
03544                             }
03545                         } else {
03546                             textDisplay << "Error: expected a 'do every' statement\r\n";
03547                             lineError = true;
03548                         }
03549                     } else {
03550                         textDisplay << "Error: expected a 'do every' statement\r\n";
03551                         lineError = true;
03552                     }
03553                 }
03554 
03555                 //if the line contains an '=' sign,the equality is evaulated-------------------------
03556                 //examples:  a = 1;  a = b + 5; a = random(100); portout[2] = 1; portout[2] = flip
03557             } else if ((tmpLine.find_first_of("=") != std::string::npos) ) { //an expression
03558                 if (ifBlockInit || whileBlockInit || elseFlag || expectingDoStatement) {
03559                     textDisplay << "Error: expected a 'do' statement\r\n";
03560                     lineError = true;
03561                 }
03562 
03563                 wholeLineEvaluated = true;
03564                 tmpString = "";
03565                 int spacesBeforeEqualSign = 0;
03566                 bool countSpaces = true;
03567                 //combine the tokens without whitespaces
03568                 for (unsigned j = i; j < sz; j++) {
03569                     tmpString.append(tokens[j]);
03570                     if (tokens[j].find_first_of("=") != std::string::npos) {
03571                         if (tokens[j].find_first_of("=") > 0) spacesBeforeEqualSign++;
03572                         countSpaces = false;
03573                     } else if (countSpaces) {
03574                         spacesBeforeEqualSign++;
03575                     }
03576                 }
03577                 if (!lineError && spacesBeforeEqualSign > 1) {
03578                     textDisplay << "Error: Variable can't have a space in it.\r\n";
03579                     lineError = true;
03580                 }
03581 
03582                 if (!lineError) {
03583                     if (blockDepth > 0) {
03584                         textDisplay.debug("Variable assignment statement\r\n");
03585                         //action* tmpAction = evaluateAssignmentForAction(tmpString);
03586                         action* tmpAction = evaluateAssignmentForAction(tmpString.data());
03587                         if (tmpAction != NULL) {
03588                             tmpEventPtrArray.back()->addAction(tmpAction);
03589 
03590                         } else {
03591                             lineError = true;
03592                         }
03593 
03594                     } else { //assignment was written outside of any block structure, so execute now
03595 
03596 
03597                         //action* tmpAction = evaluateAssignmentForAction(tmpString);
03598                         action* tmpAction = evaluateAssignmentForAction(tmpString.data());
03599 
03600                         if (tmpAction != NULL) {
03601                             tmpAction->execute();
03602 
03603                             //delete tmpAction;
03604                             tmpAction->release();
03605                         } else {
03606                             lineError = true;
03607                         }
03608                     }
03609                 }
03610             } else {
03611                 //if there was no match to any of the above, an error is given
03612                 textDisplay << "Error: statement not understood.\r\n";
03613                 lineError = true;
03614             }
03615 
03616             if (lineError) {
03617                  break; //stop parsing the rest of the line if an error was detected
03618             }
03619             if (wholeLineEvaluated) { //some of the tokens forces the whole line to be avaluated at once
03620                 i = sz; //skip ahead to end of the line
03621             }
03622 
03623         }
03624 
03625         //if there was an error, we quit compiling the code
03626         if (lineError) {
03627 
03628             textDisplay << "Line text: ";
03629             while (!tokens.empty()) {
03630                 textDisplay << tokens.front()<< " ";
03631                 tokens.erase(tokens.begin());
03632             }
03633             textDisplay << "\r\n";
03634 
03635             currentBlock.resetBuffer();
03636             while (!tokens.empty()) {
03637                 tokens.pop_back();
03638             }
03639             //delete tmpEvent;
03640             tmpEvent->release();
03641         } else {
03642 
03643             while (!tokens.empty()) {
03644                 tokens.pop_back();
03645             }
03646             //currentBlock.pop_back();
03647 
03648         }
03649 
03650     }
03651 
03652     //make sure that all blocks have a matching end statement
03653 
03654 
03655     if ((!lineError)&&(blockDepth > 0)) {
03656         textDisplay << "Error: Missing 1 or more end statements\r\n";
03657         lineError = true;
03658         currentBlock.resetBuffer();
03659     }
03660 
03661     if ((!lineError)&&(blockDepth == 0)) {
03662         textDisplay.send("~~~\r\n");
03663     }
03664 
03665     //displayMemoryLeft();
03666     //DisplayRAMBanks();
03667 
03668 }
03669 
03670 
03671 //used to return a pointer to a variable, if it exists
03672 int* scriptStream::findIntVariable(string nameInput) {
03673 
03674     textDisplay.debug("Finding variable: ");
03675     textDisplay.debug(nameInput.data());
03676     int* outPtr = NULL;
03677     bool foundIt = false;
03678     if (nameInput.find("portout") != std::string::npos) {
03679         int pos1 = nameInput.find("portout[")+8;
03680         int pos2 = nameInput.find_first_of("]",pos1);
03681         int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
03682         int portVal = 0;
03683         if ((portnum > 0) && (portnum <= numPorts)) {
03684             outPtr = &portVector[portnum-1].outState;
03685             foundIt = true;
03686         }
03687     } else if (nameInput.find("portin") != std::string::npos) {
03688         int pos1 = nameInput.find("portin[")+7;
03689         int pos2 = nameInput.find_first_of("]",pos1);
03690         int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
03691         int portVal = 0;
03692         if ((portnum > 0) && (portnum <= numPorts)) {
03693             outPtr = &portVector[portnum-1].inState;
03694             foundIt = true;
03695         }
03696     }
03697 
03698     if (!foundIt) {
03699         std::vector<intVariable*>::size_type sz = globalVariables.size();
03700         int start = 0;
03701         int end = nameInput.length()-1;
03702 
03703         for (unsigned i = 0; i < sz; i++) {
03704 
03705 
03706             if ((findStringLoc(nameInput.data(),globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
03707                 outPtr = &globalVariables[i]->value;
03708                 break;
03709             }
03710             /*
03711             if (nameInput.compare(globalVariables[i]->tag) == 0) {
03712                 outPtr = &globalVariables[i]->value;
03713                 break;
03714             }*/
03715         }
03716     }
03717     textDisplay.debug("...done\r\n");
03718 
03719     return outPtr;
03720 }
03721 
03722 
03723 //used to return a pointer to a variable, if it exists
03724 int* scriptStream::findIntVariable(const char* nameInput, int start, int end) {
03725 
03726     textDisplay.debug("Finding variable...");
03727     int* outPtr = NULL;
03728     bool foundIt = false;
03729 
03730     if (findStringLoc(nameInput,"portout[",start,end) != -1) {
03731         int pos1 = findStringLoc(nameInput,"portout[",start,end)+8;
03732         int pos2 = findStringLoc(nameInput, "]",pos1,end);
03733         if ((pos1 == -1)||(pos2 == -1)) {
03734             //syntax error
03735             return NULL;
03736         }
03737 
03738         //int portnum = atoi(nameInput.substr(pos1,pos2-pos1).data());
03739         long int portnum = strtol(nameInput+pos1,NULL,10);
03740         if ((portnum > 0) && (portnum <= numPorts)) {
03741             outPtr = &portVector[(int)portnum-1].outState;
03742             foundIt = true;
03743         }
03744     } else if (findStringLoc(nameInput,"portin[",start,end) != -1) {
03745         int pos1 = findStringLoc(nameInput,"portin[",start,end)+7;
03746         int pos2 = findStringLoc(nameInput, "]",pos1,end);
03747         if ((pos1 == -1)||(pos2 == -1)) {
03748             //syntax error
03749             return NULL;
03750         }
03751         long int portnum = strtol(nameInput+pos1,NULL,10);
03752 
03753         if ((portnum > 0) && (portnum <= numPorts)) {
03754             outPtr = &portVector[(int)portnum-1].inState;
03755             foundIt = true;
03756         }
03757     }
03758 
03759     if (!foundIt) {
03760         std::vector<intVariable*>::size_type sz = globalVariables.size();
03761         for (unsigned i = 0; i < sz; i++) {
03762             //const char* varName = globalVariables[i]->tag.data();
03763             if ((findStringLoc(nameInput,globalVariables[i]->tag,start,end) != -1) && (strlen(globalVariables[i]->tag)==(end-start+1))) {
03764                 outPtr = &globalVariables[i]->value;
03765                 break;
03766             }
03767         }
03768     }
03769     textDisplay.debug("done\r\n");
03770 
03771     return outPtr;
03772 }
03773 
03774 bool scriptStream::createIntVariable(string nameInput) {
03775     if (findIntVariable(nameInput) == NULL) {
03776         globalVariables.push_back(new intVariable(nameInput, 0));
03777         return true;
03778     } else {
03779         return false;
03780     }
03781 }
03782 
03783 action* scriptStream::evaluateAssignmentForAction(const char* expression) {
03784 
03785     //action* tmpAction = new action(); //create a new action
03786     action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
03787     if (tmpAction == NULL) {
03788         textDisplay << "Error: no action memory slots available.\r\n";
03789         return NULL;
03790     }
03791     int stringInd;
03792     int stringInd2;
03793     int afterEqualLoc;
03794     int beforeEqualLoc;
03795     int lastCharLoc = strlen(expression)-1;
03796     int multiplierInt = 1;
03797     //string afterEqual;
03798     //string beforeEqual;
03799     //The expression might have up to three variables
03800     int* tmpVar;
03801     int* tmpVar2;
03802     int* tmpVar3;
03803 
03804     stringInd = findStringLoc(expression,"=",0,strlen(expression)-1); //location of = sign, if it exists
03805     if (stringInd == -1) {
03806         //Make sure there is an equal sign
03807         return NULL;
03808     }
03809 
03810     beforeEqualLoc = stringInd-1;
03811     afterEqualLoc = stringInd+1;
03812 
03813     //location of +/- sign (only one allowed)
03814     stringInd2 = findStringLoc(expression,"+",afterEqualLoc,strlen(expression)-1);
03815     if (stringInd2 == -1) {
03816         stringInd2 = findStringLoc(expression,"-",afterEqualLoc,strlen(expression)-1);
03817         multiplierInt = -1;
03818 
03819     }
03820 
03821     tmpVar = findIntVariable(expression,0,beforeEqualLoc); //returns pointer to the variable
03822     if (findStringLoc(expression,"portout[",0,beforeEqualLoc) != -1) {  //set the output of a digital port
03823         textDisplay.debug("Portout assignment\r\n");
03824         int pos1 = findStringLoc(expression,"portout[",0,beforeEqualLoc)+8;
03825         int pos2 = findStringLoc(expression,"]",pos1,beforeEqualLoc)-1;
03826         if (pos2 < pos1) {
03827             textDisplay << "Error: expected a ] character\r\n";
03828             return NULL;
03829         }
03830 
03831         int portnum = -1;
03832         if (isNum(expression,pos1,pos2)) {
03833             portnum = atoi(expression+pos1);
03834         }
03835         int* tmpVar = findIntVariable(expression, pos1,pos2); //returns pointer to the variable, if given
03836         int portVal = 0;
03837         if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
03838             if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
03839                 portVal = atoi(expression+afterEqualLoc);
03840                 if ((portVal == 0) || (portVal == 1)) {
03841                     //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
03842                     portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
03843                     if (tmpMessage == NULL) {
03844                         textDisplay << "Error: no memory slots available.\r\n";
03845                         tmpAction->release();
03846                         return NULL;
03847                     } else {
03848                         //tmpMessage->setMessage(portVector[portnum],1,portVal);
03849                         if (tmpVar == NULL) { //a constant port number was given
03850                             tmpMessage->setMessage(NULL,portnum,portVal,portVector);
03851                         } else {
03852                             tmpMessage->setMessage(tmpVar,0,portVal,portVector);
03853                         }
03854                     }
03855 
03856 
03857                     tmpAction->set(tmpMessage);
03858 
03859                 } else {
03860                     textDisplay << "Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n";
03861                     //delete tmpAction;
03862                     tmpAction->release();
03863                     return NULL;
03864                 }
03865             } else if (findStringLoc(expression,"flip",afterEqualLoc,lastCharLoc)!=-1) {
03866                 //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
03867                 portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
03868                 if (tmpMessage == NULL) {
03869                     textDisplay << "Error: no memory slots available.\r\n";
03870                     tmpAction->release();
03871                     return NULL;
03872                 } else {
03873                     //tmpMessage->setMessage(portVector[portnum],1,-1);
03874                     if (tmpVar == NULL) { //a constant port number was given
03875                         tmpMessage->setMessage(NULL,portnum,-1,portVector);
03876                     } else {
03877                         tmpMessage->setMessage(tmpVar,0,-1,portVector);
03878                     }
03879                 }
03880                 tmpAction->set(tmpMessage);
03881             } else {
03882                 textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
03883                 //delete tmpAction;
03884                 tmpAction->release();
03885                 return NULL;
03886             }
03887         } else {
03888             textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
03889             //delete tmpAction;
03890             tmpAction->release();
03891             return NULL;
03892         }
03893     } else if (findStringLoc(expression,"portin",0,stringInd)!=-1) {
03894         textDisplay << "Error: portins can not be set\r\n";
03895         //delete tmpAction;
03896         tmpAction->release();
03897         return NULL;
03898     } else if (tmpVar != NULL) {
03899         intOperation* tmpOp;
03900         intOperation* tmpOp2;
03901         if (isNum(expression,afterEqualLoc,lastCharLoc)) { //a simple numeric assign
03902             textDisplay.debug("Numeric assignment\r\n");
03903             //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
03904             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
03905             if (tmpOp == NULL) {
03906                 textDisplay << "Error: no memory slots available.\r\n";
03907                 tmpAction->release();
03908                 return NULL;
03909             } else {
03910                 tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc));
03911             }
03912             tmpAction->set(tmpOp);
03913 
03914         } else if ((stringInd2 == -1)&&(findStringLoc(expression,"random",afterEqualLoc,lastCharLoc)!=-1)) {
03915             //assign random number
03916             //no +/- detected, so its a simple assign
03917             textDisplay.debug("Random number assignment\r\n");
03918             int highVal = getRandomParam(expression,afterEqualLoc,lastCharLoc);
03919 
03920             if (highVal > 0) {
03921                 //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
03922                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
03923                 if (tmpOp == NULL) {
03924                     textDisplay << "Error: no memory slots available.\r\n";
03925                     tmpAction->release();
03926                     return NULL;
03927                 } else {
03928                     tmpOp->setRandOp(highVal, "=", tmpVar, false);
03929                 }
03930                 tmpAction->set(tmpOp);
03931 
03932             } else {
03933                 //delete tmpAction;
03934                 tmpAction->release();
03935                 return NULL;
03936             }
03937         } else if ((stringInd2 == -1)&&(findStringLoc(expression,"clock()",afterEqualLoc,lastCharLoc)!=-1)) {
03938             //assign clock value
03939             //no +/- detected, so its a simple assign
03940             textDisplay.debug("Clock assignment to variable\r\n");
03941             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
03942             if (tmpOp == NULL) {
03943                 textDisplay << "Error: no memory slots available.\r\n";
03944                 tmpAction->release();
03945                 return NULL;
03946             } else {
03947                 tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
03948             }
03949             tmpAction->set(tmpOp);
03950 
03951         } else if (stringInd2 != -1) { //a +/- operation is there
03952             textDisplay.debug("equation assignment\r\n");
03953             //string multiplier("+");
03954             char multiplier[3];
03955             if (multiplierInt==1) {
03956                 strcpy(multiplier,"+");
03957             } else {
03958                 strcpy(multiplier,"-");
03959             }
03960 
03961             /*
03962             if (afterEqual[stringInd2] == '-') {
03963                 multiplier = "-";
03964                 multiplierInt = -1;
03965             }*/
03966             tmpVar2 = findIntVariable(expression,afterEqualLoc,stringInd2-1); //before the +/- sign
03967             tmpVar3 = findIntVariable(expression,stringInd2+1,lastCharLoc); //after the +/- sign
03968 
03969             if ((tmpVar2 != NULL) && isNum(expression,stringInd2+1,lastCharLoc)) { //variable +/- number
03970                 if (tmpVar2 == tmpVar) {
03971                     //final sign is += or -=
03972                     if (multiplierInt==1) {
03973                         strcpy(multiplier,"+=");
03974                     } else {
03975                         strcpy(multiplier,"-=");
03976                     }
03977 
03978                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
03979                     if (tmpOp == NULL) {
03980                         textDisplay << "Error: no memory slots available.\r\n";
03981                         tmpAction->release();
03982                         return NULL;
03983                     } else {
03984                         tmpOp->set(tmpVar, multiplier, atoi(expression+stringInd2+1));
03985                     }
03986                     tmpAction->set(tmpOp);
03987 
03988                 } else {
03989 
03990                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
03991                     if (tmpOp2 == NULL) {
03992                         textDisplay << "Error: no memory slots available.\r\n";
03993                         tmpAction->release();
03994                         return NULL;
03995                     } else {
03996 
03997                         tmpOp2->set(tmpVar2,multiplier, atoi(expression+stringInd2+1));
03998                         //tmpOp->set(tmpVar, tmpOp2);
03999                     }
04000 
04001                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04002                     if (tmpOp == NULL) {
04003                         textDisplay << "Error: no memory slots available.\r\n";
04004                         tmpOp2->release();
04005                         tmpAction->release();
04006                         return NULL;
04007                     } else {
04008                         tmpOp->set(tmpVar, tmpOp2);
04009                     }
04010 
04011                     tmpAction->set(tmpOp);
04012 
04013                 }
04014 
04015             } else if ((tmpVar3 != NULL) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- variable
04016                 if (tmpVar3 == tmpVar) {
04017                     //final sign is += or -=
04018                     if (multiplierInt==1) {
04019                         strcpy(multiplier,"+=");
04020                     } else {
04021                         strcpy(multiplier,"-=");
04022                     }
04023 
04024                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04025                     if (tmpOp == NULL) {
04026                         textDisplay << "Error: no memory slots available.\r\n";
04027                         tmpAction->release();
04028                         return NULL;
04029                     } else {
04030                         tmpOp->set(tmpVar, multiplier, atoi(expression+afterEqualLoc));
04031                     }
04032                     tmpAction->set(tmpOp);
04033 
04034                 } else {
04035 
04036                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04037                     if (tmpOp2 == NULL) {
04038                         textDisplay << "Error: no memory slots available.\r\n";
04039                         tmpAction->release();
04040                         return NULL;
04041                     } else {
04042                         tmpOp2->set(tmpVar3, multiplier, atoi(expression+afterEqualLoc));
04043                     }
04044                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04045 
04046                     if (tmpOp == NULL) {
04047                         textDisplay << "Error: no memory slots available.\r\n";
04048                         tmpOp2->release();
04049                         tmpAction->release();
04050                         return NULL;
04051                     } else {
04052                         tmpOp->set(tmpVar, tmpOp2);
04053                     }
04054                     tmpAction->set(tmpOp);
04055 
04056                 }
04057 
04058             } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
04059 
04060                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04061                 if (tmpOp2 == NULL) {
04062                     textDisplay << "Error: no memory slots available.\r\n";
04063                     tmpAction->release();
04064                     return NULL;
04065                 } else {
04066                     tmpOp2->set(tmpVar2, multiplier, tmpVar3);
04067                 }
04068                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04069 
04070                 if (tmpOp == NULL) {
04071                     textDisplay << "Error: no memory slots available.\r\n";
04072                     tmpOp2->release();
04073                     tmpAction->release();
04074                     return NULL;
04075                 } else {
04076 
04077                     tmpOp->set(tmpVar, tmpOp2);
04078                 }
04079                 tmpAction->set(tmpOp);
04080 
04081             } else if ( isNum(expression,stringInd2+1,lastCharLoc) && isNum(expression,afterEqualLoc,stringInd2-1) ) { //number +/- number
04082                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04083                 if (tmpOp == NULL) {
04084                     textDisplay << "Error: no memory slots available.\r\n";
04085                     tmpAction->release();
04086                     return NULL;
04087                 } else {
04088                     tmpOp->set(tmpVar, "=", atoi(expression+afterEqualLoc) + (multiplierInt * atoi(expression+stringInd2+1)) );
04089                 }
04090                 tmpAction->set(tmpOp);
04091 
04092             } else if ((findStringLoc(expression,"random", afterEqualLoc,stringInd2-1)!=-1)  && isNum(expression,stringInd2+1,lastCharLoc)) { //random +/- number
04093                 int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
04094 
04095                 if (highVal > 0) {
04096 
04097 
04098                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04099                     if (tmpOp2 == NULL) {
04100                         textDisplay << "Error: no memory slots available.\r\n";
04101                         tmpAction->release();
04102                         return NULL;
04103                     } else {
04104                         tmpOp2->setRandOp(highVal, multiplier, atoi(expression+stringInd2+1),false);
04105                     }
04106                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04107 
04108                     if (tmpOp == NULL) {
04109                         textDisplay << "Error: no memory slots available.\r\n";
04110                         tmpOp2->release();
04111                         tmpAction->release();
04112                         return NULL;
04113                     } else {
04114                         tmpOp->set(tmpVar, tmpOp2);
04115                     }
04116                     tmpAction->set(tmpOp);
04117 
04118                 } else {
04119                     //delete tmpAction;
04120                     tmpAction->release();
04121                     return NULL;
04122                 }
04123             } else if ((findStringLoc(expression,"random",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //random +/- variable
04124                 int highVal = getRandomParam(expression,afterEqualLoc,stringInd2-1);
04125 
04126                 if (highVal > 0) {
04127 
04128 
04129                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04130                     if (tmpOp2 == NULL) {
04131                         textDisplay << "Error: no memory slots available.\r\n";
04132                         tmpAction->release();
04133                         return NULL;
04134                     } else {
04135                         tmpOp2->setRandOp(highVal, multiplier, tmpVar3, false);
04136                     }
04137                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04138                     if (tmpOp == NULL) {
04139                         textDisplay << "Error: no memory slots available.\r\n";
04140                         tmpOp2->release();
04141                         tmpAction->release();
04142                         return NULL;
04143                     } else {
04144                         tmpOp->set(tmpVar, tmpOp2);
04145                     }
04146                     tmpAction->set(tmpOp);
04147 
04148                 } else {
04149                     //delete tmpAction;
04150                     tmpAction->release();
04151                     return NULL;
04152                 }
04153 
04154 
04155             } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,stringInd2-1)) { //number +/- random
04156                 int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
04157 
04158                 if (highVal > 0) {
04159 
04160 
04161                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04162                     if (tmpOp2 == NULL) {
04163                         textDisplay << "Error: no memory slots available.\r\n";
04164                         tmpAction->release();
04165                         return NULL;
04166                     } else {
04167 
04168                         tmpOp2->setRandOp(highVal, multiplier, atoi(expression+afterEqualLoc),true); //the "true" signifies that the rand value came last
04169                     }
04170                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04171                     if (tmpOp == NULL) {
04172                         textDisplay << "Error: no memory slots available.\r\n";
04173                         tmpOp2->release();
04174                         tmpAction->release();
04175                         return NULL;
04176                     } else {
04177                         tmpOp->set(tmpVar, tmpOp2);
04178                     }
04179                     tmpAction->set(tmpOp);
04180 
04181                 } else {
04182                     //delete tmpAction;
04183                     tmpAction->release();
04184                     return NULL;
04185                 }
04186             } else if ((findStringLoc(expression,"random",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- random
04187                 int highVal = getRandomParam(expression,stringInd2+1,lastCharLoc);
04188 
04189                 if (highVal > 0) {
04190 
04191 
04192                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04193                     if (tmpOp2 == NULL) {
04194                         textDisplay << "Error: no memory slots available.\r\n";
04195                         tmpAction->release();
04196                         return NULL;
04197                     } else {
04198 
04199                         tmpOp2->setRandOp(highVal, multiplier, tmpVar2, true); //the "true" signifies that the rand value came last
04200                     }
04201                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04202                     if (tmpOp == NULL) {
04203                         textDisplay << "Error: no memory slots available.\r\n";
04204                         tmpOp2->release();
04205                         tmpAction->release();
04206                         return NULL;
04207                     } else {
04208                         tmpOp->set(tmpVar, tmpOp2);
04209                     }
04210                     tmpAction->set(tmpOp);
04211 
04212                 } else {
04213                     //delete tmpAction;
04214                     tmpAction->release();
04215                     return NULL;
04216                 }
04217             }
04218 
04219 
04220             else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && isNum(expression,stringInd2+1,lastCharLoc)) { //clock() +/- number
04221 
04222                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04223                 if (tmpOp2 == NULL) {
04224                     textDisplay << "Error: no memory slots available.\r\n";
04225                     tmpAction->release();
04226                     return NULL;
04227                 } else {
04228                     tmpOp2->setClockOp(multiplier, atoi(expression+stringInd2+1),false);
04229                 }
04230                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04231 
04232                 if (tmpOp == NULL) {
04233                     textDisplay << "Error: no memory slots available.\r\n";
04234                     tmpOp2->release();
04235                     tmpAction->release();
04236                     return NULL;
04237                 } else {
04238                     tmpOp->set(tmpVar, tmpOp2);
04239                 }
04240                 tmpAction->set(tmpOp);
04241 
04242 
04243             } else if ((findStringLoc(expression,"clock()",afterEqualLoc,stringInd2-1)!=-1) && (tmpVar3 != NULL)) { //clock() +/- variable
04244 
04245 
04246 
04247                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04248                 if (tmpOp2 == NULL) {
04249                     textDisplay << "Error: no memory slots available.\r\n";
04250                     tmpAction->release();
04251                     return NULL;
04252                 } else {
04253                     tmpOp2->setClockOp(multiplier, tmpVar3, false);
04254                 }
04255                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04256                 if (tmpOp == NULL) {
04257                     textDisplay << "Error: no memory slots available.\r\n";
04258                     tmpOp2->release();
04259                     tmpAction->release();
04260                     return NULL;
04261                 } else {
04262                     tmpOp->set(tmpVar, tmpOp2);
04263                 }
04264                 tmpAction->set(tmpOp);
04265 
04266             } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && isNum(expression,afterEqualLoc,lastCharLoc)) { //number +/- clock()
04267 
04268                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04269                 if (tmpOp2 == NULL) {
04270                     textDisplay << "Error: no memory slots available.\r\n";
04271                     tmpAction->release();
04272                     return NULL;
04273                 } else {
04274 
04275                     tmpOp2->setClockOp(multiplier, atoi(expression+afterEqualLoc), true); //the "true" signifies that clock() came last
04276                 }
04277                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04278                 if (tmpOp == NULL) {
04279                     textDisplay << "Error: no memory slots available.\r\n";
04280                     tmpOp2->release();
04281                     tmpAction->release();
04282                     return NULL;
04283                 } else {
04284                     tmpOp->set(tmpVar, tmpOp2);
04285                 }
04286                 tmpAction->set(tmpOp);
04287 
04288 
04289             } else if ((findStringLoc(expression,"clock()",stringInd2+1,lastCharLoc)!=-1) && (tmpVar2 != NULL)) { //variable +/- clock()
04290 
04291 
04292                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04293                 if (tmpOp2 == NULL) {
04294                     textDisplay << "Error: no memory slots available.\r\n";
04295                     tmpAction->release();
04296                     return NULL;
04297                 } else {
04298 
04299                     tmpOp2->setClockOp(multiplier, tmpVar2, true); //the "true" signifies that clock() came last
04300                 }
04301                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04302                 if (tmpOp == NULL) {
04303                     textDisplay << "Error: no memory slots available.\r\n";
04304                     tmpOp2->release();
04305                     tmpAction->release();
04306                     return NULL;
04307                 } else {
04308                     tmpOp->set(tmpVar, tmpOp2);
04309                 }
04310                 tmpAction->set(tmpOp);
04311 
04312 
04313             }
04314 
04315             else {
04316                 textDisplay << "Expression not understood: " << expression << "\r\n";
04317                 //delete tmpAction;
04318                 tmpAction->release();
04319                 return NULL;
04320             }
04321 
04322         } else if (findIntVariable(expression,afterEqualLoc,lastCharLoc) != NULL) { //assign value of another variable
04323             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04324             if (tmpOp == NULL) {
04325                 textDisplay << "Error: no memory slots available.\r\n";
04326                 tmpAction->release();
04327                 return NULL;
04328             } else {
04329                 tmpOp->set(tmpVar, "=", findIntVariable(expression,afterEqualLoc,lastCharLoc));
04330             }
04331             tmpAction->set(tmpOp);
04332 
04333         } else {
04334             textDisplay << "Variable not found: " << expression+afterEqualLoc << "\r\n";
04335             tmpAction->release();
04336             return NULL;
04337         }
04338 
04339     } else {
04340         textDisplay << "Variable not found\r\n";
04341         tmpAction->release();
04342         return NULL;
04343     }
04344     textDisplay.debug("Assignment successful\r\n");
04345     return tmpAction;
04346 }
04347 
04348 action* scriptStream::evaluateAssignmentForAction(string expression) {
04349 
04350     //action* tmpAction = new action(); //create a new action
04351     action* tmpAction = findFirstUnUsed(actionBlock, NUMACTIONS);
04352     if (tmpAction == NULL) {
04353         textDisplay << "Error: no action memory slots available.\r\n";
04354         return NULL;
04355     }
04356     std::size_t stringInd;
04357     std::size_t stringInd2;
04358     string afterEqual;
04359     string beforeEqual;
04360     //The expression might have up to three variables
04361     int* tmpVar;
04362     int* tmpVar2;
04363     int* tmpVar3;
04364     stringInd = expression.find_first_of("="); //location of = sign, if it exists
04365     beforeEqual = expression.substr(0,stringInd); // the string after the = sign
04366     afterEqual = expression.substr(stringInd+1,std::string::npos); // the string after the = sign
04367     stringInd2 = afterEqual.find_first_of("+-"); //location of +/- sign (only one allowed)
04368     tmpVar = findIntVariable(expression.substr(0,stringInd)); //returns pointer to the variable
04369 
04370     if (beforeEqual.find("portout[") != std::string::npos) { //set the output of a digital port
04371         textDisplay.debug("Portout assignment\r\n");
04372         int pos1 = beforeEqual.find("portout[")+8;
04373         int pos2 = beforeEqual.find_first_of("]",pos1);
04374         int portnum = atoi(beforeEqual.substr(pos1,pos2-pos1).data());
04375         int* tmpVar = findIntVariable(beforeEqual.substr(pos1,pos2-pos1)); //returns pointer to the variable, if given
04376         int portVal = 0;
04377         if ((tmpVar != NULL)||((portnum > 0) && (portnum <= numPorts))) {
04378             if (isNumber(afterEqual)) { //a simple numeric assign
04379                 portVal = atoi(afterEqual.data());
04380                 if ((portVal == 0) || (portVal == 1)) {
04381                     //portMessage* tmpMessage = new portMessage(portVector[portnum],1,portVal);
04382                     portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
04383                     if (tmpMessage == NULL) {
04384                         textDisplay << "Error: no memory slots available.\r\n";
04385                         tmpAction->release();
04386                         return NULL;
04387                     } else {
04388                         //tmpMessage->setMessage(portVector[portnum],1,portVal);
04389                         if (tmpVar == NULL) { //a constant port number was given
04390                             tmpMessage->setMessage(NULL,portnum,portVal,portVector);
04391                         } else {
04392                             tmpMessage->setMessage(tmpVar,0,portVal,portVector);
04393                         }
04394                     }
04395 
04396 
04397                     tmpAction->set(tmpMessage);
04398 
04399                 } else {
04400                     textDisplay << "Error: portouts can only be directly assigned a 1, 0 or 'flip'\r\n";
04401                     //delete tmpAction;
04402                     tmpAction->release();
04403                     return NULL;
04404                 }
04405             } else if (afterEqual.compare("flip") == 0) {
04406                 //portMessage* tmpMessage = new portMessage(portVector[portnum],1,-1);
04407                 portMessage* tmpMessage = findFirstUnUsed(portMessageBlock, NUMPORTMESSAGES);
04408                 if (tmpMessage == NULL) {
04409                     textDisplay << "Error: no memory slots available.\r\n";
04410                     tmpAction->release();
04411                     return NULL;
04412                 } else {
04413                     //tmpMessage->setMessage(portVector[portnum],1,-1);
04414                     if (tmpVar == NULL) { //a constant port number was given
04415                         tmpMessage->setMessage(NULL,portnum,-1,portVector);
04416                     } else {
04417                         tmpMessage->setMessage(tmpVar,0,-1,portVector);
04418                     }
04419                 }
04420                 tmpAction->set(tmpMessage);
04421             } else {
04422                 textDisplay << "Error: portouts can only be directly assigned a 1, 0, or 'flip'\r\n";
04423                 //delete tmpAction;
04424                 tmpAction->release();
04425                 return NULL;
04426             }
04427         } else {
04428             textDisplay << "Port number not found (must be between 1 and " << numPorts << " or an existing variable)\r\n";
04429             //delete tmpAction;
04430             tmpAction->release();
04431             return NULL;
04432         }
04433     } else if (beforeEqual.find("portin") != std::string::npos) {
04434         textDisplay << "Error: portins can not be set\r\n";
04435         //delete tmpAction;
04436         tmpAction->release();
04437         return NULL;
04438     } else if (tmpVar != NULL) {
04439         intOperation* tmpOp;
04440         intOperation* tmpOp2;
04441         if (isNumber(afterEqual)) { //a simple numeric assign
04442             textDisplay.debug("Numeric assignment\r\n");
04443             //tmpOp = new intOperation(tmpVar, "=", atoi(afterEqual.data()));
04444             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04445             if (tmpOp == NULL) {
04446                 textDisplay << "Error: no memory slots available.\r\n";
04447                 tmpAction->release();
04448                 return NULL;
04449             } else {
04450                 tmpOp->set(tmpVar, "=", atoi(afterEqual.data()));
04451             }
04452             tmpAction->set(tmpOp);
04453 
04454         } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("random") != std::string::npos)) {
04455             //assign random number
04456             //no +/- detected, so its a simple assign
04457             textDisplay.debug("Random number assignment\r\n");
04458             int highVal = getRandomParam(afterEqual);
04459 
04460             if (highVal > 0) {
04461                 //tmpOp = new intOperation(highVal, "=", tmpVar); //for random assignment, we reverse the input order (because of overloading uniqueness)
04462                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04463                 if (tmpOp == NULL) {
04464                     textDisplay << "Error: no memory slots available.\r\n";
04465                     tmpAction->release();
04466                     return NULL;
04467                 } else {
04468                     tmpOp->setRandOp(highVal, "=", tmpVar, false);
04469                 }
04470                 tmpAction->set(tmpOp);
04471 
04472             } else {
04473                 //delete tmpAction;
04474                 tmpAction->release();
04475                 return NULL;
04476             }
04477         } else if ((stringInd2 == std::string::npos)&&(afterEqual.find("clock()") != std::string::npos)) {
04478             //assign clock value
04479             //no +/- detected, so its a simple assign
04480             textDisplay.debug("Clock assignment to variable\r\n");
04481             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04482             if (tmpOp == NULL) {
04483                 textDisplay << "Error: no memory slots available.\r\n";
04484                 tmpAction->release();
04485                 return NULL;
04486             } else {
04487                 tmpOp->setClockOp(tmpVar); //assigns the current clock value to tmpVar
04488             }
04489             tmpAction->set(tmpOp);
04490 
04491         } else if (stringInd2 != std::string::npos) { //a +/- operation is there
04492             textDisplay.debug("equation assignment\r\n");
04493             string multiplier("+");
04494             int multiplierInt = 1;
04495             if (afterEqual[stringInd2] == '-') {
04496                 multiplier = "-";
04497                 multiplierInt = -1;
04498             }
04499             tmpVar2 = findIntVariable(afterEqual.substr(0,stringInd2)); //before the +/- sign
04500             tmpVar3 = findIntVariable(afterEqual.substr(stringInd2+1,std::string::npos)); //after the +/- sign
04501 
04502             if ((tmpVar2 != NULL) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //variable +/- number
04503                 if (tmpVar2 == tmpVar) {
04504                     multiplier.append("="); //final sign is += or -=
04505                     //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
04506                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04507                     if (tmpOp == NULL) {
04508                         textDisplay << "Error: no memory slots available.\r\n";
04509                         tmpAction->release();
04510                         return NULL;
04511                     } else {
04512                         tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
04513                     }
04514                     tmpAction->set(tmpOp);
04515 
04516                 } else {
04517 
04518                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04519                     if (tmpOp2 == NULL) {
04520                         textDisplay << "Error: no memory slots available.\r\n";
04521                         tmpAction->release();
04522                         return NULL;
04523                     } else {
04524 
04525                         tmpOp2->set(tmpVar2,multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()));
04526                         //tmpOp->set(tmpVar, tmpOp2);
04527                     }
04528 
04529                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04530                     if (tmpOp == NULL) {
04531                         textDisplay << "Error: no memory slots available.\r\n";
04532                         tmpOp2->release();
04533                         tmpAction->release();
04534                         return NULL;
04535                     } else {
04536                         tmpOp->set(tmpVar, tmpOp2);
04537                     }
04538 
04539                     tmpAction->set(tmpOp);
04540 
04541                 }
04542 
04543             } else if ((tmpVar3 != NULL) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- variable
04544                 if (tmpVar3 == tmpVar) {
04545                     multiplier.append("="); //makes "+=" or "-="
04546                     //tmpOp = new intOperation(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
04547                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04548                     if (tmpOp == NULL) {
04549                         textDisplay << "Error: no memory slots available.\r\n";
04550                         tmpAction->release();
04551                         return NULL;
04552                     } else {
04553                         tmpOp->set(tmpVar, multiplier.data(), atoi(afterEqual.substr(0,stringInd2).data()));
04554                     }
04555                     tmpAction->set(tmpOp);
04556 
04557                 } else {
04558 
04559                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04560                     if (tmpOp2 == NULL) {
04561                         textDisplay << "Error: no memory slots available.\r\n";
04562                         tmpAction->release();
04563                         return NULL;
04564                     } else {
04565                         tmpOp2->set(tmpVar3, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()));
04566                     }
04567                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04568 
04569                     if (tmpOp == NULL) {
04570                         textDisplay << "Error: no memory slots available.\r\n";
04571                         tmpOp2->release();
04572                         tmpAction->release();
04573                         return NULL;
04574                     } else {
04575                         tmpOp->set(tmpVar, tmpOp2);
04576                     }
04577                     tmpAction->set(tmpOp);
04578 
04579                 }
04580 
04581             } else if ((tmpVar2 != NULL) && (tmpVar3 != NULL)) { //variable +/- variable
04582 
04583                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04584                 if (tmpOp2 == NULL) {
04585                     textDisplay << "Error: no memory slots available.\r\n";
04586                     tmpAction->release();
04587                     return NULL;
04588                 } else {
04589                     tmpOp2->set(tmpVar2, multiplier.data(), tmpVar3);
04590                 }
04591                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04592 
04593                 if (tmpOp == NULL) {
04594                     textDisplay << "Error: no memory slots available.\r\n";
04595                     tmpOp2->release();
04596                     tmpAction->release();
04597                     return NULL;
04598                 } else {
04599 
04600                     tmpOp->set(tmpVar, tmpOp2);
04601                 }
04602                 tmpAction->set(tmpOp);
04603 
04604             } else if ( isNumber(afterEqual.substr(stringInd2+1,std::string::npos)) && isNumber(afterEqual.substr(0,stringInd2)) ) { //number +/- number
04605                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04606                 if (tmpOp == NULL) {
04607                     textDisplay << "Error: no memory slots available.\r\n";
04608                     tmpAction->release();
04609                     return NULL;
04610                 } else {
04611                     tmpOp->set(tmpVar, "=", atoi(afterEqual.substr(0,stringInd2).data()) + (multiplierInt * atoi(afterEqual.substr(stringInd2+1,std::string::npos).data())));
04612                 }
04613                 tmpAction->set(tmpOp);
04614 
04615             } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //random +/- number
04616                 int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
04617 
04618                 if (highVal > 0) {
04619 
04620 
04621                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04622                     if (tmpOp2 == NULL) {
04623                         textDisplay << "Error: no memory slots available.\r\n";
04624                         tmpAction->release();
04625                         return NULL;
04626                     } else {
04627                         tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
04628                     }
04629                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04630 
04631                     if (tmpOp == NULL) {
04632                         textDisplay << "Error: no memory slots available.\r\n";
04633                         tmpOp2->release();
04634                         tmpAction->release();
04635                         return NULL;
04636                     } else {
04637                         tmpOp->set(tmpVar, tmpOp2);
04638                     }
04639                     tmpAction->set(tmpOp);
04640 
04641                 } else {
04642                     //delete tmpAction;
04643                     tmpAction->release();
04644                     return NULL;
04645                 }
04646             } else if ((afterEqual.substr(0,stringInd2).find("random") != std::string::npos) && (tmpVar3 != NULL)) { //random +/- variable
04647                 int highVal = getRandomParam(afterEqual.substr(0,stringInd2));
04648 
04649                 if (highVal > 0) {
04650 
04651 
04652                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04653                     if (tmpOp2 == NULL) {
04654                         textDisplay << "Error: no memory slots available.\r\n";
04655                         tmpAction->release();
04656                         return NULL;
04657                     } else {
04658                         tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar3, false);
04659                     }
04660                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04661                     if (tmpOp == NULL) {
04662                         textDisplay << "Error: no memory slots available.\r\n";
04663                         tmpOp2->release();
04664                         tmpAction->release();
04665                         return NULL;
04666                     } else {
04667                         tmpOp->set(tmpVar, tmpOp2);
04668                     }
04669                     tmpAction->set(tmpOp);
04670 
04671                 } else {
04672                     //delete tmpAction;
04673                     tmpAction->release();
04674                     return NULL;
04675                 }
04676 
04677 
04678             } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- random
04679                 int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
04680 
04681                 if (highVal > 0) {
04682 
04683 
04684                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04685                     if (tmpOp2 == NULL) {
04686                         textDisplay << "Error: no memory slots available.\r\n";
04687                         tmpAction->release();
04688                         return NULL;
04689                     } else {
04690 
04691                         tmpOp2->setRandOp(highVal, multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that the rand value came last
04692                     }
04693                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04694                     if (tmpOp == NULL) {
04695                         textDisplay << "Error: no memory slots available.\r\n";
04696                         tmpOp2->release();
04697                         tmpAction->release();
04698                         return NULL;
04699                     } else {
04700                         tmpOp->set(tmpVar, tmpOp2);
04701                     }
04702                     tmpAction->set(tmpOp);
04703 
04704                 } else {
04705                     //delete tmpAction;
04706                     tmpAction->release();
04707                     return NULL;
04708                 }
04709             } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("random") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- random
04710                 int highVal = getRandomParam(afterEqual.substr(stringInd2+1,std::string::npos));
04711 
04712                 if (highVal > 0) {
04713 
04714 
04715                     tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04716                     if (tmpOp2 == NULL) {
04717                         textDisplay << "Error: no memory slots available.\r\n";
04718                         tmpAction->release();
04719                         return NULL;
04720                     } else {
04721 
04722                         tmpOp2->setRandOp(highVal, multiplier.data(), tmpVar2, true); //the "true" signifies that the rand value came last
04723                     }
04724                     tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04725                     if (tmpOp == NULL) {
04726                         textDisplay << "Error: no memory slots available.\r\n";
04727                         tmpOp2->release();
04728                         tmpAction->release();
04729                         return NULL;
04730                     } else {
04731                         tmpOp->set(tmpVar, tmpOp2);
04732                     }
04733                     tmpAction->set(tmpOp);
04734 
04735                 } else {
04736                     //delete tmpAction;
04737                     tmpAction->release();
04738                     return NULL;
04739                 }
04740             }
04741 
04742 
04743 
04744 
04745 
04746             else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(stringInd2+1,std::string::npos))) { //clock() +/- number
04747 
04748 
04749 
04750                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04751                 if (tmpOp2 == NULL) {
04752                     textDisplay << "Error: no memory slots available.\r\n";
04753                     tmpAction->release();
04754                     return NULL;
04755                 } else {
04756                     tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(stringInd2+1,std::string::npos).data()),false);
04757                 }
04758                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04759 
04760                 if (tmpOp == NULL) {
04761                     textDisplay << "Error: no memory slots available.\r\n";
04762                     tmpOp2->release();
04763                     tmpAction->release();
04764                     return NULL;
04765                 } else {
04766                     tmpOp->set(tmpVar, tmpOp2);
04767                 }
04768                 tmpAction->set(tmpOp);
04769 
04770 
04771             } else if ((afterEqual.substr(0,stringInd2).find("clock()") != std::string::npos) && (tmpVar3 != NULL)) { //clock() +/- variable
04772 
04773 
04774 
04775                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04776                 if (tmpOp2 == NULL) {
04777                     textDisplay << "Error: no memory slots available.\r\n";
04778                     tmpAction->release();
04779                     return NULL;
04780                 } else {
04781                     tmpOp2->setClockOp(multiplier.data(), tmpVar3, false);
04782                 }
04783                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04784                 if (tmpOp == NULL) {
04785                     textDisplay << "Error: no memory slots available.\r\n";
04786                     tmpOp2->release();
04787                     tmpAction->release();
04788                     return NULL;
04789                 } else {
04790                     tmpOp->set(tmpVar, tmpOp2);
04791                 }
04792                 tmpAction->set(tmpOp);
04793 
04794 
04795 
04796 
04797             } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && isNumber(afterEqual.substr(0,stringInd2))) { //number +/- clock()
04798 
04799 
04800 
04801                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04802                 if (tmpOp2 == NULL) {
04803                     textDisplay << "Error: no memory slots available.\r\n";
04804                     tmpAction->release();
04805                     return NULL;
04806                 } else {
04807 
04808                     tmpOp2->setClockOp(multiplier.data(), atoi(afterEqual.substr(0, stringInd2).data()),true); //the "true" signifies that clock() came last
04809                 }
04810                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04811                 if (tmpOp == NULL) {
04812                     textDisplay << "Error: no memory slots available.\r\n";
04813                     tmpOp2->release();
04814                     tmpAction->release();
04815                     return NULL;
04816                 } else {
04817                     tmpOp->set(tmpVar, tmpOp2);
04818                 }
04819                 tmpAction->set(tmpOp);
04820 
04821 
04822             } else if ((afterEqual.substr(stringInd2+1,std::string::npos).find("clock()") != std::string::npos) && (tmpVar2 != NULL)) { //variable +/- clock()
04823 
04824 
04825                 tmpOp2 = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04826                 if (tmpOp2 == NULL) {
04827                     textDisplay << "Error: no memory slots available.\r\n";
04828                     tmpAction->release();
04829                     return NULL;
04830                 } else {
04831 
04832                     tmpOp2->setClockOp(multiplier.data(), tmpVar2, true); //the "true" signifies that clock() came last
04833                 }
04834                 tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04835                 if (tmpOp == NULL) {
04836                     textDisplay << "Error: no memory slots available.\r\n";
04837                     tmpOp2->release();
04838                     tmpAction->release();
04839                     return NULL;
04840                 } else {
04841                     tmpOp->set(tmpVar, tmpOp2);
04842                 }
04843                 tmpAction->set(tmpOp);
04844 
04845 
04846             }
04847 
04848             else {
04849                 textDisplay << "Expression not understood: " << afterEqual << "\r\n";
04850                 //delete tmpAction;
04851                 tmpAction->release();
04852                 return NULL;
04853             }
04854 
04855         } else if (findIntVariable(afterEqual) != NULL) { //assign value of another variable
04856             //tmpOp = new intOperation(tmpVar, "=", findIntVariable(afterEqual));
04857             tmpOp = findFirstUnUsed(intOperationBlock, NUMINTOPERATIONS);
04858             if (tmpOp == NULL) {
04859                 textDisplay << "Error: no memory slots available.\r\n";
04860                 tmpAction->release();
04861                 return NULL;
04862             } else {
04863                 tmpOp->set(tmpVar, "=", findIntVariable(afterEqual));
04864             }
04865             tmpAction->set(tmpOp);
04866 
04867         } else {
04868             textDisplay << "Variable not found: " << afterEqual << "\r\n";
04869             //delete tmpAction;
04870             tmpAction->release();
04871             return NULL;
04872         }
04873 
04874     } else {
04875         textDisplay << "Variable not found\r\n";
04876         //delete tmpAction;
04877         tmpAction->release();
04878         return NULL;
04879     }
04880     textDisplay.debug("Assignment successful\r\n");
04881     return tmpAction;
04882 }
04883 
04884 /*
04885 bool scriptStream::isOutsideParenth(string& expression,std::size_t foundItem) {
04886 
04887     int pDepth = 0;  // How many nested parentheses
04888 
04889     if (foundItem < expression.length()) {
04890         for (int i = 0; i <= foundItem; i++) {
04891             if (expression[i] == '(') {
04892                 pDepth++;
04893             } else if (expression[i] == ')') {
04894                 pDepth--;
04895             }
04896         }
04897         if (pDepth<=0) {
04898 
04899             return true;
04900         } else {
04901 
04902             return false;
04903         }
04904     } else {
04905         return true;
04906     }
04907 
04908 }
04909 
04910 std::size_t scriptStream::findFirstOrOutsideParenth(string& expression) {
04911 
04912     std::size_t foundItem = expression.find("||");
04913     while (foundItem != std::string::npos) {
04914         if (isOutsideParenth(expression,foundItem)) {
04915             break;
04916         }
04917         foundItem = expression.find("||",foundItem+1);
04918     }
04919     return foundItem;
04920 }
04921 
04922 std::size_t scriptStream::findFirstAndOutsideParenth(string& expression) {
04923 
04924     std::size_t foundItem = expression.find("&&");
04925     while (foundItem != std::string::npos) {
04926         if (isOutsideParenth(expression,foundItem)){
04927             break;
04928         }
04929         foundItem = expression.find("&&",foundItem+1);
04930     }
04931     return foundItem;
04932 }
04933 
04934 condition* scriptStream::parseConditions(string& expression) {
04935     //This function is used to parse a condition string
04936     //such as (x < y && x != z) || (y == 2)
04937     //This function first identifies the root node of the logic tree
04938     //based on operator precedence ( () > && > || ), and then recursively calls itself
04939     //to find the nodes of the branches. The basic building blocks of
04940     //the final condition object are arithmatic comparitors (a > b) and
04941     //other condition objects.
04942 
04943 
04944 
04945     condition* newCondition = NULL;
04946     bool singleCondition = false; //no compound conditions
04947     string afterComparator;
04948     string beforeComparator;
04949 
04950     std::size_t found;
04951 
04952     //To make a parse tree, we start by looking for operators with the lowest precendence
04953     //so we look for OR conditions first
04954     char currentOperator = OR_CONDITION;
04955 
04956     found = findFirstOrOutsideParenth(expression);
04957     if (found==std::string::npos) { //no or conditions outside parentheses found, so we look for AND conditions
04958         currentOperator = AND_CONDITION;
04959 
04960         found = findFirstAndOutsideParenth(expression);
04961     }
04962     if (found==std::string::npos) { //no or/and conditions outside parentheses found
04963         //if the expression is encapsulated in parentheses, remove the parentheses
04964         bool removedParenth = false;
04965         if ((expression[0] == '(') && (expression[expression.length()-1] == ')')) {
04966 
04967             expression = expression.substr(1,expression.length()-2);
04968             removedParenth = true;
04969         }
04970         if (removedParenth) { //we removed parentheses, so try again
04971             textDisplay.debug("Condition: parenth removed\r\n");
04972             return parseConditions(expression);
04973         } else {
04974             singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
04975         }
04976     }
04977 
04978     if (singleCondition) { //no compound conditions found
04979         textDisplay.debug("Single condition: ");
04980         std::size_t equalStringInd;
04981         std::size_t greaterOrEqualStringInd;
04982         std::size_t lessThanOrEqualStringInd;
04983         std::size_t notEqualStringInd;
04984         std::size_t greaterThanStringInd;
04985         std::size_t lessThanStringInd;
04986         std::size_t generalCompareStringInd;
04987 
04988 
04989         string tmpCondition = expression;
04990         string compareString;
04991         //The expression might have up to three variables
04992         int* tmpVar;
04993         int* tmpVar2;
04994         int* tmpVar3;
04995 
04996         int offset = 0;
04997         equalStringInd = tmpCondition.find("=="); //location of comparator
04998         greaterOrEqualStringInd = tmpCondition.find(">="); //location of comparator
04999         lessThanOrEqualStringInd = tmpCondition.find("<="); //location of comparator
05000         notEqualStringInd = tmpCondition.find("!="); //location of comparator
05001         greaterThanStringInd = tmpCondition.find_first_of(">"); //location of comparator
05002         lessThanStringInd = tmpCondition.find_first_of("<"); //location of comparator
05003 
05004         if ((equalStringInd != std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
05005             (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
05006 
05007             generalCompareStringInd = equalStringInd;
05008             compareString = "==";
05009             textDisplay.debug("==\r\n");
05010         } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd != std::string::npos) &&
05011                    (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos)){
05012 
05013             generalCompareStringInd = greaterOrEqualStringInd;
05014             compareString = ">=";
05015             textDisplay.debug(">=\r\n");
05016         } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
05017                    (lessThanOrEqualStringInd != std::string::npos) && (notEqualStringInd == std::string::npos)){
05018 
05019             generalCompareStringInd = lessThanOrEqualStringInd;
05020             compareString = "<=";
05021             textDisplay.debug("<=\r\n");
05022         } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
05023                    (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd != std::string::npos)){
05024 
05025             generalCompareStringInd = notEqualStringInd;
05026             compareString = "!=";
05027             textDisplay.debug("!=\r\n");
05028         } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
05029                    (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
05030                    (greaterThanStringInd != std::string::npos) && (lessThanStringInd == std::string::npos)){
05031 
05032             generalCompareStringInd = greaterThanStringInd;
05033             compareString = ">";
05034             offset = 1;
05035             textDisplay.debug(">\r\n");
05036         } else if ((equalStringInd == std::string::npos) && (greaterOrEqualStringInd == std::string::npos) &&
05037                    (lessThanOrEqualStringInd == std::string::npos) && (notEqualStringInd == std::string::npos) &&
05038                    (greaterThanStringInd == std::string::npos) && (lessThanStringInd != std::string::npos)){
05039 
05040             generalCompareStringInd = lessThanStringInd;
05041             compareString = "<";
05042             offset = 1;
05043             textDisplay.debug("<\r\n");
05044 
05045         }else {
05046             textDisplay << "Condition not understood: " << expression << "\r\n";
05047             return 0;
05048         }
05049         textDisplay.debug("Allocating memory for condition...");
05050         intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
05051 
05052         if (newCompare == NULL) {
05053             textDisplay << "Error: No memory slots available.";
05054             return NULL;
05055         }
05056         newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
05057         if (newCondition == NULL) {
05058             textDisplay << "Error: No memory slots available.";
05059             return NULL;
05060         }
05061         textDisplay.debug("success.\r\n");
05062         beforeComparator.reserve(tmpCondition.length());
05063         textDisplay << beforeComparator.capacity();
05064         textDisplay.flush();
05065 
05066         afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
05067 
05068         beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
05069 
05070         tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable
05071         if (tmpVar != NULL) { //before the comparator is a single variable
05072             tmpVar2 = findIntVariable(afterComparator); //returns pointer to the variable
05073             if (tmpVar2 != NULL) { //we are comapring a single variable to another
05074                 //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2);
05075                 //currentEvent->addCondition(new condition(newCompare));
05076                 textDisplay.debug("Compare variable to variable\r\n");
05077                 newCompare->set(tmpVar,compareString.data(),tmpVar2);
05078                 newCondition->set(newCompare);
05079 
05080 
05081             } else if (isNumber(afterComparator)) {
05082                 //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
05083                 //currentEvent->addCondition(new condition(newCompare));
05084                 textDisplay.debug("Compare variable to number\r\n");
05085                 newCompare->set(tmpVar,compareString.data(),atoi(afterComparator.data()));
05086                 newCondition->set(newCompare);
05087 
05088 
05089             } //more here
05090 
05091         } else {
05092             textDisplay << "Condition not understood: " << expression << "\r\n";
05093 
05094             return NULL;
05095         }
05096 
05097     } else { //this is a compound condition (with either && or ||)
05098         textDisplay.debug("Compound condition\r\n");
05099         afterComparator = expression.substr(found+2,std::string::npos);
05100         beforeComparator = expression.substr(0,found);
05101         newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
05102         if (newCondition == NULL) {
05103             textDisplay << "Error: No memory slots available.";
05104             return NULL;
05105         } else {
05106             newCondition->isUsed = true; //reserve the condition slot;
05107         }
05108         //recursively call this function to parse the sub conditions
05109         condition* cond1 = parseConditions(beforeComparator);
05110         if (cond1 == NULL) {
05111             newCondition->release();
05112             return NULL;
05113         }
05114         condition* cond2 = parseConditions(afterComparator);
05115         if (cond2 == NULL) {
05116             newCondition->release();
05117             cond1->release();
05118             return NULL;
05119         }
05120         newCondition->set(cond1,currentOperator, cond2);
05121 
05122     }
05123 
05124     return newCondition; //all went well, so return the newly made condition
05125 
05126 }*/
05127 
05128 
05129 bool scriptStream::isOutsideParenth(const char* expression,int foundItem,int start, int end) {
05130 
05131     int pDepth = 0;  // How many nested parentheses
05132 
05133     if ((foundItem >= start)&&(foundItem<=end)&&(foundItem < strlen(expression))&&(end < strlen(expression))&&(start <= end)&&(start>=0)) {
05134         for (int i = start; i <= foundItem; i++) {
05135             if (expression[i] == '(') {
05136                 pDepth++;
05137             } else if (expression[i] == ')') {
05138                 pDepth--;
05139             }
05140         }
05141         if (pDepth<=0) {
05142 
05143             return true;
05144         } else {
05145 
05146             return false;
05147         }
05148     } else {
05149         //error handling defaults in a true condition
05150         return true;
05151     }
05152 
05153 }
05154 
05155 int scriptStream::findFirstOrOutsideParenth(const char* expression,int start, int end) {
05156 
05157     int foundItem = findStringLoc(expression,"||",start,end);
05158     while (foundItem != -1) {
05159         if (isOutsideParenth(expression,foundItem,start,end)) {
05160             //it's out side of ()
05161             break;
05162         }
05163         //not outside ()
05164         foundItem = findStringLoc(expression,"||",foundItem+1,end);
05165     }
05166     return foundItem;
05167 }
05168 
05169 int scriptStream::findFirstAndOutsideParenth(const char* expression,int start, int end) {
05170 
05171     int foundItem = findStringLoc(expression,"&&",start,end);
05172     while (foundItem != -1) {
05173         if (isOutsideParenth(expression,foundItem,start,end)){
05174             break;
05175         }
05176         foundItem = findStringLoc(expression,"||",foundItem+1,end);
05177     }
05178     return foundItem;
05179 }
05180 
05181 
05182 condition* scriptStream::parseConditions(const char* expression,int start, int end) {
05183 
05184 
05185     //This function is used to parse a condition string
05186     //such as (x < y && x != z) || (y == 2)
05187     //This function first identifies the root node of the logic tree
05188     //based on operator precedence ( () > && > || ), and then recursively calls itself
05189     //to find the nodes of the branches. The basic building blocks of
05190     //the final condition object are arithmatic comparitors (a > b) and
05191     //other condition objects.
05192 
05193 
05194 
05195     condition* newCondition = NULL;
05196     bool singleCondition = false; //no compound conditions
05197     //string afterComparator;
05198     //string beforeComparator;
05199     int afterComparatorLoc;
05200     int beforeComparatorLoc;
05201 
05202 
05203 
05204     int found;
05205 
05206     //To make a parse tree, we start by looking for operators with the lowest precendence
05207     //so we look for OR conditions first
05208     char currentOperator = OR_CONDITION;
05209 
05210     found = findFirstOrOutsideParenth(expression,start,end);
05211     if (found==-1) { //no or conditions outside parentheses found, so we look for AND conditions
05212         currentOperator = AND_CONDITION;
05213 
05214         found = findFirstAndOutsideParenth(expression,start,end);
05215     }
05216     if (found==-1) { //no or/and conditions outside parentheses found
05217         //if the expression is encapsulated in parentheses, remove the parentheses
05218         bool removedParenth = false;
05219         if ((expression[start] == '(') && (expression[end] == ')')) {
05220 
05221             start++;
05222             end--;
05223 
05224             //expression = expression.substr(1,expression.length()-2);
05225             removedParenth = true;
05226         }
05227         if (removedParenth) { //we removed parentheses, so try again
05228             textDisplay.debug("Condition: parenth removed\r\n");
05229             return parseConditions(expression,start,end);
05230         } else {
05231             singleCondition = true; //we assume that the condition is non-compound, i.e., a>b
05232         }
05233     }
05234 
05235     if (singleCondition) { //no compound conditions found
05236         textDisplay.debug("Single condition: ");
05237         int equalStringInd;
05238         int greaterOrEqualStringInd;
05239         int lessThanOrEqualStringInd;
05240         int notEqualStringInd;
05241         int greaterThanStringInd;
05242         int lessThanStringInd;
05243         int generalCompareStringInd;
05244 
05245 
05246         //string tmpCondition = expression;
05247         char compareString[3];
05248         //The expression might have up to three variables
05249         int* tmpVar;
05250         int* tmpVar2;
05251         //int* tmpVar3;
05252 
05253         int offset = 0;
05254         equalStringInd = findStringLoc(expression,"==",start,end);  //location of comparator
05255         greaterOrEqualStringInd = findStringLoc(expression,">=",start,end); //location of comparator
05256         lessThanOrEqualStringInd = findStringLoc(expression,"<=",start,end); //location of comparator
05257         notEqualStringInd = findStringLoc(expression,"!=",start,end); //location of comparator
05258         greaterThanStringInd = findStringLoc(expression,">",start,end); //location of comparator
05259         lessThanStringInd = findStringLoc(expression,"<",start,end); //location of comparator
05260 
05261         if ((equalStringInd != -1) && (greaterOrEqualStringInd == -1) &&
05262             (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
05263 
05264             generalCompareStringInd = equalStringInd;
05265             strcpy(compareString,"==");
05266             //compareString = "==";
05267             textDisplay.debug("==\r\n");
05268         } else if ((equalStringInd == -1) && (greaterOrEqualStringInd != -1) &&
05269                    (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1)){
05270 
05271             generalCompareStringInd = greaterOrEqualStringInd;
05272             strcpy(compareString,">=");
05273             //compareString = ">=";
05274             textDisplay.debug(">=\r\n");
05275         } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
05276                    (lessThanOrEqualStringInd != -1) && (notEqualStringInd == -1)){
05277 
05278             generalCompareStringInd = lessThanOrEqualStringInd;
05279             strcpy(compareString,"<=");
05280             //compareString = "<=";
05281             textDisplay.debug("<=\r\n");
05282         } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
05283                    (lessThanOrEqualStringInd == -1) && (notEqualStringInd != -1)){
05284 
05285             generalCompareStringInd = notEqualStringInd;
05286             strcpy(compareString,"!=");
05287             //compareString = "!=";
05288             textDisplay.debug("!=\r\n");
05289         } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
05290                    (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
05291                    (greaterThanStringInd != -1) && (lessThanStringInd == -1)){
05292 
05293             generalCompareStringInd = greaterThanStringInd;
05294             strcpy(compareString,">");
05295             //compareString = ">";
05296             offset = 1;
05297             textDisplay.debug(">\r\n");
05298         } else if ((equalStringInd == -1) && (greaterOrEqualStringInd == -1) &&
05299                    (lessThanOrEqualStringInd == -1) && (notEqualStringInd == -1) &&
05300                    (greaterThanStringInd == -1) && (lessThanStringInd != -1)){
05301 
05302             generalCompareStringInd = lessThanStringInd;
05303             strcpy(compareString,"<");
05304             //compareString = "<";
05305             offset = 1;
05306             textDisplay.debug("<\r\n");
05307 
05308         }else {
05309             textDisplay << "Condition not understood: " << expression << "\r\n";
05310             return 0;
05311         }
05312         textDisplay.debug("Allocating memory for condition...");
05313         intCompare* newCompare = findFirstUnUsed(intCompareBlock, NUMINTCOMPARE);
05314 
05315         if (newCompare == NULL) {
05316             textDisplay << "Error: No memory slots available.";
05317             return NULL;
05318         }
05319         newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
05320         if (newCondition == NULL) {
05321             textDisplay << "Error: No memory slots available.";
05322             return NULL;
05323         }
05324         textDisplay.debug("success.\r\n");
05325         //beforeComparator.reserve(tmpCondition.length());
05326         //textDisplay << beforeComparator.capacity();
05327         //textDisplay.flush();
05328 
05329         afterComparatorLoc = generalCompareStringInd+2-offset;
05330         beforeComparatorLoc = generalCompareStringInd-1;
05331 
05332         //afterComparator = tmpCondition.substr(generalCompareStringInd+2-offset,std::string::npos);
05333         //beforeComparator = tmpCondition.substr(0,generalCompareStringInd);
05334 
05335         //tmpVar = findIntVariable(beforeComparator); //returns pointer to the variable
05336         tmpVar = findIntVariable(expression,start,beforeComparatorLoc);
05337 
05338         if (tmpVar != NULL) { //before the comparator is a single variable
05339             tmpVar2 = findIntVariable(expression, afterComparatorLoc, end); //returns pointer to the variable
05340             if (tmpVar2 != NULL) { //we are comapring a single variable to another
05341                 //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),tmpVar2);
05342                 //currentEvent->addCondition(new condition(newCompare));
05343                 textDisplay.debug("Compare variable to variable\r\n");
05344                 newCompare->set(tmpVar,compareString,tmpVar2);
05345                 newCondition->set(newCompare);
05346 
05347 
05348             } else if (isNum(expression, afterComparatorLoc, end)) {
05349                 //intCompare* newCompare = new intCompare(tmpVar,compareString.data(),atoi(afterComparator.data()));
05350                 //currentEvent->addCondition(new condition(newCompare));
05351                 textDisplay.debug("Compare variable to number\r\n");
05352                 newCompare->set(tmpVar,compareString,atoi(expression+afterComparatorLoc));
05353                 newCondition->set(newCompare);
05354 
05355 
05356             } else {
05357                 textDisplay << "Condition not understood: " << expression << "\r\n";
05358                 return NULL;
05359             }//more here
05360 
05361         } else {
05362             textDisplay << "Condition not understood: " << expression << "\r\n";
05363 
05364             return NULL;
05365         }
05366 
05367     } else { //this is a compound condition (with either && or ||)
05368         textDisplay.debug("Compound condition\r\n");
05369         afterComparatorLoc = found+2;
05370         beforeComparatorLoc = found-1;
05371         //afterComparator = expression.substr(found+2,std::string::npos);
05372         //beforeComparator = expression.substr(0,found);
05373         newCondition = findFirstUnUsed(conditionBlock, NUMCONDITIONS);
05374         if (newCondition == NULL) {
05375             textDisplay << "Error: No memory slots available.";
05376             return NULL;
05377         } else {
05378             newCondition->isUsed = true; //reserve the condition slot;
05379         }
05380         //recursively call this function to parse the sub conditions
05381         condition* cond1 = parseConditions(expression,start,beforeComparatorLoc);
05382         if (cond1 == NULL) {
05383             newCondition->release();
05384             return NULL;
05385         }
05386         condition* cond2 = parseConditions(expression,afterComparatorLoc,end);
05387         if (cond2 == NULL) {
05388             newCondition->release();
05389             cond1->release();
05390             return NULL;
05391         }
05392         newCondition->set(cond1,currentOperator, cond2);
05393 
05394     }
05395 
05396     return newCondition; //all went well, so return the newly made condition
05397 
05398 
05399 }
05400 
05401 
05402 
05403 
05404 bool scriptStream::evaluateConditions(string& expression, event* currentEvent) {
05405     //calls the function to parse the condition string.  The condition pointer is then
05406     //attached to the event
05407 
05408     condition* newCondition = NULL;
05409     //newCondition = parseConditions(expression);
05410     newCondition = parseConditions(expression.data(),0,expression.length()-1);
05411     if (newCondition == NULL) {
05412         return false;
05413     } else {
05414         currentEvent->addCondition(newCondition);
05415         return true;
05416     }
05417 }
05418 
05419 int scriptStream::getRandomParam(const char* expression,int start, int end) {
05420 
05421     int pos1 = findStringLoc(expression,"random(",start,end)+7;
05422     int pos2 = findStringLoc(expression,")",pos1,end);
05423     if (pos2 == -1) {
05424         textDisplay << "Error: bad syntax\r\n";
05425         return 0;
05426     }
05427 
05428     int highVal = atoi(expression+pos1);
05429 
05430     if ((highVal > 0)) {
05431         return highVal;
05432     } else {
05433         textDisplay << "Error: random parameter must be 1 or more\r\n";
05434         return 0;
05435     }
05436 }
05437 
05438 int scriptStream::getRandomParam(string expression) {
05439 
05440     int pos1 = expression.find("random(")+7;
05441     int pos2 = expression.find_first_of(")",pos1);
05442     int highVal = atoi(expression.substr(pos1,pos2-pos1).data());
05443 
05444     if ((highVal > 0)) {
05445         return highVal;
05446     } else {
05447         textDisplay << "Error: random parameter must be 1 or more\r\n";
05448         return 0;
05449     }
05450 }
05451 
05452 int scriptStream::findStringLoc(const char *refString, const char *findString,int start,int end) {
05453     //look for 'findString' inside 'refString', only considering characters in between 'start' and 'end'
05454     //return -1 if not found
05455 
05456     if ((start < strlen(refString))&&(end < strlen(refString))&&(end >= start)) {
05457         const char* charPtr = strstr(refString+start,findString);
05458         //if found, make sure it was containted within the start and end bounds
05459         if ((charPtr != NULL) && ((int)(charPtr-refString) <= (end-strlen(findString)+1))) {
05460             return (int)(charPtr-refString);
05461         }
05462     }
05463     return -1;
05464 }
05465 
05466 bool scriptStream::isNum(const char *expression, int start, int end) {
05467 
05468     if ((start>0)&&(end<strlen(expression))&&(start<=end)) {
05469 
05470         bool outcome = true;
05471         while (start <= end) {
05472             //look for any digit, or a - sign
05473             if (!((expression[start] >= 45) && (expression[start] <= 57) && (expression[start] != 46) && (expression[start] != 47))) {
05474                 outcome = false;
05475                 break;
05476             }
05477             start++;
05478         }
05479         return outcome;
05480     }
05481     return false;
05482 }
05483 
05484 bool scriptStream::areStringsSame(const char *str1, const char *str2, int start, int end) {
05485     if ((findStringLoc(str1,str2,start,end) != -1) && (strlen(str2)==(end-start+1))) {
05486         return true;
05487     } else {
05488         return false;
05489     }
05490 
05491 
05492 }
05493