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