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