Hackfix and re-enable strtoull and wcstoull, see bug #3798.
[sdcc.git] / sdcc / debugger / mcs51 / sdcdb.c
blob4eeaf41d4e52943d818f59a4a1ce8c637c926f4e
1 /*-------------------------------------------------------------------------
2 sdcdb.c - main source file for sdcdb debugger
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
24 #include "sdcdb.h"
26 char *ssdirl = DATADIR LIB_DIR_SUFFIX ":" DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "small" ;
28 #undef DATADIR
29 #include "symtab.h"
30 #include "simi.h"
31 #include "break.h"
32 #include "cmd.h"
33 #include "newalloc.h"
34 #if defined HAVE_LIBREADLINE && HAVE_LIBREADLINE != -1
35 #define HAVE_READLINE_COMPLETITION 1
36 #endif
37 #ifdef HAVE_LIBREADLINE
38 #include <readline/readline.h>
39 #include <readline/history.h>
40 #endif /* HAVE_LIBREADLINE */
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #elif defined _WIN32
44 #include <direct.h>
45 #endif
46 #ifdef HAVE_SYS_WAIT_H
47 #include <sys/wait.h>
48 #endif
50 #ifdef SDCDB_DEBUG
51 int sdcdbDebug = 0;
52 #endif
54 char *currModName = NULL;
55 cdbrecs *recsRoot = NULL;
56 set *modules = NULL; /* set of all modules */
57 set *functions = NULL; /* set of functions */
58 set *symbols = NULL; /* set of symbols */
59 set *sfrsymbols = NULL; /* set of symbols of sfr or sbit */
60 int nStructs = 0 ;
61 structdef **structs = NULL; /* all structures */
62 int nLinkrecs = 0;
63 linkrec **linkrecs = NULL; /* all linkage editor records */
64 context *currCtxt = NULL;
65 short fullname = 0;
66 short showfull = 0;
67 char userinterrupt = 0;
68 char nointerrupt = 0;
69 char contsim = 0;
70 char *simArgs[40];
71 int nsimArgs = 0;
72 char model_str[20];
73 /* fake filename & lineno to make linker */
74 char *filename = NULL;
75 int lineno = 0;
76 int fatalError = 0;
78 static void commandLoop(FILE *cmdfile);
79 #ifdef HAVE_READLINE_COMPLETITION
80 char *completionCmdSource(const char *text, int state);
81 char *completionCmdFile(const char *text, int state);
82 char *completionCmdInfo(const char *text, int state);
83 char *completionCmdShow(const char *text, int state);
84 char *completionCmdListSymbols(const char *text, int state);
85 char *completionCmdPrintType(const char *text, int state);
86 char *completionCmdPrint(const char *text, int state);
87 char *completionCmdDelUserBp(const char *text, int state);
88 char *completionCmdUnDisplay(const char *text, int state);
89 char *completionCmdSetUserBp(const char *text, int state);
90 char *completionCmdSetOption(const char *text, int state);
91 #else
92 #define completionCmdSource NULL
93 #define completionCmdFile NULL
94 #define completionCmdInfo NULL
95 #define completionCmdShow NULL
96 #define completionCmdListSymbols NULL
97 #define completionCmdPrintType NULL
98 #define completionCmdPrint NULL
99 #define completionCmdDelUserBp NULL
100 #define completionCmdUnDisplay NULL
101 #define completionCmdSetUserBp NULL
102 #define completionCmdSetOption NULL
103 #endif /* HAVE_READLINE_COMPLETITION */
105 /* command table */
106 struct cmdtab
108 const char *cmd; /* command the user will enter */
109 int (*cmdfunc)(char *,context *); /* function to execute when command is entered */
110 #ifdef HAVE_READLINE_COMPLETITION
111 rl_compentry_func_t *completion_func;
112 #else
113 void *dummy;
114 #endif /* HAVE_READLINE_COMPLETITION */
115 const char *htxt; /* short help text */
116 } cmdTab[] = {
117 /* NOTE:- the search is done from the top, so "break" should
118 precede the synonym "b" */
119 /* break point */
120 { "break" , cmdSetUserBp , completionCmdSetUserBp,
121 "{b}reak\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *<address>]"
123 { "tbreak" , cmdSetTmpUserBp , completionCmdSetUserBp/*same as "break"*/,
124 "tbreak\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *<address>]"
126 { "b" , cmdSetUserBp , completionCmdSetUserBp , NULL,},
128 { "jump" , cmdJump , NULL,
129 "jump\tContinue program being debugged at specified line or address\n"
130 "\t[LINE | FILE:LINE | *<address>]",
132 { "clear" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/,
133 "{cl}ear\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]"
135 { "cl" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/ ,
136 NULL
138 { "continue" , cmdContinue , NULL,
139 "{c}ontinue\tContinue program being debugged, after breakpoint."
141 { "condition" , cmdCondition , completionCmdDelUserBp/*same as "delete"*/,
142 "condition brkpoint_number expr\tSet condition for breakpoint."
144 { "ignore" , cmdIgnore , completionCmdDelUserBp/*same as "delete"*/,
145 "ignore brkpoint_number count\tSet ignore count for breakpoint."
147 { "commands" , cmdCommands , completionCmdDelUserBp/*same as "delete"*/,
148 "commands [brkpoint_number]\tSetting commands for breakpoint."
150 { "c" , cmdContinue , NULL ,
151 NULL
153 { "disassemble",cmdDisasmF , NULL,
154 "disassemble [startaddr [endaddress]]\tdisassemble asm commands"
156 { "delete" , cmdDelUserBp , completionCmdDelUserBp,
157 "{d}elete n\tclears break point number n"
159 { "display" , cmdDisplay , completionCmdPrint/*same as "print"*/,
160 "display [/<fmt>] [<variable>]\tprint value of given variable each time the program stops"
162 { "undisplay" , cmdUnDisplay , completionCmdUnDisplay,
163 "undisplay [<variable>]\tdon't display this variable or all"
165 { "down" , cmdDown , NULL,
166 "down\tSelect and print stack frame called by this one.\n"
167 "\tAn argument says how many frames down to go."
170 "up" , cmdUp , NULL,
171 "up\tSelect and print stack frame that called this one.\n"
172 "\tAn argument says how many frames up to go."
174 { "d" , cmdDelUserBp , completionCmdDelUserBp,
175 NULL
177 { "info" , cmdInfo , completionCmdInfo,
178 "info <break stack frame registers all-registers line source functions symbols variables>\t"
179 "list all break points, call-stack, frame or register information"
181 { "listasm" , cmdListAsm , NULL,
182 "listasm {la}\tlist assembler code for the current C line"
184 { "la" , cmdListAsm , NULL,
185 NULL
187 { "ls" , cmdListSymbols , completionCmdListSymbols,
188 "ls,lf,lm\tlist symbols,functions,modules"
190 { "lf" , cmdListFunctions, completionCmdListSymbols,
191 NULL
193 { "lm" , cmdListModules , completionCmdListSymbols,
194 NULL
196 { "list" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/,
197 "{l}ist\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]"
199 { "l" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/,
200 NULL
202 { "show" , cmdShow , completionCmdShow,
203 "show <copying warranty>\tcopying & distribution terms, warranty"
205 { "set" , cmdSetOption , completionCmdSetOption,
206 "set <srcmode>\ttoggle between c/asm.\nset variable <var> = >value\tset variable to new value"
208 { "stepi" , cmdStepi , NULL,
209 "stepi\tStep one instruction exactly."
211 { "step" , cmdStep , NULL,
212 "{s}tep\tStep program until it reaches a different source line."
214 { "source" , cmdSource , completionCmdSource,
215 "source <FILE>\tRead commands from a file named FILE."
217 { "s" , cmdStep , NULL,
218 NULL
220 { "nexti" , cmdNexti , NULL,
221 "nexti\tStep one instruction, but proceed through subroutine calls."
223 { "next" , cmdNext , NULL,
224 "{n}ext\tStep program, proceeding through subroutine calls."
226 { "n" , cmdNext , NULL,
227 NULL
229 { "run" , cmdRun , NULL,
230 "{r}un\tStart debugged program. "
232 { "r" , cmdRun , NULL,
233 NULL
235 { "ptype" , cmdPrintType , completionCmdPrintType,
236 "{pt}ype <variable>\tprint type information of a variable"
238 { "pt" , cmdPrintType , NULL,
239 NULL
241 { "print" , cmdPrint , completionCmdPrintType,
242 "{p}rint <variable>\tprint value of given variable"
244 { "output" , cmdOutput , completionCmdPrint/*same as "print"*/,
245 "output <variable>\tprint value of given variable without $ and newline"
247 { "p" , cmdPrint , completionCmdPrintType,
248 NULL
250 { "file" , cmdFile , completionCmdFile,
251 "file <filename>\tload symbolic information from <filename>"
253 { "frame" , cmdFrame , NULL,
254 "{fr}ame\tprint information about the current Stack"
256 { "finish" , cmdFinish , NULL,
257 "{fi}nish\texecute till return of current function"
259 { "fi" , cmdFinish , NULL,
260 NULL
262 { "where" , cmdWhere , NULL,
263 "where\tprint stack"
265 { "fr" , cmdFrame , NULL,
266 NULL
268 { "f" , cmdFrame , NULL,
269 NULL
271 { "x /i" , cmdDisasm1 , NULL,
272 "x\tdisassemble one asm command"
274 { "!" , cmdSimulator , NULL,
275 "!<simulator command>\tsend a command directly to the simulator"
277 { "." , cmdSimulator , NULL,
278 ".{cmd}\tswitch from simulator or debugger command mode"
280 { "help" , cmdHelp , NULL,
281 "{h|?}elp\t[CMD_NAME | 0,1,2,3(help page)] (general help or specific help)"
283 { "?" , cmdHelp , NULL,
284 NULL
286 { "h" , cmdHelp , NULL,
287 NULL
289 { "quit" , cmdQuit , NULL,
290 "{q}uit\t\"Watch me now. I'm going Down. My name is Bobby Brown\""
292 { "q" , cmdQuit , NULL,
293 NULL
297 /*-----------------------------------------------------------------*/
298 /* trimming functions */
299 /*-----------------------------------------------------------------*/
300 char *trim_left(char *s)
302 while (isspace(*s))
303 ++s;
305 return s;
308 char *trim_right(char *s)
310 char *p = &s[strlen(s) - 1];
312 while (p >= s && isspace(*p))
313 --p;
314 *++p = '\0';
316 return s;
319 char *trim(char *s)
321 return trim_right(trim_left(s));
324 /*-----------------------------------------------------------------*/
325 /* gc_strdup - make a string duplicate garbage collector aware */
326 /*-----------------------------------------------------------------*/
327 char *gc_strdup(const char *s)
329 char *ret;
330 ret = Safe_malloc(strlen(s)+1);
331 strcpy(ret, s);
332 return ret;
335 /*-----------------------------------------------------------------*/
336 /* alloccpy - allocate copy and return a new string */
337 /*-----------------------------------------------------------------*/
338 char *alloccpy ( char *s, int size)
340 char *d;
342 if (!size)
343 return NULL;
345 d = Safe_malloc(size+1);
346 memcpy(d,s,size);
347 d[size] = '\0';
349 return d;
352 /*-----------------------------------------------------------------*/
353 /* resize - resizes array of type with new size */
354 /*-----------------------------------------------------------------*/
355 void **resize (void **array, int newSize)
357 void **vptr;
359 if (array)
360 vptr = Safe_realloc(array, newSize*(sizeof(void **)));
361 else
362 vptr = calloc(1, sizeof(void **));
364 if (!vptr)
366 fprintf(stderr, "sdcdb: out of memory\n");
367 exit(1);
370 return vptr;
373 /*-----------------------------------------------------------------*/
374 /* readCdb - reads the cdb files & puts the records into cdbLine */
375 /* linked list */
376 /*-----------------------------------------------------------------*/
377 static int readCdb (FILE *file)
379 cdbrecs *currl;
380 char buffer[1024];
381 char *bp;
383 if (!(bp = fgets(buffer, sizeof(buffer), file)))
384 return 0;
386 currl = Safe_calloc(1, sizeof(cdbrecs));
387 recsRoot = currl;
389 while (1)
391 /* make sure this is a cdb record */
392 if (strchr("STLFM",*bp) && *(bp+1) == ':')
394 /* depending on the record type */
396 switch (*bp)
398 case 'S':
399 /* symbol record */
400 currl->type = SYM_REC;
401 break;
402 case 'T':
403 currl->type = STRUCT_REC;
404 break;
405 case 'L':
406 currl->type = LNK_REC;
407 break;
408 case 'F':
409 currl->type = FUNC_REC;
410 break;
411 case 'M':
412 currl->type = MOD_REC ;
413 break;
416 bp += 2;
417 currl->line = Safe_malloc(strlen(bp)+1);
418 strcpy(currl->line, bp);
421 if (!(bp = fgets(buffer, sizeof(buffer), file)))
422 break;
424 if (feof(file))
425 break;
427 currl->next = Safe_calloc(1, sizeof(cdbrecs));
428 currl = currl->next;
431 return (recsRoot->line ? 1 : 0);
434 /*-----------------------------------------------------------------*/
435 /* searchDirsFname - search directory list & return the filename */
436 /*-----------------------------------------------------------------*/
437 char *searchDirsFname (char *fname)
439 char *dirs , *sdirs;
440 FILE *rfile = NULL;
441 char buffer[128];
443 /* first try the current directory */
444 if ((rfile = fopen(fname, "r")))
446 fclose(rfile);
447 return strdup(fname) ;
450 if (!ssdirl)
451 return strdup(fname);
453 /* make a copy of the source directories */
454 dirs = sdirs = strdup(ssdirl);
456 /* assume that the separator is ':'
457 and try for each directory in the search list */
458 dirs = strtok(dirs, ":");
459 while (dirs)
461 if (dirs[strlen(dirs)] == '/')
462 sprintf(buffer, "%s%s", dirs, fname);
463 else
464 sprintf(buffer, "%s/%s", dirs, fname);
465 if ((rfile = fopen(buffer, "r")))
466 break;
467 dirs = strtok(NULL, ":");
470 free(sdirs);
471 if (rfile)
473 fclose(rfile);
474 return strdup(buffer);
476 else //not found
478 char *p, *found;
480 // sprintf(buffer, "%s", fname);
481 p = fname;
482 while (NULL != (p = strchr(p, '_')))
484 *p = '.'; // try again with '_' replaced by '.'
485 if (NULL != (found = searchDirsFname(fname)))
486 return found;
487 *p = '_'; // not found, restore '_' and try next '_'
490 return NULL;
493 /*-----------------------------------------------------------------*/
494 /* searchDirsFopen - go thru list of directories for filename given*/
495 /*-----------------------------------------------------------------*/
496 FILE *searchDirsFopen(char *fname)
498 char *dirs , *sdirs;
499 FILE *rfile = NULL;
500 char buffer[128];
502 /* first try the current directory */
503 if ((rfile = fopen(fname, "r")))
504 return rfile;
506 if (!ssdirl)
507 return NULL;
509 /* make a copy of the source directories */
510 dirs = sdirs = strdup(ssdirl);
512 /* assume that the separator is ':'
513 and try for each directory in the search list */
514 dirs = strtok(dirs, ":");
515 while (dirs)
517 sprintf(buffer, "%s/%s", dirs, fname);
518 if ((rfile = fopen(buffer, "r")))
519 break;
520 dirs = strtok(NULL, ":");
523 free(sdirs);
524 return rfile ;
527 /*-----------------------------------------------------------------*/
528 /* loadFile - loads a file into module buffer */
529 /*-----------------------------------------------------------------*/
530 srcLine **loadFile (char *name, int *nlines)
532 FILE *mfile;
533 char buffer[512];
534 char *bp;
535 srcLine **slines = NULL;
537 if (!(mfile = searchDirsFopen(name)))
539 fprintf(stderr, "sdcdb: cannot open module %s -- use '--directory=<source directory> option\n", name);
540 return NULL;
543 while ((bp = fgets(buffer, sizeof(buffer), mfile)))
545 (*nlines)++;
547 slines = (srcLine **)resize((void **)slines, *nlines);
549 slines[(*nlines)-1] = Safe_calloc(1, sizeof(srcLine));
550 slines[(*nlines)-1]->src = alloccpy(bp, strlen(bp));
551 slines[(*nlines)-1]->addr = INT_MAX;
554 fclose(mfile);
555 return slines;
559 /*-----------------------------------------------------------------*/
560 /* loadModules - reads the source files into module structure */
561 /*-----------------------------------------------------------------*/
562 static void loadModules (void)
564 cdbrecs *loop;
565 module *currMod;
566 char *rs;
568 /* go thru the records & find out the module
569 records & load the modules specified */
570 for ( loop = recsRoot ; loop ; loop = loop->next )
572 switch (loop->type)
574 /* for module records do */
575 case MOD_REC:
576 currMod = parseModule(loop->line, TRUE);
577 currModName = currMod->name ;
579 /* search the c source file and load it into buffer */
580 currMod->cfullname = searchDirsFname(currMod->c_name);
581 currMod->cLines = loadFile (currMod->c_name, &currMod->ncLines);
583 /* do the same for the assembler file */
584 currMod->afullname = searchDirsFname(currMod->asm_name);
585 currMod->asmLines = loadFile (currMod->asm_name, &currMod->nasmLines);
586 break;
588 /* if this is a function record */
589 case FUNC_REC:
590 parseFunc(loop->line);
591 break;
593 /* if this is a structure record */
594 case STRUCT_REC:
595 parseStruct(loop->line);
596 break;
598 /* if symbol then parse the symbol */
599 case SYM_REC:
600 parseSymbol(loop->line, &rs, 2);
601 break;
603 case LNK_REC:
604 parseLnkRec(loop->line);
605 break;
610 /*-----------------------------------------------------------------*/
611 /* generate extra sets of sfr and sbit symbols */
612 /*-----------------------------------------------------------------*/
613 static void specialFunctionRegs (void)
615 symbol *sym;
616 for (sym = setFirstItem(symbols); sym; sym = setNextItem(symbols))
618 if ( sym->addrspace == 'I' || sym->addrspace == 'J')
620 addSet(&sfrsymbols, sym);
624 /*-----------------------------------------------------------------*/
625 /* functionPoints - determine the execution points within a func */
626 /*-----------------------------------------------------------------*/
627 static void functionPoints (void)
629 function *func;
630 symbol *sym;
631 exePoint *ep;
633 // add _main dummy for runtime env
634 if ((func = needExtraMainFunction()))
636 function *func1;
638 /* alloc new _main function */
639 func1 = Safe_calloc(1, sizeof(function));
640 *func1 = *func;
641 func1->sym = Safe_calloc(1, sizeof(symbol));
642 *func1->sym = *func->sym;
643 func1->sym->name = alloccpy("_main", 5);
644 func1->sym->rname = alloccpy("G$_main$0$", 10);
645 /* TODO must be set by symbol information */
646 func1->sym->addr = 0;
647 func1->sym->eaddr = 0x2f;
648 addSet(&functions, func1);
651 /* for all functions do */
652 for ( func = setFirstItem(functions); func; func = setNextItem(functions))
654 int j ;
655 module *mod;
657 sym = func->sym;
659 Dprintf(D_sdcdb, ("sdcdb: func '%s' has entry '0x%x' exit '0x%x'\n",
660 func->sym->name,
661 func->sym->addr,
662 func->sym->eaddr));
664 if (!func->sym->addr && !func->sym->eaddr)
665 continue;
667 /* for all source lines in the module find
668 the ones with address >= start and <= end
669 and put them in the point */
670 mod = NULL ;
671 if (! applyToSet(modules, moduleWithName, func->modName, &mod))
672 continue;
673 func->mod = mod;
674 func->entryline= INT_MAX-2;
675 func->exitline = 0;
676 func->aentryline = INT_MAX-2;
677 func->aexitline = 0;
679 /* do it for the C Lines first */
680 for ( j = 0 ; j < mod->ncLines ; j++ )
682 if (mod->cLines[j]->addr < INT_MAX &&
683 mod->cLines[j]->addr >= sym->addr &&
684 mod->cLines[j]->addr <= sym->eaddr )
686 /* add it to the execution point */
687 if (func->entryline > j)
688 func->entryline = j;
690 if (func->exitline < j)
691 func->exitline = j;
693 ep = Safe_calloc(1, sizeof(exePoint));
694 ep->addr = mod->cLines[j]->addr ;
695 ep->line = j;
696 ep->block= mod->cLines[j]->block;
697 ep->level= mod->cLines[j]->level;
698 addSet(&func->cfpoints, ep);
701 /* check double line execution points of module */
702 for (ep = setFirstItem(mod->cfpoints); ep; ep = setNextItem(mod->cfpoints))
704 if (ep->addr >= sym->addr && ep->addr <= sym->eaddr )
706 addSet(&func->cfpoints, ep);
709 /* do the same for asm execution points */
710 for ( j = 0 ; j < mod->nasmLines ; j++ )
712 if (mod->asmLines[j]->addr < INT_MAX &&
713 mod->asmLines[j]->addr >= sym->addr &&
714 mod->asmLines[j]->addr <= sym->eaddr )
716 exePoint *ep ;
717 /* add it to the execution point */
718 if (func->aentryline > j)
719 func->aentryline = j;
721 if (func->aexitline < j)
722 func->aexitline = j;
724 /* add it to the execution point */
725 ep = Safe_calloc(1, sizeof(exePoint));
726 ep->addr = mod->asmLines[j]->addr;
727 ep->line = j;
728 addSet(&func->afpoints, ep);
731 if ( func->entryline == INT_MAX-2 )
732 func->entryline = 0;
733 if ( func->aentryline == INT_MAX-2 )
734 func->aentryline = 0;
736 #ifdef SDCDB_DEBUG
737 if (!( D_sdcdb & sdcdbDebug))
738 continue;
740 Dprintf(D_sdcdb, ("sdcdb: function '%s' has the following C exePoints\n",
741 func->sym->name));
743 exePoint *ep;
745 for (ep = setFirstItem(func->cfpoints); ep; ep = setNextItem(func->cfpoints))
747 Dprintf(D_sdcdb, ("sdcdb: {0x%x,%d} %s",
748 ep->addr, ep->line+1, mod->cLines[ep->line]->src));
751 Dprintf(D_sdcdb, ("sdcdb: and the following ASM exePoints\n"));
752 for (ep = setFirstItem(func->afpoints); ep; ep = setNextItem(func->afpoints))
754 Dprintf (D_sdcdb, ("sdcdb: {0x%x,%d} %s",
755 ep->addr, ep->line+1, mod->asmLines[ep->line]->src));
758 #endif
763 /*-----------------------------------------------------------------*/
764 /* setEntryExitBP - set the entry & exit Break Points for functions*/
765 /*-----------------------------------------------------------------*/
766 DEFSETFUNC(setEntryExitBP)
768 function *func = item;
770 if (func->sym && func->sym->addr && func->sym->eaddr)
772 /* set the entry break point */
773 setBreakPoint (func->sym->addr, CODE, FENTRY,
774 fentryCB, func->mod->c_name, func->entryline);
776 /* set the exit break point */
777 setBreakPoint (func->sym->eaddr, CODE, FEXIT,
778 fexitCB, func->mod->c_name, func->exitline);
781 return 0;
784 /*-----------------------------------------------------------------*/
785 /* cmdFile - load file into the debugger */
786 /*-----------------------------------------------------------------*/
787 int cmdFile (char *s,context *cctxt)
789 FILE *cdbFile;
790 char buffer[128];
791 char *bp;
793 s = trim_left(s);
795 if (!*s)
797 fprintf(stdout, "No exec file now.\nNo symbol file now.\n");
798 return 0;
801 sprintf(buffer, "%s.cdb", s);
802 /* try creating the cdbfile */
803 if (!(cdbFile = searchDirsFopen(buffer)))
805 fprintf(stdout, "Cannot open file\"%s\", no symbolic information loaded\n", buffer);
806 // return 0;
809 /* allocate for context */
810 currCtxt = Safe_calloc(1, sizeof(context));
812 if (cdbFile)
814 /* read in the debug information */
815 if (!readCdb (cdbFile))
817 fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
818 //return 0;
822 /* parse and load the modules required */
823 loadModules();
825 /* determine the execution points for this module */
826 functionPoints();
828 /* extract known special function registers */
829 specialFunctionRegs();
831 /* start the simulator & setup connection to it */
832 #ifdef _WIN32
833 if (INVALID_SOCKET == sock)
834 #else
835 if ( sock == -1 )
836 #endif
837 openSimulator((char **)simArgs, nsimArgs);
838 fprintf(stdout, "%s", simResponse());
839 /* now send the filename to be loaded to the simulator */
840 sprintf(buffer, "%s.ihx", s);
841 bp = searchDirsFname(buffer);
842 simLoadFile(bp);
843 free(bp);
845 /* set the break points
846 required by the debugger . i.e. the function entry
847 and function exit break points */
848 applyToSet(functions, setEntryExitBP);
850 setMainContext();
851 return 0;
854 /*-----------------------------------------------------------------*/
855 /* cmdSource - read commands from file */
856 /*-----------------------------------------------------------------*/
857 int cmdSource (char *s, context *cctxt)
859 FILE *cmdfile;
861 s = trim(s);
863 if (!( cmdfile = searchDirsFopen(s)))
865 fprintf(stderr,"commandfile '%s' not found\n",s);
866 return 0;
868 commandLoop( cmdfile );
869 fclose( cmdfile );
870 return 0;
873 /*-----------------------------------------------------------------*/
874 /* cmdHelp - help command */
875 /*-----------------------------------------------------------------*/
876 #define TEXT_OFFSET 24
878 static void printHelpLine(const char *htxt, int offs)
880 static char *spaces = NULL;
881 const char *p;
882 int state = 0;
884 if (NULL == spaces)
886 spaces = Safe_malloc(TEXT_OFFSET + 1);
887 memset(spaces, ' ', TEXT_OFFSET);
888 spaces[TEXT_OFFSET] = '\0';
891 p = htxt;
895 const char *ps = p;
896 int len;
897 while (*p && *p != '\t' && *p != '\n')
898 ++p;
899 len = p - ps;
901 if (state == 0)
903 printf("%.*s%.*s", offs, spaces, len, ps); /* command text */
905 if (len >= TEXT_OFFSET - offs)
906 printf("\n%s", spaces);
907 else
908 printf("%.*s", TEXT_OFFSET - offs - len, spaces);
910 else
912 printf("%.*s\n", len, ps); /* help text */
914 state = *p == '\t';
916 while (*p++);
919 int cmdHelp (char *s, context *cctxt)
921 int i ;
922 int endline = 999;
923 int startline = 0;
925 s = trim_left(s);
927 if (isdigit(*s))
929 endline = ((*s - '0') * 20) + 20;
930 if (endline > 0)
931 startline = endline - 20;
933 else if (*s)
935 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
937 if ((cmdTab[i].htxt) && !strcmp(cmdTab[i].cmd,s))
939 printHelpLine(cmdTab[i].htxt, 0);
940 break;
943 return 0;
946 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
948 /* command string matches */
950 if ((cmdTab[i].htxt) && (i >= startline))
951 printHelpLine(cmdTab[i].htxt, 0);
952 if (i == endline)
953 break;
956 return 0;
959 #define MAX_CMD_LEN 512
960 static char cmdbuff[MAX_CMD_LEN];
961 static int sim_cmd_mode = 0;
963 /*-----------------------------------------------------------------
964 interpretCmd - interpret and do the command. Return 0 to continue,
965 return 1 to exit program.
966 |-----------------------------------------------------------------*/
967 int interpretCmd (char *s)
969 static char *pcmd = NULL;
970 int i ;
971 int rv = 0 ;
973 /* if nothing & previous command exists then
974 execute the previous command again */
975 if (*s == '\n' && pcmd)
976 strcpy(s,pcmd);
978 /* if previous command exists & is different
979 from the current command then copy it */
980 if (pcmd)
982 if (strcmp(pcmd,s))
984 free(pcmd);
985 pcmd = strdup(s);
988 else
990 pcmd = strdup(s);
993 /* trim trailing blanks */
994 s = trim_right(s);
996 if (sim_cmd_mode)
998 if (strcmp(s,".") == 0)
1000 sim_cmd_mode = 0;
1001 return 0;
1003 else if (s[0] == '.')
1005 /* kill the preceeding '.' and pass on as SDCDB command */
1006 char *s1 = s+1;
1007 char *s2 = s;
1008 while (*s1 != 0)
1009 *s2++ = *s1++;
1010 *s2 = 0;
1012 else
1014 cmdSimulator (s, currCtxt);
1015 return 0;
1018 else
1020 if (strcmp(s,".") ==0)
1022 sim_cmd_mode = 1;
1023 return 0;
1027 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1029 /* command string matches */
1030 if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0)
1032 if (!cmdTab[i].cmdfunc)
1033 return 1;
1035 rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
1037 /* if full name then give the file name & position */
1038 if (fullname && showfull && currCtxt && currCtxt->func)
1040 showfull = 0;
1041 if (srcMode == SRC_CMODE)
1042 fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
1043 currCtxt->func->mod->cfullname,
1044 currCtxt->cline+1,currCtxt->addr);
1045 else
1046 fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
1047 currCtxt->func->mod->afullname,
1048 currCtxt->asmline,currCtxt->addr);
1049 displayAll(currCtxt);
1051 goto ret;
1054 fprintf(stdout,"Undefined command: \"%s\". Try \"help\".\n",s);
1056 ret:
1057 return rv;
1060 static FILE *actualcmdfile=NULL ;
1061 static char *actualcmds=NULL;
1062 static int stopcmdlist;
1063 /*-----------------------------------------------------------------*/
1064 /* getNextCmdLine get additional lines used by special commands */
1065 /*-----------------------------------------------------------------*/
1066 char *getNextCmdLine(void)
1068 //fprintf(stderr,"getNextCmdLine() actualcmdfile=%p\n",actualcmdfile);
1069 if (!actualcmdfile)
1070 return NULL;
1071 fprintf(stdout,">");
1072 fflush(stdout);
1073 if (fgets(cmdbuff,sizeof(cmdbuff),actualcmdfile) == NULL)
1075 // fprintf(stderr,"getNextCmdLine() returns null\n");
1076 return NULL;
1078 //fprintf(stderr,"getNextCmdLine() returns: %s",cmdbuff);
1079 return cmdbuff;
1082 void setCmdLine( char *cmds )
1084 actualcmds = cmds;
1087 void stopCommandList()
1089 stopcmdlist = 1;
1092 #ifdef HAVE_READLINE_COMPLETITION
1093 // helper function for doing readline completion.
1094 // input: toknum=index of token to find (0=first token)
1095 // output: *start=first character index of the token,
1096 // or the index of '\0'
1097 // *end=first blank character right after the token,
1098 // or the index of '\0'
1099 // return value: 0=token not found, 1=token found
1100 int completionHelper_GetTokenNumber(int toknum, int *start, int *end)
1102 int tok_index;
1103 const char *p = rl_line_buffer;
1105 tok_index = 0;
1106 *start = *end = 0;
1107 while (p[*end] != 0)
1109 // start = skip blanks from end
1110 *start = *end;
1111 while (p[*start] && isspace( p[*start] ))
1112 (*start)++;
1114 // end = skip non-blanks from start
1115 *end = *start;
1116 while (p[*end] && !isspace( p[*end] ))
1117 (*end)++;
1119 if (tok_index == toknum)
1120 return 1; // found
1122 tok_index++;
1125 return 0; // not found
1128 // helper function for doing readline completion.
1129 // returns the token number that we were asked to complete.
1130 // 0=first token (command name), 1=second token...
1131 int completionHelper_GetCurrTokenNumber()
1133 int toknum, start, end;
1135 toknum = start = end = 0;
1136 while (1)
1138 if (!completionHelper_GetTokenNumber(toknum, &start, &end))
1139 return toknum;
1141 if (rl_point <= end)
1142 return toknum;
1144 toknum++;
1148 // exapmle for vallist on entry:
1149 // "copying\0warranty\0";
1150 char *completionCompleteFromStrList(const char *text, int state, char *vallist)
1152 static char *ptr;
1153 int len;
1155 if (state == 0)
1156 ptr = vallist;
1157 else
1158 ptr += strlen(ptr)+1;
1160 len = strlen(text);
1161 while (*ptr)
1163 if ( (len < strlen(ptr)) && !strncmp(text, ptr, len) )
1164 return strdup(ptr);
1166 ptr += strlen(ptr)+1;
1169 return NULL;
1172 // readline library completion function.
1173 // completes from the list of all sdcdb command.
1174 char *completionCommandsList(const char *text, int state)
1176 static int i = 0;
1178 if (state == 0) // new completion?
1179 { // yes, only complete if this is the first token on the line.
1180 int ok = 0; // try to complete this request?
1181 char *p = rl_line_buffer;
1183 // skip blanks
1184 while (p && isspace(*p))
1186 if (p-rl_line_buffer == rl_point)
1187 ok = 1;
1188 p++;
1191 while (p && !isspace(*p))
1193 if (p-rl_line_buffer == rl_point)
1194 ok = 1;
1195 p++;
1198 if (p-rl_line_buffer == rl_point)
1199 ok = 1;
1201 if ( !ok )
1202 return NULL; // no more completions
1204 i = 0; // ok, gonna complete. initialize static variable.
1206 else
1208 i++;
1211 for (; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1213 int len = strlen(text);
1214 if (len <= strlen(cmdTab[i].cmd))
1216 if (strncmp(text,cmdTab[i].cmd,len) == 0)
1217 return strdup(cmdTab[i].cmd);
1221 return NULL; // no more completions
1224 // readline library completion function.
1225 // completes from the list of symbols.
1226 char *completionSymbolName(const char *text, int state)
1228 static symbol *sy;
1230 if (state == 0) // new completion?
1231 sy = setFirstItem(symbols); // yes
1232 else
1233 sy = setNextItem(symbols);
1235 for (; sy != NULL; )
1237 int len = strlen(text);
1238 if (len <= strlen(sy->name))
1240 if (strncmp(text,sy->name,len) == 0)
1241 return strdup(sy->name);
1244 sy = setNextItem(symbols);
1246 return NULL;
1249 // readline library completion function.
1250 // completes from the list known functions.
1251 // module_flag - if false, ignore function module name
1252 // if true, compare against module_name:fnction_name
1253 char *completionFunctionName(const char *text, int state, int module_flag)
1255 static function *f;
1257 if (state == 0) // new completion?
1258 f = setFirstItem(functions); // yes
1259 else
1260 f = setNextItem(functions);
1262 for (; f != NULL; )
1264 int text_len = strlen(text);
1266 if (!module_flag)
1268 if (text_len <= strlen(f->sym->name) &&
1269 !strncmp(text,f->sym->name,text_len))
1271 return strdup(f->sym->name);
1274 else
1276 int modname_len = strlen(f->mod->c_name);
1277 int funcname_len = strlen(f->sym->name);
1278 char *functext = malloc(modname_len+funcname_len+2);
1279 //assert(functext);
1280 strcpy(functext,f->mod->c_name);
1281 strcat(functext,":");
1282 strcat(functext,f->sym->name);
1283 if (text_len <= strlen(functext) &&
1284 !strncmp(text,functext,text_len))
1286 return functext;
1288 else
1290 free(functext);
1293 f = setNextItem(functions);
1295 return NULL;
1298 // readline library completion function.
1299 // completes from the list known modules.
1300 char *completionModuleName(const char *text, int state)
1302 static module *m;
1304 if (state == 0) // new completion?
1305 m = setFirstItem(modules); // yes
1306 else
1307 m = setNextItem(modules);
1309 for (; m != NULL; )
1311 int len = strlen(text);
1312 if ( (len <= strlen(m->c_name)) &&
1313 !strncmp(text,m->c_name,len) )
1315 return strdup(m->c_name);
1318 if ( (len <= strlen(m->asm_name)) &&
1319 (strncmp(text,m->asm_name,len) == 0) )
1321 return strdup(m->asm_name);
1324 m = setNextItem(modules);
1326 return NULL;
1329 // readline completion function for "file" command
1330 char *completionCmdFile(const char *text, int state)
1332 if (state == 0)
1334 if (completionHelper_GetCurrTokenNumber() != 1)
1335 return NULL;
1338 // we use filename_completion_function() from the readline library.
1339 return rl_filename_completion_function(text, state);
1342 // readline completion function for "source" command
1343 char *completionCmdSource(const char *text, int state)
1345 return completionCmdFile(text, state);
1348 // readline completion function for "info" command
1349 char *completionCmdInfo(const char *text, int state)
1351 if (state == 0)
1353 if (completionHelper_GetCurrTokenNumber() != 1)
1354 return NULL;
1357 return completionCompleteFromStrList(text, state,
1358 "break\0stack\0frame\0registers\0all-registers\0"
1359 "line\0source\0functions\0symbols\0variables\0");
1362 // readline completion function for "show" command
1363 char *completionCmdShow(const char *text, int state)
1365 if (state == 0)
1367 if (completionHelper_GetCurrTokenNumber() != 1)
1368 return NULL;
1370 return completionCompleteFromStrList(text, state, "copying\0warranty\0");
1373 // readline completion function for "la" command
1374 char *completionCmdListSymbols(const char *text, int state)
1376 if (state == 0)
1378 if (completionHelper_GetCurrTokenNumber() != 1)
1379 return NULL;
1381 return completionCompleteFromStrList(text, state, "v1\0v2\0");
1384 char *completionCmdPrintType(const char *text, int state)
1386 if (state == 0)
1388 if (completionHelper_GetCurrTokenNumber() != 1)
1389 return NULL;
1391 return completionSymbolName(text, state);
1394 char *completionCmdPrint(const char *text, int state)
1396 if (state == 0)
1398 int i = completionHelper_GetCurrTokenNumber();
1399 if (i != 1 && i != 2)
1400 return NULL;
1402 return completionSymbolName(text, state);
1405 char *completionCmdDelUserBp(const char *text, int state)
1407 static breakp *bp;
1408 static int k;
1410 if (state == 0)
1412 if (completionHelper_GetCurrTokenNumber() != 1)
1413 return NULL;
1415 if (!userBpPresent)
1416 return NULL;
1418 bp = hTabFirstItem(bptable,&k);
1420 else
1422 bp = hTabNextItem(bptable,&k);
1425 for ( ; bp ; bp = hTabNextItem(bptable,&k))
1427 if (bp->bpType == USER || bp->bpType == TMPUSER)
1429 char buff[20];
1430 sprintf(buff, "%d", bp->bpnum);
1431 return strdup(buff);
1435 return NULL;
1438 // readline completion function for "undisplay" command
1439 char *completionCmdUnDisplay(const char *text, int state)
1441 static dsymbol *dsym;
1443 if (state == 0)
1445 if (completionHelper_GetCurrTokenNumber() != 1)
1446 return NULL;
1447 dsym = setFirstItem(dispsymbols);
1450 if (dsym)
1452 char buff[30];
1453 sprintf(buff, "%d", dsym->dnum);
1454 dsym = setNextItem(dispsymbols);
1455 return strdup(buff);
1457 return NULL;
1460 char *completionCmdSetUserBp(const char *text, int state)
1462 static int internal_state; // 0=calling completionFunctionName(text, state, 0)
1463 // 1=calling completionFunctionName(text, 1, 1)
1464 if (state == 0)
1466 if (completionHelper_GetCurrTokenNumber() != 1)
1467 return NULL;
1469 internal_state = 0;
1471 if (internal_state == 0)
1473 char *p = completionFunctionName(text, state, 0);
1474 if (p)
1475 return p;
1476 internal_state = 1;
1477 return completionFunctionName(text, 0, 1);
1479 else
1481 return completionFunctionName(text, 1, 1);
1485 char *completionCmdSetOption(const char *text, int state)
1487 static int currtok;
1489 if (state == 0)
1491 int start,end;
1493 currtok = completionHelper_GetCurrTokenNumber();
1495 if (currtok == 2 || currtok == 3)
1497 // make sure token 1 == "variable"
1498 completionHelper_GetTokenNumber(1, &start, &end);
1499 if (end - start != 8 ||
1500 strncmp(rl_line_buffer+start,"variable",8))
1502 return NULL;
1505 else if (currtok != 1)
1507 return NULL;
1511 switch (currtok)
1513 case 1:
1514 return completionCompleteFromStrList(text, state,
1515 #ifdef SDCDB_DEBUG
1516 "debug\0"
1517 #endif
1518 "srcmode\0listsize\0variable\0");
1519 case 2:
1520 return completionSymbolName(text, state);
1522 case 3:
1523 return completionCompleteFromStrList(text, state, "=\0");
1525 return NULL;
1528 // our main readline completion function
1529 // calls the other completion functions as needed.
1530 char *completionMain(const char *text, int state)
1532 static rl_compentry_func_t *compl_func;
1533 int i, start, end, len;
1535 if (state == 0) // new completion?
1537 compl_func = NULL;
1539 if (completionHelper_GetCurrTokenNumber() == 0)
1541 compl_func = &completionCommandsList;
1543 else
1544 { // not completing first token, find the right completion
1545 // function according to the first token the user typed.
1546 completionHelper_GetTokenNumber(0, &start, &end);
1547 len = end-start;
1549 for (i=0; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1551 if (!strncmp(rl_line_buffer+start,cmdTab[i].cmd,len) &&
1552 cmdTab[i].cmd[len] == '\0')
1554 compl_func = cmdTab[i].completion_func;
1555 break;
1559 if (!compl_func)
1560 return NULL;
1563 return (*compl_func)(text,state);
1565 #endif /* HAVE_READLINE_COMPLETITION */
1567 /*-----------------------------------------------------------------*/
1568 /* commandLoop - the main command loop or loop over command file */
1569 /*-----------------------------------------------------------------*/
1570 static void commandLoop(FILE *cmdfile)
1572 char *line, save_ch, *s;
1573 #ifdef HAVE_LIBREADLINE
1574 char *line_read;
1576 FILE *old_rl_instream, *old_rl_outstream;
1577 actualcmdfile = cmdfile;
1579 #ifdef HAVE_READLINE_COMPLETITION
1580 rl_completion_entry_function = completionMain;
1581 #endif /* HAVE_READLINE_COMPLETITION */
1582 rl_readline_name = "sdcdb"; // Allow conditional parsing of the ~/.inputrc file.
1584 // save readline's input/output streams
1585 // this is done to support nested calls to commandLoop()
1586 // i wonder if it works...
1587 old_rl_instream = rl_instream;
1588 old_rl_outstream = rl_outstream;
1590 // set new streams for readline
1591 if ( cmdfile == stdin )
1592 rl_instream = rl_outstream = NULL; // use stdin/stdout pair
1593 else
1594 rl_instream = rl_outstream = cmdfile;
1596 while (1)
1598 if ( cmdfile == stdin )
1600 if (sim_cmd_mode)
1601 line_read = (char*)readline ("(sim) ");
1602 else
1603 line_read = (char*)readline ("(sdcdb) ");
1605 else
1606 line_read = (char*)readline ("");
1608 if (line_read)
1610 /* If the line has any text in it,
1611 save it on the history. */
1612 if (line_read && *line_read)
1613 add_history (line_read);
1615 // FIX: readline returns malloced string.
1616 // should check the source to verify it can be used
1617 // directly. for now - just copy it to cmdbuff.
1618 strcpy(cmdbuff,line_read);
1619 #if defined(_WIN32) || defined(HAVE_RL_FREE)
1620 rl_free(line_read);
1621 #else
1622 free(line_read);
1623 #endif
1624 line_read = NULL;
1626 else
1628 break; // EOF
1630 #else /* HAVE_LIBREADLINE */
1631 actualcmdfile = cmdfile;
1633 while (1)
1635 if ( cmdfile == stdin )
1637 if (sim_cmd_mode)
1638 printf("(sim) ");
1639 else
1640 fprintf(stdout,"(sdcdb) ");
1641 fflush(stdout);
1643 //fprintf(stderr,"commandLoop actualcmdfile=%p cmdfile=%p\n",
1644 // actualcmdfile,cmdfile);
1645 if (fgets(cmdbuff,sizeof(cmdbuff),cmdfile) == NULL)
1646 break;
1647 #endif /* HAVE_LIBREADLINE */
1649 if (interpretCmd(cmdbuff))
1650 break;
1652 while ( actualcmds )
1654 strcpy(cmdbuff,actualcmds);
1655 actualcmds = NULL;
1656 stopcmdlist= 0;
1657 for ( line = cmdbuff; *line ; line = s )
1659 if ( (s=strchr(line ,'\n')))
1661 save_ch = *++s;
1662 *s = '\0';
1664 else
1666 s += strlen( line );
1667 save_ch = '\0';
1669 if (interpretCmd( line ))
1671 *s = save_ch;
1672 break;
1674 *s = save_ch;
1675 if ( stopcmdlist )
1676 break;
1680 #ifdef HAVE_LIBREADLINE
1681 // restore readline's input/output streams
1682 rl_instream = old_rl_instream;
1683 rl_outstream = old_rl_outstream;
1684 #endif /* HAVE_LIBREADLINE */
1687 /*-----------------------------------------------------------------*/
1688 /* printVersionInfo - print the version information */
1689 /*-----------------------------------------------------------------*/
1690 static void printVersionInfo(void)
1692 fprintf(stdout,
1693 "SDCDB is free software and you are welcome to distribute copies of it\n"
1694 "under certain conditions; type \"show copying\" to see the conditions.\n"
1695 "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
1696 "SDCDB " SDCDB_VERSION ". Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n");
1699 /*-----------------------------------------------------------------*/
1700 /* printHelp - print help */
1701 /*-----------------------------------------------------------------*/
1702 static void printHelp(void)
1704 fprintf(stdout, "Type ? for help\n");
1707 /*-----------------------------------------------------------------*/
1708 /* escapeQuotes - escape double quotes */
1709 /*-----------------------------------------------------------------*/
1710 #define CHUNK 256
1712 static const char *escapeQuotes(const char *arg)
1714 #define extend(n) do { if ((size_t)(ps - str + (n)) > strLen) str = Safe_realloc (str, strLen += CHUNK); } while (0)
1716 static char *str = NULL;
1717 static size_t strLen = 0;
1718 char *ps;
1719 const char *pa;
1721 if (NULL == str)
1723 strLen = CHUNK;
1724 str = Safe_malloc (strLen);
1727 for (ps = str, pa = arg; '\0' != *pa; ++pa)
1729 if ('"' == *pa)
1731 extend (2);
1732 *ps++ = '\\'; /* excape the quote */
1733 *ps++ = *pa;
1735 else
1737 extend (1);
1738 *ps++ = *pa;
1741 extend (1);
1742 *ps = '\0';
1744 return str;
1747 /*-----------------------------------------------------------------*/
1748 /* argsToCmdLine - concatenate arguments ti command line */
1749 /*-----------------------------------------------------------------*/
1750 char *argsToCmdLine(char **args, int nargs)
1752 static char *cmd = NULL;
1753 static size_t cmdLen = 0;
1754 int i;
1755 size_t cmdPos = 0;
1757 if (NULL == cmd)
1759 cmd = Safe_malloc(CHUNK);
1760 cmdLen = CHUNK;
1763 for (i = 0; i < nargs; ++i)
1765 size_t argLen;
1766 size_t allocLen = 0;
1767 int quote = 0;
1768 const char *arg;
1770 if (0 < i)
1771 ++allocLen; /* space for space character */
1773 if (NULL != strchr(args[i], ' '))
1775 quote = 1;
1776 allocLen += 2; /* space for inital and final quote */
1777 arg = escapeQuotes(args[i]);
1779 else
1781 arg = args[i];
1784 argLen = strlen(arg);
1785 allocLen += argLen; /* space for argument */
1787 /* extend the buffer */
1788 if (cmdPos + allocLen >= cmdLen)
1792 cmdLen += cmdLen;
1794 while (cmdPos + allocLen >= cmdLen);
1795 cmd = Safe_realloc(cmd, cmdLen);
1798 if (0 < i)
1800 cmd[cmdPos++] = ' '; /* append space character */
1803 if (quote)
1805 cmd[cmdPos++] = '"'; /* append initial quote */
1808 memcpy(&cmd[cmdPos], arg, argLen); /* append argument */
1809 cmdPos += argLen;
1811 if (quote)
1812 cmd[cmdPos++] = '"'; /* append final quote */
1815 cmd[cmdPos] = '\0';
1817 return cmd;
1820 static void usage(void)
1822 const char *args =
1823 "-{h|?}, --help\tDisplay this help\n"
1824 "-v\tVerbose: show the simulator invocation commald line\n"
1825 "--directory=<dir>\tSearch modules in <dir> directory\n"
1826 "-fullname\tGive the file name & position\n"
1827 "-cd=<dir>, -cd <dir>\tChange directory to <dir>\n"
1828 #ifdef SDCDB_DEBUG
1829 "-d=<msk>\tSet debugging to <mask>\n"
1830 #endif
1831 "-contsim\tContinuous simulation\n"
1832 "-q\tIgnored\n"
1833 "-m<model>\tModel string: avr, xa, z80\n"
1834 "-z\tAll remaining options are for simulator";
1836 const char *simArgs =
1837 "-t <cpu>, -cpu <cpu>\tCpu type\n"
1838 "-frequency <frequency>, -X <frequency>\tXTAL Frequency\n"
1839 "-{s|S} <serial_port>\tSerial port\n"
1840 "-k\tNetwork serial port";
1842 printf("usage: sdcdb [args] [simulator args] [filename]\n"
1843 "args:\n");
1844 printHelpLine(args, 2);
1845 printf("simulator args:\n");
1846 printHelpLine(simArgs, 2);
1847 putchar('\n');
1848 printVersionInfo();
1851 /*-----------------------------------------------------------------*/
1852 /* parseCmdLine - parse the commandline arguments */
1853 /*-----------------------------------------------------------------*/
1854 static void parseCmdLine (int argc, char **argv)
1856 int i;
1857 char *filename = NULL;
1858 int passon_args_flag = 0; /* if true, pass on args to simulator */
1859 int verbose = 0;
1861 Dprintf(D_sdcdb, ("sdcdb: parseCmdLine\n"));
1862 contsim = 0;
1864 for (i = 1; i < argc ; i++)
1866 if (passon_args_flag) /* if true, pass on args to simulator */
1868 simArgs[nsimArgs++] = strdup(argv[i]);
1869 continue;
1872 /* if this is an option */
1873 if (argv[i][0] == '-')
1875 /* display usage */
1876 if (strcmp(argv[i], "-h") == 0 ||
1877 strcmp(argv[i], "-?") == 0 ||
1878 strcmp(argv[i], "--help") == 0)
1880 usage();
1881 exit(0);
1884 /* verbose */
1885 if (strcmp(argv[i], "-v") == 0)
1887 verbose = 1;
1888 continue;
1891 /* if directory then mark directory */
1892 if (strncmp(argv[i], "--directory=", 12) == 0)
1894 if (!ssdirl)
1896 ssdirl = &argv[i][12];
1898 else
1900 char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
1901 strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
1902 ssdirl = p;
1904 continue;
1907 if (strcmp(argv[i], "-fullname") == 0)
1909 fullname = TRUE;
1910 continue;
1913 if (strncmp(argv[i], "-cd=", 4) == 0)
1915 if (0 > chdir(&argv[i][4]))
1917 fprintf(stderr, "can't change directory to %s\n", &argv[i][4]);
1918 exit(1);
1920 continue;
1923 if (strcmp(argv[i], "-cd") == 0)
1925 i++;
1926 if (0 > chdir(argv[i]))
1928 fprintf(stderr, "can't change directory to %s\n", argv[i]);
1929 exit(1);
1931 continue;
1934 #ifdef SDCDB_DEBUG
1935 if (strncmp(argv[i], "-d=", 3) == 0)
1937 sdcdbDebug = strtol(&argv[i][3],0,0);
1938 continue;
1940 #endif
1941 if (strcmp(argv[i], "-contsim") == 0)
1943 contsim=1;
1944 continue;
1946 if (strcmp(argv[i], "-q") == 0)
1948 continue;
1951 /* model string */
1952 if (strncmp(argv[i],"-m", 2) == 0)
1954 strncpy(model_str, &argv[i][2], 15);
1955 if (strcmp(model_str, "avr") == 0)
1956 simArgs[0] = "savr";
1957 else if (strcmp(model_str, "xa") == 0)
1958 simArgs[0] = "sxa";
1959 else if (strcmp(model_str, "z80") == 0)
1960 simArgs[0] = "sz80";
1961 continue;
1964 /* -z all remaining options are for simulator */
1965 if (strcmp(argv[i], "-z") == 0)
1967 passon_args_flag = 1;
1968 continue;
1971 /* the simulator arguments */
1973 /* cpu */
1974 if (strcmp(argv[i], "-t") == 0 ||
1975 strcmp(argv[i], "-cpu") == 0)
1977 simArgs[nsimArgs++] = "-t";
1978 simArgs[nsimArgs++] = strdup(argv[++i]);
1979 continue;
1982 /* XTAL Frequency */
1983 if (strcmp(argv[i], "-X") == 0 ||
1984 strcmp(argv[i], "-frequency") == 0)
1986 simArgs[nsimArgs++] = "-X";
1987 simArgs[nsimArgs++] = strdup(argv[++i]);
1988 continue;
1991 /* serial port */
1992 if ((strcmp(argv[i], "-S") == 0) ||
1993 (strcmp(argv[i], "-s") == 0))
1995 simArgs[nsimArgs++] = strdup(argv[i]);
1996 simArgs[nsimArgs++] = strdup(argv[++i]);
1997 continue;
2000 /* network serial port */
2001 if ((strcmp(argv[i], "-k") == 0))
2003 simArgs[nsimArgs++] = strdup(argv[i]);
2004 simArgs[nsimArgs++] = strdup(argv[++i]);
2005 continue;
2008 fprintf(stderr,"unknown option %s --- ignored\n", argv[i]);
2010 else
2012 FILE* file;
2014 /* must be file name */
2015 if (filename)
2017 fprintf(stderr,
2018 "too many filenames .. parameter '%s' ignored\n",
2019 argv[i]);
2020 continue ;
2023 file = fopen(argv[i], "r");
2024 if (file)
2026 /* file exists: strip the cdb or ihx extension */
2027 char *p = strrchr(argv[i], '.');
2029 fclose(file);
2030 if (NULL != p &&
2031 (0 == strcmp(p, ".cdb") || 0 == strcmp(p, ".ihx")))
2033 *p = '\0';
2036 filename = argv[i];
2040 if (filename)
2041 cmdFile(filename,NULL);
2043 if (verbose)
2044 printf("+ %s\n", argsToCmdLine(simArgs, nsimArgs));
2047 /*-----------------------------------------------------------------*/
2048 /* setsignals - catch some signals */
2049 /*-----------------------------------------------------------------*/
2050 #include <signal.h>
2051 static void
2052 bad_signal(int sig)
2054 if ( simactive )
2055 closeSimulator();
2056 exit(1);
2059 static void
2060 sigintr(int sig)
2062 /* may be interrupt from user: stop debugger and also simulator */
2063 userinterrupt = 1;
2064 if ( !nointerrupt )
2065 sendSim("stop\n");
2068 #ifndef _WIN32
2069 /* the only child can be the simulator */
2070 static void sigchld(int sig)
2072 /* the only child can be the simulator */
2073 int status;
2074 wait ( &status );
2075 simactive = 0;
2077 #endif
2079 static void
2080 setsignals()
2082 signal(SIGINT , sigintr );
2083 signal(SIGABRT, bad_signal);
2084 signal(SIGTERM, bad_signal);
2086 #ifndef _WIN32
2087 signal(SIGHUP , SIG_IGN);
2088 signal(SIGCONT, SIG_IGN);
2089 signal(SIGCHLD, sigchld );
2091 signal(SIGALRM, bad_signal);
2092 //signal(SIGFPE, bad_signal);
2093 //signal(SIGILL, bad_signal);
2094 signal(SIGPIPE, bad_signal);
2095 signal(SIGQUIT, bad_signal);
2096 //signal(SIGSEGV, bad_signal);
2097 #endif
2100 /*-----------------------------------------------------------------*/
2101 /* main - */
2102 /*-----------------------------------------------------------------*/
2104 int main ( int argc, char **argv)
2106 simArgs[nsimArgs++] = "s51";
2107 simArgs[nsimArgs++] = "-P";
2108 simArgs[nsimArgs++] = "-r";
2109 simArgs[nsimArgs++] = "9756";
2111 /* parse command line */
2112 parseCmdLine(argc, argv);
2114 printVersionInfo();
2115 printHelp();
2116 printf("WARNING: SDCDB is EXPERIMENTAL.\n");
2118 setsignals();
2120 commandLoop(stdin);
2122 return 0;