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