1 /*-------------------------------------------------------------------------
2 sdcdb.c - main source file for sdcdb debugger
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
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.
9
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.
14
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.
18
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 -------------------------------------------------------------------------*/
23
24 #include "sdcdb.h"
25
26 char *ssdirl = DATADIR LIB_DIR_SUFFIX ":" DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "small" ;
27
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
49
50 #ifdef SDCDB_DEBUG
51 int sdcdbDebug = 0;
52 #endif
53
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;
77
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 */
104
105 /* command table */
106 struct cmdtab
107 {
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>]"
122 },
123 { "tbreak" , cmdSetTmpUserBp , completionCmdSetUserBp/*same as "break"*/,
124 "tbreak\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION | *<address>]"
125 },
126 { "b" , cmdSetUserBp , completionCmdSetUserBp , NULL,},
127
128 { "jump" , cmdJump , NULL,
129 "jump\tContinue program being debugged at specified line or address\n"
130 "\t[LINE | FILE:LINE | *<address>]",
131 },
132 { "clear" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/,
133 "{cl}ear\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]"
134 },
135 { "cl" , cmdClrUserBp , completionCmdSetUserBp/*same as "break"*/ ,
136 NULL
137 },
138 { "continue" , cmdContinue , NULL,
139 "{c}ontinue\tContinue program being debugged, after breakpoint."
140 },
141 { "condition" , cmdCondition , completionCmdDelUserBp/*same as "delete"*/,
142 "condition brkpoint_number expr\tSet condition for breakpoint."
143 },
144 { "ignore" , cmdIgnore , completionCmdDelUserBp/*same as "delete"*/,
145 "ignore brkpoint_number count\tSet ignore count for breakpoint."
146 },
147 { "commands" , cmdCommands , completionCmdDelUserBp/*same as "delete"*/,
148 "commands [brkpoint_number]\tSetting commands for breakpoint."
149 },
150 { "c" , cmdContinue , NULL ,
151 NULL
152 },
153 { "disassemble",cmdDisasmF , NULL,
154 "disassemble [startaddr [endaddress]]\tdisassemble asm commands"
155 },
156 { "delete" , cmdDelUserBp , completionCmdDelUserBp,
157 "{d}elete n\tclears break point number n"
158 },
159 { "display" , cmdDisplay , completionCmdPrint/*same as "print"*/,
160 "display [/<fmt>] [<variable>]\tprint value of given variable each time the program stops"
161 },
162 { "undisplay" , cmdUnDisplay , completionCmdUnDisplay,
163 "undisplay [<variable>]\tdon't display this variable or all"
164 },
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."
168 },
169 {
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."
173 },
174 { "d" , cmdDelUserBp , completionCmdDelUserBp,
175 NULL
176 },
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"
180 },
181 { "listasm" , cmdListAsm , NULL,
182 "listasm {la}\tlist assembler code for the current C line"
183 },
184 { "la" , cmdListAsm , NULL,
185 NULL
186 },
187 { "ls" , cmdListSymbols , completionCmdListSymbols,
188 "ls,lf,lm\tlist symbols,functions,modules"
189 },
190 { "lf" , cmdListFunctions, completionCmdListSymbols,
191 NULL
192 },
193 { "lm" , cmdListModules , completionCmdListSymbols,
194 NULL
195 },
196 { "list" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/,
197 "{l}ist\t[LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]"
198 },
199 { "l" , cmdListSrc , completionCmdSetUserBp/*same as "break"*/,
200 NULL
201 },
202 { "show" , cmdShow , completionCmdShow,
203 "show <copying warranty>\tcopying & distribution terms, warranty"
204 },
205 { "set" , cmdSetOption , completionCmdSetOption,
206 "set <srcmode>\ttoggle between c/asm.\nset variable <var> = >value\tset variable to new value"
207 },
208 { "stepi" , cmdStepi , NULL,
209 "stepi\tStep one instruction exactly."
210 },
211 { "step" , cmdStep , NULL,
212 "{s}tep\tStep program until it reaches a different source line."
213 },
214 { "source" , cmdSource , completionCmdSource,
215 "source <FILE>\tRead commands from a file named FILE."
216 },
217 { "s" , cmdStep , NULL,
218 NULL
219 },
220 { "nexti" , cmdNexti , NULL,
221 "nexti\tStep one instruction, but proceed through subroutine calls."
222 },
223 { "next" , cmdNext , NULL,
224 "{n}ext\tStep program, proceeding through subroutine calls."
225 },
226 { "n" , cmdNext , NULL,
227 NULL
228 },
229 { "run" , cmdRun , NULL,
230 "{r}un\tStart debugged program. "
231 },
232 { "r" , cmdRun , NULL,
233 NULL
234 },
235 { "ptype" , cmdPrintType , completionCmdPrintType,
236 "{pt}ype <variable>\tprint type information of a variable"
237 },
238 { "pt" , cmdPrintType , NULL,
239 NULL
240 },
241 { "print" , cmdPrint , completionCmdPrintType,
242 "{p}rint <variable>\tprint value of given variable"
243 },
244 { "output" , cmdOutput , completionCmdPrint/*same as "print"*/,
245 "output <variable>\tprint value of given variable without $ and newline"
246 },
247 { "p" , cmdPrint , completionCmdPrintType,
248 NULL
249 },
250 { "file" , cmdFile , completionCmdFile,
251 "file <filename>\tload symbolic information from <filename>"
252 },
253 { "frame" , cmdFrame , NULL,
254 "{fr}ame\tprint information about the current Stack"
255 },
256 { "finish" , cmdFinish , NULL,
257 "{fi}nish\texecute till return of current function"
258 },
259 { "fi" , cmdFinish , NULL,
260 NULL
261 },
262 { "where" , cmdWhere , NULL,
263 "where\tprint stack"
264 },
265 { "fr" , cmdFrame , NULL,
266 NULL
267 },
268 { "f" , cmdFrame , NULL,
269 NULL
270 },
271 { "x /i" , cmdDisasm1 , NULL,
272 "x\tdisassemble one asm command"
273 },
274 { "!" , cmdSimulator , NULL,
275 "!<simulator command>\tsend a command directly to the simulator"
276 },
277 { "." , cmdSimulator , NULL,
278 ".{cmd}\tswitch from simulator or debugger command mode"
279 },
280 { "help" , cmdHelp , NULL,
281 "{h|?}elp\t[CMD_NAME | 0,1,2,3(help page)] (general help or specific help)"
282 },
283 { "?" , cmdHelp , NULL,
284 NULL
285 },
286 { "h" , cmdHelp , NULL,
287 NULL
288 },
289 { "quit" , cmdQuit , NULL,
290 "{q}uit\t\"Watch me now. I'm going Down. My name is Bobby Brown\""
291 },
292 { "q" , cmdQuit , NULL,
293 NULL
294 }
295 };
296
297 /*-----------------------------------------------------------------*/
298 /* trimming functions */
299 /*-----------------------------------------------------------------*/
trim_left(char * s)300 char *trim_left(char *s)
301 {
302 while (isspace(*s))
303 ++s;
304
305 return s;
306 }
307
trim_right(char * s)308 char *trim_right(char *s)
309 {
310 char *p = &s[strlen(s) - 1];
311
312 while (p >= s && isspace(*p))
313 --p;
314 *++p = '\0';
315
316 return s;
317 }
318
trim(char * s)319 char *trim(char *s)
320 {
321 return trim_right(trim_left(s));
322 }
323
324 /*-----------------------------------------------------------------*/
325 /* gc_strdup - make a string duplicate garbage collector aware */
326 /*-----------------------------------------------------------------*/
gc_strdup(const char * s)327 char *gc_strdup(const char *s)
328 {
329 char *ret;
330 ret = Safe_malloc(strlen(s)+1);
331 strcpy(ret, s);
332 return ret;
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* alloccpy - allocate copy and return a new string */
337 /*-----------------------------------------------------------------*/
alloccpy(char * s,int size)338 char *alloccpy ( char *s, int size)
339 {
340 char *d;
341
342 if (!size)
343 return NULL;
344
345 d = Safe_malloc(size+1);
346 memcpy(d,s,size);
347 d[size] = '\0';
348
349 return d;
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* resize - resizes array of type with new size */
354 /*-----------------------------------------------------------------*/
resize(void ** array,int newSize)355 void **resize (void **array, int newSize)
356 {
357 void **vptr;
358
359 if (array)
360 vptr = Safe_realloc(array, newSize*(sizeof(void **)));
361 else
362 vptr = calloc(1, sizeof(void **));
363
364 if (!vptr)
365 {
366 fprintf(stderr, "sdcdb: out of memory\n");
367 exit(1);
368 }
369
370 return vptr;
371 }
372
373 /*-----------------------------------------------------------------*/
374 /* readCdb - reads the cdb files & puts the records into cdbLine */
375 /* linked list */
376 /*-----------------------------------------------------------------*/
readCdb(FILE * file)377 static int readCdb (FILE *file)
378 {
379 cdbrecs *currl;
380 char buffer[1024];
381 char *bp;
382
383 if (!(bp = fgets(buffer, sizeof(buffer), file)))
384 return 0;
385
386 currl = Safe_calloc(1, sizeof(cdbrecs));
387 recsRoot = currl;
388
389 while (1)
390 {
391 /* make sure this is a cdb record */
392 if (strchr("STLFM",*bp) && *(bp+1) == ':')
393 {
394 /* depending on the record type */
395
396 switch (*bp)
397 {
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;
414 }
415
416 bp += 2;
417 currl->line = Safe_malloc(strlen(bp));
418 strncpy(currl->line, bp, strlen(bp)-1);
419 currl->line[strlen(bp)-1] = '\0';
420 }
421
422 if (!(bp = fgets(buffer, sizeof(buffer), file)))
423 break;
424
425 if (feof(file))
426 break;
427
428 currl->next = Safe_calloc(1, sizeof(cdbrecs));
429 currl = currl->next;
430 }
431
432 return (recsRoot->line ? 1 : 0);
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* searchDirsFname - search directory list & return the filename */
437 /*-----------------------------------------------------------------*/
searchDirsFname(char * fname)438 char *searchDirsFname (char *fname)
439 {
440 char *dirs , *sdirs;
441 FILE *rfile = NULL;
442 char buffer[128];
443
444 /* first try the current directory */
445 if ((rfile = fopen(fname, "r")))
446 {
447 fclose(rfile);
448 return strdup(fname) ;
449 }
450
451 if (!ssdirl)
452 return strdup(fname);
453
454 /* make a copy of the source directories */
455 dirs = sdirs = strdup(ssdirl);
456
457 /* assume that the separator is ':'
458 and try for each directory in the search list */
459 dirs = strtok(dirs, ":");
460 while (dirs)
461 {
462 if (dirs[strlen(dirs)] == '/')
463 sprintf(buffer, "%s%s", dirs, fname);
464 else
465 sprintf(buffer, "%s/%s", dirs, fname);
466 if ((rfile = fopen(buffer, "r")))
467 break;
468 dirs = strtok(NULL, ":");
469 }
470
471 free(sdirs);
472 if (rfile)
473 {
474 fclose(rfile);
475 return strdup(buffer);
476 }
477 else //not found
478 {
479 char *p, *found;
480
481 // sprintf(buffer, "%s", fname);
482 p = fname;
483 while (NULL != (p = strchr(p, '_')))
484 {
485 *p = '.'; // try again with '_' replaced by '.'
486 if (NULL != (found = searchDirsFname(fname)))
487 return found;
488 *p = '_'; // not found, restore '_' and try next '_'
489 }
490 }
491 return NULL;
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* searchDirsFopen - go thru list of directories for filename given*/
496 /*-----------------------------------------------------------------*/
searchDirsFopen(char * fname)497 FILE *searchDirsFopen(char *fname)
498 {
499 char *dirs , *sdirs;
500 FILE *rfile = NULL;
501 char buffer[128];
502
503 /* first try the current directory */
504 if ((rfile = fopen(fname, "r")))
505 return rfile;
506
507 if (!ssdirl)
508 return NULL;
509
510 /* make a copy of the source directories */
511 dirs = sdirs = strdup(ssdirl);
512
513 /* assume that the separator is ':'
514 and try for each directory in the search list */
515 dirs = strtok(dirs, ":");
516 while (dirs)
517 {
518 sprintf(buffer, "%s/%s", dirs, fname);
519 if ((rfile = fopen(buffer, "r")))
520 break;
521 dirs = strtok(NULL, ":");
522 }
523
524 free(sdirs);
525 return rfile ;
526 }
527
528 /*-----------------------------------------------------------------*/
529 /* loadFile - loads a file into module buffer */
530 /*-----------------------------------------------------------------*/
loadFile(char * name,int * nlines)531 srcLine **loadFile (char *name, int *nlines)
532 {
533 FILE *mfile;
534 char buffer[512];
535 char *bp;
536 srcLine **slines = NULL;
537
538 if (!(mfile = searchDirsFopen(name)))
539 {
540 fprintf(stderr, "sdcdb: cannot open module %s -- use '--directory=<source directory> option\n", name);
541 return NULL;
542 }
543
544 while ((bp = fgets(buffer, sizeof(buffer), mfile)))
545 {
546 (*nlines)++;
547
548 slines = (srcLine **)resize((void **)slines, *nlines);
549
550 slines[(*nlines)-1] = Safe_calloc(1, sizeof(srcLine));
551 slines[(*nlines)-1]->src = alloccpy(bp, strlen(bp));
552 slines[(*nlines)-1]->addr = INT_MAX;
553 }
554
555 fclose(mfile);
556 return slines;
557 }
558
559
560 /*-----------------------------------------------------------------*/
561 /* loadModules - reads the source files into module structure */
562 /*-----------------------------------------------------------------*/
loadModules(void)563 static void loadModules (void)
564 {
565 cdbrecs *loop;
566 module *currMod;
567 char *rs;
568
569 /* go thru the records & find out the module
570 records & load the modules specified */
571 for ( loop = recsRoot ; loop ; loop = loop->next )
572 {
573 switch (loop->type)
574 {
575 /* for module records do */
576 case MOD_REC:
577 currMod = parseModule(loop->line, TRUE);
578 currModName = currMod->name ;
579
580 /* search the c source file and load it into buffer */
581 currMod->cfullname = searchDirsFname(currMod->c_name);
582 currMod->cLines = loadFile (currMod->c_name, &currMod->ncLines);
583
584 /* do the same for the assembler file */
585 currMod->afullname = searchDirsFname(currMod->asm_name);
586 currMod->asmLines = loadFile (currMod->asm_name, &currMod->nasmLines);
587 break;
588
589 /* if this is a function record */
590 case FUNC_REC:
591 parseFunc(loop->line);
592 break;
593
594 /* if this is a structure record */
595 case STRUCT_REC:
596 parseStruct(loop->line);
597 break;
598
599 /* if symbol then parse the symbol */
600 case SYM_REC:
601 parseSymbol(loop->line, &rs, 2);
602 break;
603
604 case LNK_REC:
605 parseLnkRec(loop->line);
606 break;
607 }
608 }
609 }
610
611 /*-----------------------------------------------------------------*/
612 /* generate extra sets of sfr and sbit symbols */
613 /*-----------------------------------------------------------------*/
specialFunctionRegs(void)614 static void specialFunctionRegs (void)
615 {
616 symbol *sym;
617 for (sym = setFirstItem(symbols); sym; sym = setNextItem(symbols))
618 {
619 if ( sym->addrspace == 'I' || sym->addrspace == 'J')
620 {
621 addSet(&sfrsymbols, sym);
622 }
623 }
624 }
625 /*-----------------------------------------------------------------*/
626 /* functionPoints - determine the execution points within a func */
627 /*-----------------------------------------------------------------*/
functionPoints(void)628 static void functionPoints (void)
629 {
630 function *func;
631 symbol *sym;
632 exePoint *ep;
633
634 // add _main dummy for runtime env
635 if ((func = needExtraMainFunction()))
636 {
637 function *func1;
638
639 /* alloc new _main function */
640 func1 = Safe_calloc(1, sizeof(function));
641 *func1 = *func;
642 func1->sym = Safe_calloc(1, sizeof(symbol));
643 *func1->sym = *func->sym;
644 func1->sym->name = alloccpy("_main", 5);
645 func1->sym->rname = alloccpy("G$_main$0$", 10);
646 /* TODO must be set by symbol information */
647 func1->sym->addr = 0;
648 func1->sym->eaddr = 0x2f;
649 addSet(&functions, func1);
650 }
651
652 /* for all functions do */
653 for ( func = setFirstItem(functions); func; func = setNextItem(functions))
654 {
655 int j ;
656 module *mod;
657
658 sym = func->sym;
659
660 Dprintf(D_sdcdb, ("sdcdb: func '%s' has entry '0x%x' exit '0x%x'\n",
661 func->sym->name,
662 func->sym->addr,
663 func->sym->eaddr));
664
665 if (!func->sym->addr && !func->sym->eaddr)
666 continue;
667
668 /* for all source lines in the module find
669 the ones with address >= start and <= end
670 and put them in the point */
671 mod = NULL ;
672 if (! applyToSet(modules, moduleWithName, func->modName, &mod))
673 continue;
674 func->mod = mod;
675 func->entryline= INT_MAX-2;
676 func->exitline = 0;
677 func->aentryline = INT_MAX-2;
678 func->aexitline = 0;
679
680 /* do it for the C Lines first */
681 for ( j = 0 ; j < mod->ncLines ; j++ )
682 {
683 if (mod->cLines[j]->addr < INT_MAX &&
684 mod->cLines[j]->addr >= sym->addr &&
685 mod->cLines[j]->addr <= sym->eaddr )
686 {
687 /* add it to the execution point */
688 if (func->entryline > j)
689 func->entryline = j;
690
691 if (func->exitline < j)
692 func->exitline = j;
693
694 ep = Safe_calloc(1, sizeof(exePoint));
695 ep->addr = mod->cLines[j]->addr ;
696 ep->line = j;
697 ep->block= mod->cLines[j]->block;
698 ep->level= mod->cLines[j]->level;
699 addSet(&func->cfpoints, ep);
700 }
701 }
702 /* check double line execution points of module */
703 for (ep = setFirstItem(mod->cfpoints); ep; ep = setNextItem(mod->cfpoints))
704 {
705 if (ep->addr >= sym->addr && ep->addr <= sym->eaddr )
706 {
707 addSet(&func->cfpoints, ep);
708 }
709 }
710 /* do the same for asm execution points */
711 for ( j = 0 ; j < mod->nasmLines ; j++ )
712 {
713 if (mod->asmLines[j]->addr < INT_MAX &&
714 mod->asmLines[j]->addr >= sym->addr &&
715 mod->asmLines[j]->addr <= sym->eaddr )
716 {
717 exePoint *ep ;
718 /* add it to the execution point */
719 if (func->aentryline > j)
720 func->aentryline = j;
721
722 if (func->aexitline < j)
723 func->aexitline = j;
724
725 /* add it to the execution point */
726 ep = Safe_calloc(1, sizeof(exePoint));
727 ep->addr = mod->asmLines[j]->addr;
728 ep->line = j;
729 addSet(&func->afpoints, ep);
730 }
731 }
732 if ( func->entryline == INT_MAX-2 )
733 func->entryline = 0;
734 if ( func->aentryline == INT_MAX-2 )
735 func->aentryline = 0;
736
737 #ifdef SDCDB_DEBUG
738 if (!( D_sdcdb & sdcdbDebug))
739 continue;
740
741 Dprintf(D_sdcdb, ("sdcdb: function '%s' has the following C exePoints\n",
742 func->sym->name));
743 {
744 exePoint *ep;
745
746 for (ep = setFirstItem(func->cfpoints); ep; ep = setNextItem(func->cfpoints))
747 {
748 Dprintf(D_sdcdb, ("sdcdb: {0x%x,%d} %s",
749 ep->addr, ep->line+1, mod->cLines[ep->line]->src));
750 }
751
752 Dprintf(D_sdcdb, ("sdcdb: and the following ASM exePoints\n"));
753 for (ep = setFirstItem(func->afpoints); ep; ep = setNextItem(func->afpoints))
754 {
755 Dprintf (D_sdcdb, ("sdcdb: {0x%x,%d} %s",
756 ep->addr, ep->line+1, mod->asmLines[ep->line]->src));
757 }
758 }
759 #endif
760 }
761 }
762
763
764 /*-----------------------------------------------------------------*/
765 /* setEntryExitBP - set the entry & exit Break Points for functions*/
766 /*-----------------------------------------------------------------*/
DEFSETFUNC(setEntryExitBP)767 DEFSETFUNC(setEntryExitBP)
768 {
769 function *func = item;
770
771 if (func->sym && func->sym->addr && func->sym->eaddr)
772 {
773 /* set the entry break point */
774 setBreakPoint (func->sym->addr, CODE, FENTRY,
775 fentryCB, func->mod->c_name, func->entryline);
776
777 /* set the exit break point */
778 setBreakPoint (func->sym->eaddr, CODE, FEXIT,
779 fexitCB, func->mod->c_name, func->exitline);
780 }
781
782 return 0;
783 }
784
785 /*-----------------------------------------------------------------*/
786 /* cmdFile - load file into the debugger */
787 /*-----------------------------------------------------------------*/
cmdFile(char * s,context * cctxt)788 int cmdFile (char *s,context *cctxt)
789 {
790 FILE *cdbFile;
791 char buffer[128];
792 char *bp;
793
794 s = trim_left(s);
795
796 if (!*s)
797 {
798 fprintf(stdout, "No exec file now.\nNo symbol file now.\n");
799 return 0;
800 }
801
802 sprintf(buffer, "%s.cdb", s);
803 /* try creating the cdbfile */
804 if (!(cdbFile = searchDirsFopen(buffer)))
805 {
806 fprintf(stdout, "Cannot open file\"%s\", no symbolic information loaded\n", buffer);
807 // return 0;
808 }
809
810 /* allocate for context */
811 currCtxt = Safe_calloc(1, sizeof(context));
812
813 if (cdbFile)
814 {
815 /* read in the debug information */
816 if (!readCdb (cdbFile))
817 {
818 fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
819 //return 0;
820 }
821 }
822
823 /* parse and load the modules required */
824 loadModules();
825
826 /* determine the execution points for this module */
827 functionPoints();
828
829 /* extract known special function registers */
830 specialFunctionRegs();
831
832 /* start the simulator & setup connection to it */
833 #ifdef _WIN32
834 if (INVALID_SOCKET == sock)
835 #else
836 if ( sock == -1 )
837 #endif
838 openSimulator((char **)simArgs, nsimArgs);
839 fprintf(stdout, "%s", simResponse());
840 /* now send the filename to be loaded to the simulator */
841 sprintf(buffer, "%s.ihx", s);
842 bp = searchDirsFname(buffer);
843 simLoadFile(bp);
844 free(bp);
845
846 /* set the break points
847 required by the debugger . i.e. the function entry
848 and function exit break points */
849 applyToSet(functions, setEntryExitBP);
850
851 setMainContext();
852 return 0;
853 }
854
855 /*-----------------------------------------------------------------*/
856 /* cmdSource - read commands from file */
857 /*-----------------------------------------------------------------*/
cmdSource(char * s,context * cctxt)858 int cmdSource (char *s, context *cctxt)
859 {
860 FILE *cmdfile;
861
862 s = trim(s);
863
864 if (!( cmdfile = searchDirsFopen(s)))
865 {
866 fprintf(stderr,"commandfile '%s' not found\n",s);
867 return 0;
868 }
869 commandLoop( cmdfile );
870 fclose( cmdfile );
871 return 0;
872 }
873
874 /*-----------------------------------------------------------------*/
875 /* cmdHelp - help command */
876 /*-----------------------------------------------------------------*/
877 #define TEXT_OFFSET 24
878
printHelpLine(const char * htxt,int offs)879 static void printHelpLine(const char *htxt, int offs)
880 {
881 static char *spaces = NULL;
882 const char *p;
883 int state = 0;
884
885 if (NULL == spaces)
886 {
887 spaces = Safe_malloc(TEXT_OFFSET + 1);
888 memset(spaces, ' ', TEXT_OFFSET);
889 spaces[TEXT_OFFSET] = '\0';
890 }
891
892 p = htxt;
893
894 do
895 {
896 const char *ps = p;
897 int len;
898 while (*p && *p != '\t' && *p != '\n')
899 ++p;
900 len = p - ps;
901
902 if (state == 0)
903 {
904 printf("%.*s%.*s", offs, spaces, len, ps); /* command text */
905
906 if (len >= TEXT_OFFSET - offs)
907 printf("\n%s", spaces);
908 else
909 printf("%.*s", TEXT_OFFSET - offs - len, spaces);
910 }
911 else
912 {
913 printf("%.*s\n", len, ps); /* help text */
914 }
915 state = *p == '\t';
916 }
917 while (*p++);
918 }
919
cmdHelp(char * s,context * cctxt)920 int cmdHelp (char *s, context *cctxt)
921 {
922 int i ;
923 int endline = 999;
924 int startline = 0;
925
926 s = trim_left(s);
927
928 if (isdigit(*s))
929 {
930 endline = ((*s - '0') * 20) + 20;
931 if (endline > 0)
932 startline = endline - 20;
933 }
934 else if (*s)
935 {
936 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
937 {
938 if ((cmdTab[i].htxt) && !strcmp(cmdTab[i].cmd,s))
939 {
940 printHelpLine(cmdTab[i].htxt, 0);
941 break;
942 }
943 }
944 return 0;
945 }
946
947 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
948 {
949 /* command string matches */
950
951 if ((cmdTab[i].htxt) && (i >= startline))
952 printHelpLine(cmdTab[i].htxt, 0);
953 if (i == endline)
954 break;
955 }
956
957 return 0;
958 }
959
960 #define MAX_CMD_LEN 512
961 static char cmdbuff[MAX_CMD_LEN];
962 static int sim_cmd_mode = 0;
963
964 /*-----------------------------------------------------------------
965 interpretCmd - interpret and do the command. Return 0 to continue,
966 return 1 to exit program.
967 |-----------------------------------------------------------------*/
interpretCmd(char * s)968 int interpretCmd (char *s)
969 {
970 static char *pcmd = NULL;
971 int i ;
972 int rv = 0 ;
973
974 /* if nothing & previous command exists then
975 execute the previous command again */
976 if (*s == '\n' && pcmd)
977 strcpy(s,pcmd);
978
979 /* if previous command exists & is different
980 from the current command then copy it */
981 if (pcmd)
982 {
983 if (strcmp(pcmd,s))
984 {
985 free(pcmd);
986 pcmd = strdup(s);
987 }
988 }
989 else
990 {
991 pcmd = strdup(s);
992 }
993
994 /* trim trailing blanks */
995 s = trim_right(s);
996
997 if (sim_cmd_mode)
998 {
999 if (strcmp(s,".") == 0)
1000 {
1001 sim_cmd_mode = 0;
1002 return 0;
1003 }
1004 else if (s[0] == '.')
1005 {
1006 /* kill the preceeding '.' and pass on as SDCDB command */
1007 char *s1 = s+1;
1008 char *s2 = s;
1009 while (*s1 != 0)
1010 *s2++ = *s1++;
1011 *s2 = 0;
1012 }
1013 else
1014 {
1015 cmdSimulator (s, currCtxt);
1016 return 0;
1017 }
1018 }
1019 else
1020 {
1021 if (strcmp(s,".") ==0)
1022 {
1023 sim_cmd_mode = 1;
1024 return 0;
1025 }
1026 }
1027
1028 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1029 {
1030 /* command string matches */
1031 if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0)
1032 {
1033 if (!cmdTab[i].cmdfunc)
1034 return 1;
1035
1036 rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
1037
1038 /* if full name then give the file name & position */
1039 if (fullname && showfull && currCtxt && currCtxt->func)
1040 {
1041 showfull = 0;
1042 if (srcMode == SRC_CMODE)
1043 fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
1044 currCtxt->func->mod->cfullname,
1045 currCtxt->cline+1,currCtxt->addr);
1046 else
1047 fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
1048 currCtxt->func->mod->afullname,
1049 currCtxt->asmline,currCtxt->addr);
1050 displayAll(currCtxt);
1051 }
1052 goto ret;
1053 }
1054 }
1055 fprintf(stdout,"Undefined command: \"%s\". Try \"help\".\n",s);
1056
1057 ret:
1058 return rv;
1059 }
1060
1061 static FILE *actualcmdfile=NULL ;
1062 static char *actualcmds=NULL;
1063 static int stopcmdlist;
1064 /*-----------------------------------------------------------------*/
1065 /* getNextCmdLine get additional lines used by special commands */
1066 /*-----------------------------------------------------------------*/
getNextCmdLine(void)1067 char *getNextCmdLine(void)
1068 {
1069 //fprintf(stderr,"getNextCmdLine() actualcmdfile=%p\n",actualcmdfile);
1070 if (!actualcmdfile)
1071 return NULL;
1072 fprintf(stdout,">");
1073 fflush(stdout);
1074 if (fgets(cmdbuff,sizeof(cmdbuff),actualcmdfile) == NULL)
1075 {
1076 // fprintf(stderr,"getNextCmdLine() returns null\n");
1077 return NULL;
1078 }
1079 //fprintf(stderr,"getNextCmdLine() returns: %s",cmdbuff);
1080 return cmdbuff;
1081 }
1082
setCmdLine(char * cmds)1083 void setCmdLine( char *cmds )
1084 {
1085 actualcmds = cmds;
1086 }
1087
stopCommandList()1088 void stopCommandList()
1089 {
1090 stopcmdlist = 1;
1091 }
1092
1093 #ifdef HAVE_READLINE_COMPLETITION
1094 // helper function for doing readline completion.
1095 // input: toknum=index of token to find (0=first token)
1096 // output: *start=first character index of the token,
1097 // or the index of '\0'
1098 // *end=first blank character right after the token,
1099 // or the index of '\0'
1100 // return value: 0=token not found, 1=token found
completionHelper_GetTokenNumber(int toknum,int * start,int * end)1101 int completionHelper_GetTokenNumber(int toknum, int *start, int *end)
1102 {
1103 int tok_index;
1104 const char *p = rl_line_buffer;
1105
1106 tok_index = 0;
1107 *start = *end = 0;
1108 while (p[*end] != 0)
1109 {
1110 // start = skip blanks from end
1111 *start = *end;
1112 while (p[*start] && isspace( p[*start] ))
1113 (*start)++;
1114
1115 // end = skip non-blanks from start
1116 *end = *start;
1117 while (p[*end] && !isspace( p[*end] ))
1118 (*end)++;
1119
1120 if (tok_index == toknum)
1121 return 1; // found
1122
1123 tok_index++;
1124 }
1125
1126 return 0; // not found
1127 }
1128
1129 // helper function for doing readline completion.
1130 // returns the token number that we were asked to complete.
1131 // 0=first token (command name), 1=second token...
completionHelper_GetCurrTokenNumber()1132 int completionHelper_GetCurrTokenNumber()
1133 {
1134 int toknum, start, end;
1135
1136 toknum = start = end = 0;
1137 while (1)
1138 {
1139 if (!completionHelper_GetTokenNumber(toknum, &start, &end))
1140 return toknum;
1141
1142 if (rl_point <= end)
1143 return toknum;
1144
1145 toknum++;
1146 }
1147 }
1148
1149 // exapmle for vallist on entry:
1150 // "copying\0warranty\0";
completionCompleteFromStrList(const char * text,int state,char * vallist)1151 char *completionCompleteFromStrList(const char *text, int state, char *vallist)
1152 {
1153 static char *ptr;
1154 int len;
1155
1156 if (state == 0)
1157 ptr = vallist;
1158 else
1159 ptr += strlen(ptr)+1;
1160
1161 len = strlen(text);
1162 while (*ptr)
1163 {
1164 if ( (len < strlen(ptr)) && !strncmp(text, ptr, len) )
1165 return strdup(ptr);
1166
1167 ptr += strlen(ptr)+1;
1168 }
1169
1170 return NULL;
1171 }
1172
1173 // readline library completion function.
1174 // completes from the list of all sdcdb command.
completionCommandsList(const char * text,int state)1175 char *completionCommandsList(const char *text, int state)
1176 {
1177 static int i = 0;
1178
1179 if (state == 0) // new completion?
1180 { // yes, only complete if this is the first token on the line.
1181 int ok = 0; // try to complete this request?
1182 char *p = rl_line_buffer;
1183
1184 // skip blanks
1185 while (p && isspace(*p))
1186 {
1187 if (p-rl_line_buffer == rl_point)
1188 ok = 1;
1189 p++;
1190 }
1191
1192 while (p && !isspace(*p))
1193 {
1194 if (p-rl_line_buffer == rl_point)
1195 ok = 1;
1196 p++;
1197 }
1198
1199 if (p-rl_line_buffer == rl_point)
1200 ok = 1;
1201
1202 if ( !ok )
1203 return NULL; // no more completions
1204
1205 i = 0; // ok, gonna complete. initialize static variable.
1206 }
1207 else
1208 {
1209 i++;
1210 }
1211
1212 for (; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1213 {
1214 int len = strlen(text);
1215 if (len <= strlen(cmdTab[i].cmd))
1216 {
1217 if (strncmp(text,cmdTab[i].cmd,len) == 0)
1218 return strdup(cmdTab[i].cmd);
1219 }
1220 }
1221
1222 return NULL; // no more completions
1223 }
1224
1225 // readline library completion function.
1226 // completes from the list of symbols.
completionSymbolName(const char * text,int state)1227 char *completionSymbolName(const char *text, int state)
1228 {
1229 static symbol *sy;
1230
1231 if (state == 0) // new completion?
1232 sy = setFirstItem(symbols); // yes
1233 else
1234 sy = setNextItem(symbols);
1235
1236 for (; sy != NULL; )
1237 {
1238 int len = strlen(text);
1239 if (len <= strlen(sy->name))
1240 {
1241 if (strncmp(text,sy->name,len) == 0)
1242 return strdup(sy->name);
1243 }
1244
1245 sy = setNextItem(symbols);
1246 }
1247 return NULL;
1248 }
1249
1250 // readline library completion function.
1251 // completes from the list known functions.
1252 // module_flag - if false, ignore function module name
1253 // if true, compare against module_name:fnction_name
completionFunctionName(const char * text,int state,int module_flag)1254 char *completionFunctionName(const char *text, int state, int module_flag)
1255 {
1256 static function *f;
1257
1258 if (state == 0) // new completion?
1259 f = setFirstItem(functions); // yes
1260 else
1261 f = setNextItem(functions);
1262
1263 for (; f != NULL; )
1264 {
1265 int text_len = strlen(text);
1266
1267 if (!module_flag)
1268 {
1269 if (text_len <= strlen(f->sym->name) &&
1270 !strncmp(text,f->sym->name,text_len))
1271 {
1272 return strdup(f->sym->name);
1273 }
1274 }
1275 else
1276 {
1277 int modname_len = strlen(f->mod->c_name);
1278 int funcname_len = strlen(f->sym->name);
1279 char *functext = malloc(modname_len+funcname_len+2);
1280 //assert(functext);
1281 strcpy(functext,f->mod->c_name);
1282 strcat(functext,":");
1283 strcat(functext,f->sym->name);
1284 if (text_len <= strlen(functext) &&
1285 !strncmp(text,functext,text_len))
1286 {
1287 return functext;
1288 }
1289 else
1290 {
1291 free(functext);
1292 }
1293 }
1294 f = setNextItem(functions);
1295 }
1296 return NULL;
1297 }
1298
1299 // readline library completion function.
1300 // completes from the list known modules.
completionModuleName(const char * text,int state)1301 char *completionModuleName(const char *text, int state)
1302 {
1303 static module *m;
1304
1305 if (state == 0) // new completion?
1306 m = setFirstItem(modules); // yes
1307 else
1308 m = setNextItem(modules);
1309
1310 for (; m != NULL; )
1311 {
1312 int len = strlen(text);
1313 if ( (len <= strlen(m->c_name)) &&
1314 !strncmp(text,m->c_name,len) )
1315 {
1316 return strdup(m->c_name);
1317 }
1318
1319 if ( (len <= strlen(m->asm_name)) &&
1320 (strncmp(text,m->asm_name,len) == 0) )
1321 {
1322 return strdup(m->asm_name);
1323 }
1324
1325 m = setNextItem(modules);
1326 }
1327 return NULL;
1328 }
1329
1330 // readline completion function for "file" command
completionCmdFile(const char * text,int state)1331 char *completionCmdFile(const char *text, int state)
1332 {
1333 if (state == 0)
1334 {
1335 if (completionHelper_GetCurrTokenNumber() != 1)
1336 return NULL;
1337 }
1338
1339 // we use filename_completion_function() from the readline library.
1340 return rl_filename_completion_function(text, state);
1341 }
1342
1343 // readline completion function for "source" command
completionCmdSource(const char * text,int state)1344 char *completionCmdSource(const char *text, int state)
1345 {
1346 return completionCmdFile(text, state);
1347 }
1348
1349 // readline completion function for "info" command
completionCmdInfo(const char * text,int state)1350 char *completionCmdInfo(const char *text, int state)
1351 {
1352 if (state == 0)
1353 {
1354 if (completionHelper_GetCurrTokenNumber() != 1)
1355 return NULL;
1356 }
1357
1358 return completionCompleteFromStrList(text, state,
1359 "break\0stack\0frame\0registers\0all-registers\0"
1360 "line\0source\0functions\0symbols\0variables\0");
1361 }
1362
1363 // readline completion function for "show" command
completionCmdShow(const char * text,int state)1364 char *completionCmdShow(const char *text, int state)
1365 {
1366 if (state == 0)
1367 {
1368 if (completionHelper_GetCurrTokenNumber() != 1)
1369 return NULL;
1370 }
1371 return completionCompleteFromStrList(text, state, "copying\0warranty\0");
1372 }
1373
1374 // readline completion function for "la" command
completionCmdListSymbols(const char * text,int state)1375 char *completionCmdListSymbols(const char *text, int state)
1376 {
1377 if (state == 0)
1378 {
1379 if (completionHelper_GetCurrTokenNumber() != 1)
1380 return NULL;
1381 }
1382 return completionCompleteFromStrList(text, state, "v1\0v2\0");
1383 }
1384
completionCmdPrintType(const char * text,int state)1385 char *completionCmdPrintType(const char *text, int state)
1386 {
1387 if (state == 0)
1388 {
1389 if (completionHelper_GetCurrTokenNumber() != 1)
1390 return NULL;
1391 }
1392 return completionSymbolName(text, state);
1393 }
1394
completionCmdPrint(const char * text,int state)1395 char *completionCmdPrint(const char *text, int state)
1396 {
1397 if (state == 0)
1398 {
1399 int i = completionHelper_GetCurrTokenNumber();
1400 if (i != 1 && i != 2)
1401 return NULL;
1402 }
1403 return completionSymbolName(text, state);
1404 }
1405
completionCmdDelUserBp(const char * text,int state)1406 char *completionCmdDelUserBp(const char *text, int state)
1407 {
1408 static breakp *bp;
1409 static int k;
1410
1411 if (state == 0)
1412 {
1413 if (completionHelper_GetCurrTokenNumber() != 1)
1414 return NULL;
1415
1416 if (!userBpPresent)
1417 return NULL;
1418
1419 bp = hTabFirstItem(bptable,&k);
1420 }
1421 else
1422 {
1423 bp = hTabNextItem(bptable,&k);
1424 }
1425
1426 for ( ; bp ; bp = hTabNextItem(bptable,&k))
1427 {
1428 if (bp->bpType == USER || bp->bpType == TMPUSER)
1429 {
1430 char buff[20];
1431 sprintf(buff, "%d", bp->bpnum);
1432 return strdup(buff);
1433 }
1434 }
1435
1436 return NULL;
1437 }
1438
1439 // readline completion function for "undisplay" command
completionCmdUnDisplay(const char * text,int state)1440 char *completionCmdUnDisplay(const char *text, int state)
1441 {
1442 static dsymbol *dsym;
1443
1444 if (state == 0)
1445 {
1446 if (completionHelper_GetCurrTokenNumber() != 1)
1447 return NULL;
1448 dsym = setFirstItem(dispsymbols);
1449 }
1450
1451 if (dsym)
1452 {
1453 char buff[30];
1454 sprintf(buff, "%d", dsym->dnum);
1455 dsym = setNextItem(dispsymbols);
1456 return strdup(buff);
1457 }
1458 return NULL;
1459 }
1460
completionCmdSetUserBp(const char * text,int state)1461 char *completionCmdSetUserBp(const char *text, int state)
1462 {
1463 static int internal_state; // 0=calling completionFunctionName(text, state, 0)
1464 // 1=calling completionFunctionName(text, 1, 1)
1465 if (state == 0)
1466 {
1467 if (completionHelper_GetCurrTokenNumber() != 1)
1468 return NULL;
1469
1470 internal_state = 0;
1471 }
1472 if (internal_state == 0)
1473 {
1474 char *p = completionFunctionName(text, state, 0);
1475 if (p)
1476 return p;
1477 internal_state = 1;
1478 return completionFunctionName(text, 0, 1);
1479 }
1480 else
1481 {
1482 return completionFunctionName(text, 1, 1);
1483 }
1484 }
1485
completionCmdSetOption(const char * text,int state)1486 char *completionCmdSetOption(const char *text, int state)
1487 {
1488 static int currtok;
1489
1490 if (state == 0)
1491 {
1492 int start,end;
1493
1494 currtok = completionHelper_GetCurrTokenNumber();
1495
1496 if (currtok == 2 || currtok == 3)
1497 {
1498 // make sure token 1 == "variable"
1499 completionHelper_GetTokenNumber(1, &start, &end);
1500 if (end - start != 8 ||
1501 strncmp(rl_line_buffer+start,"variable",8))
1502 {
1503 return NULL;
1504 }
1505 }
1506 else if (currtok != 1)
1507 {
1508 return NULL;
1509 }
1510 }
1511
1512 switch (currtok)
1513 {
1514 case 1:
1515 return completionCompleteFromStrList(text, state,
1516 #ifdef SDCDB_DEBUG
1517 "debug\0"
1518 #endif
1519 "srcmode\0listsize\0variable\0");
1520 case 2:
1521 return completionSymbolName(text, state);
1522
1523 case 3:
1524 return completionCompleteFromStrList(text, state, "=\0");
1525 }
1526 return NULL;
1527 }
1528
1529 // our main readline completion function
1530 // calls the other completion functions as needed.
completionMain(const char * text,int state)1531 char *completionMain(const char *text, int state)
1532 {
1533 static rl_compentry_func_t *compl_func;
1534 int i, start, end, len;
1535
1536 if (state == 0) // new completion?
1537 {
1538 compl_func = NULL;
1539
1540 if (completionHelper_GetCurrTokenNumber() == 0)
1541 {
1542 compl_func = &completionCommandsList;
1543 }
1544 else
1545 { // not completing first token, find the right completion
1546 // function according to the first token the user typed.
1547 completionHelper_GetTokenNumber(0, &start, &end);
1548 len = end-start;
1549
1550 for (i=0; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
1551 {
1552 if (!strncmp(rl_line_buffer+start,cmdTab[i].cmd,len) &&
1553 cmdTab[i].cmd[len] == '\0')
1554 {
1555 compl_func = cmdTab[i].completion_func;
1556 break;
1557 }
1558 }
1559 }
1560 if (!compl_func)
1561 return NULL;
1562 }
1563
1564 return (*compl_func)(text,state);
1565 }
1566 #endif /* HAVE_READLINE_COMPLETITION */
1567
1568 /*-----------------------------------------------------------------*/
1569 /* commandLoop - the main command loop or loop over command file */
1570 /*-----------------------------------------------------------------*/
commandLoop(FILE * cmdfile)1571 static void commandLoop(FILE *cmdfile)
1572 {
1573 char *line, save_ch, *s;
1574 #ifdef HAVE_LIBREADLINE
1575 char *line_read;
1576
1577 FILE *old_rl_instream, *old_rl_outstream;
1578 actualcmdfile = cmdfile;
1579
1580 #ifdef HAVE_READLINE_COMPLETITION
1581 rl_completion_entry_function = completionMain;
1582 #endif /* HAVE_READLINE_COMPLETITION */
1583 rl_readline_name = "sdcdb"; // Allow conditional parsing of the ~/.inputrc file.
1584
1585 // save readline's input/output streams
1586 // this is done to support nested calls to commandLoop()
1587 // i wonder if it works...
1588 old_rl_instream = rl_instream;
1589 old_rl_outstream = rl_outstream;
1590
1591 // set new streams for readline
1592 if ( cmdfile == stdin )
1593 rl_instream = rl_outstream = NULL; // use stdin/stdout pair
1594 else
1595 rl_instream = rl_outstream = cmdfile;
1596
1597 while (1)
1598 {
1599 if ( cmdfile == stdin )
1600 {
1601 if (sim_cmd_mode)
1602 line_read = (char*)readline ("(sim) ");
1603 else
1604 line_read = (char*)readline ("(sdcdb) ");
1605 }
1606 else
1607 line_read = (char*)readline ("");
1608
1609 if (line_read)
1610 {
1611 /* If the line has any text in it,
1612 save it on the history. */
1613 if (line_read && *line_read)
1614 add_history (line_read);
1615
1616 // FIX: readline returns malloced string.
1617 // should check the source to verify it can be used
1618 // directly. for now - just copy it to cmdbuff.
1619 strcpy(cmdbuff,line_read);
1620 #if defined(_WIN32) || defined(HAVE_RL_FREE)
1621 rl_free(line_read);
1622 #else
1623 free(line_read);
1624 #endif
1625 line_read = NULL;
1626 }
1627 else
1628 {
1629 break; // EOF
1630 }
1631 #else /* HAVE_LIBREADLINE */
1632 actualcmdfile = cmdfile;
1633
1634 while (1)
1635 {
1636 if ( cmdfile == stdin )
1637 {
1638 if (sim_cmd_mode)
1639 printf("(sim) ");
1640 else
1641 fprintf(stdout,"(sdcdb) ");
1642 fflush(stdout);
1643 }
1644 //fprintf(stderr,"commandLoop actualcmdfile=%p cmdfile=%p\n",
1645 // actualcmdfile,cmdfile);
1646 if (fgets(cmdbuff,sizeof(cmdbuff),cmdfile) == NULL)
1647 break;
1648 #endif /* HAVE_LIBREADLINE */
1649
1650 if (interpretCmd(cmdbuff))
1651 break;
1652
1653 while ( actualcmds )
1654 {
1655 strcpy(cmdbuff,actualcmds);
1656 actualcmds = NULL;
1657 stopcmdlist= 0;
1658 for ( line = cmdbuff; *line ; line = s )
1659 {
1660 if ( (s=strchr(line ,'\n')))
1661 {
1662 save_ch = *++s;
1663 *s = '\0';
1664 }
1665 else
1666 {
1667 s += strlen( line );
1668 save_ch = '\0';
1669 }
1670 if (interpretCmd( line ))
1671 {
1672 *s = save_ch;
1673 break;
1674 }
1675 *s = save_ch;
1676 if ( stopcmdlist )
1677 break;
1678 }
1679 }
1680 }
1681 #ifdef HAVE_LIBREADLINE
1682 // restore readline's input/output streams
1683 rl_instream = old_rl_instream;
1684 rl_outstream = old_rl_outstream;
1685 #endif /* HAVE_LIBREADLINE */
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* printVersionInfo - print the version information */
1690 /*-----------------------------------------------------------------*/
1691 static void printVersionInfo(void)
1692 {
1693 fprintf(stdout,
1694 "SDCDB is free software and you are welcome to distribute copies of it\n"
1695 "under certain conditions; type \"show copying\" to see the conditions.\n"
1696 "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
1697 "SDCDB " SDCDB_VERSION ". Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n");
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* printHelp - print help */
1702 /*-----------------------------------------------------------------*/
1703 static void printHelp(void)
1704 {
1705 fprintf(stdout, "Type ? for help\n");
1706 }
1707
1708 /*-----------------------------------------------------------------*/
1709 /* escapeQuotes - escape double quotes */
1710 /*-----------------------------------------------------------------*/
1711 #define CHUNK 256
1712
1713 static const char *escapeQuotes(const char *arg)
1714 {
1715 #define extend(n) do { if ((size_t)(ps - str + (n)) > strLen) str = Safe_realloc (str, strLen += CHUNK); } while (0)
1716
1717 static char *str = NULL;
1718 static size_t strLen = 0;
1719 char *ps;
1720 const char *pa;
1721
1722 if (NULL == str)
1723 {
1724 strLen = CHUNK;
1725 str = Safe_malloc (strLen);
1726 }
1727
1728 for (ps = str, pa = arg; '\0' != *pa; ++pa)
1729 {
1730 if ('"' == *pa)
1731 {
1732 extend (2);
1733 *ps++ = '\\'; /* excape the quote */
1734 *ps++ = *pa;
1735 }
1736 else
1737 {
1738 extend (1);
1739 *ps++ = *pa;
1740 }
1741 }
1742 extend (1);
1743 *ps = '\0';
1744
1745 return str;
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* argsToCmdLine - concatenate arguments ti command line */
1750 /*-----------------------------------------------------------------*/
1751 char *argsToCmdLine(char **args, int nargs)
1752 {
1753 static char *cmd = NULL;
1754 static size_t cmdLen = 0;
1755 int i;
1756 size_t cmdPos = 0;
1757
1758 if (NULL == cmd)
1759 {
1760 cmd = Safe_malloc(CHUNK);
1761 cmdLen = CHUNK;
1762 }
1763
1764 for (i = 0; i < nargs; ++i)
1765 {
1766 size_t argLen;
1767 size_t allocLen = 0;
1768 int quote = 0;
1769 const char *arg;
1770
1771 if (0 < i)
1772 ++allocLen; /* space for space character */
1773
1774 if (NULL != strchr(args[i], ' '))
1775 {
1776 quote = 1;
1777 allocLen += 2; /* space for inital and final quote */
1778 arg = escapeQuotes(args[i]);
1779 }
1780 else
1781 {
1782 arg = args[i];
1783 }
1784
1785 argLen = strlen(arg);
1786 allocLen += argLen; /* space for argument */
1787
1788 /* extend the buffer */
1789 if (cmdPos + allocLen >= cmdLen)
1790 {
1791 do
1792 {
1793 cmdLen += cmdLen;
1794 }
1795 while (cmdPos + allocLen >= cmdLen);
1796 cmd = Safe_realloc(cmd, cmdLen);
1797 }
1798
1799 if (0 < i)
1800 {
1801 cmd[cmdPos++] = ' '; /* append space character */
1802 }
1803
1804 if (quote)
1805 {
1806 cmd[cmdPos++] = '"'; /* append initial quote */
1807 }
1808
1809 memcpy(&cmd[cmdPos], arg, argLen); /* append argument */
1810 cmdPos += argLen;
1811
1812 if (quote)
1813 cmd[cmdPos++] = '"'; /* append final quote */
1814 }
1815
1816 cmd[cmdPos] = '\0';
1817
1818 return cmd;
1819 }
1820
1821 static void usage(void)
1822 {
1823 const char *args =
1824 "-{h|?}, --help\tDisplay this help\n"
1825 "-v\tVerbose: show the simulator invocation commald line\n"
1826 "--directory=<dir>\tSearch modules in <dir> directory\n"
1827 "-fullname\tGive the file name & position\n"
1828 "-cd=<dir>, -cd <dir>\tChange directory to <dir>\n"
1829 #ifdef SDCDB_DEBUG
1830 "-d=<msk>\tSet debugging to <mask>\n"
1831 #endif
1832 "-contsim\tContinuous simulation\n"
1833 "-q\tIgnored\n"
1834 "-m<model>\tModel string: avr, xa, z80\n"
1835 "-z\tAll remaining options are for simulator";
1836
1837 const char *simArgs =
1838 "-t <cpu>, -cpu <cpu>\tCpu type\n"
1839 "-frequency <frequency>, -X <frequency>\tXTAL Frequency\n"
1840 "-{s|S} <serial_port>\tSerial port\n"
1841 "-k\tNetwork serial port";
1842
1843 printf("usage: sdcdb [args] [simulator args] [filename]\n"
1844 "args:\n");
1845 printHelpLine(args, 2);
1846 printf("simulator args:\n");
1847 printHelpLine(simArgs, 2);
1848 putchar('\n');
1849 printVersionInfo();
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* parseCmdLine - parse the commandline arguments */
1854 /*-----------------------------------------------------------------*/
1855 static void parseCmdLine (int argc, char **argv)
1856 {
1857 int i;
1858 char *filename = NULL;
1859 int passon_args_flag = 0; /* if true, pass on args to simulator */
1860 int verbose = 0;
1861
1862 Dprintf(D_sdcdb, ("sdcdb: parseCmdLine\n"));
1863 contsim = 0;
1864
1865 for (i = 1; i < argc ; i++)
1866 {
1867 if (passon_args_flag) /* if true, pass on args to simulator */
1868 {
1869 simArgs[nsimArgs++] = strdup(argv[i]);
1870 continue;
1871 }
1872
1873 /* if this is an option */
1874 if (argv[i][0] == '-')
1875 {
1876 /* display usage */
1877 if (strcmp(argv[i], "-h") == 0 ||
1878 strcmp(argv[i], "-?") == 0 ||
1879 strcmp(argv[i], "--help") == 0)
1880 {
1881 usage();
1882 exit(0);
1883 }
1884
1885 /* verbose */
1886 if (strcmp(argv[i], "-v") == 0)
1887 {
1888 verbose = 1;
1889 continue;
1890 }
1891
1892 /* if directory then mark directory */
1893 if (strncmp(argv[i], "--directory=", 12) == 0)
1894 {
1895 if (!ssdirl)
1896 {
1897 ssdirl = &argv[i][12];
1898 }
1899 else
1900 {
1901 char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
1902 strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
1903 ssdirl = p;
1904 }
1905 continue;
1906 }
1907
1908 if (strcmp(argv[i], "-fullname") == 0)
1909 {
1910 fullname = TRUE;
1911 continue;
1912 }
1913
1914 if (strncmp(argv[i], "-cd=", 4) == 0)
1915 {
1916 if (0 > chdir(&argv[i][4]))
1917 {
1918 fprintf(stderr, "can't change directory to %s\n", &argv[i][4]);
1919 exit(1);
1920 }
1921 continue;
1922 }
1923
1924 if (strcmp(argv[i], "-cd") == 0)
1925 {
1926 i++;
1927 if (0 > chdir(argv[i]))
1928 {
1929 fprintf(stderr, "can't change directory to %s\n", argv[i]);
1930 exit(1);
1931 }
1932 continue;
1933 }
1934
1935 #ifdef SDCDB_DEBUG
1936 if (strncmp(argv[i], "-d=", 3) == 0)
1937 {
1938 sdcdbDebug = strtol(&argv[i][3],0,0);
1939 continue;
1940 }
1941 #endif
1942 if (strcmp(argv[i], "-contsim") == 0)
1943 {
1944 contsim=1;
1945 continue;
1946 }
1947 if (strcmp(argv[i], "-q") == 0)
1948 {
1949 continue;
1950 }
1951
1952 /* model string */
1953 if (strncmp(argv[i],"-m", 2) == 0)
1954 {
1955 strncpy(model_str, &argv[i][2], 15);
1956 if (strcmp(model_str, "avr") == 0)
1957 simArgs[0] = "savr";
1958 else if (strcmp(model_str, "xa") == 0)
1959 simArgs[0] = "sxa";
1960 else if (strcmp(model_str, "z80") == 0)
1961 simArgs[0] = "sz80";
1962 continue;
1963 }
1964
1965 /* -z all remaining options are for simulator */
1966 if (strcmp(argv[i], "-z") == 0)
1967 {
1968 passon_args_flag = 1;
1969 continue;
1970 }
1971
1972 /* the simulator arguments */
1973
1974 /* cpu */
1975 if (strcmp(argv[i], "-t") == 0 ||
1976 strcmp(argv[i], "-cpu") == 0)
1977 {
1978 simArgs[nsimArgs++] = "-t";
1979 simArgs[nsimArgs++] = strdup(argv[++i]);
1980 continue;
1981 }
1982
1983 /* XTAL Frequency */
1984 if (strcmp(argv[i], "-X") == 0 ||
1985 strcmp(argv[i], "-frequency") == 0)
1986 {
1987 simArgs[nsimArgs++] = "-X";
1988 simArgs[nsimArgs++] = strdup(argv[++i]);
1989 continue;
1990 }
1991
1992 /* serial port */
1993 if ((strcmp(argv[i], "-S") == 0) ||
1994 (strcmp(argv[i], "-s") == 0))
1995 {
1996 simArgs[nsimArgs++] = strdup(argv[i]);
1997 simArgs[nsimArgs++] = strdup(argv[++i]);
1998 continue;
1999 }
2000
2001 /* network serial port */
2002 if ((strcmp(argv[i], "-k") == 0))
2003 {
2004 simArgs[nsimArgs++] = strdup(argv[i]);
2005 simArgs[nsimArgs++] = strdup(argv[++i]);
2006 continue;
2007 }
2008
2009 fprintf(stderr,"unknown option %s --- ignored\n", argv[i]);
2010 }
2011 else
2012 {
2013 FILE* file;
2014
2015 /* must be file name */
2016 if (filename)
2017 {
2018 fprintf(stderr,
2019 "too many filenames .. parameter '%s' ignored\n",
2020 argv[i]);
2021 continue ;
2022 }
2023
2024 file = fopen(argv[i], "r");
2025 if (file)
2026 {
2027 /* file exists: strip the cdb or ihx extension */
2028 char *p = strrchr(argv[i], '.');
2029
2030 fclose(file);
2031 if (NULL != p &&
2032 (0 == strcmp(p, ".cdb") || 0 == strcmp(p, ".ihx")))
2033 {
2034 *p = '\0';
2035 }
2036 }
2037 filename = argv[i];
2038 }
2039 }
2040
2041 if (filename)
2042 cmdFile(filename,NULL);
2043
2044 if (verbose)
2045 printf("+ %s\n", argsToCmdLine(simArgs, nsimArgs));
2046 }
2047
2048 /*-----------------------------------------------------------------*/
2049 /* setsignals - catch some signals */
2050 /*-----------------------------------------------------------------*/
2051 #include <signal.h>
2052 static void
2053 bad_signal(int sig)
2054 {
2055 if ( simactive )
2056 closeSimulator();
2057 exit(1);
2058 }
2059
2060 static void
2061 sigintr(int sig)
2062 {
2063 /* may be interrupt from user: stop debugger and also simulator */
2064 userinterrupt = 1;
2065 if ( !nointerrupt )
2066 sendSim("stop\n");
2067 }
2068
2069 #ifndef _WIN32
2070 /* the only child can be the simulator */
2071 static void sigchld(int sig)
2072 {
2073 /* the only child can be the simulator */
2074 int status;
2075 wait ( &status );
2076 simactive = 0;
2077 }
2078 #endif
2079
2080 static void
2081 setsignals()
2082 {
2083 signal(SIGINT , sigintr );
2084 signal(SIGABRT, bad_signal);
2085 signal(SIGTERM, bad_signal);
2086
2087 #ifndef _WIN32
2088 signal(SIGHUP , SIG_IGN);
2089 signal(SIGCONT, SIG_IGN);
2090 signal(SIGCHLD, sigchld );
2091
2092 signal(SIGALRM, bad_signal);
2093 //signal(SIGFPE, bad_signal);
2094 //signal(SIGILL, bad_signal);
2095 signal(SIGPIPE, bad_signal);
2096 signal(SIGQUIT, bad_signal);
2097 //signal(SIGSEGV, bad_signal);
2098 #endif
2099 }
2100
2101 /*-----------------------------------------------------------------*/
2102 /* main - */
2103 /*-----------------------------------------------------------------*/
2104
2105 int main ( int argc, char **argv)
2106 {
2107 simArgs[nsimArgs++] = "s51";
2108 simArgs[nsimArgs++] = "-P";
2109 simArgs[nsimArgs++] = "-r";
2110 simArgs[nsimArgs++] = "9756";
2111
2112 /* parse command line */
2113 parseCmdLine(argc, argv);
2114
2115 printVersionInfo();
2116 printHelp();
2117 printf("WARNING: SDCDB is EXPERIMENTAL.\n");
2118
2119 setsignals();
2120
2121 commandLoop(stdin);
2122
2123 return 0;
2124 }
2125