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.
Dependents: mbed_controller_demo
Fork of CMDB by
cmdb.cpp
- Committer:
- hillkim7
- Date:
- 2015-03-12
- Revision:
- 27:ed36b4c73d4c
- Parent:
- 26:34c65d3f6da0
File content as of revision 27:ed36b4c73d4c:
/*
_____________________________________________________________________________
Project: mBed Command Interpreter
Filename: cmdb.h
Version: 0.80
_____________________________________________________________________________
Date Comment
-------- --------------------------------------------------------------
10022011 -Rewritten into C++ class.
-Pass Serial into constructor for printf, putc and getc.
-CID_<subsystem> must be handled internally.
-Fixed a number of old Index/Id conflicts.
-Got a working version. Much work to be done though.
-Handle CID_HELP internally (like all system commands (IDLE/MACRO etc).
-Handle subsystems internally.
-Removed CMD_TBL_LEN.
-CID_LAST is now defined as CID_HELP+1.
11022011 -Added Documentation.
-Added code to take number limits from the C++ Runtime instead of hard defined values.
-Renamed id to cid in cmd.
-Added MAX_LONG and MIN_LONG (long==int on mbed).
-Removed cmdb_ prefix from members.
-Tested Macro Support and added it to the Demo.
-Added CID_COMMANDS.
-Fixed a small bug in parse.
-v0.76
24032011 -Fixed some left-over bugs caused by index/id mixup.
09052011 -Added present(), replace() and indexof() methods.
replace() can be used to replace the complete command vector
by a changed done. Inserting directly into cmdb's copy fails
somehow.
19092011 -Added PrintSection(), PrintValue() and PrintValuef() for
easier Windows Ini File style output. As I use it to transfer
data back to the PC (Easy parsing AND you can add/remove
debug information without breaking PC code).
20092011 -Breaking change, Made all cmd object static const like:
static const cmd HELP = {"Help",GLOBALCMD,CID_HELP,"%s","Help"};
this saves just to much ram memory on the heap.
Thanks to Igor Skochinsky.
-Made some more const string static.
-v0.80
20092011 -Corrected Comment Alignment.
-v0.81
-------- --------------------------------------------------------------
TODO's
10022011 -Tweak and Review Documentation.
11022011 -Check & Test **PARM masks.
-Remove prefix from class members?
-------- --------------------------------------------------------------
_____________________________________________________________________________
*/
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include "cmdb.h"
#include "mbed.h"
//------------------------------------------------------------------------------
Cmdb::Cmdb(Serial& _serial, std::vector<cmd>& _cmds, void (*_callback)(Cmdb&,int)) :
serial(_serial), cmds(_cmds) {
echo = true;
bold = true;
NoComment = NULL;
DefComPos = 72;
subsystem = -1;
user_callback = _callback;
init(true);
}
const char* Cmdb::NoComment;
int Cmdb::DefComPos;
//------------------------------------------------------------------------------
// Public Stuff.
//------------------------------------------------------------------------------
bool Cmdb::macro_hasnext() {
return macro_ptr!=-1 && macro_ptr<MAX_CMD_LEN && macro_buf[macro_ptr];
}
char Cmdb::macro_next() {
char ch = macro_buf[macro_ptr++];
if (macro_ptr==MAX_CMD_LEN) {
macro_reset();
}
//Translate Special Characters Back
switch (ch) {
case '|':
return cr;
case '_':
return sp;
default:
return ch;
}
}
char Cmdb::macro_peek() {
return macro_buf[macro_ptr];
}
void Cmdb::macro_reset() {
macro_ptr = -1;
macro_buf[0] = '\0';
}
//------------------------------------------------------------------------------
bool Cmdb::hasnext() {
return serial.readable()==1;
}
char Cmdb::next() {
return serial.getc();
}
//------------------------------------------------------------------------------
bool Cmdb::scan(const char c) {
int i;
//See http://www.interfacebus.com/ASCII_Table.html
if (c == '\r') { // cr?
print(crlf); // Output it and ...
if (cmdndx) {
strncpy(lstbuf,cmdbuf,cmdndx);
lstbuf[cmdndx]='\0';
cmd_dispatcher(cmdbuf);
}
init(false);
prompt();
return true;
}
//TODO BACKSPACE NOT CORRECT FOR TELNET!
if (c == '\b') { // Backspace
if (cmdndx != 0) {
print(bs);
cmdbuf [--cmdndx] = '\0';
} else {
printch(bell); // Output Error
}
return false;
}
if (c == '\177') { // Delete
while (cmdndx>0) {
print(bs);
cmdbuf [--cmdndx] = '\0';
}
return false;
}
//Reset Escape Buffer.
if (c == '\033') {
if (escndx!=0) {
//_putchar(bell); // Output Error
//printf("%s\r\n",escbuf);
}
escndx = 0;
escbuf [escndx] = '\0'; // NULL-Terminate buffer
}
//Extract Escape Sequence.
if (c == '\033' || escndx ) { // Wait for escape
escbuf [escndx++] = (unsigned char) c; // Add to the buffer
escbuf [escndx] = '\0'; // NULL-Terminate buffer
if (isalpha(c)) {
switch (escid_search(escbuf)) {
case EID_CURSOR_LEFT : {
if (cmdndx != 0) { // Backspace?
print(bs);
cmdbuf [--cmdndx] = '\0';
} else {
printch(bell); // Output char
}
break;
}
case EID_CURSOR_UP : {
for (i=0; i<cmdndx; i++) {
print(bs);
}
cmdndx=strlen(lstbuf);
strncpy(cmdbuf,lstbuf,cmdndx);
cmdbuf[cmdndx]='\0';
printf("%s",cmdbuf);
break;
}
case EID_CURSOR_RIGHT:
break;
case EID_CURSOR_DOWN :
break;
case EID_LAST :
break;
default :
printch(bell);
break;
}
escndx=0;
escbuf [escndx] = '\0'; // NULL-Terminate buffer
}
return false;
}
if (c=='\n') { // LF
return false; // Dump it
}
if (!isprint (c)) { // Printable character?
printch(bell);
return false;
}
if (cmdndx >= MAX_CMD_LEN) { // Past buffer length?
printch(bell);
return false;
}
cmdbuf [cmdndx++] = (unsigned char) c; // Add to the buffer
cmdbuf [cmdndx] = '\0'; // NULL-Terminate buffer
if (echo) {
printch(c); // Output char
}
return false;
}
//------------------------------------------------------------------------------
int Cmdb::printf(const char *format, ...) {
int cnt;
va_list args;
char buf[1024];
memset(buf,'\0',sizeof(buf));
va_start(args, format);
cnt = vsnprintf(buf, sizeof(buf), format, args);
if (cnt==-1) {
//Error
}
va_end(args);
return print(buf);
}
int Cmdb::print(const char *msg) {
return serial.printf(msg);
}
int Cmdb::println(const char *msg) {
return serial.printf("%s\r\n", msg);
}
int Cmdb::printsection(const char *section) {
return printf("[%s]\r\n", section);
}
int Cmdb::printmsg(const char *msg) {
return printf("Msg=%s\r\n", msg);
}
int Cmdb::printerror(const char *errormsg) {
int a = printsection("Error");
return a==0?a:a+printmsg(errormsg);
}
int Cmdb::printerrorf(const char *format, ...) {
char buf[256];
int a = printsection("Error");
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
return a + printf("Msg=%s\r\n", buf);
}
int Cmdb::printvaluef(const char *key, const char *format, ...) {
char buf[256];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
return printf("%s=%s\r\n",key, buf);
}
int Cmdb::printvaluef(const char *key, const int width, const char *comment, const char *format, ...) {
char buf[256];
int cnt = printf("%s=",key);
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (comment!=NULL) {
cnt += printf("%s", buf);
if (cnt<width) {
cnt += printf("%-*s ; %s\r\n", width - cnt - 1, "", comment);
} else {
cnt += printf("%s ; %s\r\n", "", comment);
}
} else {
cnt += printf("%s\r\n",buf);
}
return cnt;
}
int Cmdb::printvalue(const char *key, const char *value, const char *comment, const int width) {
if (comment) {
char buf[256];
int cnt = 0;
memset(buf,'\0',sizeof(buf));
cnt = snprintf(buf, sizeof(buf), "%s=%s", key, value);
if (cnt<=width) {
return printf("%-*s ; %s\r\n", width - cnt + 1, buf, comment);
} else {
return printf("%s ; %s\r\n", buf, comment);
}
} else {
return printf("%s=%s\r\n", key, value);
}
}
int Cmdb::printcomment(const char *comment, const int width) {
return printf("%-*s; %s\r\n", width, "", comment);
}
char Cmdb::printch(const char ch) {
return serial.putc(ch);
}
//Mode=1 ; Profile Position Mode
//1234567890123456789012
//------------------------------------------------------------------------------
void Cmdb::init(const char full) {
if (full) {
echo = true;
bold = true;
subsystem = -1;
lstbuf [cmdndx] = '\0';
macro_reset();
prompt();
}
cmdndx = 0;
cmdbuf [cmdndx] = '\0';
escndx = 0;
escbuf [escndx] = '\0';
}
//------------------------------------------------------------------------------
//Private Stuff.
//------------------------------------------------------------------------------
int Cmdb::escid_search(char *escstr) {
for (int i=0; i<ESC_TBL_LEN; i++) {
if (strcmp (esc_tbl[i].escstr, escstr) == 0)
return (esc_tbl[i].id);
}
return (EID_LAST);
}
int Cmdb::cmdid_search(char *cmdstr) {
//Warning, we return the ID but somewhere assume it's equal to the array index!
for (int i=0; i<cmds.size(); i++) {
if ((stricmp((char*)cmds[i].cmdstr, cmdstr) == 0) && ((cmds[i].subs == subsystem) || (cmds[i].subs<0)))
return (cmds[i].cid);
}
return CID_LAST;
}
int Cmdb::cmdid_index(int cmdid) {
for (int i=0; i<cmds.size(); i++) {
if (cmds[i].cid==cmdid)
return i;
}
return -1;
}
//------------------------------------------------------------------------------
int Cmdb::parse(char *cmd) {
//Command
char cmdstr_buf [1 + MAX_CMD_LEN];
//Parameters
char argstr_buf [1 + MAX_CMD_LEN];
char *argsep;
char prmstr_buf [1 + MAX_CMD_LEN]; //copy of sscanf pattern
char *tok; //current token
void *toks[MAX_ARGS]; //pointers to string tokens IN commandline (argstr_buf)
char *prms[MAX_ARGS]; //patterns IN copy of sscanf string (*parms)
char typ = '\0'; //Var type
char mod = '\0'; //Var modifier (for cardinal types)
unsigned int base; //Var number base (8,10,16)
//unsigned int bytes; //Var size in bytes (used for malloc)
float f; //Temp var for conversion, 4 bytes
//unsigned char b; //Temp var for conversion, 1 byte
//char c; //Temp var for conversion, 1 byte
//short h; //Temp var for conversion, 2 bytes
//int k; //Temp var for conversion, 2 bytes
long l; //Temp var for conversion, 4 bytes
char* endptr; //strtoXX() Error detection
int cid = -1; //Signals empty string...
int ndx = -1;
//Init (global) variables.
argfnd=0;
argcnt=0;
error =0;
//Zero the two string buffers for splitting cmd string into.
zeromemory((char*)cmdstr_buf,sizeof(cmdstr_buf));
zeromemory(argstr_buf,sizeof(argstr_buf));
//Make it worse in Lint
for (int i=0; i<MAX_ARGS; i++) {
parms[i].type=PARM_UNUSED;
zeromemory((char*)&(parms[i].val),sizeof(parms[i].val));
}
/*------------------------------------------------
First, copy the command and convert it to all
uppercase.
------------------------------------------------*/
strncpy(cmdstr_buf, cmd, sizeof (cmdstr_buf) - 1);
cmdstr_buf [sizeof (cmdstr_buf) - 1] = '\0';
/*------------------------------------------------
Next, find the end of the first thing in the
buffer. Since the command ends with a space,
we'll look for that. NULL-Terminate the command
and keep a pointer to the arguments.
------------------------------------------------*/
argsep = strchr(cmdstr_buf, ' ');
if (argsep == NULL) {
argstr_buf [0] = '\0';
} else {
strcpy (argstr_buf, argsep + 1);
*argsep = '\0';
}
/*------------------------------------------------
Search for a command ID, then switch on it.
------------------------------------------------*/
//1) Find the Command Id
cid = cmdid_search(cmdstr_buf);
if (cid!=CID_LAST) {
//2) Tokenize a copy of the parms from the cmd_tbl.
ndx = cmdid_index(cid);
//Get Format patterns from cmd_tbl[id].parms.
//note: strtok inserts \0 into the original string. Hence the copy.
zeromemory((char *)(&prmstr_buf),sizeof(prmstr_buf));
strncpy (prmstr_buf, cmds[ndx].parms, sizeof (prmstr_buf) - 1);
argcnt=0;
tok = strtok(prmstr_buf, " ");
while (tok != NULL) {
//Store Pointers
prms[argcnt++] = tok;
//printf("prm_%2.2d='%s'\r\n",argcnt, tok);
tok = strtok(NULL, " ");
}
//3) Tokenize the commandline.
//Get Tokens from arguments.
//Note: strtok inserts \0 into the original string. Won't harm here as we do not re-use it.
argfnd=0;
if (strlen(argstr_buf)!=0) {
tok = strtok(argstr_buf, " ");
} else {
tok=NULL;
}
while (tok != NULL) {
//Store Pointers
toks[argfnd++]=tok;
//printf("tok_%2.2d='%s'\r\n",argfnd, tok);
tok = strtok(NULL, " ");
}
if (argfnd==argcnt || (cid==CID_HELP && argfnd==0)) {
error = 0;
for (int i=0; i<argcnt; i++) {
//printf("prm_%2.2d=%s\r\n",i, prms[i]);
switch (strlen(prms[i])) {
case 0:
break;
case 1:
break;
case 2: //Simple pattern, no modifier
mod='\0';
typ=prms[i][1];
break;
case 3: //pattern with Modifier.
mod=prms[i][1];
typ=prms[i][2];
break;
default:
break;
}
switch (typ) {
case 'o' :
base=8;
break;
case 'x' :
base=16;
break;
default:
base=10;
break;
}
endptr = (char*)toks[i];
switch (typ) {
//Signed Cardinal Types
case 'd' : //Check mod
case 'i' : //Check mod
switch (mod) {
case 'b' : //char
//test range
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_CHAR && l<=MAX_CHAR) {
parms[i].type=PARM_CHAR;
parms[i].val.uc =(unsigned char)l;
} else {
error = i+1;
}
break;
case 'h' : //short
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_SHORT && l<=MAX_SHORT) {
parms[i].type=PARM_SHORT;
parms[i].val.w=(short)l;
} else {
error = i+1;
}
break;
case 'l' : //long
l=strtol((char*)toks[i], &endptr, base);
parms[i].type=PARM_LONG;
parms[i].val.l=l;
break;
default: //int
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_INT && l<=MAX_INT) {
parms[i].type=PARM_INT;
parms[i].val.l=(int)l;
} else {
error = i+1;
}
break;
}
if (error==0 &&
(endptr==toks[i] //No Conversion at all.
|| *endptr)) { //Incomplete conversion.
error = i+1;
}
break;
//Unsigned Cardinal Types
case 'u' : //Check mod
case 'o' : //Check mod
case 'x' : //Check mod
switch (mod) {
case 'b' : //char
//test range
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_BYTE && l<=MAX_BYTE) {
parms[i].type=PARM_CHAR;
parms[i].val.uc =(unsigned char)l;
} else {
error = i+1;
}
break;
case 'h' : //short
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_USHORT && l<=MAX_USHORT) {
parms[i].type=PARM_SHORT;
parms[i].val.w=(short)l;
} else {
error = i+1;
}
break;
case 'l' : //long
l=strtol((char*)toks[i], &endptr, base);
parms[i].type=PARM_LONG;
parms[i].val.l=l;
break;
default: //int
l=strtol((char*)toks[i], &endptr, base);
if (l>=MIN_UINT && l<=MAX_UINT) {
parms[i].type=PARM_INT;
parms[i].val.l=(int)l;
} else {
error = i+1;
}
break;
}
if (error==0 &&
(endptr==toks[i] //No Conversion at all.
|| *endptr)) { //Incomplete conversion.
error = i+1;
}
break;
}
//Floating Point Types
switch (typ) {
case 'e' :
case 'f' :
case 'g' :
f = strtod((char*)toks[i], &endptr);
parms[i].type=PARM_FLOAT;
parms[i].val.f=f;
if (error==0 &&
(endptr==toks[i] //No Conversion at all.
|| *endptr)) { //Incomplete conversion.
error = i;
}
break;
}
//String types
switch (typ) {
case 'c' :
parms[i].type=PARM_CHAR;
parms[i].val.c=((char*)toks[i])[0];
if (error==0 && strlen((char*)toks[i])!=1) { //Incomplete conversion.
error = i;
}
break;
case 's' :
parms[i].type=PARM_STRING;
strncpy(parms[i].val.s,(char*)toks[i], strlen((char*)toks[i]));
break;
}
}
} else {
//cid=CID_LAST;
}
}
return cid;
}
//------------------------------------------------------------------------------
void Cmdb::cmd_dispatcher(char *cmd) {
int cid;
int ndx;
cid = parse(cmd);
ndx = cmdid_index(cid);
if (cid!=-1) {
//printf("cmds[%d]=%d\r\n",ndx, cid);
/*------------------------------------------------
Process the command and it's arguments that are
found. id contains the command id and argcnt &
argfnd the number of found and expected paramaters
parms contains the parsed argument values and their
types.
------------------------------------------------*/
//printf("cmds[%d]=%d\r\n",ndx, cid);
if (cid==CID_LAST) {
print("Unknown command, type 'Help' for a list of available commands.\r\n");
} else {
//printf("cmds[%d]=%d [%s]\r\n",ndx, cid, cmds[ndx].cmdstr);
//Test for more commandline than allowed too.
//i.e. run 1 is wrong.
if (argcnt==0 && argfnd==0 && error==0 && ndx!=-1 && cmds[ndx].subs==SUBSYSTEM) {
//Handle all SubSystems.
subsystem=cid;
} else if ( ((cid==CID_HELP) || (argcnt==argfnd)) && error==0 ) {
switch (cid) {
#ifdef ENABLEMACROS
/////// GLOBAL MACRO COMMANDS ///////
//Define Macro from commandline
case CID_MACRO:
macro_ptr=-1;
zeromemory((char*)macro_buf, sizeof(macro_buf));
strncpy(macro_buf, STRINGPARM(0), sizeof(macro_buf) - 1);
//DEBUG
printf("Macro=%s\r\n",macro_buf);
break;
//Run Macro
case CID_RUN:
macro_ptr=0;
break;
//List Macro's
case CID_MACROS:
print("[Macro]\r\n");
if (macro_buf[0]!='\0') {
printf("Value=%s\r\n",macro_buf);
} else {
printf(";No Macro Defined\r\n");
}
break;
#endif //ENABLEMACROS
#ifdef STATEMACHINE
/////// GLOBAL STATEMACHINE COMMANDS ///////
//Start State Machine
case CID_STATE:
statemachine(BYTEPARM(0));
break;
#endif
/////// GLOBAL COMMANDS ///////
case CID_COMMANDS:
cmd_dump();
break;
//Echo
case CID_ECHO:
echo = BOOLPARM(0);
break;
//Bold
case CID_BOLD:
bold = BOOLPARM(0);
break;
//Warm Boot
case CID_BOOT:
//mbed_reset();
break;
//Sends an ANSI escape code to clear the screen.
case CID_CLS:
print(cls);
break;
//Returns to CMD> prompt where most commands are disabled.
case CID_IDLE:
subsystem=-1;
break;
//Help
case CID_HELP: {
print("\r\n");
if (argfnd>0) {
cid = cmdid_search(STRINGPARM(0));
} else {
cid=CID_LAST;
}
if (argfnd>0 && cid!=CID_LAST) {
//Help with a valid command as first parameter
ndx = cmdid_index(cid);
switch (cmds[ndx].subs) {
case SUBSYSTEM: { //Dump whole subsystem
printf("%s subsystem commands:\r\n\r\n",cmds[ndx].cmdstr);
//Count SubSystem Commands.
int subcmds =0;
for (int i=0; i<cmds.size(); i++) {
if (cmds[i].subs==cid) {
subcmds++;
}
}
//Print SubSystem Commands.
for (int i=0; i<cmds.size()-1; i++) {
if (cmds[i].subs==cid) {
subcmds--;
if (subcmds!=0) {
cmd_help("",i,",\r\n");
} else {
cmd_help("",i,".\r\n");
}
}
}
}
break;
case GLOBALCMD: //Dump command only
//print("Global command:\r\n\r\n",cmd_tbl[cmd_tbl[ndx].subs].cmdstr);
cmd_help("Syntax: ",ndx,".\r\n");
break;
default: { //Dump one subsystem command
int sndx = cmdid_index(cmds[ndx].subs);
printf("%s subsystem command:\r\n\r\n",cmds[sndx].cmdstr);
cmd_help("Syntax: ",ndx,".\r\n");
}
break;
}
} else {
if (argfnd>0) {
//Help with invalid command as first parameter
print("Unknown command, type 'Help' for a list of available commands.\r\n");
} else {
//Help
//Dump Active Subsystem, Global & Other (dormant) Subsystems
//-1 because we want comma's and for the last a .
for (int i=0; i<cmds.size()-1; i++) {
if ((cmds[i].subs<0) || (cmds[i].subs==subsystem)) {
cmd_help("",i,",\r\n");
}
}
cmd_help("",cmds.size()-1,".\r\n");
}
}
print("\r\n");
break;
} //CID_HELP
default : {
// Do a Call to the Application's Command Dispatcher.
(*user_callback)(*this, cid);
}
}
} else {
cmd_help("Syntax: ",ndx,".\r\n");
}
}
} else {
//cid==-1
}
}
//------------------------------------------------------------------------------
//----Dump commands table as a ini file.
//------------------------------------------------------------------------------
void Cmdb::cmd_dump() {
int ndx;
int j;
int k;
int lastmod;
k = 0;
lastmod = 0;
for (ndx=0; ndx<cmds.size(); ndx++) {
#ifndef SHOWHIDDEN
if (cmds[ndx].subs==HIDDENSUB) {
continue;
}
#endif
switch (cmds[ndx].subs) {
case SUBSYSTEM :
printf("[command%2.2d]\r\n",ndx+1);
print("type=Subsystem\r\n");
print("subsystem=Global\r\n");
break;
case HIDDENSUB :
#ifdef SHOWHIDDEN
printf("[command%2.2d]\r\n",ndx+1);
print("type=HiddenSubystem\r\n");
print("subsystem=Global\r\n");
#endif
break;
case GLOBALCMD :
printf("[command%2.2d]\r\n",ndx+1);
print("type=GlobalCommand\r\n");
print("subsystem=Global\r\n");
break;
default :
int sndx = cmdid_index(cmds[ndx].subs);
if (cmds[sndx].subs==HIDDENSUB) {
#ifdef SHOWHIDDEN
printf("[command%2.2d]\r\n",ndx+1);
print("type=HiddenCommand\r\n");
print("subsystem=HiddenSubystem\r\n");
#endif
continue;
}
printf("[command%2.2d]\r\n",ndx+1);
print("type=Command\r\n");
printf("subsystem=%s\r\n",cmds[sndx].cmdstr);
}
if (cmds[ndx].subs==HIDDENSUB) {
continue;
}
printf("command=%s\r\n",cmds[ndx].cmdstr);
printf("helpmsg=%s\r\n",cmds[ndx].cmddescr);
print("parameters=");
for (j=0; j<strlen(cmds[ndx].parms); j++) {
switch (cmds[ndx].parms[j]) {
case '%' :
lastmod=0;
break;
case 'b' :
lastmod=8;
break;
case 'h' :
lastmod=16;
break;
case 'l' :
lastmod=32;
break;
case 'd' :
case 'i' : {
switch (lastmod) {
case 0 :
case 16 :
print("int");
k+=3;
break;
case 8 :
print("shortint");
k+=8;
break;
case 32:
print("longint");
k+=7;
break;
}
break;
}
case 'u' :
case 'o' :
case 'x' : {
switch (lastmod) {
case 0 :
case 16 :
print("word");
k+=4;
break;
case 8 :
print("byte");
k+=4;
break;
case 32 :
print("dword");
k+=5;
break;
}
switch (cmds[ndx].parms[j]) {
case 'o' :
print("[o]");
k+=3;
break;
case 'x' :
print("[h]");
k+=3;
break;
}
break;
}
case 'e' :
case 'f' :
case 'g' :
print("float");
k+=5;
break;
case 'c' :
print("char");
k+=4;
break;
case 's' :
print("string");
k+=6;
break;
case ' ' :
printch(sp);
k++;
break;
}
}
print("\r\n");
printf("syntax=%s\r\n",cmds[ndx].parmdescr);
}
}
void Cmdb::prompt(void) {
#ifdef SUBSYSTEMPROMPTS
if (subsystem!=-1) {
int ndx = cmdid_index(subsystem);
printf("%s>",cmds[ndx].cmdstr);
return;
}
#endif //SUBSYSTEMPROMPTS
printf(PROMPT);
}
void Cmdb::cmd_help(char *pre, int ndx, char *post) {
int j;
int k;
int lastmod;
k=0;
lastmod=0;
switch (cmds[ndx].subs) {
case SUBSYSTEM :
break;
case GLOBALCMD :
break;
case HIDDENSUB :
return;
default :
if (strlen(pre)==0 && bold) {
print(boldon);
}
break;
}
print(pre);
k+=strlen(pre);
if (k==0) {
printf("%12s",cmds[ndx].cmdstr);
k+=12;
} else {
if (strlen(pre)>0 && bold) {
print(boldon);
}
printf("%s",cmds[ndx].cmdstr);
k+=strlen(cmds[ndx].cmdstr);
if (strlen(pre)>0 && bold) {
print(boldoff);
}
}
if (strlen(cmds[ndx].parms)) {
printch(sp);
k++;
}
for (j=0; j<strlen(cmds[ndx].parms); j++) {
switch (cmds[ndx].parms[j]) {
case '%' :
lastmod=0;
break;
case 'b' :
lastmod=8;
break;
case 'h' :
lastmod=16;
break;
case 'l' :
lastmod=32;
break;
case 'd' :
case 'i' : {
switch (lastmod) {
case 0 :
case 16 :
print("int");
k+=3;
break;
case 8 :
print("shortint");
k+=8;
break;
case 32:
print("longint");
k+=7;
break;
}
break;
}
case 'u' :
case 'o' :
case 'x' : {
switch (lastmod) {
case 0 :
case 16 :
print("word");
k+=4;
break;
case 8 :
print("byte");
k+=4;
break;
case 32 :
print("dword");
k+=5;
break;
}
switch (cmds[ndx].parms[j]) {
case 'o' :
print("[o]");
k+=3;
break;
case 'x' :
print("[h]");
k+=3;
break;
}
break;
}
case 'e' :
case 'f' :
case 'g' :
print("float");
k+=5;
break;
case 'c' :
print("char");
k+=4;
break;
case 's' :
print("string");
k+=6;
break;
case ' ' :
printch(sp);
k++;
break;
}
}
for (j=k; j<40; j++) printch(sp);
switch (cmds[ndx].subs) {
case SUBSYSTEM :
if (ndx==subsystem) {
printf("- %s (active subsystem)%s",cmds[ndx].cmddescr,post);
} else {
printf("- %s (dormant subsystem)%s",cmds[ndx].cmddescr,post);
}
break;
case HIDDENSUB :
break;
case GLOBALCMD :
printf("- %s (global command)%s",cmds[ndx].cmddescr,post);
break;
default :
printf("- %s%s",cmds[ndx].cmddescr,post);
if (strlen(pre)==0 && bold) {
print(boldoff);
}
break;
}
if (strlen(pre)>0 && strlen(cmds[ndx].parmdescr)) {
printf("Params: %s",cmds[ndx].parmdescr);
print("\r\n");
}
}
//------------------------------------------------------------------------------
//----Wrappers
//------------------------------------------------------------------------------
void Cmdb::zeromemory(char *p,unsigned int siz) {
memset(p,'\0',siz);
}
int Cmdb::stricmp (char *s1, char *s2) {
int i;
int len1,len2;
len1=strlen(s1);
len2=strlen(s2);
for (i = 0; (i<len1) && (i<len2); i++) {
if ( toupper (s1[i])<toupper(s2[i]) ) return (-1);
if ( toupper (s1[i])>toupper(s2[i]) ) return (+1);
}
if (len1<len2) return (-1);
if (len1>len2) return (+1);
return (0);
}
//------------------------------------------------------------------------------
