fix some things
[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[20];
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\"",buffer);
562   return 0;
563     }
564
565     /* allocate for context */
566     currCtxt = Safe_calloc(1,sizeof(context));
567
568     /* readin the debug information */
569     if (!readCdb (cdbFile)) {
570   fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
571   return 0;
572     }
573
574     /* parse and load the modules required */
575     loadModules();
576
577     /* determine the execution points for this
578        module */
579     functionPoints();
580
581     /* start the simulator & setup connection to it */
582     openSimulator((char **)simArgs,nsimArgs);
583     fprintf(stdout,"%s",simResponse());
584     /* now send the filename to be loaded to the simulator */
585     sprintf(buffer,"%s.ihx",s);
586     bp=searchDirsFname(buffer);
587     simLoadFile(bp);
588     free(bp);
589
590     /*set the break points
591        required by the debugger . i.e. the function entry
592        and function exit break points */
593     applyToSet(functions,setEntryExitBP);
594
595     /* ad we are done */
596     return 0;
597 }
598
599 /*-----------------------------------------------------------------*/
600 /* cmdHelp - help command                                          */
601 /*-----------------------------------------------------------------*/
602 int cmdHelp (char *s, context *cctxt)
603 {
604     int i ;
605     int endline = 999;
606     int startline = 0;
607
608     while (isspace(*s))
609       ++s;
610     if (isdigit(*s)) {
611       endline = ((*s - '0') * 20) + 20;
612       if (endline > 0)
613         startline = endline - 20;
614     }
615
616     for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
617
618       /* command string matches */
619       
620       if ((cmdTab[i].htxt) && (i >= startline))
621         fprintf(stdout,"%s",cmdTab[i].htxt);
622       if (i == endline)
623         break;
624     }
625
626     return 0;
627 }
628
629 #define MAX_CMD_LEN 512
630 static char cmdbuff[MAX_CMD_LEN];
631 static int sim_cmd_mode = 0;
632
633 /*-----------------------------------------------------------------
634  interpretCmd - interpret and do the command.  Return 0 to continue,
635    return 1 to exit program.
636 |-----------------------------------------------------------------*/
637 int interpretCmd (char *s)
638 {
639     static char *pcmd = NULL;
640     int i ;
641     int rv = 0 ;
642
643     /* if nothing & previous command exists then
644        execute the previous command again */
645     if (*s == '\n' && pcmd)
646       strcpy(s,pcmd);
647
648     /* if previous command exists & is different
649        from the current command then copy it */
650     if (pcmd) {
651       if (strcmp(pcmd,s)) {
652          free(pcmd);
653          pcmd = strdup(s);
654       }
655     } else
656       pcmd = strdup(s);
657
658     /* lookup the command table and do the task required */
659     strtok(s,"\n");
660
661     if (sim_cmd_mode) {
662       if (strcmp(s,".") == 0) {
663         sim_cmd_mode = 0;
664         return 0;
665       }
666       else if (s[0] == '.') {
667         /* kill the preceeding '.' and pass on as SDCDB command */
668         char *s1 = s+1;
669         char *s2 = s;
670         while (*s1 != 0)
671           *s2++ = *s1++;
672         *s2 = 0;
673       } else {
674         cmdSimulator (s, currCtxt);
675         return 0;
676       }
677     } else {
678       if (strcmp(s,".") ==0) {
679         sim_cmd_mode = 1;
680         return 0;
681       }
682     }
683
684     for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
685
686       /* command string matches */
687       if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) {
688         if (!cmdTab[i].cmdfunc)
689           return 1;
690
691         rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
692
693         /* if full name then give the file name & position */
694         if (fullname && currCtxt && currCtxt->func) {
695           if (srcMode == SRC_CMODE)
696             fprintf(stdout,"\032\032%s:%d:1\n",
697                     currCtxt->func->mod->cfullname,
698                     currCtxt->cline+1);
699           else
700             fprintf(stdout,"\032\032%s:%d:1\n",
701                     currCtxt->func->mod->afullname,
702                     currCtxt->asmline+1);
703         }
704         goto ret;
705       }
706     }
707
708     fprintf(stdout,"Undefined command: \"%s\".  Try \"help\".\n",s);
709  ret:
710     return rv;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* commandLoop - the main command loop                             */
715 /*-----------------------------------------------------------------*/
716 void commandLoop()
717 {
718  char *prompt = "(sdcdb) ";
719  char *sim_prompt = "(sim) ";
720
721   while (1) {
722     if (sim_cmd_mode)
723       printf("%s",sim_prompt);
724     else
725       fprintf(stdout,"%s",prompt);
726
727     fflush(stdout);
728
729     if (fgets(cmdbuff,sizeof(cmdbuff),stdin) == NULL)
730       break;
731
732 #if 0
733     /* make a way to go into "ucSim" mode */
734     if (cmdbuff[0] == '$') {
735       if (sim_cmd_mode) sim_cmd_mode = 0;
736       else sim_cmd_mode = 1;
737       continue;
738     }
739 #endif
740
741     if (interpretCmd(cmdbuff))
742       break;
743   }
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* printVersionInfo - print the version information                */
748 /*-----------------------------------------------------------------*/
749 static void printVersionInfo()
750 {
751     fprintf(stdout,
752       "SDCDB is free software and you are welcome to distribute copies of it\n"
753       "under certain conditions; type \"show copying\" to see the conditions.\n"
754       "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
755       "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n"
756       "Type ? for help\n");
757
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* parseCmdLine - parse the commandline arguments                  */
762 /*-----------------------------------------------------------------*/
763 static void parseCmdLine (int argc, char **argv)
764 {
765     int i ;
766     char *filename = NULL;
767     int passon_args_flag = 0;  /* if true, pass on args to simulator */
768
769     for ( i = 1; i < argc ; i++) {
770   //fprintf(stdout,"%s\n",argv[i]);
771
772   if (passon_args_flag) { /* if true, pass on args to simulator */
773     simArgs[nsimArgs++] = strdup(argv[i]);
774     continue;
775   }
776
777   /* if this is an option */
778   if (argv[i][0] == '-') {
779
780       /* if directory then mark directory */
781       if (strncmp(argv[i],"--directory=",12) == 0) {
782     if (!ssdirl)
783         ssdirl = &argv[i][12];
784     else {
785         char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
786         strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
787         ssdirl = p;
788     }
789     continue;
790       }
791
792       if (strncmp(argv[i],"-fullname",9) == 0) {
793     fullname = TRUE;
794     continue;
795       }
796
797       if (strcmp(argv[i],"-cd") == 0) {
798     i++;
799     chdir(argv[i]);
800     continue;
801       }
802
803       if (strncmp(argv[i],"-cd=",4) == 0) {
804     chdir(argv[i][4]);
805     continue;
806       }
807
808       /* model string */
809       if (strncmp(argv[i],"-m",2) == 0) {
810         strncpy(model_str, &argv[i][2], 15);
811         if (strcmp(model_str,"avr") == 0)
812           simArgs[0] = "savr";
813         else if (strcmp(model_str,"xa") == 0)
814           simArgs[0] = "sxa";
815         else if (strcmp(model_str,"z80") == 0)
816           simArgs[0] = "sz80";
817         continue ;
818       }
819
820       /* -z all remaining options are for simulator */
821       if (strcmp(argv[i],"-z") == 0) {
822         passon_args_flag = 1;
823         continue ;
824       }
825
826       /* the simulator arguments */
827
828       /* cpu */
829       if (strcmp(argv[i],"-t") == 0 ||
830     strcmp(argv[i],"-cpu") == 0) {
831
832         simArgs[nsimArgs++] = "-t";
833         simArgs[nsimArgs++] = strdup(argv[++i]);
834         continue ;
835       }
836
837       /* XTAL Frequency */
838       if (strcmp(argv[i],"-X") == 0 ||
839     strcmp(argv[i],"-frequency") == 0) {
840         simArgs[nsimArgs++] = "-X";
841         simArgs[nsimArgs++] = strdup(argv[++i]);
842         continue ;
843       }
844
845       /* serial port */
846       if ( (strcmp(argv[i],"-S") == 0) ||
847            (strcmp(argv[i],"-s") == 0)) {
848         simArgs[nsimArgs++] = "-s";
849         simArgs[nsimArgs++] = strdup(argv[++i]);
850         continue ;
851       }
852
853       fprintf(stderr,"unknown option %s --- ignored\n",
854         argv[i]);
855
856   } else {
857       /* must be file name */
858       if (filename) {
859     fprintf(stderr,"too many filenames .. parameter '%s' ignored\n",
860       argv[i]);
861     continue ;
862       }
863
864       filename = strtok(argv[i],".");
865
866   }
867     }
868
869     if (filename)
870   cmdFile(filename,NULL);
871 }
872
873 /*-----------------------------------------------------------------*/
874 /* main -                                                          */
875 /*-----------------------------------------------------------------*/
876
877 int main ( int argc, char **argv)
878 {
879     printVersionInfo();
880     printf("WARNING: SDCDB is EXPERIMENTAL and NOT A FULLY FUNCTIONING TOOL.\n");
881
882     simArgs[nsimArgs++] = "s51";
883     simArgs[nsimArgs++] = "-P";
884     simArgs[nsimArgs++] = "-r 9756";
885     /* parse command line */
886
887     parseCmdLine(argc,argv);
888
889     commandLoop();
890
891     return 0;
892 }