Auxiliaries I use for CreaBot
Embed:
(wiki syntax)
Show/hide line numbers
CMD_Interpreter.cpp
00001 // ***************************************************************** 00002 // Handle all the LEDs with some general function wrappers functions 00003 // ***************************************************************** 00004 #include "CMD_Interpreter.h" 00005 00006 //************************************ 00007 // Interpreter Class Creation 00008 //************************************ 00009 // Strategy: the interpreter accumulates characters in its input buffer 00010 // it flags the presence of complete lines 00011 // it also flags Overflow of the buffer in which case all subsequent characters 00012 // are lost until the queue is emptied, and a CR-LF is received 00013 // Defined States of the interpreter: 00014 // MyState = isStartNew, isLineFilling, isOverflow, isWaitNewLine}; 00015 00016 // #define DEBUG(...) { snprintf(buff, sizeof(buff), __VA_ARGS__); DataLog( buff ); } 00017 00018 Interpreter::Interpreter( void ) 00019 { Reinit( ); 00020 MyState = isStartNew; 00021 AllCommands = NULL; 00022 NumCommands = 0; 00023 } 00024 00025 void Interpreter::FillCommands( int aNumCommands, const EXE_CMD_TYPE *ACommands ) 00026 { int cnt; 00027 AllCommands = new EXE_CMD_TYPE[ aNumCommands ]; 00028 for( cnt=0; cnt<aNumCommands; cnt++) 00029 { AllCommands[cnt] = ACommands[cnt]; } ; 00030 NumCommands = aNumCommands; 00031 } 00032 00033 void Interpreter::Reinit( void ) { 00034 MyState = isWaitNewLine; // indicates no buffer overflow 00035 WriteIndex = 0; // points to next index to write to 00036 LinesComplete = 0; // indicates that no complete line is currently available 00037 // Start Scanning at the start 00038 ScanIndex = 0; 00039 BufAvail = BuffLen;// the full buffer size is available 00040 } 00041 00042 // Barebone function, assumes that checks havee been performed by writeBuf! 00043 void Interpreter::AddChar( char aChar ) { 00044 if (aChar == 8) // is it a backspace code, then remove one character: 00045 { if (BufAvail<BuffLen) { // there's actually a character to be removed 00046 BufAvail++; // Buffer regrows 00047 if (WriteIndex == 0) {WriteIndex=BuffLen-1;} 00048 else {WriteIndex--;} // recoil the write index 00049 } 00050 } 00051 else { 00052 if (WriteIndex == BuffLen-1) {WriteIndex=0;} 00053 else {WriteIndex++;} 00054 RingBuf[WriteIndex]=aChar; // all right, buffer it! 00055 BufAvail--; // Buffer is shrinking 00056 if (BufAvail==0) { MyState = isOverflow; } 00057 } 00058 } 00059 00060 // High level method to add a Char to the buffer, 00061 // Separates at Chars 10, 13, 0; replaced by a single 0 char 00062 // Blocking write when buffer has overflowed 00063 void Interpreter::writeBuf(char aChar) { 00064 bool LineEnds = aChar==10 || aChar==13 || aChar==0; 00065 switch (MyState) { 00066 case isOverflow: break; 00067 case isStartNew: // ready for the next line to start 00068 // avoid that consecutive CR LF are counted as multiple lines 00069 if (!LineEnds) {AddChar(aChar ); MyState = isLineFilling; } 00070 break; 00071 case isLineFilling:// New line has started filling 00072 if (!LineEnds) {AddChar(aChar);} 00073 else 00074 {MyState = isStartNew; // ready for the next line 00075 // Between consecutive commands, the endstring=NULL character is inserted 00076 // this is to indicate that line was already counted as completed 00077 AddChar(0 ); // append a line end char, will detect bufferFull! 00078 LinesComplete++; } // count completed lines 00079 break; 00080 case isWaitNewLine: // waiting for a new line end to arrive after an overflow 00081 if (LineEnds) { MyState = isStartNew; } 00082 break; 00083 default: MyState = isOverflow; // goes into error state, should never happen though 00084 } 00085 } // writeBuf 00086 00087 // Barebone function, that performs the checks to be performed! 00088 // Passes back the actC, and reads already the nextChar into actC 00089 char Interpreter::GetAChar( void ) { 00090 char oldC = actC; 00091 if (BufAvail==BuffLen) { actC = 0; LinesComplete=0; } // buffer is empty, no more lines!! 00092 else // something is in the buffer 00093 { if (ScanIndex == BuffLen) {ScanIndex=0;} 00094 else {ScanIndex++;} 00095 actC=RingBuf[ScanIndex]; // all right, get it 00096 if (actC==0) {LinesComplete--; } // now there is one line less in the storage 00097 BufAvail++; // Buffer is increasing 00098 } // something is in the buffer 00099 return oldC; 00100 } 00101 00102 // skip true blank, but also Tab characters 00103 void Interpreter::SkipBlanks( void ) { 00104 while(BufAvail<BuffLen && (actC==' ' || actC==9|| actC==0)) { GetAChar(); } 00105 } // SkipBlanks 00106 00107 int Interpreter::ReadAnInt( void ) { 00108 bool Negative = false; 00109 int Result = 0; 00110 if (actC=='-') {Negative = true; GetAChar(); } 00111 else if (actC=='+') {Negative = false; GetAChar(); } 00112 while(BufAvail<BuffLen && actC>='0' && actC<='9') 00113 { Result = Result * 10 + (GetAChar()-'0') ; } 00114 return Negative? -Result : Result; 00115 } // ReadAnInt 00116 00117 00118 RD_CMD_TYPE Interpreter::ParseCommand( void ) { 00119 RD_CMD_TYPE cmd; // locally built command 00120 actC=RingBuf[ScanIndex]; // initialiye the actC variable, as the first char to use 00121 SkipBlanks(); 00122 // Next Character is the command 00123 cmd.Command = GetAChar(); 00124 // Next Blanks are to be omitted, but are not even mandatory 00125 SkipBlanks(); 00126 if ((actC>='0' && actC<='9') || actC=='-' || actC=='+' ) 00127 { cmd.Parameter= ReadAnInt(); cmd.NumParam = 1; } 00128 else { cmd.Parameter= 0; cmd.NumParam = 0; } 00129 SkipBlanks( ); // There should be at least a trailing NUL character to be removed 00130 return cmd; // return the built command 00131 } 00132 00133 bool Interpreter::executeCommand(RD_CMD_TYPE cmd) { 00134 int CmdNr; 00135 bool Found; 00136 CmdNr = 0; 00137 Found = false; 00138 // DEBUG("Com '%c'=%d %d NPar=%d \n\r",cmd.Command, cmd.Command, cmd.Parameter, cmd.NumParam); 00139 // While not found go through all the commands, linear; they are not sorted by alphabet. 00140 while(CmdNr<NumCommands && !Found) 00141 { // DEBUG("NR:%d \n\r", CmdNr); 00142 if (AllCommands[CmdNr].cmd == cmd.Command) 00143 { // the command character matches 00144 if (cmd.NumParam == AllCommands[CmdNr].Npar) 00145 { // DEBUG("Execute: %s \n\r", AllCommands[CmdNr].help); 00146 AllCommands[CmdNr].Handler( cmd.Parameter ); // then call the handler 00147 } 00148 // else { DataLog("Param Mismatch!\n\r"); } // Inform about Parameter error 00149 Found = true; // and mark as found 00150 } 00151 else { CmdNr++; } // go on serarching 00152 } // while 00153 // if ( !Found ) { CmdInval(cmd.Command) ; } // call invalid command function 00154 return Found; 00155 } 00156 00157 bool Interpreter::ProcessPresentCommands( void ) 00158 { RD_CMD_TYPE Readcmd; 00159 if (MyState==isOverflow) { Reinit(); } 00160 if(LinesComplete>0) 00161 { // DEBUG("X: Scan=%d ", Interp.ScanIndex); 00162 Readcmd = ParseCommand(); 00163 executeCommand( Readcmd ); 00164 //DEBUG("state=%d; wix=%d; rix=%d; buf=%s ", Interp.MyState, Interp.WriteIndex, Interp.ScanIndex, &Interp.RingBuf[Interp.ScanIndex]); 00165 return true; 00166 } 00167 else { return false; } 00168 } 00169 00170 char *ParamHelp[] = {" ", "<param>", "<par><par>"}; 00171 00172 void Interpreter::PrtCmdHelp (Serial *aSerial ) // Display list of Commands 00173 { EXE_CMD_TYPE *com; 00174 int CmdNr; 00175 char *parStr; 00176 // DataLog("List of commands: \n\r"); 00177 // Go Through all commands in the table 00178 for (CmdNr = 0; CmdNr<NumCommands; CmdNr++ ) 00179 { com = &AllCommands[CmdNr]; // get a pointer to the command 00180 parStr = ParamHelp[com->Npar]; // Get the string that represents the number of parameters 00181 aSerial->printf( " %c %s => %s \n\r", com->cmd, parStr, com->help.c_str() ); // output the full command help 00182 } 00183 } 00184 00185 /* 00186 void Interpreter::CmdInval( int param ) // Feedback that the command is invalid 00187 { DEBUG( " Invalid command %d = '%c'; use: 'h' for help. \n\r", param, char(param) ) ; 00188 } 00189 00190 string Interpreter::GetLastMessage( void ) 00191 { string LastMsg = LastMessage; 00192 LastMessage = ""; // Empty the old Message 00193 return LastMsg; 00194 } 00195 00196 void Interpreter::DataLog( char *DebugMessage ) 00197 { if (LastMessage=="" ) { LastMessage = DebugMessage; } 00198 else { LastMessage = LastMessage + "\n\r" + DebugMessage; } 00199 }; 00200 */
Generated on Mon Jul 18 2022 17:02:22 by
