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