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