X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=debugger%2Fmcs51%2Fsdcdb.c;h=8df52526574ae2c77fc29e30d94becfd3d10f9d0;hb=HEAD;hp=f23dba382323e584626d477e2f6742312c660f29;hpb=331ae7a198d9092d6c3b0588572c70812810bfc6;p=fw%2Fsdcc diff --git a/debugger/mcs51/sdcdb.c b/debugger/mcs51/sdcdb.c index f23dba38..8df52526 100644 --- a/debugger/mcs51/sdcdb.c +++ b/debugger/mcs51/sdcdb.c @@ -21,133 +21,257 @@ what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ +#define link unix_link +#define _GNU_SOURCE +#include +#undef link #include "sdcdb.h" #include "symtab.h" #include "simi.h" #include "break.h" #include "cmd.h" #include "newalloc.h" +#if defined HAVE_LIBREADLINE && HAVE_LIBREADLINE != -1 +#define HAVE_READLINE_COMPLETITION 1 +#endif +#ifdef HAVE_LIBREADLINE +#include +#include +#endif /* HAVE_LIBREADLINE */ + +#ifdef SDCDB_DEBUG +int sdcdbDebug = 0; +#endif char *currModName = NULL; cdbrecs *recsRoot = NULL ; set *modules = NULL; /* set of all modules */ set *functions = NULL ; /* set of functions */ set *symbols = NULL ; /* set of symbols */ +set *sfrsymbols= NULL ; /* set of symbols of sfr or sbit */ int nStructs = 0 ; structdef **structs = NULL ; /* all structures */ int nLinkrecs = 0; linkrec **linkrecs = NULL; /* all linkage editor records */ context *currCtxt = NULL; short fullname = 0; -char *ssdirl = SDCC_LIB_DIR ":" SDCC_LIB_DIR "/small" ; -char *simArgs[8]; +short showfull = 0; +char userinterrupt = 0; +char nointerrupt = 0; +char contsim = 0; +char *ssdirl = DATADIR LIB_DIR_SUFFIX ":" DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "small" ; +char *simArgs[40]; int nsimArgs = 0; - +char model_str[20]; /* fake filename & lineno to make linker */ char *filename=NULL; +char *current_directory; int lineno = 0; int fatalError = 0; +static void commandLoop(FILE *cmdfile); +#ifdef HAVE_READLINE_COMPLETITION +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_COMPLETITION */ + /* 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_COMPLETITION + rl_compentry_func_t *completion_func; +#else + void *dummy; +#endif /* HAVE_READLINE_COMPLETITION */ 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 , - "{b}reak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n", + { "break" , cmdSetUserBp , completionCmdSetUserBp, + "{b}reak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *
]\n", + }, + { "tbreak" , cmdSetTmpUserBp , completionCmdSetUserBp/*same as "break"*/, + "tbreak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *
]\n", }, - { "b" , cmdSetUserBp , NULL }, + { "b" , cmdSetUserBp , completionCmdSetUserBp , NULL,}, - { "clear" , cmdClrUserBp , + { "jump" , cmdJump , NULL, + "jump\t\t\tContinue program being debugged at specified line or address\n [LINE | FILE:LINE | *
]\n", + }, + { "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" }, - { "c" , cmdContinue , NULL }, + { "condition" , cmdCondition , completionCmdDelUserBp/*same as "delete"*/, + "condition brkpoint_number expr\t\tSet condition for breakpoint.\n" + }, + { "ignore" , cmdIgnore , completionCmdDelUserBp/*same as "delete"*/, + "ignore brkpoint_number count\t\tSet ignore count for breakpoint.\n" + }, + { "commands" , cmdCommands , completionCmdDelUserBp/*same as "delete"*/, + "commands [brkpoint_number]\t\tSetting commands for breakpoint.\n" + }, + { "c" , cmdContinue , NULL , NULL,}, - { "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" }, - { "d" , cmdDelUserBp , NULL }, - - { "help" , cmdHelp , - "{h|?}elp\t\t this message\n" + { "display" , cmdDisplay , completionCmdPrint/*same as "print"*/, + "display [/] []\t print value of given variable each time the program stops\n" + }, + { "undisplay" , cmdUnDisplay , completionCmdUnDisplay, + "undisplay []\t dont display this variable or all\n" }, - { "?" , cmdHelp , NULL }, - { "h" , cmdHelp , NULL }, + { "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 , NULL, + "up\t\tSelect and print stack frame that called this one.\nAn argument says how many frames up to go.\n" + }, + { "d" , cmdDelUserBp , completionCmdDelUserBp, NULL }, - { "info" , cmdInfo , - "info\n" - "\t {break}\t list all break points\n" - "\t {stack}\t information about call stack\n" - "\t {frame}\t current frame information\n" - "\t {registers}\t display value of all registers\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 }, - { "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 , - "show\n" - "\t {copying}\t copying & distribution terms\n" - "\t {warranty}\t warranty information\n" + { "l" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/, NULL }, + { "show" , cmdShow , completionCmdShow, + "show" + " \t copying & distribution terms, warranty\n" + }, + { "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 , NULL, + "{s}tep\t\t\tStep program until it reaches a different source line.\n" }, - { "set" , cmdSetOption , NULL }, - { "step" , cmdStep , - "{s}tep\t\t\t Step program until it reaches a different source line.\n" + { "source" , cmdSource , completionCmdSource, + "source \t\t\tRead commands from a file named FILE.\n" }, - { "s" , cmdStep , NULL }, - { "next" , cmdNext , - "{n}ext\t\t\t Step program, proceeding through subroutine calls.\n" + { "s" , cmdStep , NULL, NULL }, + { "nexti" , cmdNexti , NULL, + "nexti\t\t\tStep one instruction, but proceed through subroutine calls.\n" }, - { "n" , cmdNext , NULL }, - { "run" , cmdRun , - "{r}un\t\t\t Start debugged program. \n" + { "next" , cmdNext , NULL, + "{n}ext\t\t\tStep program, proceeding through subroutine calls.\n" }, - { "r" , cmdRun , NULL }, - { "ptype" , cmdPrintType , - "{pt}ype \t print type information of a variable\n" + { "n" , cmdNext , NULL, NULL }, + { "run" , cmdRun , NULL, + "{r}un\t\t\tStart debugged program. \n" }, - { "pt" , cmdPrintType , NULL }, - { "print" , cmdPrint , + { "r" , cmdRun , NULL, NULL }, + { "ptype" , cmdPrintType , completionCmdPrintType, + "{pt}ype \tprint type information of a variable\n" + }, + { "pt" , cmdPrintType , NULL, NULL }, + { "print" , cmdPrint , completionCmdPrintType, "{p}rint \t print value of given variable\n" }, - { "p" , cmdPrint , NULL }, - { "file" , cmdFile , + { "output" , cmdOutput , completionCmdPrint/*same as "print"*/, + "output \t print value of given variable without $ and newline \n" + }, + { "p" , cmdPrint , completionCmdPrintType, NULL }, + { "file" , cmdFile , completionCmdFile, "file \t\t load symbolic information from \n" }, - { "frame" , cmdFrame , - "{fr}ame\t\t\t print information about the current Stack\n" + { "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 }, - { "fr" , cmdFrame , NULL }, - { "f" , cmdFrame , NULL }, - { "!" , 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" }, - { "quit" , cmdQuit , + { "." , cmdSimulator , NULL, + ".{cmd}\t switch from simulator or debugger command mode\n" + }, + { "help" , cmdHelp , NULL, + "{h|?}elp\t [CMD_NAME | 0,1,2,3(help page)] (general help or specific help)\n" + }, + { "?" , cmdHelp , NULL, NULL }, + { "h" , cmdHelp , NULL, NULL }, + + { "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) - 1]; + + while (p >= s && isspace(*p)) + --p; + *++p = '\0'; + + return s; +} + +char *trim(char *s) +{ + return trim_right(trim_left(s)); +} + /*-----------------------------------------------------------------*/ /* gc_strdup - make a string duplicate garbage collector aware */ /*-----------------------------------------------------------------*/ @@ -167,7 +291,7 @@ char *alloccpy ( char *s, int size) char *d; if (!size) - return NULL; + return NULL; d = Safe_malloc(size+1); memcpy(d,s,size); @@ -184,13 +308,13 @@ void **resize (void **array, int newSize) void **vptr; if (array) - vptr = Safe_realloc(array,newSize*(sizeof(void **))); + vptr = Safe_realloc(array,newSize*(sizeof(void **))); else - vptr = calloc(1, sizeof(void **)); + vptr = calloc(1, sizeof(void **)); if (!vptr) { - fprintf(stderr,"sdcdb: out of memory \n"); - exit(1); + fprintf(stderr,"sdcdb: out of memory \n"); + exit(1); } return vptr; @@ -208,49 +332,49 @@ static int readCdb (FILE *file) char *bp ; if (!(bp = fgets(buffer,sizeof(buffer),file))) - return 0; + return 0; currl = Safe_calloc(1,sizeof(cdbrecs)); recsRoot = currl ; while (1) { - /* make sure this is a cdb record */ - if (strchr("STLFM",*bp) && *(bp+1) == ':') { - /* depending on the record type */ - - switch (*bp) { - case 'S': - /* symbol record */ - currl->type = SYM_REC; - break; - case 'T': - currl->type = STRUCT_REC; - break; - case 'L': - currl->type = LNK_REC; - break; - case 'F': - currl->type = FUNC_REC; - break; - case 'M': - currl->type = MOD_REC ; - } - - bp += 2; - currl->line = Safe_malloc(strlen(bp)); - strncpy(currl->line,bp,strlen(bp)-1); - currl->line[strlen(bp)-1] = '\0'; - } - - if (!(bp = fgets(buffer,sizeof(buffer),file))) - break; - - if (feof(file)) - break; - - currl->next = Safe_calloc(1,sizeof(cdbrecs)); - currl = currl->next; + /* make sure this is a cdb record */ + if (strchr("STLFM",*bp) && *(bp+1) == ':') { + /* depending on the record type */ + + switch (*bp) { + case 'S': + /* symbol record */ + currl->type = SYM_REC; + break; + case 'T': + currl->type = STRUCT_REC; + break; + case 'L': + currl->type = LNK_REC; + break; + case 'F': + currl->type = FUNC_REC; + break; + case 'M': + currl->type = MOD_REC ; + } + + bp += 2; + currl->line = Safe_malloc(strlen(bp)); + strncpy(currl->line,bp,strlen(bp)-1); + currl->line[strlen(bp)-1] = '\0'; + } + + if (!(bp = fgets(buffer,sizeof(buffer),file))) + break; + + if (feof(file)) + break; + + currl->next = Safe_calloc(1,sizeof(cdbrecs)); + currl = currl->next; } return (recsRoot->line ? 1 : 0); @@ -263,16 +387,16 @@ char *searchDirsFname (char *fname) { char *dirs , *sdirs; FILE *rfile = NULL; - char buffer[128]; + char buffer[1024]; /* first try the current directory */ if ((rfile = fopen(fname,"r"))) { - fclose(rfile); - return strdup(fname) ; + fclose(rfile); + return strdup(fname) ; } if (!ssdirl) - return strdup(fname); + return strdup(fname); /* make a copy of the source directories */ dirs = sdirs = strdup(ssdirl); @@ -281,21 +405,21 @@ char *searchDirsFname (char *fname) and try for each directory in the search list */ dirs = strtok(dirs,":"); while (dirs) { - if (dirs[strlen(dirs)] == '/') - sprintf(buffer,"%s%s",dirs,fname); - else - sprintf(buffer,"%s/%s",dirs,fname); - if ((rfile = fopen(buffer,"r"))) - break ; - dirs = strtok(NULL,":"); + if (dirs[strlen(dirs)] == '/') + sprintf(buffer,"%s%s",dirs,fname); + else + sprintf(buffer,"%s/%s",dirs,fname); + if ((rfile = fopen(buffer,"r"))) + break ; + dirs = strtok(NULL,":"); } free(sdirs); if (rfile) { - fclose(rfile); - return strdup(buffer); + fclose(rfile); + return strdup(buffer); } else - return strdup(fname); + return strdup(fname); } /*-----------------------------------------------------------------*/ @@ -305,14 +429,14 @@ FILE *searchDirsFopen(char *fname) { char *dirs , *sdirs; FILE *rfile = NULL; - char buffer[128]; + char buffer[1024]; /* first try the current directory */ if ((rfile = fopen(fname,"r"))) - return rfile; + return rfile; if (!ssdirl) - return NULL; + return NULL; /* make a copy of the source directories */ dirs = sdirs = strdup(ssdirl); @@ -320,10 +444,10 @@ FILE *searchDirsFopen(char *fname) and try for each directory in the search list */ dirs = strtok(dirs,":"); while (dirs) { - sprintf(buffer,"%s/%s",dirs,fname); - if ((rfile = fopen(buffer,"r"))) - break ; - dirs = strtok(NULL,":"); + sprintf(buffer,"%s/%s",dirs,fname); + if ((rfile = fopen(buffer,"r"))) + break ; + dirs = strtok(NULL,":"); } free(sdirs); @@ -343,17 +467,18 @@ srcLine **loadFile (char *name, int *nlines) if (!(mfile = searchDirsFopen(name))) { - fprintf(stderr,"sdcdb: cannot open module %s -- use '--directory= option\n",name); - return NULL; + fprintf(stderr,"sdcdb: cannot open module %s -- use '--directory= option\n",name); + return NULL; } while ((bp = fgets(buffer,sizeof(buffer),mfile))) { - (*nlines)++; + (*nlines)++; - slines = (srcLine **)resize((void **)slines,*nlines); + slines = (srcLine **)resize((void **)slines,*nlines); - slines[(*nlines)-1] = Safe_calloc(1,sizeof(srcLine)); - slines[(*nlines)-1]->src = alloccpy(bp,strlen(bp)); + slines[(*nlines)-1] = Safe_calloc(1,sizeof(srcLine)); + slines[(*nlines)-1]->src = alloccpy(bp,strlen(bp)); + slines[(*nlines)-1]->addr= INT_MAX; } fclose(mfile); @@ -364,7 +489,7 @@ srcLine **loadFile (char *name, int *nlines) /*-----------------------------------------------------------------*/ /* loadModules - reads the source files into module structure */ /*-----------------------------------------------------------------*/ -static void loadModules () +static void loadModules (void) { cdbrecs *loop; module *currMod; @@ -374,167 +499,198 @@ static void loadModules () records & load the modules specified */ for ( loop = recsRoot ; loop ; loop = loop->next ) { - switch (loop->type) { - /* for module records do */ - case MOD_REC: - currMod = parseModule(loop->line,TRUE); - currModName = currMod->name ; - - currMod->cfullname = searchDirsFname(currMod->c_name); - - /* load it into buffer */ - currMod->cLines = loadFile (currMod->c_name, - &currMod->ncLines); - - /* do the same for the assembler file */ - currMod->afullname = searchDirsFname(currMod->asm_name); - currMod->asmLines=loadFile (currMod->asm_name, - &currMod->nasmLines); - break; - - /* if this is a function record */ - case FUNC_REC: - parseFunc(loop->line); - break; - - /* if this is a structure record */ - case STRUCT_REC: - parseStruct(loop->line); - break; - - /* if symbol then parse the symbol */ - case SYM_REC: - parseSymbol(loop->line,&rs); - break; - - case LNK_REC: - parseLnkRec(loop->line); - break; - } + switch (loop->type) { + /* for module records do */ + case MOD_REC: + currMod = parseModule(loop->line, TRUE); + currModName = currMod->name ; + + currMod->cfullname = searchDirsFname(currMod->c_name); + + /* load it into buffer */ + currMod->cLines = loadFile (currMod->c_name, + &currMod->ncLines); + + /* do the same for the assembler file */ + currMod->afullname = searchDirsFname(currMod->asm_name); + currMod->asmLines=loadFile (currMod->asm_name, + &currMod->nasmLines); + break; + + /* if this is a function record */ + case FUNC_REC: + parseFunc(loop->line); + break; + + /* if this is a structure record */ + case STRUCT_REC: + parseStruct(loop->line); + break; + + /* if symbol then parse the symbol */ + case SYM_REC: + parseSymbol(loop->line,&rs,2); + break; + + case LNK_REC: + parseLnkRec(loop->line); + break; + } } } /*-----------------------------------------------------------------*/ -/* functionPoints - determine the execution points within a func */ +/* generate extra sets of sfr and sbit symbols */ /*-----------------------------------------------------------------*/ -static void functionPoints () +static void specialFunctionRegs (void) { - function *func; symbol *sym; - - /* for all functions do */ - for ( func = setFirstItem(functions); func; - func = setNextItem(functions)) { - int j ; - module *mod; - - sym = func->sym; - -#ifdef SDCDB_DEBUG - printf("func '%s' has entry '%x' exit '%x'\n", - func->sym->name, - func->sym->addr, - func->sym->eaddr); -#endif - if (!func->sym->addr && !func->sym->eaddr) - continue ; - - /* for all source lines in the module find - the ones with address >= start and <= end - and put them in the point */ - mod = NULL ; - if (! applyToSet(modules,moduleWithName,func->modName,&mod)) - continue ; - func->mod = mod ; - func->entryline= INT_MAX; - func->exitline = 0; - func->aentryline = INT_MAX ; - func->aexitline = 0; - - /* do it for the C Lines first */ - for ( j = 0 ; j < mod->ncLines ; j++ ) { - if (mod->cLines[j]->addr >= sym->addr && - mod->cLines[j]->addr <= sym->eaddr ) { - - exePoint *ep ; - - /* add it to the execution point */ - if (func->entryline > j) - func->entryline = j; - - if (func->exitline < j) - func->exitline = j; - - ep = Safe_calloc(1,sizeof(exePoint)); - ep->addr = mod->cLines[j]->addr ; - ep->line = j; - ep->block= mod->cLines[j]->block; - ep->level= mod->cLines[j]->level; - addSet(&func->cfpoints,ep); - } - } - - /* do the same for asm execution points */ - for ( j = 0 ; j < mod->nasmLines ; j++ ) { - if (mod->asmLines[j]->addr >= sym->addr && - mod->asmLines[j]->addr <= sym->eaddr ) { - - exePoint *ep ; - /* add it to the execution point */ - if (func->aentryline > j) - func->aentryline = j; - - if (func->aexitline < j) - func->aexitline = j; - - /* add it to the execution point */ - ep = Safe_calloc(1,sizeof(exePoint)); - ep->addr = mod->asmLines[j]->addr ; - ep->line = j; - addSet(&func->afpoints,ep); - } - } - -#ifdef SDCDB_DEBUG - printf("function '%s' has the following C exePoints\n", - func->sym->name); - { - exePoint *ep; - - for (ep = setFirstItem(func->cfpoints); ep; - ep = setNextItem(func->cfpoints)) - fprintf (stdout,"{%x,%d} %s",ep->addr,ep->line,mod->cLines[ep->line]->src); - - fprintf(stdout," and the following ASM exePoints\n"); - for (ep = setFirstItem(func->afpoints); ep; - ep = setNextItem(func->afpoints)) - fprintf (stdout,"{%x,%d} %s",ep->addr,ep->line,mod->asmLines[ep->line]->src); - - } -#endif + for (sym = setFirstItem(symbols); + sym ; + sym = setNextItem(symbols)) + { + if ( sym->addrspace == 'I' || + sym->addrspace == 'J') + { + addSet(&sfrsymbols,sym); + } } } - - /*-----------------------------------------------------------------*/ -/* setEntryExitBP - set the entry & exit Break Points for functions*/ +/* functionPoints - determine the execution points within a func */ /*-----------------------------------------------------------------*/ -DEFSETFUNC(setEntryExitBP) +static void functionPoints (void) { - function *func = item; + function *func; + symbol *sym; + exePoint *ep ; - if (func->sym && func->sym->addr && func->sym->eaddr) { + // add _main dummy for runtime env + if ((func = needExtraMainFunction())) + { + function *func1; + + /* alloc new _main function */ + func1 = Safe_calloc(1,sizeof(function)); + *func1 = *func; + func1->sym = Safe_calloc(1,sizeof(symbol)); + *func1->sym = *func->sym; + func1->sym->name = alloccpy("_main",5); + func1->sym->rname = alloccpy("G$_main$0$",10); + /* TODO must be set by symbol information */ + func1->sym->addr = 0; + func1->sym->eaddr = 0x2f; + addSet(&functions,func1); + } - /* set the entry break point */ - setBreakPoint (func->sym->addr , CODE , FENTRY , - fentryCB ,func->mod->c_name , func->entryline); + /* for all functions do */ + for ( func = setFirstItem(functions); func; + func = setNextItem(functions)) { + int j ; + module *mod; + + sym = func->sym; + + Dprintf(D_sdcdb, ("sdcdb: func '%s' has entry '0x%x' exit '0x%x'\n", + func->sym->name, + func->sym->addr, + func->sym->eaddr)); + + if (!func->sym->addr && !func->sym->eaddr) + continue ; + + /* for all source lines in the module find + the ones with address >= start and <= end + and put them in the point */ + mod = NULL ; + if (! applyToSet(modules,moduleWithName,func->modName,&mod)) + continue ; + func->mod = mod ; + func->entryline= INT_MAX-2; + func->exitline = 0; + func->aentryline = INT_MAX-2 ; + func->aexitline = 0; + + /* do it for the C Lines first */ + for ( j = 0 ; j < mod->ncLines ; j++ ) { + if (mod->cLines[j]->addr < INT_MAX && + mod->cLines[j]->addr >= sym->addr && + mod->cLines[j]->addr <= sym->eaddr ) { + + + /* add it to the execution point */ + if (func->entryline > j) + func->entryline = j; + + if (func->exitline < j) + func->exitline = j; + + ep = Safe_calloc(1,sizeof(exePoint)); + ep->addr = mod->cLines[j]->addr ; + ep->line = j; + ep->block= mod->cLines[j]->block; + ep->level= mod->cLines[j]->level; + addSet(&func->cfpoints,ep); + } + } + /* check double line execution points of module */ + for (ep = setFirstItem(mod->cfpoints); ep; + ep = setNextItem(mod->cfpoints)) + { + if (ep->addr >= sym->addr && + ep->addr <= sym->eaddr ) + { + addSet(&func->cfpoints,ep); + } + } + /* do the same for asm execution points */ + for ( j = 0 ; j < mod->nasmLines ; j++ ) { + if (mod->asmLines[j]->addr < INT_MAX && + mod->asmLines[j]->addr >= sym->addr && + mod->asmLines[j]->addr <= sym->eaddr ) { + + exePoint *ep ; + /* add it to the execution point */ + if (func->aentryline > j) + func->aentryline = j; + + if (func->aexitline < j) + func->aexitline = j; + + /* add it to the execution point */ + ep = Safe_calloc(1,sizeof(exePoint)); + ep->addr = mod->asmLines[j]->addr ; + ep->line = j; + addSet(&func->afpoints,ep); + } + } + if ( func->entryline == INT_MAX-2 ) + func->entryline = 0; + if ( func->aentryline == INT_MAX-2 ) + func->aentryline = 0; - /* set the exit break point */ - setBreakPoint (func->sym->eaddr , CODE , FEXIT , - fexitCB ,func->mod->c_name , func->exitline ); +#ifdef SDCDB_DEBUG + if (!( D_sdcdb & sdcdbDebug)) + continue; + + Dprintf(D_sdcdb, ("sdcdb: function '%s' has the following C exePoints\n", + func->sym->name)); + { + exePoint *ep; + + for (ep = setFirstItem(func->cfpoints); ep; + ep = setNextItem(func->cfpoints)) + Dprintf(D_sdcdb, ("sdcdb: {0x%x,%d} %s", + ep->addr,ep->line+1,mod->cLines[ep->line]->src)); + + Dprintf(D_sdcdb, ("sdcdb: and the following ASM exePoints\n")); + for (ep = setFirstItem(func->afpoints); ep; + ep = setNextItem(func->afpoints)) + Dprintf (D_sdcdb, ("sdcdb: {0x%x,%d} %s", + ep->addr,ep->line+1,mod->asmLines[ep->line]->src)); + } +#endif } - - return 0; } /*-----------------------------------------------------------------*/ @@ -543,29 +699,32 @@ DEFSETFUNC(setEntryExitBP) int cmdFile (char *s,context *cctxt) { FILE *cdbFile; - char buffer[128]; + char buffer[1024]; 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; + fprintf(stdout,"No exec file now.\nNo symbol file now.\n"); + return 0; } sprintf(buffer,"%s.cdb",s); /* try creating the cdbfile */ if (!(cdbFile = searchDirsFopen(buffer))) { - fprintf(stdout,"Cannot open file\"%s\"",buffer); - return 0; + fprintf(stdout,"Cannot open file\"%s\", no symbolic information loaded\n",buffer); + // return 0; } /* allocate for context */ currCtxt = Safe_calloc(1,sizeof(context)); - /* readin the debug information */ - if (!readCdb (cdbFile)) { - fprintf(stdout,"No symbolic information found in file %s.cdb\n",s); - return 0; + if (cdbFile) { + /* readin the debug information */ + if (!readCdb (cdbFile)) { + fprintf(stdout,"No symbolic information found in file %s.cdb\n",s); + //return 0; + } } /* parse and load the modules required */ @@ -575,8 +734,16 @@ int cmdFile (char *s,context *cctxt) module */ functionPoints(); + /* extract known special function registers */ + specialFunctionRegs(); + /* start the simulator & setup connection to it */ - openSimulator((char **)simArgs,nsimArgs); +#ifdef _WIN32 + if (INVALID_SOCKET == sock) +#else + if ( sock == -1 ) +#endif + openSimulator((char **)simArgs,nsimArgs); fprintf(stdout,"%s",simResponse()); /* now send the filename to be loaded to the simulator */ sprintf(buffer,"%s.ihx",s); @@ -587,9 +754,28 @@ int cmdFile (char *s,context *cctxt) /*set the break points required by the debugger . i.e. the function entry and function exit break points */ - applyToSet(functions,setEntryExitBP); +// applyToSet(functions,setEntryExitBP); + + setMainContext(); + return 0; +} + +/*-----------------------------------------------------------------*/ +/* cmdSource - read commands from file */ +/*-----------------------------------------------------------------*/ +int cmdSource (char *s, context *cctxt) +{ + FILE *cmdfile; + + s = trim(s); - /* ad we are done */ + if (!( cmdfile = searchDirsFopen(s))) + { + fprintf(stderr,"commandfile '%s' not found\n",s); + return 0; + } + commandLoop( cmdfile ); + fclose( cmdfile ); return 0; } @@ -599,67 +785,136 @@ int cmdFile (char *s,context *cctxt) int cmdHelp (char *s, context *cctxt) { int i ; + int endline = 999; + int startline = 0; + + s = trim_left(s); + + if (isdigit(*s)) { + endline = ((*s - '0') * 20) + 20; + if (endline > 0) + startline = endline - 20; + } + else if (*s) + { + for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) + { + if ((cmdTab[i].htxt) && !strcmp(cmdTab[i].cmd,s)) + { + s = strrchr(cmdTab[i].htxt,'\t'); + if ( !s ) + s = cmdTab[i].htxt; + else + s++; + fprintf(stdout,"%s",s); + break; + } + } + return 0; + } for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) { - /* command string matches */ - if (cmdTab[i].htxt) - fprintf(stdout,"%s",cmdTab[i].htxt); + /* command string matches */ + + if ((cmdTab[i].htxt) && (i >= startline)) + fprintf(stdout,"%s",cmdTab[i].htxt); + if (i == endline) + break; } return 0; } #define MAX_CMD_LEN 512 -char *prompt = "(sdcdb) "; -char cmdbuff[MAX_CMD_LEN]; +static char cmdbuff[MAX_CMD_LEN]; +static int sim_cmd_mode = 0; -/*-----------------------------------------------------------------*/ -/* interpretCmd - interpret and do the command */ -/*-----------------------------------------------------------------*/ +char * +canonname(char *file) +{ + static char buffer[1024]; + if (*file == '/') + return file; + sprintf(buffer,"%s/%s", current_directory, file); + return buffer; +} + +/*----------------------------------------------------------------- + interpretCmd - interpret and do the command. Return 0 to continue, + return 1 to exit program. +|-----------------------------------------------------------------*/ int interpretCmd (char *s) { static char *pcmd = NULL; int i ; int rv = 0 ; + /* if nothing & previous command exists then execute the previous command again */ - if (*s == '\n' && pcmd) - strcpy(s,pcmd); + if ((*s == '\n' || *s == '\0') && pcmd) + strcpy(s,pcmd); + /* if previous command exists & is different from the current command then copy it */ if (pcmd) { - if (strcmp(pcmd,s)) { - free(pcmd); - pcmd = strdup(s); - } + if (strcmp(pcmd,s)) { + free(pcmd); + pcmd = strdup(s); + } } else - pcmd = strdup(s); - /* lookup the command table and do the - task required */ - strtok(s,"\n"); + pcmd = strdup(s); + + /* trim trailing blanks */ + s = trim_right(s); + + if (sim_cmd_mode) { + if (strcmp(s,".") == 0) { + sim_cmd_mode = 0; + return 0; + } + else if (s[0] == '.') { + /* kill the preceeding '.' and pass on as SDCDB command */ + char *s1 = s+1; + char *s2 = s; + while (*s1 != 0) + *s2++ = *s1++; + *s2 = 0; + } else { + cmdSimulator (s, currCtxt); + return 0; + } + } else { + if (strcmp(s,".") ==0) { + sim_cmd_mode = 1; + return 0; + } + } for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) { - /* command string matches */ - if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) { - if (!cmdTab[i].cmdfunc) - return 1; - rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt); - - /* if full name then give the file name & position */ - if (fullname && currCtxt && currCtxt->func) { - if (srcMode == SRC_CMODE) - fprintf(stdout,"\032\032%s:%d:1\n", - currCtxt->func->mod->cfullname, - currCtxt->cline+1); - else - fprintf(stdout,"\032\032%s:%d:1\n", - currCtxt->func->mod->afullname, - currCtxt->asmline+1); - } - goto ret; - } + /* command string matches */ + if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) { + if (!cmdTab[i].cmdfunc) + return 1; + + rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt); + + /* if full name then give the file name & position */ + if (fullname && showfull && currCtxt && currCtxt->func) { + showfull = 0; + if (srcMode == SRC_CMODE) + fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n", + canonname(currCtxt->func->mod->cfullname), + currCtxt->cline+1,currCtxt->addr); + else + fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n", + canonname(currCtxt->func->mod->afullname), + currCtxt->asmline,currCtxt->addr); + displayAll(currCtxt); + } + goto ret; + } } fprintf(stdout,"Undefined command: \"%s\". Try \"help\".\n",s); @@ -667,36 +922,630 @@ int interpretCmd (char *s) return rv; } +static FILE *actualcmdfile=NULL ; +static char *actualcmds=NULL; +static int stopcmdlist; /*-----------------------------------------------------------------*/ -/* commandLoop - the main command loop */ +/* getNextCmdLine get additional lines used by special commands */ /*-----------------------------------------------------------------*/ -void commandLoop() +char *getNextCmdLine(void) { + //fprintf(stderr,"getNextCmdLine() actualcmdfile=%p\n",actualcmdfile); + if (!actualcmdfile) + return NULL; + fprintf(stdout,">"); + fflush(stdout); + if (fgets(cmdbuff,sizeof(cmdbuff),actualcmdfile) == NULL) + { + // fprintf(stderr,"getNextCmdLine() returns null\n"); + return NULL; + } + //fprintf(stderr,"getNextCmdLine() returns: %s",cmdbuff); + return cmdbuff; +} - while (1) { - fprintf(stdout,"%s",prompt); - fflush(stdout); +void setCmdLine( char *cmds ) +{ + actualcmds = cmds; +} - if (fgets(cmdbuff,sizeof(cmdbuff),stdin) == NULL) - break; +void stopCommandList() +{ + stopcmdlist = 1; +} + +#ifdef HAVE_READLINE_COMPLETITION +// 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] && isspace( p[*start] )) + (*start)++; + + // end = skip non-blanks from start + *end = *start; + while (p[*end] && !isspace( 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; - if (interpretCmd(cmdbuff)) - break; + 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 && isspace(*p)) + { + if (p-rl_line_buffer == rl_point) + ok = 1; + p++; + } + + while (p && !isspace(*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_COMPLETITION */ + +/*-----------------------------------------------------------------*/ +/* 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_LIBREADLINE + FILE *old_rl_instream, *old_rl_outstream; + actualcmdfile = cmdfile; + +#ifdef HAVE_READLINE_COMPLETITION + rl_completion_entry_function = completionMain; +#endif /* HAVE_READLINE_COMPLETITION */ + 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 ) + { + if (sim_cmd_mode) + printf("(sim) "); + else + 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_LIBREADLINE */ + + if (interpretCmd(cmdbuff)) + break; + + while ( actualcmds ) + { + strcpy(cmdbuff,actualcmds); + actualcmds = NULL; + stopcmdlist= 0; + for ( line = cmdbuff; *line ; line = s ) + { + if ( (s=strchr(line ,'\n'))) + { + save_ch = *++s; + *s = '\0'; + } + else + { + s += strlen( line ); + save_ch = '\0'; + } + if (interpretCmd( line )) + { + *s = save_ch; + break; + } + *s = save_ch; + if ( stopcmdlist ) + break; + } + } + } +#ifdef HAVE_LIBREADLINE + // restore readline's input/output streams + rl_instream = old_rl_instream; + rl_outstream = old_rl_outstream; +#endif /* HAVE_LIBREADLINE */ +} + /*-----------------------------------------------------------------*/ /* printVersionInfo - print the version information */ /*-----------------------------------------------------------------*/ static void printVersionInfo() { fprintf(stdout, - "SDCDB is free software and you are welcome to distribute copies of it\n" - "under certain conditions; type \"show copying\" to see the conditions.\n" - "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n" - "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n" - "Type ? for help\n"); + "SDCDB is free software and you are welcome to distribute copies of it\n" + "under certain conditions; type \"show copying\" to see the conditions.\n" + "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n" + "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n" + "Type ? for help\n"); } @@ -707,90 +1556,198 @@ static void parseCmdLine (int argc, char **argv) { int i ; char *filename = NULL; - char buffer[100]; - for ( i = 1; i < argc ; i++) { - fprintf(stdout,"%s\n",argv[i]); + int passon_args_flag = 0; /* if true, pass on args to simulator */ - /* if this is an option */ - if (argv[i][0] == '-') { + Dprintf(D_sdcdb, ("sdcdb: parseCmdLine\n")); + contsim=0; - /* if directory then mark directory */ - if (strncmp(argv[i],"--directory=",12) == 0) { - if (!ssdirl) - ssdirl = &argv[i][12]; - else { - char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2); - strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl); - ssdirl = p; - } - continue; - } - - if (strncmp(argv[i],"-fullname",9) == 0) { - fullname = TRUE; - continue; - } - - if (strcmp(argv[i],"-cd") == 0) { - i++; - chdir(argv[i]); - continue; - } - - if (strncmp(argv[i],"-cd=",4) == 0) { - chdir(argv[i][4]); - continue; - } - - /* the simulator arguments */ - - /* cpu */ - if (strcmp(argv[i],"-t") == 0 || - strcmp(argv[i],"-cpu") == 0) { - - simArgs[nsimArgs++] = "-t"; - simArgs[nsimArgs++] = strdup(argv[++i]); - continue ; - } - - /* XTAL Frequency */ - if (strcmp(argv[i],"-X") == 0 || - strcmp(argv[i],"-frequency") == 0) { - simArgs[nsimArgs++] = "-X"; - simArgs[nsimArgs++] = strdup(argv[++i]); - continue ; - } - - /* serial port */ - if (strcmp(argv[i],"-s") == 0) { - simArgs[nsimArgs++] = "-s"; - simArgs[nsimArgs++] = strdup(argv[++i]); - continue ; - } - - if (strcmp(argv[i],"-S") == 0) { - simArgs[nsimArgs++] = "-s"; - simArgs[nsimArgs++] = strdup(argv[++i]); - continue ; - } - - fprintf(stderr,"unknown option %s --- ignored\n", - argv[i]); - } else { - /* must be file name */ - if (filename) { - fprintf(stderr,"too many filenames .. parameter '%s' ignored\n", - argv[i]); - continue ; - } - - filename = strtok(argv[i],"."); - - } + for ( i = 1; i < argc ; i++) { + //fprintf(stdout,"%s\n",argv[i]); + + if (passon_args_flag) { /* if true, pass on args to simulator */ + simArgs[nsimArgs++] = strdup(argv[i]); + continue; + } + + /* if this is an option */ + if (argv[i][0] == '-') { + + /* if directory then mark directory */ + if (strncmp(argv[i],"--directory=",12) == 0) { + if (!ssdirl) + ssdirl = &argv[i][12]; + else { + char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2); + strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl); + ssdirl = p; + } + continue; + } + + if (strncmp(argv[i],"-fullname",9) == 0) { + fullname = TRUE; + continue; + } + + if (strcmp(argv[i],"-cd") == 0) { + i++; + chdir(argv[i]); + continue; + } + + if (strncmp(argv[i],"-cd=",4) == 0) { + chdir(argv[i]+4); + continue; + } + +#ifdef SDCDB_DEBUG + if (strncmp(argv[i],"-d=",3) == 0) { + sdcdbDebug = strtol(&argv[i][3],0,0); + continue; + } +#endif + if (strncmp(argv[i],"-contsim",8) == 0) { + contsim=1; + continue; + } + if (strncmp(argv[i],"-q",2) == 0) { + continue; + } + + /* model string */ + if (strncmp(argv[i],"-m",2) == 0) { + strncpy(model_str, &argv[i][2], 15); + if (strcmp(model_str,"avr") == 0) + simArgs[0] = "savr"; + else if (strcmp(model_str,"xa") == 0) + simArgs[0] = "sxa"; + else if (strcmp(model_str,"z80") == 0) + simArgs[0] = "sz80"; + continue ; + } + + /* -z all remaining options are for simulator */ + if (strcmp(argv[i],"-z") == 0) { + passon_args_flag = 1; + continue ; + } + + /* the simulator arguments */ + + /* cpu */ + if (strcmp(argv[i],"-t") == 0 || + strcmp(argv[i],"-cpu") == 0) { + + simArgs[nsimArgs++] = "-t"; + simArgs[nsimArgs++] = strdup(argv[++i]); + continue ; + } + + /* XTAL Frequency */ + if (strcmp(argv[i],"-X") == 0 || + strcmp(argv[i],"-frequency") == 0) { + simArgs[nsimArgs++] = "-X"; + simArgs[nsimArgs++] = strdup(argv[++i]); + continue ; + } + + /* serial port */ + if ( (strcmp(argv[i],"-S") == 0) || + (strcmp(argv[i],"-s") == 0) || + (strcmp(argv[i],"-T") == 0) || + (strcmp(argv[i],"--tty") == 0)) { + simArgs[nsimArgs++] = "--tty"; + simArgs[nsimArgs++] = strdup(argv[++i]); + continue ; + } + + /* network serial port */ + if ( (strcmp(argv[i],"-k") == 0)) { + simArgs[nsimArgs++] = strdup(argv[i]); + simArgs[nsimArgs++] = strdup(argv[++i]); + continue ; + } + + fprintf(stderr,"unknown option %s --- ignored\n", + argv[i]); + + } else { + /* must be file name */ + if (filename) { + fprintf(stderr,"too many filenames .. parameter '%s' ignored\n", + argv[i]); + continue ; + } + + if (-1 != access(argv[i], 0)) { + /* file exists: strip the cdb or ihx externsion */ + char *p = strrchr(argv[i], '.'); + + if (NULL != p && + (0 == strcmp(p, ".cdb") || 0 == strcmp(p, ".ihx"))) + *p = '\0'; + } + filename = argv[i]; + + } } if (filename) - cmdFile(filename,NULL); + cmdFile(filename,NULL); +} + +/*-----------------------------------------------------------------*/ +/* setsignals - catch some signals */ +/*-----------------------------------------------------------------*/ +#include +static void +bad_signal(int sig) +{ + if ( simactive ) + closeSimulator(); + exit(1); +} + +static void +sigintr(int sig) +{ + /* may be interrupt from user: stop debugger and also simulator */ + userinterrupt = 1; + if ( !nointerrupt ) + sendSim("stop\n"); +} + +#ifndef _WIN32 +/* the only child can be the simulator */ +static void sigchld(int sig) +{ + /* the only child can be the simulator */ + int status, retpid; + retpid = wait ( &status ); + /* if ( retpid == simPid ) */ + simactive = 0; +} +#endif + +static void +setsignals() +{ + signal(SIGINT , sigintr ); + signal(SIGABRT, bad_signal); + signal(SIGTERM, bad_signal); + +#ifndef _WIN32 + signal(SIGHUP , SIG_IGN); + signal(SIGCONT, SIG_IGN); + signal(SIGCHLD, sigchld ); + + signal(SIGALRM, bad_signal); + //signal(SIGFPE, bad_signal); + //signal(SIGILL, bad_signal); + signal(SIGPIPE, bad_signal); + signal(SIGQUIT, bad_signal); + //signal(SIGSEGV, bad_signal); +#endif } /*-----------------------------------------------------------------*/ @@ -800,10 +1757,18 @@ static void parseCmdLine (int argc, char **argv) int main ( int argc, char **argv) { printVersionInfo(); + printf("WARNING: SDCDB is EXPERIMENTAL.\n"); + + current_directory = get_current_dir_name(); + simArgs[nsimArgs++] = "ao-dbg"; + simArgs[nsimArgs++] = "-P"; + simArgs[nsimArgs++] = "-r 9756"; /* parse command line */ + + setsignals(); parseCmdLine(argc,argv); - commandLoop(); + commandLoop(stdin); return 0; }