Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of stateScript_v2 by
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
Generated on Tue Jul 12 2022 17:07:31 by
1.7.2
