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.
cmdb.cpp
00001 /* 00002 _____________________________________________________________________________ 00003 00004 Project: mBed Command Interpreter 00005 Filename: cmdb.h 00006 Version: 0.80 00007 _____________________________________________________________________________ 00008 Date Comment 00009 -------- -------------------------------------------------------------- 00010 10022011 -Rewritten into C++ class. 00011 -Pass Serial into constructor for printf, putc and getc. 00012 -CID_<subsystem> must be handled internally. 00013 -Fixed a number of old Index/Id conflicts. 00014 -Got a working version. Much work to be done though. 00015 -Handle CID_HELP internally (like all system commands (IDLE/MACRO etc). 00016 -Handle subsystems internally. 00017 -Removed CMD_TBL_LEN. 00018 -CID_LAST is now defined as CID_HELP+1. 00019 11022011 -Added Documentation. 00020 -Added code to take number limits from the C++ Runtime instead of hard defined values. 00021 -Renamed id to cid in cmd. 00022 -Added MAX_LONG and MIN_LONG (long==int on mbed). 00023 -Removed cmdb_ prefix from members. 00024 -Tested Macro Support and added it to the Demo. 00025 -Added CID_COMMANDS. 00026 -Fixed a small bug in parse. 00027 -v0.76 00028 24032011 -Fixed some left-over bugs caused by index/id mixup. 00029 09052011 -Added present(), replace() and indexof() methods. 00030 replace() can be used to replace the complete command vector 00031 by a changed done. Inserting directly into cmdb's copy fails 00032 somehow. 00033 19092011 -Added PrintSection(), PrintValue() and PrintValuef() for 00034 easier Windows Ini File style output. As I use it to transfer 00035 data back to the PC (Easy parsing AND you can add/remove 00036 debug information without breaking PC code). 00037 20092011 -Breaking change, Made all cmd object static const like: 00038 00039 static const cmd HELP = {"Help",GLOBALCMD,CID_HELP,"%s","Help"}; 00040 00041 this saves just to much ram memory on the heap. 00042 Thanks to Igor Skochinsky. 00043 00044 -Made some more const string static. 00045 -v0.80 00046 00047 20092011 -Corrected Comment Alignment. 00048 -v0.81 00049 -------- -------------------------------------------------------------- 00050 TODO's 00051 10022011 -Tweak and Review Documentation. 00052 11022011 -Check & Test **PARM masks. 00053 -Remove prefix from class members? 00054 -------- -------------------------------------------------------------- 00055 _____________________________________________________________________________ 00056 */ 00057 00058 #include <vector> 00059 #include <stdlib.h> 00060 //#include <stdio.h> 00061 #include <stdarg.h> 00062 #include <ctype.h> 00063 #include <string.h> 00064 00065 #include "cmdb.h" 00066 #include "mbed.h" 00067 00068 //------------------------------------------------------------------------------ 00069 00070 Cmdb::Cmdb(const RawSerial& _serial, std::vector<cmd>& _cmds, void (*_callback)(Cmdb&,int)) : 00071 serial(_serial), cmds(_cmds) { 00072 echo = true; 00073 bold = true; 00074 00075 NoComment = NULL; 00076 DefComPos = 72; 00077 00078 subsystem = -1; 00079 00080 user_callback = _callback; 00081 00082 init(true); 00083 } 00084 00085 const char* Cmdb::NoComment; 00086 00087 int Cmdb::DefComPos; 00088 00089 //------------------------------------------------------------------------------ 00090 // Public Stuff. 00091 //------------------------------------------------------------------------------ 00092 00093 bool Cmdb::macro_hasnext() { 00094 return macro_ptr!=-1 && macro_ptr<MAX_CMD_LEN && macro_buf[macro_ptr]; 00095 } 00096 00097 char Cmdb::macro_next() { 00098 char ch = macro_buf[macro_ptr++]; 00099 00100 if (macro_ptr==MAX_CMD_LEN) { 00101 macro_reset(); 00102 } 00103 00104 //Translate Special Characters Back 00105 switch (ch) { 00106 case '|': 00107 return cr; 00108 case '_': 00109 return sp; 00110 default: 00111 return ch; 00112 } 00113 } 00114 00115 char Cmdb::macro_peek() { 00116 return macro_buf[macro_ptr]; 00117 } 00118 00119 void Cmdb::macro_reset() { 00120 macro_ptr = -1; 00121 macro_buf[0] = '\0'; 00122 } 00123 00124 //------------------------------------------------------------------------------ 00125 00126 bool Cmdb::hasnext() { 00127 return serial.readable()==1; 00128 } 00129 00130 char Cmdb::next() { 00131 return serial.getc(); 00132 } 00133 00134 //------------------------------------------------------------------------------ 00135 00136 bool Cmdb::scan(const char c) { 00137 int i; 00138 00139 //See http://www.interfacebus.com/ASCII_Table.html 00140 00141 if (c == '\r') { // cr? 00142 print(crlf); // Output it and ... 00143 if (cmdndx) { 00144 strncpy(lstbuf,cmdbuf,cmdndx); 00145 lstbuf[cmdndx]='\0'; 00146 00147 cmd_dispatcher(cmdbuf); 00148 } 00149 init(false); 00150 prompt(); 00151 00152 return true; 00153 } 00154 00155 //TODO BACKSPACE NOT CORRECT FOR TELNET! 00156 00157 if (c == '\b') { // Backspace 00158 if (cmdndx != 0) { 00159 print(bs); 00160 cmdbuf [--cmdndx] = '\0'; 00161 } else { 00162 printch(bell); // Output Error 00163 } 00164 return false; 00165 } 00166 00167 if (c == '\177') { // Delete 00168 while (cmdndx>0) { 00169 print(bs); 00170 cmdbuf [--cmdndx] = '\0'; 00171 } 00172 return false; 00173 } 00174 00175 //Reset Escape Buffer. 00176 if (c == '\033') { 00177 if (escndx!=0) { 00178 //_putchar(bell); // Output Error 00179 //printf("%s\r\n",escbuf); 00180 } 00181 escndx = 0; 00182 escbuf [escndx] = '\0'; // NULL-Terminate buffer 00183 } 00184 00185 //Extract Escape Sequence. 00186 if (c == '\033' || escndx ) { // Wait for escape 00187 escbuf [escndx++] = (unsigned char) c; // Add to the buffer 00188 escbuf [escndx] = '\0'; // NULL-Terminate buffer 00189 if (isalpha(c)) { 00190 switch (escid_search(escbuf)) { 00191 case EID_CURSOR_LEFT : { 00192 if (cmdndx != 0) { // Backspace? 00193 print(bs); 00194 cmdbuf [--cmdndx] = '\0'; 00195 } else { 00196 printch(bell); // Output char 00197 } 00198 break; 00199 } 00200 case EID_CURSOR_UP : { 00201 for (i=0; i<cmdndx; i++) { 00202 print(bs); 00203 } 00204 cmdndx=strlen(lstbuf); 00205 strncpy(cmdbuf,lstbuf,cmdndx); 00206 cmdbuf[cmdndx]='\0'; 00207 printf("%s",cmdbuf); 00208 break; 00209 } 00210 case EID_CURSOR_RIGHT: 00211 break; 00212 case EID_CURSOR_DOWN : 00213 break; 00214 case EID_LAST : 00215 break; 00216 default : 00217 printch(bell); 00218 break; 00219 } 00220 escndx=0; 00221 escbuf [escndx] = '\0'; // NULL-Terminate buffer 00222 } 00223 return false; 00224 } 00225 00226 if (c=='\n') { // LF 00227 return false; // Dump it 00228 } 00229 00230 if (!isprint (c)) { // Printable character? 00231 printch(bell); 00232 return false; 00233 } 00234 00235 if (cmdndx >= MAX_CMD_LEN) { // Past buffer length? 00236 printch(bell); 00237 return false; 00238 } 00239 00240 cmdbuf [cmdndx++] = (unsigned char) c; // Add to the buffer 00241 cmdbuf [cmdndx] = '\0'; // NULL-Terminate buffer 00242 00243 if (echo) { 00244 printch(c); // Output char 00245 } 00246 00247 return false; 00248 } 00249 00250 //------------------------------------------------------------------------------ 00251 00252 int Cmdb::printf(const char *format, ...) { 00253 int cnt; 00254 00255 va_list args; 00256 char buf[1024]; 00257 00258 memset(buf,'\0',sizeof(buf)); 00259 00260 va_start(args, format); 00261 cnt = vsnprintf(buf, sizeof(buf), format, args); 00262 if (cnt==-1) { 00263 //Error 00264 } 00265 va_end(args); 00266 00267 return print(buf); 00268 } 00269 00270 int Cmdb::print(const char *msg) { 00271 return serial.printf(msg); 00272 } 00273 00274 int Cmdb::println(const char *msg) { 00275 return serial.printf("%s\r\n", msg); 00276 } 00277 00278 int Cmdb::printsection(const char *section) { 00279 return printf("[%s]\r\n", section); 00280 } 00281 00282 int Cmdb::printmsg(const char *msg) { 00283 return printf("Msg=%s\r\n", msg); 00284 } 00285 00286 int Cmdb::printerror(const char *errormsg) { 00287 int a = printsection("Error"); 00288 return a==0?a:a+printmsg(errormsg); 00289 } 00290 00291 int Cmdb::printerrorf(const char *format, ...) { 00292 char buf[256]; 00293 00294 int a = printsection("Error"); 00295 00296 va_list args; 00297 va_start(args, format); 00298 00299 vsnprintf(buf, sizeof(buf), format, args); 00300 00301 va_end(args); 00302 00303 return a + printf("Msg=%s\r\n", buf); 00304 } 00305 00306 int Cmdb::printvaluef(const char *key, const char *format, ...) { 00307 char buf[256]; 00308 00309 va_list args; 00310 va_start(args, format); 00311 00312 vsnprintf(buf, sizeof(buf), format, args); 00313 00314 va_end(args); 00315 00316 return printf("%s=%s\r\n",key, buf); 00317 } 00318 00319 int Cmdb::printvaluef(const char *key, const int width, const char *comment, const char *format, ...) { 00320 char buf[256]; 00321 00322 int cnt = printf("%s=",key); 00323 00324 va_list args; 00325 va_start(args, format); 00326 00327 vsnprintf(buf, sizeof(buf), format, args); 00328 00329 va_end(args); 00330 00331 if (comment!=NULL) { 00332 cnt += printf("%s", buf); 00333 00334 if (cnt<width) { 00335 cnt += printf("%-*s ; %s\r\n", width - cnt - 1, "", comment); 00336 } else { 00337 cnt += printf("%s ; %s\r\n", "", comment); 00338 } 00339 } else { 00340 cnt += printf("%s\r\n",buf); 00341 } 00342 00343 return cnt; 00344 } 00345 00346 int Cmdb::printvalue(const char *key, const char *value, const char *comment, const int width) { 00347 if (comment) { 00348 char buf[256]; 00349 int cnt = 0; 00350 00351 memset(buf,'\0',sizeof(buf)); 00352 00353 cnt = snprintf(buf, sizeof(buf), "%s=%s", key, value); 00354 00355 if (cnt<=width) { 00356 return printf("%-*s ; %s\r\n", width - cnt + 1, buf, comment); 00357 } else { 00358 return printf("%s ; %s\r\n", buf, comment); 00359 } 00360 } else { 00361 return printf("%s=%s\r\n", key, value); 00362 } 00363 } 00364 00365 int Cmdb::printcomment(const char *comment, const int width) { 00366 return printf("%-*s; %s\r\n", width, "", comment); 00367 } 00368 00369 char Cmdb::printch(const char ch) { 00370 return serial.putc(ch); 00371 } 00372 00373 //Mode=1 ; Profile Position Mode 00374 //1234567890123456789012 00375 00376 //------------------------------------------------------------------------------ 00377 00378 void Cmdb::init(const char full) { 00379 if (full) { 00380 echo = true; 00381 bold = true; 00382 00383 subsystem = -1; 00384 00385 lstbuf [cmdndx] = '\0'; 00386 00387 macro_reset(); 00388 00389 prompt(); 00390 } 00391 00392 cmdndx = 0; 00393 cmdbuf [cmdndx] = '\0'; 00394 00395 escndx = 0; 00396 escbuf [escndx] = '\0'; 00397 } 00398 00399 //------------------------------------------------------------------------------ 00400 //Private Stuff. 00401 //------------------------------------------------------------------------------ 00402 00403 int Cmdb::escid_search(char *escstr) { 00404 for (int i=0; i<ESC_TBL_LEN; i++) { 00405 if (strcmp (esc_tbl[i].escstr, escstr) == 0) 00406 return (esc_tbl[i].id); 00407 } 00408 00409 return (EID_LAST); 00410 } 00411 00412 int Cmdb::cmdid_search(char *cmdstr) { 00413 //Warning, we return the ID but somewhere assume it's equal to the array index! 00414 for (int i=0; i<cmds.size(); i++) { 00415 if ((stricmp((char*)cmds[i].cmdstr, cmdstr) == 0) && ((cmds[i].subs == subsystem) || (cmds[i].subs<0))) 00416 return (cmds[i].cid); 00417 } 00418 00419 return CID_LAST; 00420 } 00421 00422 int Cmdb::cmdid_index(int cmdid) { 00423 for (int i=0; i<cmds.size(); i++) { 00424 if (cmds[i].cid==cmdid) 00425 return i; 00426 } 00427 00428 return -1; 00429 } 00430 00431 //------------------------------------------------------------------------------ 00432 00433 int Cmdb::parse(char *cmd) { 00434 //Command 00435 char cmdstr_buf [1 + MAX_CMD_LEN]; 00436 00437 //Parameters 00438 char argstr_buf [1 + MAX_CMD_LEN]; 00439 char *argsep; 00440 00441 char prmstr_buf [1 + MAX_CMD_LEN]; //copy of sscanf pattern 00442 char *tok; //current token 00443 void *toks[MAX_ARGS]; //pointers to string tokens IN commandline (argstr_buf) 00444 char *prms[MAX_ARGS]; //patterns IN copy of sscanf string (*parms) 00445 00446 char typ = '\0'; //Var type 00447 char mod = '\0'; //Var modifier (for cardinal types) 00448 unsigned int base; //Var number base (8,10,16) 00449 //unsigned int bytes; //Var size in bytes (used for malloc) 00450 00451 float f; //Temp var for conversion, 4 bytes 00452 //unsigned char b; //Temp var for conversion, 1 byte 00453 //char c; //Temp var for conversion, 1 byte 00454 //short h; //Temp var for conversion, 2 bytes 00455 //int k; //Temp var for conversion, 2 bytes 00456 long l; //Temp var for conversion, 4 bytes 00457 00458 char* endptr; //strtoXX() Error detection 00459 00460 int cid = -1; //Signals empty string... 00461 int ndx = -1; 00462 00463 //Init (global) variables. 00464 argfnd=0; 00465 argcnt=0; 00466 error =0; 00467 00468 //Zero the two string buffers for splitting cmd string into. 00469 zeromemory((char*)cmdstr_buf,sizeof(cmdstr_buf)); 00470 zeromemory(argstr_buf,sizeof(argstr_buf)); 00471 00472 //Make it worse in Lint 00473 for (int i=0; i<MAX_ARGS; i++) { 00474 parms[i].type=PARM_UNUSED; 00475 zeromemory((char*)&(parms[i].val),sizeof(parms[i].val)); 00476 } 00477 00478 /*------------------------------------------------ 00479 First, copy the command and convert it to all 00480 uppercase. 00481 ------------------------------------------------*/ 00482 00483 strncpy(cmdstr_buf, cmd, sizeof (cmdstr_buf) - 1); 00484 cmdstr_buf [sizeof (cmdstr_buf) - 1] = '\0'; 00485 00486 /*------------------------------------------------ 00487 Next, find the end of the first thing in the 00488 buffer. Since the command ends with a space, 00489 we'll look for that. NULL-Terminate the command 00490 and keep a pointer to the arguments. 00491 ------------------------------------------------*/ 00492 00493 argsep = strchr(cmdstr_buf, ' '); 00494 00495 if (argsep == NULL) { 00496 argstr_buf [0] = '\0'; 00497 } else { 00498 strcpy (argstr_buf, argsep + 1); 00499 *argsep = '\0'; 00500 } 00501 00502 /*------------------------------------------------ 00503 Search for a command ID, then switch on it. 00504 ------------------------------------------------*/ 00505 00506 //1) Find the Command Id 00507 cid = cmdid_search(cmdstr_buf); 00508 00509 if (cid!=CID_LAST) { 00510 //2) Tokenize a copy of the parms from the cmd_tbl. 00511 00512 ndx = cmdid_index(cid); 00513 00514 //Get Format patterns from cmd_tbl[id].parms. 00515 //note: strtok inserts \0 into the original string. Hence the copy. 00516 zeromemory((char *)(&prmstr_buf),sizeof(prmstr_buf)); 00517 00518 strncpy (prmstr_buf, cmds[ndx].parms, sizeof (prmstr_buf) - 1); 00519 00520 argcnt=0; 00521 tok = strtok(prmstr_buf, " "); 00522 while (tok != NULL) { 00523 //Store Pointers 00524 prms[argcnt++] = tok; 00525 00526 //printf("prm_%2.2d='%s'\r\n",argcnt, tok); 00527 00528 tok = strtok(NULL, " "); 00529 } 00530 00531 //3) Tokenize the commandline. 00532 00533 //Get Tokens from arguments. 00534 //Note: strtok inserts \0 into the original string. Won't harm here as we do not re-use it. 00535 00536 argfnd=0; 00537 00538 if (strlen(argstr_buf)!=0) { 00539 tok = strtok(argstr_buf, " "); 00540 } else { 00541 tok=NULL; 00542 } 00543 00544 while (tok != NULL) { 00545 //Store Pointers 00546 toks[argfnd++]=tok; 00547 00548 //printf("tok_%2.2d='%s'\r\n",argfnd, tok); 00549 00550 tok = strtok(NULL, " "); 00551 } 00552 00553 if (argfnd==argcnt || (cid==CID_HELP && argfnd==0)) { 00554 00555 error = 0; 00556 00557 for (int i=0; i<argcnt; i++) { 00558 //printf("prm_%2.2d=%s\r\n",i, prms[i]); 00559 00560 switch (strlen(prms[i])) { 00561 case 0: 00562 break; 00563 case 1: 00564 break; 00565 case 2: //Simple pattern, no modifier 00566 mod='\0'; 00567 typ=prms[i][1]; 00568 00569 break; 00570 case 3: //pattern with Modifier. 00571 mod=prms[i][1]; 00572 typ=prms[i][2]; 00573 00574 break; 00575 default: 00576 break; 00577 } 00578 00579 switch (typ) { 00580 case 'o' : 00581 base=8; 00582 break; 00583 case 'x' : 00584 base=16; 00585 break; 00586 default: 00587 base=10; 00588 break; 00589 } 00590 00591 endptr = (char*)toks[i]; 00592 00593 switch (typ) { 00594 //Signed Cardinal Types 00595 case 'd' : //Check mod 00596 case 'i' : //Check mod 00597 switch (mod) { 00598 case 'b' : //char 00599 //test range 00600 l=strtol((char*)toks[i], &endptr, base); 00601 if (l>=MIN_CHAR && l<=MAX_CHAR) { 00602 parms[i].type=PARM_CHAR; 00603 parms[i].val.uc =(unsigned char)l; 00604 } else { 00605 error = i+1; 00606 } 00607 00608 break; 00609 case 'h' : //short 00610 l=strtol((char*)toks[i], &endptr, base); 00611 if (l>=MIN_SHORT && l<=MAX_SHORT) { 00612 parms[i].type=PARM_SHORT; 00613 parms[i].val.w=(short)l; 00614 } else { 00615 error = i+1; 00616 } 00617 00618 break; 00619 case 'l' : //long 00620 l=strtol((char*)toks[i], &endptr, base); 00621 parms[i].type=PARM_LONG; 00622 parms[i].val.l=l; 00623 00624 break; 00625 default: //int 00626 l=strtol((char*)toks[i], &endptr, base); 00627 if (l>=MIN_INT && l<=MAX_INT) { 00628 parms[i].type=PARM_INT; 00629 parms[i].val.l=(int)l; 00630 } else { 00631 error = i+1; 00632 } 00633 break; 00634 } 00635 00636 if (error==0 && 00637 (endptr==toks[i] //No Conversion at all. 00638 || *endptr)) { //Incomplete conversion. 00639 error = i+1; 00640 } 00641 00642 break; 00643 00644 //Unsigned Cardinal Types 00645 case 'u' : //Check mod 00646 case 'o' : //Check mod 00647 case 'x' : //Check mod 00648 switch (mod) { 00649 case 'b' : //char 00650 //test range 00651 l=strtol((char*)toks[i], &endptr, base); 00652 if (l>=MIN_BYTE && l<=MAX_BYTE) { 00653 parms[i].type=PARM_CHAR; 00654 parms[i].val.uc =(unsigned char)l; 00655 } else { 00656 error = i+1; 00657 } 00658 00659 break; 00660 case 'h' : //short 00661 l=strtol((char*)toks[i], &endptr, base); 00662 if (l>=MIN_USHORT && l<=MAX_USHORT) { 00663 parms[i].type=PARM_SHORT; 00664 parms[i].val.w=(short)l; 00665 } else { 00666 error = i+1; 00667 } 00668 00669 break; 00670 case 'l' : //long 00671 l=strtol((char*)toks[i], &endptr, base); 00672 parms[i].type=PARM_LONG; 00673 parms[i].val.l=l; 00674 00675 break; 00676 default: //int 00677 l=strtol((char*)toks[i], &endptr, base); 00678 if (l>=MIN_UINT && l<=MAX_UINT) { 00679 parms[i].type=PARM_INT; 00680 parms[i].val.l=(int)l; 00681 } else { 00682 error = i+1; 00683 } 00684 break; 00685 } 00686 00687 if (error==0 && 00688 (endptr==toks[i] //No Conversion at all. 00689 || *endptr)) { //Incomplete conversion. 00690 error = i+1; 00691 } 00692 00693 break; 00694 } 00695 00696 //Floating Point Types 00697 switch (typ) { 00698 case 'e' : 00699 case 'f' : 00700 case 'g' : 00701 f = strtod((char*)toks[i], &endptr); 00702 00703 parms[i].type=PARM_FLOAT; 00704 parms[i].val.f=f; 00705 00706 if (error==0 && 00707 (endptr==toks[i] //No Conversion at all. 00708 || *endptr)) { //Incomplete conversion. 00709 error = i; 00710 } 00711 00712 break; 00713 } 00714 00715 //String types 00716 switch (typ) { 00717 case 'c' : 00718 parms[i].type=PARM_CHAR; 00719 parms[i].val.c=((char*)toks[i])[0]; 00720 00721 if (error==0 && strlen((char*)toks[i])!=1) { //Incomplete conversion. 00722 error = i; 00723 } 00724 00725 break; 00726 00727 case 's' : 00728 parms[i].type=PARM_STRING; 00729 strncpy(parms[i].val.s,(char*)toks[i], strlen((char*)toks[i])); 00730 00731 break; 00732 } 00733 } 00734 } else { 00735 //cid=CID_LAST; 00736 } 00737 } 00738 00739 return cid; 00740 } 00741 00742 //------------------------------------------------------------------------------ 00743 00744 void Cmdb::cmd_dispatcher(char *cmd) { 00745 int cid; 00746 int ndx; 00747 00748 cid = parse(cmd); 00749 ndx = cmdid_index(cid); 00750 00751 if (cid!=-1) { 00752 //printf("cmds[%d]=%d\r\n",ndx, cid); 00753 00754 /*------------------------------------------------ 00755 Process the command and it's arguments that are 00756 found. id contains the command id and argcnt & 00757 argfnd the number of found and expected paramaters 00758 parms contains the parsed argument values and their 00759 types. 00760 ------------------------------------------------*/ 00761 00762 //printf("cmds[%d]=%d\r\n",ndx, cid); 00763 00764 if (cid==CID_LAST) { 00765 print("Unknown command, type 'Help' for a list of available commands.\r\n"); 00766 } else { 00767 //printf("cmds[%d]=%d [%s]\r\n",ndx, cid, cmds[ndx].cmdstr); 00768 00769 //Test for more commandline than allowed too. 00770 //i.e. run 1 is wrong. 00771 00772 if (argcnt==0 && argfnd==0 && error==0 && ndx!=-1 && cmds[ndx].subs==SUBSYSTEM) { 00773 //Handle all SubSystems. 00774 subsystem=cid; 00775 } else if ( ((cid==CID_HELP) || (argcnt==argfnd)) && error==0 ) { 00776 switch (cid) { 00777 00778 #ifdef ENABLEMACROS 00779 /////// GLOBAL MACRO COMMANDS /////// 00780 00781 //Define Macro from commandline 00782 case CID_MACRO: 00783 macro_ptr=-1; 00784 00785 zeromemory((char*)macro_buf, sizeof(macro_buf)); 00786 strncpy(macro_buf, STRINGPARM(0), sizeof(macro_buf) - 1); 00787 00788 //DEBUG 00789 printf("Macro=%s\r\n",macro_buf); 00790 break; 00791 00792 //Run Macro 00793 case CID_RUN: 00794 macro_ptr=0; 00795 break; 00796 00797 //List Macro's 00798 case CID_MACROS: 00799 print("[Macro]\r\n"); 00800 if (macro_buf[0]!='\0') { 00801 printf("Value=%s\r\n",macro_buf); 00802 } else { 00803 printf(";No Macro Defined\r\n"); 00804 } 00805 break; 00806 00807 #endif //ENABLEMACROS 00808 00809 #ifdef STATEMACHINE 00810 /////// GLOBAL STATEMACHINE COMMANDS /////// 00811 00812 //Start State Machine 00813 case CID_STATE: 00814 statemachine(BYTEPARM(0)); 00815 00816 break; 00817 #endif 00818 00819 /////// GLOBAL COMMANDS /////// 00820 case CID_COMMANDS: 00821 cmd_dump(); 00822 break; 00823 00824 //Echo 00825 case CID_ECHO: 00826 echo = BOOLPARM(0); 00827 break; 00828 00829 //Bold 00830 case CID_BOLD: 00831 bold = BOOLPARM(0); 00832 break; 00833 00834 //Warm Boot 00835 case CID_BOOT: 00836 mbed_reset(); 00837 break; 00838 00839 //Sends an ANSI escape code to clear the screen. 00840 case CID_CLS: 00841 print(cls); 00842 break; 00843 00844 //Returns to CMD> prompt where most commands are disabled. 00845 case CID_IDLE: 00846 subsystem=-1; 00847 break; 00848 00849 //Help 00850 case CID_HELP: { 00851 print("\r\n"); 00852 00853 if (argfnd>0) { 00854 cid = cmdid_search(STRINGPARM(0)); 00855 } else { 00856 cid=CID_LAST; 00857 } 00858 00859 if (argfnd>0 && cid!=CID_LAST) { 00860 00861 //Help with a valid command as first parameter 00862 ndx = cmdid_index(cid); 00863 00864 switch (cmds[ndx].subs) { 00865 case SUBSYSTEM: { //Dump whole subsystem 00866 printf("%s subsystem commands:\r\n\r\n",cmds[ndx].cmdstr); 00867 00868 //Count SubSystem Commands. 00869 int subcmds =0; 00870 for (int i=0; i<cmds.size(); i++) { 00871 if (cmds[i].subs==cid) { 00872 subcmds++; 00873 } 00874 } 00875 00876 //Print SubSystem Commands. 00877 for (int i=0; i<cmds.size()-1; i++) { 00878 if (cmds[i].subs==cid) { 00879 subcmds--; 00880 if (subcmds!=0) { 00881 cmd_help("",i,",\r\n"); 00882 } else { 00883 cmd_help("",i,".\r\n"); 00884 } 00885 } 00886 } 00887 } 00888 break; 00889 00890 case GLOBALCMD: //Dump command only 00891 //print("Global command:\r\n\r\n",cmd_tbl[cmd_tbl[ndx].subs].cmdstr); 00892 cmd_help("Syntax: ",ndx,".\r\n"); 00893 00894 break; 00895 00896 default: { //Dump one subsystem command 00897 int sndx = cmdid_index(cmds[ndx].subs); 00898 00899 printf("%s subsystem command:\r\n\r\n",cmds[sndx].cmdstr); 00900 00901 cmd_help("Syntax: ",ndx,".\r\n"); 00902 } 00903 break; 00904 } 00905 } else { 00906 if (argfnd>0) { 00907 //Help with invalid command as first parameter 00908 print("Unknown command, type 'Help' for a list of available commands.\r\n"); 00909 } else { 00910 //Help 00911 00912 //Dump Active Subsystem, Global & Other (dormant) Subsystems 00913 //-1 because we want comma's and for the last a . 00914 for (int i=0; i<cmds.size()-1; i++) { 00915 if ((cmds[i].subs<0) || (cmds[i].subs==subsystem)) { 00916 cmd_help("",i,",\r\n"); 00917 } 00918 } 00919 cmd_help("",cmds.size()-1,".\r\n"); 00920 } 00921 } 00922 print("\r\n"); 00923 break; 00924 } //CID_HELP 00925 00926 default : { 00927 // Do a Call to the Application's Command Dispatcher. 00928 (*user_callback)(*this, cid); 00929 } 00930 } 00931 } else { 00932 cmd_help("Syntax: ",ndx,".\r\n"); 00933 } 00934 00935 } 00936 00937 } else { 00938 //cid==-1 00939 } 00940 } 00941 00942 //------------------------------------------------------------------------------ 00943 //----Dump commands table as a ini file. 00944 //------------------------------------------------------------------------------ 00945 00946 void Cmdb::cmd_dump() { 00947 int ndx; 00948 int j; 00949 int k; 00950 int lastmod; 00951 00952 k = 0; 00953 lastmod = 0; 00954 00955 for (ndx=0; ndx<cmds.size(); ndx++) { 00956 00957 #ifndef SHOWHIDDEN 00958 if (cmds[ndx].subs==HIDDENSUB) { 00959 continue; 00960 } 00961 #endif 00962 00963 switch (cmds[ndx].subs) { 00964 case SUBSYSTEM : 00965 printf("[command%2.2d]\r\n",ndx+1); 00966 print("type=Subsystem\r\n"); 00967 print("subsystem=Global\r\n"); 00968 break; 00969 case HIDDENSUB : 00970 #ifdef SHOWHIDDEN 00971 printf("[command%2.2d]\r\n",ndx+1); 00972 print("type=HiddenSubystem\r\n"); 00973 print("subsystem=Global\r\n"); 00974 #endif 00975 break; 00976 case GLOBALCMD : 00977 printf("[command%2.2d]\r\n",ndx+1); 00978 print("type=GlobalCommand\r\n"); 00979 print("subsystem=Global\r\n"); 00980 break; 00981 default : 00982 int sndx = cmdid_index(cmds[ndx].subs); 00983 00984 if (cmds[sndx].subs==HIDDENSUB) { 00985 #ifdef SHOWHIDDEN 00986 printf("[command%2.2d]\r\n",ndx+1); 00987 print("type=HiddenCommand\r\n"); 00988 print("subsystem=HiddenSubystem\r\n"); 00989 #endif 00990 continue; 00991 } 00992 00993 printf("[command%2.2d]\r\n",ndx+1); 00994 print("type=Command\r\n"); 00995 printf("subsystem=%s\r\n",cmds[sndx].cmdstr); 00996 } 00997 00998 if (cmds[ndx].subs==HIDDENSUB) { 00999 continue; 01000 } 01001 01002 printf("command=%s\r\n",cmds[ndx].cmdstr); 01003 printf("helpmsg=%s\r\n",cmds[ndx].cmddescr); 01004 print("parameters="); 01005 for (j=0; j<strlen(cmds[ndx].parms); j++) { 01006 switch (cmds[ndx].parms[j]) { 01007 case '%' : 01008 lastmod=0; 01009 break; 01010 01011 case 'b' : 01012 lastmod=8; 01013 break; 01014 case 'h' : 01015 lastmod=16; 01016 break; 01017 case 'l' : 01018 lastmod=32; 01019 break; 01020 01021 case 'd' : 01022 case 'i' : { 01023 switch (lastmod) { 01024 case 0 : 01025 case 16 : 01026 print("int"); 01027 k+=3; 01028 break; 01029 case 8 : 01030 print("shortint"); 01031 k+=8; 01032 break; 01033 case 32: 01034 print("longint"); 01035 k+=7; 01036 break; 01037 } 01038 break; 01039 } 01040 01041 case 'u' : 01042 case 'o' : 01043 case 'x' : { 01044 switch (lastmod) { 01045 case 0 : 01046 case 16 : 01047 print("word"); 01048 k+=4; 01049 break; 01050 case 8 : 01051 print("byte"); 01052 k+=4; 01053 break; 01054 case 32 : 01055 print("dword"); 01056 k+=5; 01057 break; 01058 } 01059 01060 switch (cmds[ndx].parms[j]) { 01061 case 'o' : 01062 print("[o]"); 01063 k+=3; 01064 break; 01065 case 'x' : 01066 print("[h]"); 01067 k+=3; 01068 break; 01069 } 01070 01071 break; 01072 } 01073 01074 case 'e' : 01075 case 'f' : 01076 case 'g' : 01077 print("float"); 01078 k+=5; 01079 break; 01080 01081 case 'c' : 01082 print("char"); 01083 k+=4; 01084 break; 01085 01086 case 's' : 01087 print("string"); 01088 k+=6; 01089 break; 01090 01091 case ' ' : 01092 printch(sp); 01093 k++; 01094 break; 01095 } 01096 } 01097 print("\r\n"); 01098 printf("syntax=%s\r\n",cmds[ndx].parmdescr); 01099 } 01100 } 01101 01102 void Cmdb::prompt(void) { 01103 #ifdef SUBSYSTEMPROMPTS 01104 if (subsystem!=-1) { 01105 int ndx = cmdid_index(subsystem); 01106 01107 printf("%s>",cmds[ndx].cmdstr); 01108 01109 return; 01110 } 01111 #endif //SUBSYSTEMPROMPTS 01112 01113 printf(PROMPT); 01114 } 01115 01116 void Cmdb::cmd_help(char *pre, int ndx, char *post) { 01117 int j; 01118 int k; 01119 int lastmod; 01120 01121 k=0; 01122 lastmod=0; 01123 01124 switch (cmds[ndx].subs) { 01125 case SUBSYSTEM : 01126 break; 01127 case GLOBALCMD : 01128 break; 01129 case HIDDENSUB : 01130 return; 01131 default : 01132 if (strlen(pre)==0 && bold) { 01133 print(boldon); 01134 } 01135 break; 01136 } 01137 01138 print(pre); 01139 k+=strlen(pre); 01140 01141 if (k==0) { 01142 printf("%12s",cmds[ndx].cmdstr); 01143 k+=12; 01144 } else { 01145 if (strlen(pre)>0 && bold) { 01146 print(boldon); 01147 } 01148 01149 printf("%s",cmds[ndx].cmdstr); 01150 k+=strlen(cmds[ndx].cmdstr); 01151 01152 if (strlen(pre)>0 && bold) { 01153 print(boldoff); 01154 } 01155 } 01156 01157 if (strlen(cmds[ndx].parms)) { 01158 printch(sp); 01159 k++; 01160 } 01161 01162 for (j=0; j<strlen(cmds[ndx].parms); j++) { 01163 switch (cmds[ndx].parms[j]) { 01164 case '%' : 01165 lastmod=0; 01166 break; 01167 01168 case 'b' : 01169 lastmod=8; 01170 break; 01171 case 'h' : 01172 lastmod=16; 01173 break; 01174 case 'l' : 01175 lastmod=32; 01176 break; 01177 01178 case 'd' : 01179 case 'i' : { 01180 switch (lastmod) { 01181 case 0 : 01182 case 16 : 01183 print("int"); 01184 k+=3; 01185 break; 01186 case 8 : 01187 print("shortint"); 01188 k+=8; 01189 break; 01190 case 32: 01191 print("longint"); 01192 k+=7; 01193 break; 01194 } 01195 break; 01196 } 01197 01198 case 'u' : 01199 case 'o' : 01200 case 'x' : { 01201 switch (lastmod) { 01202 case 0 : 01203 case 16 : 01204 print("word"); 01205 k+=4; 01206 break; 01207 case 8 : 01208 print("byte"); 01209 k+=4; 01210 break; 01211 case 32 : 01212 print("dword"); 01213 k+=5; 01214 break; 01215 } 01216 01217 switch (cmds[ndx].parms[j]) { 01218 case 'o' : 01219 print("[o]"); 01220 k+=3; 01221 break; 01222 case 'x' : 01223 print("[h]"); 01224 k+=3; 01225 break; 01226 } 01227 01228 break; 01229 } 01230 01231 case 'e' : 01232 case 'f' : 01233 case 'g' : 01234 print("float"); 01235 k+=5; 01236 break; 01237 01238 case 'c' : 01239 print("char"); 01240 k+=4; 01241 break; 01242 01243 case 's' : 01244 print("string"); 01245 k+=6; 01246 break; 01247 01248 case ' ' : 01249 printch(sp); 01250 k++; 01251 break; 01252 } 01253 } 01254 01255 for (j=k; j<40; j++) printch(sp); 01256 01257 switch (cmds[ndx].subs) { 01258 case SUBSYSTEM : 01259 if (ndx==subsystem) { 01260 printf("- %s (active subsystem)%s",cmds[ndx].cmddescr,post); 01261 } else { 01262 printf("- %s (dormant subsystem)%s",cmds[ndx].cmddescr,post); 01263 } 01264 break; 01265 case HIDDENSUB : 01266 break; 01267 case GLOBALCMD : 01268 printf("- %s (global command)%s",cmds[ndx].cmddescr,post); 01269 break; 01270 default : 01271 printf("- %s%s",cmds[ndx].cmddescr,post); 01272 if (strlen(pre)==0 && bold) { 01273 print(boldoff); 01274 } 01275 break; 01276 } 01277 01278 if (strlen(pre)>0 && strlen(cmds[ndx].parmdescr)) { 01279 printf("Params: %s",cmds[ndx].parmdescr); 01280 print("\r\n"); 01281 } 01282 } 01283 01284 //------------------------------------------------------------------------------ 01285 //----Wrappers 01286 //------------------------------------------------------------------------------ 01287 01288 void Cmdb::zeromemory(char *p,unsigned int siz) { 01289 memset(p,'\0',siz); 01290 } 01291 01292 int Cmdb::stricmp (char *s1, char *s2) { 01293 int i; 01294 int len1,len2; 01295 01296 len1=strlen(s1); 01297 len2=strlen(s2); 01298 01299 for (i = 0; (i<len1) && (i<len2); i++) { 01300 if ( toupper (s1[i])<toupper(s2[i]) ) return (-1); 01301 if ( toupper (s1[i])>toupper(s2[i]) ) return (+1); 01302 } 01303 01304 if (len1<len2) return (-1); 01305 if (len1>len2) return (+1); 01306 01307 return (0); 01308 } 01309 01310 //------------------------------------------------------------------------------
Generated on Wed Jul 13 2022 19:03:15 by
1.7.2