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