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