📄 cli.c
字号:
/************************************************************* * File: mon/cli.c * Purpose: Command line interface for MON * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970216 Start of revision history * 970216 Switched over to using addCmdRec() * 970303 trace_mode removed. * 970409 Switched over to using addEnvRec() * 971007 Removed %s from printf on break in gotintr * 980420 Added ifndef around flush_target for NON_CACHED build * 980602 Added shrc_needed to delay execution of shrc cmds. * 980715 Added arg to shrc() call. * 980717 Always flush D then I for copyback D caches. * 980725 Added compare command. */#include <setjmp.h>#include <signal.h>#include <string.h>#include <mon.h>#include <termio.h>#include <stdio.h>#define PREGS /* enable pseudo regs */jmp_buf intrbuf;int xvwmode; /* crossview mode */int noecho;char prnbuf[LINESZ];char line[LINESZ];CmdRec *cmdChain;extern int clilst,*curlst;extern int shrc_needed;int gotintr();char *badhexsym = "%s: neither hex value nor symbol\n";Optdesc sh_opts[] = { {"","The command shell"}, {"^P","recall previous cmd"}, {"^N","recall next cmd"}, {"^F","move cursor right"}, {"^B","move cursor left"}, {"^A","move cursor far left"}, {"^E","move cursor far right"}, {"^D","delete char at cursor"}, {"^H","delete char before cursor"}, {"",""}, {"!!","repeat last cmd"}, {"!str","recall and execute cmd str"}, {"!num","recall and execute cmd num"}, {"",""}, {"+-*/()","operators"}, {"^addr","contents of address"}, {"@name","contents of register"}, {"&name","value of symbol"}, {"0xnum","hex number"}, {"0onum","octal number"}, {"0tnum","decimal number"}, {0}};int do_vers();char full_vers_info[80];Optdesc vers_opts[] = { {"[-a]","display version info"}, {"-a","display all version info"}, {0}};#ifdef CROSSVIEWint do_cp(),do_echo(),do_sc(),do_gc(),do_sr(),do_mr();int gmx(),smx(),do_init(),do_lo();#endifextern Optdesc ab_opts[];int ab_cmd();CmdRec moncmds[] = { {"h",h_opts,help}, {"hi",hi_opts,dohi}, {"m",m_opts,modify}, {"r",r_opts,registers}, {"d",d_opts,dump}, {"l",l_opts,dis}, {"copy",copy_opts,copy}, {"fill",fill_opts,fill}, {"search",search_opts,search}, {"compare",compare_opts,compare_cmd}, {"when",w_opts,when}, {"g",g_opts,go}, {"c",c_opts,cont}, {"t",t_opts,trace}, {"to",to_opts,trace}, {"b",b_opts,setbp}, {"db",db_opts,clrbp}, {"sym",sym_opts,do_sym}, {"ls",ls_opts,do_ls}, {"set",set_opts,do_set}, {"vers",vers_opts,do_vers}, {"sh",sh_opts,no_cmd}, {"more",more_opts,no_cmd},#ifdef GDB_SUPPORT {"debug",debug_opts,debug},#endif {"ab",ab_opts,ab_cmd}, /* access (data) bpts */#ifdef CROSSVIEW {"xvw",crossview_opts,no_cmd}, {"cp",0,do_cp}, /* copy memory range */ {"echo",0,do_echo}, /* echo args */ {"sc",0,do_sc}, /* set config */ {"gc",0,do_gc}, /* get config */ {"sr",0,do_sr}, /* set register */ {"mr",0,do_mr}, /* display modified regs */ {"gmb",0,gmx}, /* get memory as bytes */ {"smb",0,smx}, /* set memory as bytes */ {"gmh",0,gmx}, /* get memory as half-words */ {"smh",0,smx}, /* set memory as half-words */ {"gmw",0,gmx}, /* get memory as words */ {"smw",0,smx}, /* set memory as words */ {"lo",0,do_lo}, /* binary download */ {"init",0,do_init}, /* warm (cold) reboot */#endif {0}};/************************************************************** moninit()*/moninit(){int i;for (i=0;moncmds[i].name;i++) addCmdRec(&moncmds[i]);histinit();envinit();ioctl_setup(STDIN);c0regNames = regs_hw;c2cRegNames = regs_hw;c2dRegNames = regs_hw;if (!matchenv("regstyle")) regnames = regs_hw;else regnames = regs_sw;}/************************************************************** monmain()* Called after moninit has been executed* o Prompts for commands and calls do_cmd to execute them* o The setjmp is used to pass control back here if a ^C is typed*/monmain(){int i,t1,rptcmd;char prompt[20],tmp[8],*p,*t;char buf[100];Ulong adr;#ifdef PMCCioctl(STDIN,SETINTR,intrbuf);if (setjmp(intrbuf) == 1) { /* on INTR */ if (curlst == &clilst && regChain) { /* 970826 */ adr = getPc(); disasm(buf,adr,read_target(XT_MEM,adr,4)); printf("break!\n%s\n",buf); /* 971007 */ } else printf("break!\n"); /* 971007 */ }#elsesetjmp(intrbuf);if (signal(SIGINT,SIG_IGN) != SIG_IGN) signal(SIGINT,gotintr);#endifdisableints();swlst(1);if (bptTmpId != -1) { clrbpt(bptTmpId); bptTmpId = -1; }if (shrc_needed) { shrc_needed = 0; shrc(1); }while (1) { ioctl_restore(STDIN); /* in case it has been left in a funny state */#ifndef NON_CACHED flush_target(DCACHE); flush_target(ICACHE);#endif if (!*line) { /* line is empty */ /* don't hang if the env var is bad */ if (getMonEnv("prompt")) strcpy(prompt,getMonEnv("prompt")); else strcpy(prompt,"BAD> "); if (p = strchr(prompt,'!')) { strdchr(p); /* delete the bang */ sprintf(tmp,"%d",histno); stristr(p,tmp); } printf("%s",prompt); get_cmd(line); if (!*line || strempty(line)) { /* blank */ rptcmd = matchenv("rptcmd"); if (rptcmd) { /* repeat requested */ t = gethistn(histno-1); if (rptcmd == 1) strcpy(line,t); /* all cmds */ else if (rptcmd == 2) { /* trace only */ if (wordsz(t) > 10) continue; getword(tmp,t); if (strequ(tmp,"t")||strequ(tmp,"to")) strcpy(line,tmp); else continue; } else { printf("bad rptcmd value [%s]\n", getMonEnv("rptcmd")); continue; } } else continue; } } do_cmd(line); }}#if 0/************************************************************** gotintr()*/gotintr(){char buf[100];Ulong adr;signal(SIGINT,gotintr);if (curlst == &clilst && regChain) { /* 970826 */ adr = getPc(); disasm(buf,adr,read_target(XT_MEM,adr,4)); printf("break!\n%s\n",buf); /* 971007 */ }else printf("break!\n"); /* 971007 */longjmp(intrbuf,0);}#endif/************************************************************** do_cmd(p)* execute a command, the string pointed to by p.* warning: p does get written to* o Commands are invoked as if executed from a standard command* shell. i.e. they are passed an argc/argv argument list.*/do_cmd(cmd)char *cmd;{char *av[MAX_AC]; /* argument holder */int ac; /* # of arguments */char *t,tmp[200];int i,c,r;CmdRec *p;for (;*cmd;) { /* look for ';' that is not enclosed within "" or '' */ for (t=cmd;*t;) { c = *t; if(c == '\'' || c == '"') { t++; while(*t && *t != c) ++t; if(*t) t++; } else if (c == ';') break; else t++; } /* copy the 1st cmd into tmp, and then remove it from cmd */ strNcpy(tmp,cmd,t-cmd); if (c == ';') i = (t-cmd)+1; else i = t-cmd; for (;i>0;i--) strdchr(cmd); /* find and then execute the command specified in tmp */ ac = argvize(av,tmp); if(ac > 0) { if (strequ(av[0],"stop")) return(1); for (p=cmdChain;p;p=p->next) if (strequ(p->name,av[0])) break; if (p) (p->func)(ac,av,p); else printf("%s: Command not found.\n",av[0]); } }return(0);}Optdesc h_opts[] = { {"[*|cmd..]","The help command"}, {0}};/************************************************************** help(ac,av)* the 'help' command*/help(ac,av)int ac;char *av[];{int i,j,namemax,optsmax,descmax,len;int ln,siz;CmdRec *p;namemax = optsmax = descmax = 0;for (p=cmdChain;p;p=p->next) { len = strlen(p->name); if (len > namemax) namemax = len; if (p->opts) { if (p->opts->name) { len = strlen(p->opts->name); if (len > optsmax) optsmax = len; } if (p->opts->desc) { len = strlen(p->opts->desc); if (len > descmax) descmax = len; } } }if (!atob(&siz,getMonEnv("moresz"),10)) { printf("%s: bad moresz value\n",getMonEnv("moresz")); return(1); }ioctl_cbreak(0L);ln = siz;if (ac >= 2) { /* extended help */ if (strequ(av[1],"*")) { /* all commands */ for (p=cmdChain;p;p=p->next) { if (prhelp(p,&ln,siz,namemax,optsmax)) break; } } else { /* specific commands */ for (j=1;j<ac;j++) { for (p=cmdChain;p;p=p->next) { if (strequ(p->name,av[j])) break; } if (p) { if (prhelp(p,&ln,siz,namemax,optsmax)) break; } else printf("%s: Command not found\n",av[j]); } } }else { /* general help only */ for (p=cmdChain,i=0;p;p=p->next) { if (!p->opts) continue; printf("%*s %-*s",namemax,p->name,descmax,p->opts->desc); if (i%2 != 0) printf("\n"); else printf(" "); i++; } if (i%2 != 0) printf("\n"); }return(0);}/************************************************************** prhelp(n,lnp,siz,namemax,optsmax)*/prhelp(p,lnp,siz,namemax,optsmax)int *lnp,siz,namemax,optsmax;CmdRec *p;{Optdesc *o;int i;if (!p->opts) return(0);sprintf(prnbuf,"%*s %-*s %s",namemax,p->name,optsmax, p->opts->name, p->opts->desc);if (more(prnbuf,lnp,siz)) return(1);o = p->opts;if (o) { for (i=1;o[i].name;i++) { sprintf(prnbuf,"%*s %15s %s",namemax,"", o[i].name,o[i].desc); if (more(prnbuf,lnp,siz)) return(1); } }return(0);}/************************************************************** no_cmd(ac,av)*/no_cmd(ac,av)int ac;char *av[];{printf("The %s command cannot be invoked by name.\n",av[0]);return(0);}/************************************************************** printfb(fmt,a1,a2,a3,a4)* A buffered printf used for printing the PMON banner.*/printfb(fmt,a1,a2,a3,a4)char *fmt;Ulong a1,a2,a3,a4;{char tmp[80];int len,islf;islf = 0;sprintf(tmp,fmt,a1,a2,a3,a4);len = strlen(tmp);if (len == 0) return(0);if (!strcmp(fmt,"\n")) islf = 1;if ((strlen(prnbuf)+len) > 70 || islf) { printf("\n"); *prnbuf = 0; }if (strlen(prnbuf)) strcat(prnbuf," ");strcat(prnbuf,tmp);printf("%s ",tmp);}/************************************************************** get_rsa(vp,p)* Get Register/Symbol/Address* This function evaluates expressions on the command line* using recursive decent. It understands expressions* containing any combination of register names, symbols,* constants, perens, and the operators +-* /. In addition* it also permits the '^' operator to dereference any* address.*/get_rsa(vp,p)unsigned long *vp;char *p;{int r,inbase,inalpha;unsigned long v1,v2;char *q,subexpr[LINESZ];/* strip enclosing parens */while (*p == '(' && strbalp(p) == p+strlen(p)-1) { strdchr(p); p[strlen(p)-1] = 0; }if (q=strrpset(p,"+-")) { /* is compound */ strNcpy(subexpr,p,q-p); r = get_rsa(&v1,subexpr); if (r == 0) return(r); r = get_rsa(&v2,q+1); if (r == 0) return(r); if (*q == '+') *vp = v1 + v2; else *vp = v1 - v2; return(1); }if (q=strrpset(p,"*/")) { strNcpy(subexpr,p,q-p); r = get_rsa(&v1,subexpr); if (r == 0) return(r); r = get_rsa(&v2,q+1); if (r == 0) return(r); if (*q == '*') *vp = v1 * v2; else *vp = v1 / v2; return(1); }if (*p == '^') { r = get_rsa(&v2,p+1); if (r == 0) return(r); *vp = read_target(XT_MEM,v2,4); return(1); }if (*p == '@') {#ifdef PREGS /* preg */ if (ispreg(&p[1])) { *vp = getPreg(p[1]-'a'); r = 1; } else { r = getreg(vp,&p[1]); if (r == 0) printf("%s: bad register name\n",&p[1]); }#else r = getreg(vp,&p[1]); if (r == 0) printf("%s: bad register name\n",&p[1]);#endif }else if (strequ(p,".")) { r = getreg(vp,"pc"); if (r == 0) printf("%s: bad register name\n",&p[1]); }else if (*p == '&') { r = sym2adr(vp,&p[1]); if (r == 0) printf("%s: bad symbol name\n",&p[1]); }else if (isdigit(*p)) { inbase = matchenv("inbase"); if (inbase == IB_TEN) r = atob(vp,p,10); else if (inbase == IB_SIXTEEN) r = atob(vp,p,16); else if (inbase == IB_EIGHT) r = atob(vp,p,8); else if (inbase == IB_AUTO) r = atob(vp,p,0); else { printf("%s: bad inbase value\n",getMonEnv("inbase")); return(0); } if (r == 0) { r = atob(vp,p,0); if (r == 0) printf("%s: bad base %s value\n", p,getMonEnv("inbase")); } }else if (isxdigit(*p)) { inalpha = matchenv("inalpha"); if (inalpha == IA_HEX) { r = atob(vp,p,16); if (r == 0) { r = sym2adr(vp,p); if (r == 0) printf(badhexsym,p); } } else if (inalpha == IA_SYMBOL) { r = sym2adr(vp,p); if (r == 0) { r = atob(vp,p,16); if (r == 0) printf(badhexsym,p); } } else { printf("%s: bad inalpha value\n",getMonEnv("inalpha")); return(0); } }else { r = sym2adr(vp,p); if (r == 0) printf("%s: bad symbol name\n",p); }return(r);}/************************************************************** stop(cmdstr)*/stop(cmdstr)char *cmdstr;{char cmd[LINESZ];#ifdef CROSSVIEWif (xvwmode) longjmp(intrbuf,2);#endifif (cmdstr) strcpy(cmd,cmdstr);else strcpy(cmd,getMonEnv("brkcmd"));do_cmd(cmd);longjmp(intrbuf,2);}/************************************************************** addCmdRec(p)* add a CmdRec to the cmdChain*/addCmdRec(p)CmdRec *p;{CmdRec *q;p->next = 0;if (!cmdChain) { /* empty */ cmdChain = p; }else { for (q=cmdChain;q->next;q=q->next) ; /* find end of chain */ q->next = p; }}/************************************************************** do_vers(ac,av)* display version number*/do_vers(ac,av)int ac;char *av[];{if (ac == 1) printf("%s\n",vers);else printf("%s\n",full_vers_info);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -