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