From 149f5ee3233356176308957ed2d93a2c093a74f8 Mon Sep 17 00:00:00 2001 From: borutr Date: Tue, 10 Oct 2006 19:46:28 +0000 Subject: [PATCH] * debugger/mcs51/break.[ch], debugger/mcs51/cmd.c, debugger/mcs51/sdcdb.[ch], debugger/mcs51/simi.c: [ 1185668 ] add gnu readline support to sdcdb - prepared for READLINE, not enabled yet git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4407 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 7 + debugger/mcs51/break.c | 46 +-- debugger/mcs51/break.h | 2 + debugger/mcs51/cmd.c | 100 +++--- debugger/mcs51/sdcdb.c | 726 ++++++++++++++++++++++++++++++++++++----- debugger/mcs51/sdcdb.h | 8 + debugger/mcs51/simi.c | 4 +- 7 files changed, 735 insertions(+), 158 deletions(-) diff --git a/ChangeLog b/ChangeLog index d783487a..13ded01b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-10-10 Borut Razem + + * debugger/mcs51/break.[ch], debugger/mcs51/cmd.c, + debugger/mcs51/sdcdb.[ch], debugger/mcs51/simi.c: + [ 1185668 ] add gnu readline support to sdcdb - + prepared for READLINE, not enabled yet + 2006-10-10 Raphael Neider * src/pic16/pcode.c (pic16_pCode2str): use isACCESS_BANK macro diff --git a/debugger/mcs51/break.c b/debugger/mcs51/break.c index f3597ddb..f1c07845 100644 --- a/debugger/mcs51/break.c +++ b/debugger/mcs51/break.c @@ -27,10 +27,10 @@ #include "cmd.h" #include "newalloc.h" -static hTab *bptable = NULL; +hTab *bptable = NULL; char doingSteps = 0; char userBpPresent = 0; - + /* call stack can be 1024 deep */ STACK_DCL(callStack,function *,1024); @@ -59,7 +59,7 @@ void resetHitCount() int k; breakp *bp; for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { bp->hitCnt = 0; bp->ignoreCnt = 0; @@ -96,7 +96,7 @@ int setBreakPoint (unsigned addr, char addrType, char bpType, if (bpType == USER || bpType == TMPUSER) { for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl; - bpl = hTabNextItemWK(bptable)) + bpl = hTabNextItemWK(bptable)) { /* if also a user break point then issue Note : */ @@ -137,11 +137,11 @@ void deleteSTEPbp () Dprintf(D_break, ("break: Deleting all STEP BPs\n")); /* for break points delete if they are STEP */ for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { /* if this is a step then delete */ - if (bp->bpType == STEP) + if (bp->bpType == STEP) { hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL); Safe_free(bp); @@ -162,11 +162,11 @@ void deleteNEXTbp () /* for break points delete if they are NEXT */ for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { /* if this is a step then delete */ - if (bp->bpType == NEXT) + if (bp->bpType == NEXT) { hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL); Safe_free(bp); @@ -202,7 +202,7 @@ void deleteUSERbp (int bpnum) point matches or bpnumber == -1 (meaning delete all user break points */ if ((bp->bpType == USER || bp->bpType == TMPUSER ) - && ( bp->bpnum == bpnum || bpnum == -1)) + && ( bp->bpnum == bpnum || bpnum == -1)) { hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL); @@ -238,10 +238,10 @@ void setUserbpCommand (int bpnum, char *cmds) bpnum, cmds)); for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { if ((bp->bpType == USER || bp->bpType == TMPUSER ) - && ( bp->bpnum == bpnum )) + && ( bp->bpnum == bpnum )) { if ( bp->commands ) Safe_free(bp->commands); @@ -263,10 +263,10 @@ void setUserbpCondition (int bpnum, char *cond) bpnum, cond?cond:"")); for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { if ((bp->bpType == USER || bp->bpType == TMPUSER ) - && ( bp->bpnum == bpnum )) + && ( bp->bpnum == bpnum )) { if ( bp->condition ) Safe_free(bp->condition); @@ -288,10 +288,10 @@ void setUserbpIgnCount (int bpnum, int ignorecnt ) bpnum, ignorecnt)); for ( bp = hTabFirstItem(bptable,&k); bp ; - bp = hTabNextItem(bptable,&k)) + bp = hTabNextItem(bptable,&k)) { if ((bp->bpType == USER || bp->bpType == TMPUSER ) - && ( bp->bpnum == bpnum )) + && ( bp->bpnum == bpnum )) { bp->ignoreCnt = bp->hitCnt + ignorecnt; return; @@ -340,7 +340,7 @@ void listUSERbp () if ( bp->hitCnt > 0 ) fprintf(stdout,"\tbreakpoint already hit %d time%s\n", bp->hitCnt,bp->hitCnt>1?"s":"" ); - + } } @@ -367,13 +367,13 @@ void clearUSERbp ( unsigned int addr ) bp = hTabNextItemWK(bptable)) { /* if this is a step then delete */ - if (bp->bpType == USER || bp->bpType == TMPUSER) + if (bp->bpType == USER || bp->bpType == TMPUSER) { hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL); /* if this leaves no other break points then send command to simulator to delete bp from this addr */ - if (hTabSearch(bptable,bp->addr) == NULL) + if (hTabSearch(bptable,bp->addr) == NULL) { simClearBP(bp->addr); } @@ -409,7 +409,7 @@ int dispatchCB (unsigned addr, context *ctxt) } /* dispatch the call back functions */ - for (; bp; bp = hTabNextItemWK(bptable)) + for (; bp; bp = hTabNextItemWK(bptable)) { rv += (*bp->callBack)(addr,bp,ctxt); } @@ -434,12 +434,12 @@ BP_CALLBACK(fentryCB) ctxt->func->stkaddr = simGetValue (0x81,'I',1); Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n", - ctxt->func->sym->name, + ctxt->func->sym->name, ctxt->func->stkaddr, p_callStack)); /* and set laddr of calling function to return addr from stack */ if ((func = STACK_PEEK(callStack))) - { + { /* extern stack ?? 'A' */ func->laddr = simGetValue (ctxt->func->stkaddr-1,'B',2); } @@ -497,7 +497,7 @@ BP_CALLBACK(userBpCB) Dprintf(D_break, ("break: userBpCB: commands:%p\n", bp->commands)); setCmdLine(bp->commands); } - + if (srcMode == SRC_CMODE) { fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n", bp->bpnum, @@ -524,7 +524,7 @@ BP_CALLBACK(userBpCB) /* if this leaves no other break points then send command to simulator to delete bp from this addr */ - if (hTabSearch(bptable,bp->addr) == NULL) + if (hTabSearch(bptable,bp->addr) == NULL) { simClearBP (bp->addr); Dprintf(D_break, ("break: simClearBP 0x%x\n", bp->addr)); diff --git a/debugger/mcs51/break.h b/debugger/mcs51/break.h index c0b2e16b..062cb22e 100644 --- a/debugger/mcs51/break.h +++ b/debugger/mcs51/break.h @@ -68,6 +68,8 @@ typedef struct breakp extern char userBpPresent; extern char doingSteps; +extern hTab *bptable; + int setBreakPoint (unsigned , char , char, diff --git a/debugger/mcs51/cmd.c b/debugger/mcs51/cmd.c index 0865e0b2..059826bb 100644 --- a/debugger/mcs51/cmd.c +++ b/debugger/mcs51/cmd.c @@ -334,7 +334,7 @@ static int printOrSetSymValue (symbol *sym, context *cctxt, char *rs, char *val, char cmp); int srcMode = SRC_CMODE ; -static set *dispsymbols = NULL ; /* set of displayable symbols */ +set *dispsymbols = NULL ; /* set of displayable symbols */ static int currentFrame = 0; /* actual displayed frame */ /*-----------------------------------------------------------------*/ /* funcWithName - returns function with name */ @@ -747,20 +747,16 @@ void simGo (unsigned int gaddr) /*-----------------------------------------------------------------*/ static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym) { - char *bp = s+strlen(s) -1; + char *bp; char save_ch ; *fmt = FMT_NON; *sym = NULL; - while (isspace(*s)) s++; + s = trim(s); if (!*s) return (char *)0; - while (isspace(*bp)) bp--; - bp++ ; - *bp = '\0'; - if ( *s == '/' ) { /* format of printout */ @@ -781,7 +777,7 @@ static char *preparePrint(char *s, context *cctxt, int *fmt, symbol **sym) break; } s++; - while (isspace(*s)) s++; + s = trim_left(s); } for ( bp = s; *bp && ( isalnum( *bp ) || *bp == '_' || *bp == '$'); bp++ ); save_ch = *bp; @@ -857,14 +853,14 @@ static int cmdDisasm (char *s, context *cctxt, int args) if ( args > 0 ) { - while (*s && isspace(*s)) s++; + s = trim_left(s); if ( isdigit(*s)) { saddr = strtol(s,&s,0); if ( args > 1 ) { - while (*s && isspace(*s)) s++; + s = trim_left(s); if ( isdigit(*s)) eaddr = strtol(s,0,0); @@ -980,13 +976,8 @@ static int commonSetUserBp(char *s, context *cctxt, char bpType) fprintf(stdout,"No symbol table is loaded. Use the \"file\" command.\n"); return 0; } - /* white space skip */ - while (*s && isspace(*s)) s++; - - /* null terminate it after stripping trailing blanks*/ - bp = s + strlen(s); - while (bp != s && isspace(*bp)) bp--; - *bp = '\0'; + /* trim left and right */ + s = trim(s); /* case a) nothing */ /* if nothing given then current location : we know @@ -1148,7 +1139,7 @@ int cmdSetUserBp (char *s, context *cctxt) /*-----------------------------------------------------------------*/ int cmdJump (char *s, context *cctxt) { - char *bp ; + char *bp; function *func = NULL; if (STACK_EMPTY(callStack)) { @@ -1156,13 +1147,9 @@ int cmdJump (char *s, context *cctxt) return 0; } - /* white space skip */ - while (*s && isspace(*s)) s++; + /* trim left and right */ + s = trim(s); - /* null terminate it after stripping trailing blanks*/ - bp = s + strlen(s); - while (bp != s && isspace(*bp)) bp--; - *bp = '\0'; if (! *s ) { fprintf(stdout,"No argument: need line or *addr.\n"); @@ -1262,7 +1249,7 @@ int cmdListAsm (char *s, context *cctxt) /*-----------------------------------------------------------------*/ int cmdSetOption (char *s, context *cctxt) { - while (*s && isspace(*s)) s++; + s = trim_left(s); if (strncmp(s,"srcmode",7) == 0 ) { if (srcMode == SRC_CMODE) srcMode = SRC_AMODE; @@ -1299,7 +1286,7 @@ int cmdSetOption (char *s, context *cctxt) s = rs; while (*s && *s != '=') s++; *s++ = '\0'; - while (isspace(*s)) *s++ = '\0'; + s = trim_left(s); if (*s && sym) { printOrSetSymValue(sym,cctxt,0,0,0,rs,s,'\0'); @@ -1337,14 +1324,14 @@ int cmdContinue (char *s, context *cctxt) int cmdIgnore (char *s, context *cctxt) { int bpnum, cnt ; - while (isspace(*s)) s++; + s = trim_left(s); if (!*s ) { fprintf(stdout,"Argument required (breakpoint number).\n"); return 0; } bpnum = strtol(s,&s,10); - while (isspace(*s)) s++; + s = trim_left(s); if (!*s ) { fprintf(stdout,"Second argument (specified ignore-count) is missing."); @@ -1361,14 +1348,14 @@ int cmdIgnore (char *s, context *cctxt) int cmdCondition (char *s, context *cctxt) { int bpnum ; - while (isspace(*s)) s++; + s = trim_left(s); if (!*s ) { fprintf(stdout,"Argument required (breakpoint number).\n"); return 0; } bpnum = strtol(s,&s,10); - while (isspace(*s)) s++; + s = trim_left(s); if (*s) s = Safe_strdup(s); else @@ -1384,7 +1371,7 @@ int cmdCommands (char *s, context *cctxt) { int bpnum ; char *cmds,*line; - while (isspace(*s)) s++; + s = trim_left(s); if (!*s ) bpnum = getLastBreakptNumber(); @@ -1394,7 +1381,7 @@ int cmdCommands (char *s, context *cctxt) cmds = NULL; while ((line = getNextCmdLine())) { - while (isspace(*line)) line++; + line = trim_left(line); if (!strncmp(line,"end",3)) break; if (! cmds ) @@ -1417,7 +1404,7 @@ int cmdCommands (char *s, context *cctxt) int cmdDelUserBp (char *s, context *cctxt) { int bpnum ; - while (isspace(*s)) s++; + s = trim_left(s); if (!*s ) { if (userBpPresent) { @@ -2025,22 +2012,23 @@ static int infomode = 0; /*-----------------------------------------------------------------*/ int cmdInfo (char *s, context *cctxt) { - while (isspace(*s)) s++; + /* trim left and_right*/ + s = trim(s); /* list all break points */ - if (strncmp(s,"break",5) == 0) { + if (strcmp(s,"break") == 0) { listUSERbp(); return 0; } /* info frame same as frame */ - if (strcmp(s,"frame") == 0) { - cmdFrame (s,cctxt); + if (strncmp(s,"frame",5) == 0) { + cmdFrame (s+5,cctxt); return 0; } if (strncmp(s,"line",4) == 0) { - infomode=1; + infomode=1; cmdListSrc (s+4,cctxt); return 0; } @@ -2073,7 +2061,7 @@ int cmdInfo (char *s, context *cctxt) } return 0; } - if (strncmp(s,"functions",7) == 0) + if (strcmp(s,"functions") == 0) { function *f; module *m = NULL; @@ -2092,7 +2080,7 @@ int cmdInfo (char *s, context *cctxt) /* info stack display call stack */ if (strcmp(s,"stack") == 0) { infoStack(cctxt); - showfull = 1; + showfull = 1; return 0; } @@ -2151,7 +2139,7 @@ int cmdListSrc (char *s, context *cctxt) function *func = NULL; - while (*s && isspace(*s)) s++; + s = trim_left(s); /* if the user has spcified line numer then the line number can be of the following formats @@ -2921,7 +2909,7 @@ int conditionIsTrue( char *s, context *cctxt) } s++ ; } - while (isspace(*s)) *s++ = '\0'; + s = trim_left(s); fmt = printOrSetSymValue(sym,cctxt,0,0,0,rs,s,cmp_char); } Safe_free(dup); @@ -3034,7 +3022,7 @@ int cmdUnDisplay (char *s, context *cctxt) dsymbol *dsym; int dnum; - while (isspace(*s)) s++; + s = trim_left(s); if (!*s) { for (dsym = setFirstItem(dispsymbols); @@ -3069,14 +3057,11 @@ int cmdUnDisplay (char *s, context *cctxt) /*-----------------------------------------------------------------*/ int cmdPrintType (char *s, context *cctxt) { - symbol *sym ; - char *bp = s+strlen(s) -1; + symbol *sym ; - while (isspace(*s)) s++; + /* trim left and right */ + s = trim(s); if (!*s) return 0; - while (isspace(*bp)) bp--; - bp++ ; - *bp = '\0'; if ((sym = symLookup(s,cctxt))) { printTypeInfo(sym->type); @@ -3111,13 +3096,8 @@ int cmdClrUserBp (char *s, context *cctxt) return 0; } - /* white space skip */ - while (*s && isspace(*s)) s++; - - /* null terminate it after stripping trailing blanks*/ - bp = s + strlen(s); - while (bp != s && isspace(*bp)) bp--; - *bp = '\0'; + /* trim left and right */ + s = trim(s); /* case a) nothing */ /* if nothing given then current location : we know @@ -3274,7 +3254,7 @@ static void printFrame() /*-----------------------------------------------------------------*/ int cmdUp(char *s, context *cctxt) { - while (isspace(*s)) s++; + s = trim_left(s); if ( *s ) currentFrame += strtol(s,0,10); else @@ -3289,7 +3269,7 @@ int cmdUp(char *s, context *cctxt) /*-----------------------------------------------------------------*/ int cmdDown(char *s, context *cctxt) { - while (isspace(*s)) s++; + s = trim_left(s); if ( *s ) currentFrame -= strtol(s,0,10); else @@ -3306,7 +3286,7 @@ int cmdFrame (char *s, context *cctxt) function *func = NULL; int framenr = 0; - while (isspace(*s)) s++; + s = trim_left(s); if ( *s ) currentFrame = strtol(s,0,10); printFrame(); @@ -3346,7 +3326,7 @@ int cmdFinish (char *s, context *ctxt) int cmdShow (char *s, context *cctxt) { /* skip white space */ - while (*s && isspace(*s)) s++ ; + s = trim_left(s); if (strcmp(s,"copying") == 0) { fputs(copying,stdout); diff --git a/debugger/mcs51/sdcdb.c b/debugger/mcs51/sdcdb.c index b007cdad..4b9c8bb1 100644 --- a/debugger/mcs51/sdcdb.c +++ b/debugger/mcs51/sdcdb.c @@ -27,6 +27,10 @@ #include "break.h" #include "cmd.h" #include "newalloc.h" +#ifdef HAVE_READLINE +#include +#include +#endif /* HAVE_READLINE */ #ifdef SDCDB_DEBUG int sdcdbDebug = 0; @@ -58,151 +62,208 @@ int lineno = 0; int fatalError = 0; static void commandLoop(FILE *cmdfile); +#ifdef HAVE_READLINE +char *completionCmdSource(const char *text, int state); +char *completionCmdFile(const char *text, int state); +char *completionCmdInfo(const char *text, int state); +char *completionCmdShow(const char *text, int state); +char *completionCmdListSymbols(const char *text, int state); +char *completionCmdPrintType(const char *text, int state); +char *completionCmdPrint(const char *text, int state); +char *completionCmdDelUserBp(const char *text, int state); +char *completionCmdUnDisplay(const char *text, int state); +char *completionCmdSetUserBp(const char *text, int state); +char *completionCmdSetOption(const char *text, int state); +#else +#define completionCmdSource NULL +#define completionCmdFile NULL +#define completionCmdInfo NULL +#define completionCmdShow NULL +#define completionCmdListSymbols NULL +#define completionCmdPrintType NULL +#define completionCmdPrint NULL +#define completionCmdDelUserBp NULL +#define completionCmdUnDisplay NULL +#define completionCmdSetUserBp NULL +#define completionCmdSetOption NULL +#endif /* HAVE_READLINE */ /* command table */ struct cmdtab { char *cmd ; /* command the user will enter */ int (*cmdfunc)(char *,context *); /* function to execute when command is entered */ +#ifdef HAVE_READLINE + rl_compentry_func_t *completion_func; +#else + void *dummy; +#endif /* HAVE_READLINE */ char *htxt ; /* short help text */ } cmdTab[] = { /* NOTE:- the search is done from the top, so "break" should precede the synonym "b" */ /* break point */ - { "break" , cmdSetUserBp , + { "break" , cmdSetUserBp , completionCmdSetUserBp, "{b}reak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *
]\n", }, - { "tbreak" , cmdSetTmpUserBp , + { "tbreak" , cmdSetTmpUserBp , completionCmdSetUserBp/*same as "break"*/, "tbreak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *
]\n", }, - { "b" , cmdSetUserBp , NULL }, + { "b" , cmdSetUserBp , completionCmdSetUserBp , NULL,}, - { "jump" , cmdJump , + { "jump" , cmdJump , NULL, "jump\t\t\tContinue program being debugged at specified line or address\n [LINE | FILE:LINE | *
]\n", }, - { "clear" , cmdClrUserBp , + { "clear" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/, "{cl}ear\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n" }, - { "cl" , cmdClrUserBp , NULL }, + { "cl" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/ , NULL,}, - { "continue" , cmdContinue , + { "continue" , cmdContinue , NULL, "{c}ontinue\t\t Continue program being debugged, after breakpoint.\n" }, - { "condition" , cmdCondition , + { "condition" , cmdCondition , completionCmdDelUserBp/*same as "delete"*/, "condition brkpoint_number expr\t\tSet condition for breakpoint.\n" }, - { "ignore" , cmdIgnore , - "brkpoint_number count\t\tSet ignore count for breakpoint.\n" + { "ignore" , cmdIgnore , completionCmdDelUserBp/*same as "delete"*/, + "ignore brkpoint_number count\t\tSet ignore count for breakpoint.\n" }, - { "commands" , cmdCommands , + { "commands" , cmdCommands , completionCmdDelUserBp/*same as "delete"*/, "commands [brkpoint_number]\t\tSetting commands for breakpoint.\n" }, - { "c" , cmdContinue , NULL }, + { "c" , cmdContinue , NULL , NULL,}, - { "disassemble",cmdDisasmF , "disassemble [startaddr [endaddress]]\tdisassemble asm commands\n" }, - { "delete" , cmdDelUserBp , + { "disassemble",cmdDisasmF , NULL, "disassemble [startaddr [endaddress]]\tdisassemble asm commands\n" }, + { "delete" , cmdDelUserBp , completionCmdDelUserBp, "{d}elete n\t\t clears break point number n\n" }, - { "display" , cmdDisplay , + { "display" , cmdDisplay , completionCmdPrint/*same as "print"*/, "display [/] []\t print value of given variable each time the program stops\n" }, - { "undisplay" , cmdUnDisplay , + { "undisplay" , cmdUnDisplay , completionCmdUnDisplay, "undisplay []\t dont display this variable or all\n" }, - { "down" , cmdDown , + { "down" , cmdDown , NULL, "down\t\tSelect and print stack frame called by this one.\nAn argument says how many frames down to go.\n" }, - { "up" , cmdUp , + { "up" , cmdUp , NULL, "up\t\tSelect and print stack frame that called this one.\nAn argument says how many frames up to go.\n" }, - { "d" , cmdDelUserBp , NULL }, + { "d" , cmdDelUserBp , completionCmdDelUserBp, NULL }, - { "info" , cmdInfo , - "info \n" + { "info" , cmdInfo , completionCmdInfo, + "info \n" "\t list all break points, call-stack, frame or register information\n" }, - { "listasm" , cmdListAsm , + { "listasm" , cmdListAsm , NULL, "listasm {la}\t\t list assembler code for the current C line\n" }, - { "la" , cmdListAsm , NULL }, - { "ls" , cmdListSymbols , "ls,lf,lm\t\t list symbols,functions,modules\n" }, - { "lf" , cmdListFunctions, NULL }, - { "lm" , cmdListModules , NULL }, - { "list" , cmdListSrc , + { "la" , cmdListAsm , NULL, NULL }, + { "ls" , cmdListSymbols , completionCmdListSymbols, "ls,lf,lm\t\t list symbols,functions,modules\n" }, + { "lf" , cmdListFunctions, completionCmdListSymbols, NULL }, + { "lm" , cmdListModules , completionCmdListSymbols, NULL }, + { "list" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/, "{l}ist\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n" }, - { "l" , cmdListSrc , NULL }, - { "show" , cmdShow , + { "l" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/, NULL }, + { "show" , cmdShow , completionCmdShow, "show" " \t copying & distribution terms, warranty\n" }, - { "set" , cmdSetOption , "set \t\t toggle between c/asm.\nset variable = >value\t\tset variable to new value\n" }, - { "stepi" , cmdStepi , + { "set" , cmdSetOption , completionCmdSetOption, "set \t\t toggle between c/asm.\nset variable = >value\t\tset variable to new value\n" }, + { "stepi" , cmdStepi , NULL, "stepi\t\t\tStep one instruction exactly.\n" }, - { "step" , cmdStep , + { "step" , cmdStep , NULL, "{s}tep\t\t\tStep program until it reaches a different source line.\n" }, - { "source" , cmdSource , + { "source" , cmdSource , completionCmdSource, "source \t\t\tRead commands from a file named FILE.\n" }, - { "s" , cmdStep , NULL }, - { "nexti" , cmdNexti , + { "s" , cmdStep , NULL, NULL }, + { "nexti" , cmdNexti , NULL, "nexti\t\t\tStep one instruction, but proceed through subroutine calls.\n" }, - { "next" , cmdNext , + { "next" , cmdNext , NULL, "{n}ext\t\t\tStep program, proceeding through subroutine calls.\n" }, - { "n" , cmdNext , NULL }, - { "run" , cmdRun , + { "n" , cmdNext , NULL, NULL }, + { "run" , cmdRun , NULL, "{r}un\t\t\tStart debugged program. \n" }, - { "r" , cmdRun , NULL }, - { "ptype" , cmdPrintType , + { "r" , cmdRun , NULL, NULL }, + { "ptype" , cmdPrintType , completionCmdPrintType, "{pt}ype \tprint type information of a variable\n" }, - { "pt" , cmdPrintType , NULL }, - { "print" , cmdPrint , + { "pt" , cmdPrintType , NULL, NULL }, + { "print" , cmdPrint , completionCmdPrintType, "{p}rint \t print value of given variable\n" }, - { "output" , cmdOutput , + { "output" , cmdOutput , completionCmdPrint/*same as "print"*/, "output \t print value of given variable without $ and newline \n" }, - { "p" , cmdPrint , NULL }, - { "file" , cmdFile , + { "p" , cmdPrint , completionCmdPrintType, NULL }, + { "file" , cmdFile , completionCmdFile, "file \t\t load symbolic information from \n" }, - { "frame" , cmdFrame , + { "frame" , cmdFrame , NULL, "{fr}ame\t\t print information about the current Stack\n" }, - { "finish" , cmdFinish , + { "finish" , cmdFinish , NULL, "{fi}nish\t\t execute till return of current function\n" }, - { "fi" , cmdFinish , NULL }, - { "where" , cmdWhere , "where\t\t print stack\n" }, - { "fr" , cmdFrame , NULL }, - { "f" , cmdFrame , NULL }, - { "x /i" , cmdDisasm1 , "x\t\t disassemble one asm command\n" }, - { "!" , cmdSimulator , + { "fi" , cmdFinish , NULL, NULL }, + { "where" , cmdWhere , NULL, "where\t\t print stack\n" }, + { "fr" , cmdFrame , NULL, NULL }, + { "f" , cmdFrame , NULL, NULL }, + { "x /i" , cmdDisasm1 , NULL, "x\t\t disassemble one asm command\n" }, + { "!" , cmdSimulator , NULL, "!\t send a command directly to the simulator\n" }, - { "." , cmdSimulator , + { "." , cmdSimulator , NULL, ".{cmd}\t switch from simulator or debugger command mode\n" }, - { "help" , cmdHelp , + { "help" , cmdHelp , NULL, "{h|?}elp\t [CMD_NAME | 0,1,2,3(help page)] (general help or specific help)\n" }, - { "?" , cmdHelp , NULL }, - { "h" , cmdHelp , NULL }, + { "?" , cmdHelp , NULL, NULL }, + { "h" , cmdHelp , NULL, NULL }, - { "quit" , cmdQuit , + { "quit" , cmdQuit , NULL, "{q}uit\t\t\t \"Watch me now. Iam going Down. My name is Bobby Brown\"\n" }, - { "q" , cmdQuit , NULL } + { "q" , cmdQuit , NULL, NULL } }; +/*-----------------------------------------------------------------*/ +/* trimming functions */ +/*-----------------------------------------------------------------*/ +char *trim_left(char *s) +{ + while (isspace(*s)) + ++s; + + return s; +} + +char *trim_right(char *s) +{ + char *p = &s[strlen(s)]; + + while (p > s && isspace(*--p)) + ; + *p = '\0'; + + return s; +} + +char *trim(char *s) +{ + return trim_right(trim_left(s)); +} + /*-----------------------------------------------------------------*/ /* gc_strdup - make a string duplicate garbage collector aware */ /*-----------------------------------------------------------------*/ @@ -655,7 +716,8 @@ int cmdFile (char *s,context *cctxt) char buffer[128]; char *bp; - while (isspace(*s)) s++; + s = trim_left(s); + if (!*s) { fprintf(stdout,"No exec file now.\nNo symbol file now.\n"); return 0; @@ -718,13 +780,8 @@ int cmdFile (char *s,context *cctxt) int cmdSource (char *s, context *cctxt) { FILE *cmdfile; - char *bp = s+strlen(s) -1; - while (isspace(*s)) - ++s; - - while (isspace(*bp)) bp--; - *++bp = '\0'; + s = trim(s); if (!( cmdfile = searchDirsFopen(s))) { @@ -745,8 +802,8 @@ int cmdHelp (char *s, context *cctxt) int endline = 999; int startline = 0; - while (isspace(*s)) - ++s; + s = trim_left(s); + if (isdigit(*s)) { endline = ((*s - '0') * 20) + 20; if (endline > 0) @@ -812,8 +869,8 @@ int interpretCmd (char *s) } else pcmd = strdup(s); - /* lookup the command table and do the task required */ - strtok(s,"\n"); + /* trim tailing blanks */ + s = trim_right(s); if (sim_cmd_mode) { if (strcmp(s,".") == 0) { @@ -901,13 +958,531 @@ void stopCommandList() stopcmdlist = 1; } +#ifdef HAVE_READLINE +// helper function for doing readline completion. +// input: toknum=index of token to find (0=first token) +// output: *start=first character index of the token, +// or the index of '\0' +// *end=first blank character right after the token, +// or the index of '\0' +// return value: 0=token not found, 1=token found +int completionHelper_GetTokenNumber(int toknum, int *start, int *end) +{ + int tok_index; + const char *p = rl_line_buffer; + + tok_index = 0; + *start = *end = 0; + while (p[*end] != 0) + { + // start = skip blanks from end + *start = *end; + while (p[*start] && isblank( p[*start] )) + (*start)++; + + // end = skip non-blanks from start + *end = *start; + while (p[*end] && !isblank( p[*end] )) + (*end)++; + + if (tok_index == toknum) + return 1; // found + + tok_index++; + } + + return 0; // not found +} + +// helper function for doing readline completion. +// returns the token number that we were asked to complete. +// 0=first token (command name), 1=second token... +int completionHelper_GetCurrTokenNumber() +{ + int toknum, start, end; + + toknum = start = end = 0; + while (1) + { + if (!completionHelper_GetTokenNumber(toknum, &start, &end)) + return toknum; + + if (rl_point <= end) + return toknum; + + toknum++; + } +} + +// exapmle for vallist on entry: +// "copying\0warranty\0"; +char *completionCompleteFromStrList(const char *text, int state, char *vallist) +{ + static char *ptr; + int len; + + if (state == 0) + ptr = vallist; + else + ptr += strlen(ptr)+1; + + len = strlen(text); + while (*ptr) + { + if ( (len < strlen(ptr)) && + !strncmp(text, ptr, len) ) + return strdup(ptr); + + ptr += strlen(ptr)+1; + } + + return NULL; +} + +// readline library completion function. +// completes from the list of all sdcdb command. +char *completionCommandsList(const char *text, int state) +{ + static int i = 0; + + if (state == 0) // new completion? + { // yes, only complete if this is the first token on the line. + int ok = 0; // try to complete this request? + char *p = rl_line_buffer; + + // skip blanks + while (p && isblank(*p)) + { + if (p-rl_line_buffer == rl_point) + ok = 1; + p++; + } + + while (p && !isblank(*p)) + { + if (p-rl_line_buffer == rl_point) + ok = 1; + p++; + } + + if (p-rl_line_buffer == rl_point) + ok = 1; + + if ( !ok ) + return NULL; // no more completions + + i = 0; // ok, gonna complete. initialize static variable. + } + else i++; + + for (; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) + { + int len = strlen(text); + if (len <= strlen(cmdTab[i].cmd)) + { + if (strncmp(text,cmdTab[i].cmd,len) == 0) + return strdup(cmdTab[i].cmd); + } + } + + return NULL; // no more completions +} + +// readline library completion function. +// completes from the list of symbols. +char *completionSymbolName(const char *text, int state) +{ + static symbol *sy; + + if (state == 0) // new completion? + sy = setFirstItem(symbols); // yes + else + sy = setNextItem(symbols); + + for (; sy != NULL; ) + { + int len = strlen(text); + if (len <= strlen(sy->name)) + { + if (strncmp(text,sy->name,len) == 0) + return strdup(sy->name); + } + + sy = setNextItem(symbols); + } + return NULL; +} + +// readline library completion function. +// completes from the list known functions. +// module_flag - if false, ignore function module name +// if true, compare against module_name:fnction_name +char *completionFunctionName(const char *text, int state, int module_flag) +{ + static function *f; + + if (state == 0) // new completion? + f = setFirstItem(functions); // yes + else + f = setNextItem(functions); + + for (; f != NULL; ) + { + int text_len = strlen(text); + + if (!module_flag) + { + if (text_len <= strlen(f->sym->name) && + !strncmp(text,f->sym->name,text_len)) + return strdup(f->sym->name); + } + else + { + int modname_len = strlen(f->mod->c_name); + int funcname_len = strlen(f->sym->name); + char *functext = malloc(modname_len+funcname_len+2); + //assert(functext); + strcpy(functext,f->mod->c_name); + strcat(functext,":"); + strcat(functext,f->sym->name); + if (text_len <= strlen(functext) && + !strncmp(text,functext,text_len)) + return functext; + else + free(functext); + } + f = setNextItem(functions); + } + return NULL; +} + +// readline library completion function. +// completes from the list known modules. +char *completionModuleName(const char *text, int state) +{ + static module *m; + + if (state == 0) // new completion? + m = setFirstItem(modules); // yes + else + m = setNextItem(modules); + + for (; m != NULL; ) + { + int len = strlen(text); + if ( (len <= strlen(m->c_name)) && + !strncmp(text,m->c_name,len) ) + return strdup(m->c_name); + + if ( (len <= strlen(m->asm_name)) && + (strncmp(text,m->asm_name,len) == 0) ) + return strdup(m->asm_name); + + m = setNextItem(modules); + } + return NULL; +} + +// readline completion function for "file" command +char *completionCmdFile(const char *text, int state) +{ + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + } + + // we use filename_completion_function() from the readline library. + return rl_filename_completion_function(text, state); +} + +// readline completion function for "source" command +char *completionCmdSource(const char *text, int state) +{ + return completionCmdFile(text, state); +} + +// readline completion function for "info" command +char *completionCmdInfo(const char *text, int state) +{ + static char *ptr; + + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + } + + return completionCompleteFromStrList(text, state, + "break\0stack\0frame\0registers\0all-registers\0" + "line\0source\0functions\0symbols\0variables\0"); +} + +// readline completion function for "show" command +char *completionCmdShow(const char *text, int state) +{ + static char *ptr; + + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + } + return completionCompleteFromStrList(text, state, "copying\0warranty\0"); +} + +// readline completion function for "la" command +char *completionCmdListSymbols(const char *text, int state) +{ + static char *ptr; + + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + } + return completionCompleteFromStrList(text, state, "v1\0v2\0"); +} + +char *completionCmdPrintType(const char *text, int state) +{ + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + } + return completionSymbolName(text, state); +} + +char *completionCmdPrint(const char *text, int state) +{ + if (state == 0) + { + int i = completionHelper_GetCurrTokenNumber(); + if (i != 1 && i != 2) + return NULL; + } + return completionSymbolName(text, state); +} + +char *completionCmdDelUserBp(const char *text, int state) +{ + static breakp *bp; + static int k; + + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + + if (!userBpPresent) + return NULL; + + bp = hTabFirstItem(bptable,&k); + } + else + bp = hTabNextItem(bptable,&k); + + for ( ; bp ; bp = hTabNextItem(bptable,&k)) + { + if (bp->bpType == USER || bp->bpType == TMPUSER) + { + char buff[20]; + sprintf(buff, "%d", bp->bpnum); + return strdup(buff); + } + } + + return NULL; +} + +// readline completion function for "undisplay" command +char *completionCmdUnDisplay(const char *text, int state) +{ + static dsymbol *dsym; + + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + dsym = setFirstItem(dispsymbols); + } + + if (dsym) + { + char buff[30]; + sprintf(buff, "%d", dsym->dnum); + dsym = setNextItem(dispsymbols); + return strdup(buff); + } + return NULL; +} + +char *completionCmdSetUserBp(const char *text, int state) +{ + static int internal_state; // 0=calling completionFunctionName(text, state, 0) + // 1=calling completionFunctionName(text, 1, 1) + if (state == 0) + { + if (completionHelper_GetCurrTokenNumber() != 1) + return NULL; + + internal_state = 0; + } + if (internal_state == 0) + { + char *p = completionFunctionName(text, state, 0); + if (p) + return p; + internal_state = 1; + return completionFunctionName(text, 0, 1); + } + else + { + return completionFunctionName(text, 1, 1); + } +} + +char *completionCmdSetOption(const char *text, int state) +{ + static char *ptr; + static int currtok; + + if (state == 0) + { + int start,end; + + currtok = completionHelper_GetCurrTokenNumber(); + + if (currtok == 2 || currtok == 3) + { + // make sure token 1 == "variable" + completionHelper_GetTokenNumber(1, &start, &end); + if (end - start != 8 || + strncmp(rl_line_buffer+start,"variable",8)) + return NULL; + } + else if (currtok != 1) + { + return NULL; + } + } + + switch (currtok) + { + case 1: + return completionCompleteFromStrList(text, state, +#ifdef SDCDB_DEBUG + "debug\0" +#endif + "srcmode\0listsize\0variable\0"); + case 2: + return completionSymbolName(text, state); + + case 3: + return completionCompleteFromStrList(text, state, "=\0"); + } +} + +// our main readline completion function +// calls the other completion functions as needed. +char *completionMain(const char *text, int state) +{ + static rl_compentry_func_t *compl_func; + int i, start, end, len; + + if (state == 0) // new completion? + { + compl_func = NULL; + + if (completionHelper_GetCurrTokenNumber() == 0) + compl_func = &completionCommandsList; + else + { // not completing first token, find the right completion + // function according to the first token the user typed. + completionHelper_GetTokenNumber(0, &start, &end); + len = end-start; + + for (i=0; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) + { + if (!strncmp(rl_line_buffer+start,cmdTab[i].cmd,len) && + cmdTab[i].cmd[len] == '\0') + { + compl_func = cmdTab[i].completion_func; + break; + } + } + } + if (!compl_func) + return NULL; + } + + return (*compl_func)(text,state); +} +#endif /* HAVE_READLINE */ + /*-----------------------------------------------------------------*/ /* commandLoop - the main command loop or loop over command file */ /*-----------------------------------------------------------------*/ static void commandLoop(FILE *cmdfile) { char *line, save_ch, *s; + char *line_read; + +#ifdef HAVE_READLINE + FILE *old_rl_instream, *old_rl_outstream; actualcmdfile = cmdfile; + + rl_completion_entry_function = completionMain; + rl_readline_name = "sdcdb"; // Allow conditional parsing of the ~/.inputrc file. + + // save readline's input/output streams + // this is done to support nested calls to commandLoop() + // i wonder if it works... + old_rl_instream = rl_instream; + old_rl_outstream = rl_outstream; + + // set new streams for readline + if ( cmdfile == stdin ) + rl_instream = rl_outstream = NULL; // use stdin/stdout pair + else + rl_instream = rl_outstream = cmdfile; + + while (1) + { + if ( cmdfile == stdin ) + { + if (sim_cmd_mode) + line_read = (char*)readline ("(sim)"); + else + line_read = (char*)readline ("(sdcdb)"); + } + else + line_read = (char*)readline (""); + + if (line_read) + { + /* If the line has any text in it, + save it on the history. */ + if (line_read && *line_read) + add_history (line_read); + + // FIX: readline returns malloced string. + // should check the source to verify it can be used + // directly. for now - just copy it to cmdbuff. + strcpy(cmdbuff,line_read); +#if defined(_WIN32) || defined(HAVE_RL_FREE) + rl_free(line_read); +#else + free(line_read); +#endif + line_read = NULL; + } + else + break; // EOF +#else + actualcmdfile = cmdfile; + while (1) { if ( cmdfile == stdin ) @@ -918,14 +1493,14 @@ static void commandLoop(FILE *cmdfile) fprintf(stdout,"(sdcdb) "); fflush(stdout); } - //fprintf(stderr,"commandLoop actualcmdfile=%p cmdfile=%p\n", // actualcmdfile,cmdfile); if (fgets(cmdbuff,sizeof(cmdbuff),cmdfile) == NULL) break; +#endif /* HAVE_READLINE */ - if (interpretCmd(cmdbuff)) - break; + if (interpretCmd(cmdbuff)) + break; while ( actualcmds ) { @@ -955,6 +1530,11 @@ static void commandLoop(FILE *cmdfile) } } } +#ifdef HAVE_READLINE + // restore readline's input/output streams + rl_instream = old_rl_instream; + rl_outstream = old_rl_outstream; +#endif /* HAVE_READLINE */ } /*-----------------------------------------------------------------*/ diff --git a/debugger/mcs51/sdcdb.h b/debugger/mcs51/sdcdb.h index 8328e178..d3eaab8b 100644 --- a/debugger/mcs51/sdcdb.h +++ b/debugger/mcs51/sdcdb.h @@ -251,6 +251,8 @@ extern set *modules ; /* set of modules */ extern set *functions; /* set of functions */ extern set *symbols ; /* set of symbols */ extern set *sfrsymbols;/* set of symbols of sfr or sbit */ +extern set *dispsymbols; /* set of displayable symbols */ + extern char *currModName ; extern char userinterrupt ; @@ -271,4 +273,10 @@ char *searchDirsFname (char *); char *getNextCmdLine(void ); void setCmdLine( char * ); void stopCommandList( void ); + +/* trimming functions */ +extern char *trim_left(char *s); +extern char *trim_right(char *s); +extern char *trim(char *s); + #endif diff --git a/debugger/mcs51/simi.c b/debugger/mcs51/simi.c index 1e9089e5..31242505 100644 --- a/debugger/mcs51/simi.c +++ b/debugger/mcs51/simi.c @@ -589,7 +589,7 @@ unsigned long simGetValue (unsigned int addr,char mem, int size) case of bit variables which case it becomes [address] [assembler bit address] [v] */ /* first skip thru white space */ - while (isspace(*resp)) resp++ ; + resp = trim_left(resp); if (strncmp(resp, "0x",2) == 0) resp += 2; @@ -611,7 +611,7 @@ unsigned long simGetValue (unsigned int addr,char mem, int size) for (i = 0 ; i < size ; i++ ) { /* skip white space */ - while (isspace(*resp)) resp++ ; + resp = trim_left(resp); b[i] = strtol(resp,&resp,16); } -- 2.47.2