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