ddd fixes
[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
31 #ifdef SDCDB_DEBUG
32 int   sdcdbDebug = 0;
33 #endif
34
35 char *currModName = NULL;
36 cdbrecs *recsRoot = NULL ;
37 set  *modules = NULL;    /* set of all modules */
38 set  *functions = NULL ; /* set of functions */
39 set  *symbols = NULL   ; /* set of symbols */
40 int nStructs = 0 ;
41 structdef **structs = NULL ; /* all structures */
42 int nLinkrecs = 0;
43 linkrec **linkrecs = NULL; /* all linkage editor records */
44 context *currCtxt = NULL;
45 short fullname = 0;
46 short showfull = 0;
47 short userinterrupt = 0;
48 char *ssdirl = DATADIR LIB_DIR_SUFFIX ":" DATADIR LIB_DIR_SUFFIX "/small" ;
49 char *simArgs[40];
50 int nsimArgs = 0;
51 char model_str[20];
52
53 /* fake filename & lineno to make linker */
54 char *filename=NULL;
55 int lineno = 0;
56 int fatalError = 0;
57
58 /* command table */
59 struct cmdtab
60 {
61     char      *cmd ;  /* command the user will enter */
62     int (*cmdfunc)(char *,context *);   /* function to execute when command is entered */
63     char *htxt ;    /* short help text */
64
65 } cmdTab[] = {
66     /* NOTE:- the search is done from the top, so "break" should
67        precede the synonym "b" */
68     /* break point */
69     { "break"    ,  cmdSetUserBp  ,
70       "{b}reak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n",
71     },
72     { "b"        ,  cmdSetUserBp  , NULL },
73
74     { "clear"    ,  cmdClrUserBp  ,
75       "{cl}ear\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n"
76     },
77     { "cl"       ,  cmdClrUserBp  , NULL },
78
79     { "continue" ,  cmdContinue   ,
80       "{c}ontinue\t\t Continue program being debugged, after breakpoint.\n"
81     },
82     { "c"        ,  cmdContinue   , NULL },
83
84     { "disassemble",cmdDisasmF    , "x disassemble asm commands\n" },
85     { "delete" ,  cmdDelUserBp  ,
86       "{d}elete n\t\t clears break point number n\n"
87     },
88     { "display"    ,  cmdDisplay     ,
89       "display [<variable>]\t print value of given variable each time the program stops\n"
90     },
91     { "undisplay"  ,  cmdUnDisplay   ,
92       "undisplay [<variable>]\t dont display this variable or all\n"
93     },
94     { "d"        ,  cmdDelUserBp  , NULL },
95
96     { "info"     ,  cmdInfo       ,
97       "info <break stack frame registers all-registers>\n"
98       "\t list all break points, call-stack, frame or register information\n"
99     },
100
101     { "listasm"  ,  cmdListAsm    ,
102       "listasm {la}\t\t list assembler code for the current C line\n"
103     },
104     { "la"       ,  cmdListAsm    , NULL },
105     { "ls"       ,  cmdListSymbols  , "ls,lf,lm\t\t list symbols,functions,modules\n" },
106     { "lf"       ,  cmdListFunctions, NULL },
107     { "lm"       ,  cmdListModules  , NULL },
108     { "list"     ,  cmdListSrc    ,
109       "{l}ist\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n"
110     },
111     { "l"        ,  cmdListSrc    , NULL },
112     { "show"     ,  cmdShow       ,
113       "show"
114       " <copying warranty>\t copying & distribution terms, warranty\n"
115     },
116     { "set"      ,  cmdSetOption  , "set <srcmode>\t\t toggle between c/asm.\nset variable <var> = >value\t\tset variable to new value\n" },
117     { "step"     ,  cmdStep       ,
118       "{s}tep\t\t\t Step program until it reaches a different source line.\n"
119     },
120     { "s"        ,  cmdStep       , NULL },
121     { "next"     ,  cmdNext       ,
122       "{n}ext\t\t\t Step program, proceeding through subroutine calls.\n"
123     },
124     { "n"        ,  cmdNext       , NULL },
125     { "run"      ,  cmdRun        ,
126       "{r}un\t\t\t Start debugged program. \n"
127     },
128     { "r"        ,  cmdRun        , NULL },
129     { "ptype"    ,  cmdPrintType  ,
130       "{pt}ype <variable>\t print type information of a variable\n"
131     },
132     { "pt"       ,  cmdPrintType  , NULL },
133     { "print"    ,  cmdPrint      ,
134       "{p}rint <variable>\t print value of given variable\n"
135     },
136     { "output"   ,  cmdOutput      ,
137       "output <variable>\t print value of given variable without $ and newline \n"
138     },
139     { "p"        ,  cmdPrint      , NULL },
140     { "file"     ,  cmdFile       ,
141       "file <filename>\t\t load symbolic information from <filename>\n"
142     },
143     { "frame"    ,  cmdFrame      ,
144       "{fr}ame\t\t\t print information about the current Stack\n"
145     },
146     { "finish"   ,  cmdFinish     ,
147       "{fi}nish\t\t execute till return of current function\n"
148     },
149     { "fi"       ,  cmdFinish     , NULL },
150     { "where"    ,  cmdWhere      , "where\t\t\t print stack\n" },
151     { "fr"       ,  cmdFrame      , NULL },
152     { "f"        ,  cmdFrame      , NULL },
153     { "x /i"     ,  cmdDisasm1    , "x\t\t disassemble one asm command\n" },
154     { "!"        ,  cmdSimulator  ,
155       "!<simulator command>\t send a command directly to the simulator\n"
156     },
157     { "."        ,  cmdSimulator  ,
158       ".{cmd}\t switch from simulator or debugger command mode\n"
159     },
160     { "help"     ,  cmdHelp       ,
161       "{h|?}elp\t [CMD_NAME | 0,1,2,3(help page)] (general help or specific help)\n"
162     },
163     { "?"        ,  cmdHelp       , NULL },
164     { "h"        ,  cmdHelp       , NULL },
165
166     { "quit"     ,  cmdQuit       ,
167       "{q}uit\t\t\t \"Watch me now. Iam going Down. My name is Bobby Brown\"\n"
168     },
169     { "q"        ,  cmdQuit       , NULL }
170 };
171
172 /*-----------------------------------------------------------------*/
173 /* gc_strdup - make a string duplicate garbage collector aware     */
174 /*-----------------------------------------------------------------*/
175 char *gc_strdup(const char *s)
176 {
177     char *ret;
178     ret = Safe_malloc(strlen(s)+1);
179     strcpy(ret, s);
180     return ret;
181 }
182
183 /*-----------------------------------------------------------------*/
184 /* alloccpy - allocate copy and return a new string                */
185 /*-----------------------------------------------------------------*/
186 char *alloccpy ( char *s, int size)
187 {
188     char *d;
189
190     if (!size)
191   return NULL;
192
193     d = Safe_malloc(size+1);
194     memcpy(d,s,size);
195     d[size] = '\0';
196
197     return d;
198 }
199
200 /*-----------------------------------------------------------------*/
201 /* resize - resizes array of type with new size                    */
202 /*-----------------------------------------------------------------*/
203 void **resize (void **array, int newSize)
204 {
205     void **vptr;
206
207     if (array)
208   vptr = Safe_realloc(array,newSize*(sizeof(void **)));
209     else
210   vptr = calloc(1, sizeof(void **));
211
212     if (!vptr) {
213   fprintf(stderr,"sdcdb: out of memory \n");
214   exit(1);
215     }
216
217     return vptr;
218
219 }
220
221 /*-----------------------------------------------------------------*/
222 /* readCdb - reads the cdb files & puts the records into cdbLine   */
223 /*           linked list                                           */
224 /*-----------------------------------------------------------------*/
225 static int readCdb (FILE *file)
226 {
227     cdbrecs *currl ;
228     char buffer[1024];
229     char *bp ;
230
231     if (!(bp = fgets(buffer,sizeof(buffer),file)))
232       return 0;
233
234     currl = Safe_calloc(1,sizeof(cdbrecs));
235     recsRoot = currl ;
236
237     while (1) {
238
239   /* make sure this is a cdb record */
240   if (strchr("STLFM",*bp) && *(bp+1) == ':') {
241       /* depending on the record type */
242
243       switch (*bp) {
244       case 'S':
245     /* symbol record */
246     currl->type = SYM_REC;
247     break;
248       case 'T':
249     currl->type = STRUCT_REC;
250     break;
251       case 'L':
252     currl->type = LNK_REC;
253     break;
254       case 'F':
255     currl->type = FUNC_REC;
256     break;
257       case 'M':
258     currl->type = MOD_REC ;
259       }
260
261       bp += 2;
262       currl->line = Safe_malloc(strlen(bp));
263       strncpy(currl->line,bp,strlen(bp)-1);
264       currl->line[strlen(bp)-1] = '\0';
265   }
266
267   if (!(bp = fgets(buffer,sizeof(buffer),file)))
268       break;
269
270   if (feof(file))
271       break;
272
273   currl->next = Safe_calloc(1,sizeof(cdbrecs));
274   currl = currl->next;
275     }
276
277     return (recsRoot->line ? 1 : 0);
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* searchDirsFname - search directory list & return the filename   */
282 /*-----------------------------------------------------------------*/
283 char *searchDirsFname (char *fname)
284 {
285     char *dirs , *sdirs;
286     FILE *rfile = NULL;
287     char buffer[128];
288
289     /* first try the current directory */
290     if ((rfile = fopen(fname,"r"))) {
291   fclose(rfile);
292   return strdup(fname) ;
293     }
294
295     if (!ssdirl)
296   return strdup(fname);
297
298     /* make a copy of the source directories */
299     dirs = sdirs = strdup(ssdirl);
300
301     /* assume that the separator is ':'
302        and try for each directory in the search list */
303     dirs = strtok(dirs,":");
304     while (dirs) {
305   if (dirs[strlen(dirs)] == '/')
306       sprintf(buffer,"%s%s",dirs,fname);
307   else
308       sprintf(buffer,"%s/%s",dirs,fname);
309   if ((rfile = fopen(buffer,"r")))
310       break ;
311   dirs = strtok(NULL,":");
312     }
313
314     free(sdirs);
315     if (rfile) {
316   fclose(rfile);
317   return strdup(buffer);
318     } else
319   return strdup(fname);
320 }
321
322 /*-----------------------------------------------------------------*/
323 /* searchDirsFopen - go thru list of directories for filename given*/
324 /*-----------------------------------------------------------------*/
325 FILE *searchDirsFopen(char *fname)
326 {
327     char *dirs , *sdirs;
328     FILE *rfile = NULL;
329     char buffer[128];
330
331     /* first try the current directory */
332     if ((rfile = fopen(fname,"r")))
333   return rfile;
334
335     if (!ssdirl)
336   return NULL;
337     /* make a copy of the source directories */
338     dirs = sdirs = strdup(ssdirl);
339
340     /* assume that the separator is ':'
341        and try for each directory in the search list */
342     dirs = strtok(dirs,":");
343     while (dirs) {
344   sprintf(buffer,"%s/%s",dirs,fname);
345   if ((rfile = fopen(buffer,"r")))
346       break ;
347   dirs = strtok(NULL,":");
348     }
349
350     free(sdirs);
351     return rfile ;
352
353 }
354
355 /*-----------------------------------------------------------------*/
356 /* loadFile - loads a file into module buffer                      */
357 /*-----------------------------------------------------------------*/
358 srcLine **loadFile (char *name, int *nlines)
359 {
360     FILE *mfile ;
361     char buffer[512];
362     char *bp;
363     srcLine **slines = NULL;
364
365
366     if (!(mfile = searchDirsFopen(name))) {
367   fprintf(stderr,"sdcdb: cannot open module %s -- use '--directory=<source directory> option\n",name);
368   return NULL;
369     }
370
371     while ((bp = fgets(buffer,sizeof(buffer),mfile))) {
372   (*nlines)++;
373
374   slines = (srcLine **)resize((void **)slines,*nlines);
375
376   slines[(*nlines)-1] = Safe_calloc(1,sizeof(srcLine));
377   slines[(*nlines)-1]->src = alloccpy(bp,strlen(bp));
378     }
379
380     fclose(mfile);
381     return slines;
382 }
383
384
385 /*-----------------------------------------------------------------*/
386 /* loadModules - reads the source files into module structure      */
387 /*-----------------------------------------------------------------*/
388 static void loadModules ()
389 {
390     cdbrecs *loop;
391     module *currMod;
392     char *rs;
393
394     /* go thru the records & find out the module
395        records & load the modules specified */
396     for ( loop = recsRoot ; loop ; loop = loop->next ) {
397
398   switch (loop->type) {
399   /* for module records do */
400   case MOD_REC:
401       currMod = parseModule(loop->line,TRUE);
402       currModName = currMod->name ;
403
404       currMod->cfullname = searchDirsFname(currMod->c_name);
405
406       /* load it into buffer */
407       currMod->cLines = loadFile (currMod->c_name,
408           &currMod->ncLines);
409
410       /* do the same for the assembler file */
411       currMod->afullname = searchDirsFname(currMod->asm_name);
412       currMod->asmLines=loadFile (currMod->asm_name,
413           &currMod->nasmLines);
414       break;
415
416   /* if this is a function record */
417   case FUNC_REC:
418       parseFunc(loop->line);
419       break;
420
421   /* if this is a structure record */
422   case STRUCT_REC:
423       parseStruct(loop->line);
424       break;
425
426   /* if symbol then parse the symbol */
427   case  SYM_REC:
428       parseSymbol(loop->line,&rs);
429       break;
430
431   case LNK_REC:
432       parseLnkRec(loop->line);
433       break;
434   }
435     }
436 }
437
438 /*-----------------------------------------------------------------*/
439 /* functionPoints - determine the execution points within a func   */
440 /*-----------------------------------------------------------------*/
441 static void functionPoints ()
442 {
443     function *func;
444     symbol *sym;
445
446     /* for all functions do */
447     for ( func = setFirstItem(functions); func;
448     func = setNextItem(functions)) {
449   int j ;
450   module *mod;
451
452   sym = func->sym;
453
454   Dprintf(D_sdcdb, ("sdcdb: func '%s' has entry '0x%x' exit '0x%x'\n",
455          func->sym->name,
456          func->sym->addr,
457          func->sym->eaddr));
458
459   if (!func->sym->addr && !func->sym->eaddr)
460       continue ;
461
462   /* for all source lines in the module find
463      the ones with address >= start and <= end
464      and put them in the point */
465   mod = NULL ;
466   if (! applyToSet(modules,moduleWithName,func->modName,&mod))
467       continue ;
468   func->mod = mod ;
469   func->entryline= INT_MAX;
470   func->exitline =  0;
471   func->aentryline = INT_MAX ;
472   func->aexitline = 0;
473
474   /* do it for the C Lines first */
475   for ( j = 0 ; j < mod->ncLines ; j++ ) {
476       if (mod->cLines[j]->addr >= sym->addr &&
477     mod->cLines[j]->addr <= sym->eaddr ) {
478
479     exePoint *ep ;
480
481     /* add it to the execution point */
482     if (func->entryline > j)
483         func->entryline = j;
484
485     if (func->exitline < j)
486         func->exitline = j;
487
488     ep = Safe_calloc(1,sizeof(exePoint));
489     ep->addr =  mod->cLines[j]->addr ;
490     ep->line = j;
491     ep->block= mod->cLines[j]->block;
492     ep->level= mod->cLines[j]->level;
493     addSet(&func->cfpoints,ep);
494       }
495   }
496
497   /* do the same for asm execution points */
498   for ( j = 0 ; j < mod->nasmLines ; j++ ) {
499       if (mod->asmLines[j]->addr >= sym->addr &&
500     mod->asmLines[j]->addr <= sym->eaddr ) {
501
502     exePoint *ep ;
503     /* add it to the execution point */
504     if (func->aentryline > j)
505         func->aentryline = j;
506
507     if (func->aexitline < j)
508         func->aexitline = j;
509
510     /* add it to the execution point */
511     ep = Safe_calloc(1,sizeof(exePoint));
512     ep->addr =  mod->asmLines[j]->addr ;
513     ep->line = j;
514     addSet(&func->afpoints,ep);
515       }
516   }
517
518 #ifdef SDCDB_DEBUG
519   if (!( D_sdcdb & sdcdbDebug))
520       return;
521
522   Dprintf(D_sdcdb, ("sdcdb: function '%s' has the following C exePoints\n",
523          func->sym->name));
524   {
525       exePoint *ep;
526
527       for (ep = setFirstItem(func->cfpoints); ep;
528      ep = setNextItem(func->cfpoints))
529      Dprintf(D_sdcdb, ("sdcdb: {0x%x,%d} %s",
530          ep->addr,ep->line,mod->cLines[ep->line]->src));
531
532       Dprintf(D_sdcdb, ("sdcdb:  and the following ASM exePoints\n"));
533       for (ep = setFirstItem(func->afpoints); ep;
534            ep = setNextItem(func->afpoints))
535         Dprintf (D_sdcdb, ("sdcdb: {0x%x,%d} %s",
536             ep->addr,ep->line,mod->asmLines[ep->line]->src));
537   }
538 #endif
539     }
540 }
541
542
543 /*-----------------------------------------------------------------*/
544 /* setEntryExitBP - set the entry & exit Break Points for functions*/
545 /*-----------------------------------------------------------------*/
546 DEFSETFUNC(setEntryExitBP)
547 {
548     function *func = item;
549
550     if (func->sym && func->sym->addr && func->sym->eaddr) {
551
552   /* set the entry break point */
553   setBreakPoint (func->sym->addr , CODE , FENTRY ,
554            fentryCB ,func->mod->c_name , func->entryline);
555
556   /* set the exit break point */
557   setBreakPoint (func->sym->eaddr , CODE , FEXIT  ,
558            fexitCB  ,func->mod->c_name , func->exitline );
559     }
560
561     return 0;
562 }
563
564 /*-----------------------------------------------------------------*/
565 /* cmdFile - load file into the debugger                           */
566 /*-----------------------------------------------------------------*/
567 int cmdFile (char *s,context *cctxt)
568 {
569     FILE *cdbFile;
570     char buffer[128];
571     char *bp;
572
573     while (isspace(*s)) s++;
574     if (!*s) {
575   fprintf(stdout,"No exec file now.\nNo symbol file now.\n");
576   return 0;
577     }
578
579     sprintf(buffer,"%s.cdb",s);
580     /* try creating the cdbfile */
581     if (!(cdbFile = searchDirsFopen(buffer))) {
582       fprintf(stdout,"Cannot open file\"%s\", no symbolic information loaded\n",buffer);
583       // return 0;
584     }
585
586     /* allocate for context */
587     currCtxt = Safe_calloc(1,sizeof(context));
588
589     if (cdbFile) {
590       /* readin the debug information */
591       if (!readCdb (cdbFile)) {
592         fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
593         //return 0;
594       }
595     }
596
597     /* parse and load the modules required */
598     loadModules();
599
600     /* determine the execution points for this
601        module */
602     functionPoints();
603
604     /* start the simulator & setup connection to it */
605     if ( sock == -1 )
606         openSimulator((char **)simArgs,nsimArgs);
607     fprintf(stdout,"%s",simResponse());
608     /* now send the filename to be loaded to the simulator */
609     sprintf(buffer,"%s.ihx",s);
610     bp=searchDirsFname(buffer);
611     simLoadFile(bp);
612     free(bp);
613
614     /*set the break points
615        required by the debugger . i.e. the function entry
616        and function exit break points */
617     applyToSet(functions,setEntryExitBP);
618
619     /* ad we are done */
620     return 0;
621 }
622
623 /*-----------------------------------------------------------------*/
624 /* cmdHelp - help command                                          */
625 /*-----------------------------------------------------------------*/
626 int cmdHelp (char *s, context *cctxt)
627 {
628     int i ;
629     int endline = 999;
630     int startline = 0;
631
632     while (isspace(*s))
633       ++s;
634     if (isdigit(*s)) {
635       endline = ((*s - '0') * 20) + 20;
636       if (endline > 0)
637         startline = endline - 20;
638     }
639     else if (*s)
640     {
641         for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) 
642         {
643             if ((cmdTab[i].htxt) && !strcmp(cmdTab[i].cmd,s))
644                 fprintf(stdout,"%s",cmdTab[i].htxt);             
645         }
646         return 0;
647     }
648
649     for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
650
651       /* command string matches */
652       
653       if ((cmdTab[i].htxt) && (i >= startline))
654         fprintf(stdout,"%s",cmdTab[i].htxt);
655       if (i == endline)
656         break;
657     }
658
659     return 0;
660 }
661
662 #define MAX_CMD_LEN 512
663 static char cmdbuff[MAX_CMD_LEN];
664 static int sim_cmd_mode = 0;
665
666 /*-----------------------------------------------------------------
667  interpretCmd - interpret and do the command.  Return 0 to continue,
668    return 1 to exit program.
669 |-----------------------------------------------------------------*/
670 int interpretCmd (char *s)
671 {
672     static char *pcmd = NULL;
673     int i ;
674     int rv = 0 ;
675
676     /* if nothing & previous command exists then
677        execute the previous command again */
678     if (*s == '\n' && pcmd)
679       strcpy(s,pcmd);
680
681     /* if previous command exists & is different
682        from the current command then copy it */
683     if (pcmd) {
684       if (strcmp(pcmd,s)) {
685          free(pcmd);
686          pcmd = strdup(s);
687       }
688     } else
689       pcmd = strdup(s);
690
691     /* lookup the command table and do the task required */
692     strtok(s,"\n");
693
694     if (sim_cmd_mode) {
695       if (strcmp(s,".") == 0) {
696         sim_cmd_mode = 0;
697         return 0;
698       }
699       else if (s[0] == '.') {
700         /* kill the preceeding '.' and pass on as SDCDB command */
701         char *s1 = s+1;
702         char *s2 = s;
703         while (*s1 != 0)
704           *s2++ = *s1++;
705         *s2 = 0;
706       } else {
707         cmdSimulator (s, currCtxt);
708         return 0;
709       }
710     } else {
711       if (strcmp(s,".") ==0) {
712         sim_cmd_mode = 1;
713         return 0;
714       }
715     }
716
717     for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
718
719       /* command string matches */
720       if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) {
721         if (!cmdTab[i].cmdfunc)
722           return 1;
723
724         rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
725
726         /* if full name then give the file name & position */
727         if (fullname && showfull && currCtxt && currCtxt->func) {
728           showfull = 0;
729           if (srcMode == SRC_CMODE)
730             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
731                     currCtxt->func->mod->cfullname,
732                     currCtxt->cline,currCtxt->addr);
733           else
734             fprintf(stdout,"\032\032%s:%d:1:beg:0x%08x\n",
735                     currCtxt->func->mod->afullname,
736                     currCtxt->asmline,currCtxt->addr);
737           displayAll(currCtxt);
738         }
739         goto ret;
740       }
741     }
742
743     fprintf(stdout,"Undefined command: \"%s\".  Try \"help\".\n",s);
744  ret:
745     return rv;
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* commandLoop - the main command loop                             */
750 /*-----------------------------------------------------------------*/
751 void commandLoop()
752 {
753  char *prompt = "(sdcdb) ";
754  char *sim_prompt = "(sim) ";
755
756   while (1) {
757     if (sim_cmd_mode)
758       printf("%s",sim_prompt);
759     else
760       fprintf(stdout,"%s",prompt);
761
762     fflush(stdout);
763
764     if (fgets(cmdbuff,sizeof(cmdbuff),stdin) == NULL)
765       break;
766
767 #if 0
768     /* make a way to go into "ucSim" mode */
769     if (cmdbuff[0] == '$') {
770       if (sim_cmd_mode) sim_cmd_mode = 0;
771       else sim_cmd_mode = 1;
772       continue;
773     }
774 #endif
775
776     if (interpretCmd(cmdbuff))
777       break;
778   }
779 }
780
781 /*-----------------------------------------------------------------*/
782 /* printVersionInfo - print the version information                */
783 /*-----------------------------------------------------------------*/
784 static void printVersionInfo()
785 {
786     fprintf(stdout,
787       "SDCDB is free software and you are welcome to distribute copies of it\n"
788       "under certain conditions; type \"show copying\" to see the conditions.\n"
789       "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
790       "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n"
791       "Type ? for help\n");
792
793 }
794
795 /*-----------------------------------------------------------------*/
796 /* parseCmdLine - parse the commandline arguments                  */
797 /*-----------------------------------------------------------------*/
798 static void parseCmdLine (int argc, char **argv)
799 {
800     int i ;
801     char *filename = NULL;
802     int passon_args_flag = 0;  /* if true, pass on args to simulator */
803
804     Dprintf(D_sdcdb, ("sdcdb: parseCmdLine\n"));
805
806     for ( i = 1; i < argc ; i++) {
807   //fprintf(stdout,"%s\n",argv[i]);
808
809   if (passon_args_flag) { /* if true, pass on args to simulator */
810     simArgs[nsimArgs++] = strdup(argv[i]);
811     continue;
812   }
813
814   /* if this is an option */
815   if (argv[i][0] == '-') {
816
817       /* if directory then mark directory */
818       if (strncmp(argv[i],"--directory=",12) == 0) {
819     if (!ssdirl)
820         ssdirl = &argv[i][12];
821     else {
822         char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
823         strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
824         ssdirl = p;
825     }
826     continue;
827       }
828
829       if (strncmp(argv[i],"-fullname",9) == 0) {
830     fullname = TRUE;
831     continue;
832       }
833
834       if (strcmp(argv[i],"-cd") == 0) {
835     i++;
836     chdir(argv[i]);
837     continue;
838       }
839
840       if (strncmp(argv[i],"-cd=",4) == 0) {
841     chdir(argv[i][4]);
842     continue;
843       }
844
845 #ifdef SDCDB_DEBUG
846       if (strncmp(argv[i],"-d=",3) == 0) {
847           sdcdbDebug = strtol(&argv[i][3],0,0);
848           continue;
849       }
850 #endif
851
852       /* model string */
853       if (strncmp(argv[i],"-m",2) == 0) {
854         strncpy(model_str, &argv[i][2], 15);
855         if (strcmp(model_str,"avr") == 0)
856           simArgs[0] = "savr";
857         else if (strcmp(model_str,"xa") == 0)
858           simArgs[0] = "sxa";
859         else if (strcmp(model_str,"z80") == 0)
860           simArgs[0] = "sz80";
861         continue ;
862       }
863
864       /* -z all remaining options are for simulator */
865       if (strcmp(argv[i],"-z") == 0) {
866         passon_args_flag = 1;
867         continue ;
868       }
869
870       /* the simulator arguments */
871
872       /* cpu */
873       if (strcmp(argv[i],"-t") == 0 ||
874     strcmp(argv[i],"-cpu") == 0) {
875
876         simArgs[nsimArgs++] = "-t";
877         simArgs[nsimArgs++] = strdup(argv[++i]);
878         continue ;
879       }
880
881       /* XTAL Frequency */
882       if (strcmp(argv[i],"-X") == 0 ||
883     strcmp(argv[i],"-frequency") == 0) {
884         simArgs[nsimArgs++] = "-X";
885         simArgs[nsimArgs++] = strdup(argv[++i]);
886         continue ;
887       }
888
889       /* serial port */
890       if ( (strcmp(argv[i],"-S") == 0) ||
891            (strcmp(argv[i],"-s") == 0)) {
892         simArgs[nsimArgs++] = "-s";
893         simArgs[nsimArgs++] = strdup(argv[++i]);
894         continue ;
895       }
896
897       fprintf(stderr,"unknown option %s --- ignored\n",
898         argv[i]);
899
900   } else {
901       /* must be file name */
902       if (filename) {
903     fprintf(stderr,"too many filenames .. parameter '%s' ignored\n",
904       argv[i]);
905     continue ;
906       }
907
908       filename = strtok(argv[i],".");
909
910   }
911     }
912
913     if (filename)
914   cmdFile(filename,NULL);
915 }
916
917 /*-----------------------------------------------------------------*/
918 /* setsignals -  catch some signals                                */
919 /*-----------------------------------------------------------------*/
920 #include <signal.h>
921 static void
922 bad_signal(int sig)
923 {
924     if ( simactive )
925         closeSimulator();
926     exit(1);
927 }
928
929 static void
930 sigintr(int sig)
931 {
932     /* may be interrupt from user: stop debugger and also simulator */
933     userinterrupt = 1;
934     sendSim("\n");
935 }
936
937 /* the only child can be the simulator */
938 static void sigchld(int sig)
939 {
940     /* the only child can be the simulator */
941     int status, retpid;
942     retpid = wait ( &status );
943     /* if ( retpid == simPid ) */
944     simactive = 0;
945 }
946
947 static void
948 setsignals()
949 {
950     signal(SIGHUP , bad_signal);                
951     signal(SIGINT , sigintr );  
952     signal(SIGTERM, bad_signal);        
953     signal(SIGCHLD, sigchld );
954
955     signal(SIGABRT, bad_signal);
956     signal(SIGALRM, bad_signal);
957     signal(SIGFPE,  bad_signal);
958     signal(SIGILL,  bad_signal);
959     signal(SIGPIPE, bad_signal);
960     signal(SIGQUIT, bad_signal);
961     signal(SIGSEGV, bad_signal);
962 }
963
964 /*-----------------------------------------------------------------*/
965 /* main -                                                          */
966 /*-----------------------------------------------------------------*/
967
968 int main ( int argc, char **argv)
969 {
970     printVersionInfo();
971     printf("WARNING: SDCDB is EXPERIMENTAL.\n");
972
973     simArgs[nsimArgs++] = "s51";
974     simArgs[nsimArgs++] = "-P";
975     simArgs[nsimArgs++] = "-r 9756";
976     /* parse command line */
977
978     setsignals();
979     parseCmdLine(argc,argv);
980
981     commandLoop();
982
983     return 0;
984 }