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