* Fixed up multi bank support
[fw/sdcc] / src / SDCCmain.c
1 /*-------------------------------------------------------------------------
2   SDCCmain.c - main file               
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include <ctype.h>
27
28 #if NATIVE_WIN32
29 #include <process.h>
30 #else
31 #include "spawn.h"
32 #endif
33
34 /* This is a bit messy.  We cant include unistd.h as it defines
35    'link' which we also use.
36 */
37 int access(const char *path, int mode);
38 #define X_OK 1
39 int unlink(const char *path);
40
41 extern void             initSymt                ();
42 extern void             initMem                 ();
43 extern void             initExpr                ();
44 extern void             initiCode               ();
45 extern void             initCSupport            ();
46 extern void             initPeepHole            ();
47 extern void             createObject    ();
48 extern int              yyparse                 ();
49 extern void             glue ();
50 extern struct value    *constVal(char *s);
51 extern double            floatFromVal(struct value *);
52 extern int              fatalError ;
53 FILE  *srcFile         ;/* source file          */
54 FILE  *cdbFile = NULL  ;/* debugger information output file */
55 char  *fullSrcFileName ;/* full name for the source file */
56 char  *srcFileName     ;/* source file name with the .c stripped */
57 char  *moduleName      ;/* module name is srcFilename stripped of any path */
58 const char *preArgv[128]           ;/* pre-processor arguments  */
59 int   currRegBank = 0 ;
60 struct optimize optimize ;
61 struct options  options ;
62 char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a"*/;
63 short preProcOnly = 0;
64 short noAssemble = 0;
65 char *linkOptions[128];
66 const char *asmOptions[128];
67 char *libFiles[128] ;
68 int nlibFiles = 0;
69 char *libPaths[128] ;
70 int nlibPaths = 0;
71 char *relFiles[128];
72 int nrelFiles = 0;
73 bool verboseExec = FALSE;
74 //extern int wait (int *);
75 char    *preOutName;
76
77 #define OPTION_LARGE_MODEL "-model-large"
78 #define OPTION_SMALL_MODEL "-model-small"
79 #define OPTION_FLAT24_MODEL "-model-flat24"
80 #define OPTION_STACK_AUTO  "-stack-auto"
81 #define OPTION_STACK_10BIT "-stack-10bit"
82 #define OPTION_XSTACK      "-xstack"
83 #define OPTION_GENERIC     "-generic"
84 #define OPTION_NO_GCSE     "-nogcse"
85 #define OPTION_NO_LOOP_INV "-noinvariant"
86 #define OPTION_NO_LOOP_IND "-noinduction"
87 #define OPTION_NO_JTBOUND  "-nojtbound"
88 #define OPTION_NO_LOOPREV  "-noloopreverse"
89 #define OPTION_XREGS       "-regextend"
90 #define OPTION_COMP_ONLY   "-compile-only"
91 #define OPTION_DUMP_RAW    "-dumpraw"
92 #define OPTION_DUMP_GCSE   "-dumpgcse"
93 #define OPTION_DUMP_LOOP   "-dumploop"
94 #define OPTION_DUMP_KILL   "-dumpdeadcode"
95 #define OPTION_DUMP_RANGE  "-dumpliverange"
96 #define OPTION_DUMP_PACK   "-dumpregpack"
97 #define OPTION_DUMP_RASSGN "-dumpregassign"
98 #define OPTION_DUMP_ALL    "-dumpall"
99 #define OPTION_XRAM_LOC    "-xram-loc"
100 #define OPTION_IRAM_SIZE   "-iram-size"
101 #define OPTION_XSTACK_LOC  "-xstack-loc"
102 #define OPTION_CODE_LOC    "-code-loc"
103 #define OPTION_STACK_LOC   "-stack-loc"
104 #define OPTION_DATA_LOC    "-data-loc"
105 #define OPTION_IDATA_LOC   "-idata-loc"
106 #define OPTION_PEEP_FILE   "-peep-file"
107 #define OPTION_LIB_PATH    "-lib-path"
108 #define OPTION_INTLONG_RENT "-int-long-reent"
109 #define OPTION_FLOAT_RENT  "-float-reent"
110 #define OPTION_OUT_FMT_IHX "-out-fmt-ihx"
111 #define OPTION_OUT_FMT_S19 "-out-fmt-s19"
112 #define OPTION_CYCLOMATIC  "-cyclomatic"
113 #define OPTION_NOOVERLAY   "-nooverlay"
114 #define OPTION_MAINRETURN  "-main-return"
115 #define OPTION_NOPEEP      "-no-peep"
116 #define OPTION_ASMPEEP     "-peep-asm"
117 #define OPTION_DEBUG       "-debug"
118 #define OPTION_VERSION     "-version"
119 #define OPTION_STKAFTRDATA "-stack-after-data"
120 #define OPTION_PREPROC_ONLY "-preprocessonly"
121 #define OPTION_C1_MODE   "-c1mode"
122 #define OPTION_HELP         "-help"
123 #define OPTION_CALLEE_SAVES "-callee-saves"
124 #define OPTION_NOREGPARMS   "-noregparms"
125
126 static const char *_preCmd[] = {
127     "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1", 
128     "-I" SDCC_INCLUDE_DIR, "$l", "$1", "$2", NULL
129 };
130
131 extern PORT mcs51_port;
132 extern PORT z80_port;
133 extern PORT gbz80_port;
134 extern PORT avr_port;
135
136 PORT *port;
137
138 static PORT *_ports[] = {
139     &mcs51_port,
140     &z80_port,
141     &gbz80_port,
142     &avr_port
143 };
144
145 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
146
147 /** Sets the port to the one given by the command line option.
148     @param              The name minus the option (eg 'mcs51')
149     @return             0 on success.
150 */
151 static int _setPort(const char *name)
152 {
153     int i;
154     for (i=0; i<NUM_PORTS; i++) {
155         if (!strcmp(_ports[i]->target, name)) {
156             port = _ports[i];
157             return 0;
158         }
159     }
160     /* Error - didnt find */
161     werror(E_UNKNOWN_TARGET,name);
162     exit(1);
163 }
164
165 static void _buildCmdLine(char *into, char **args, const char **cmds, 
166                           const char *p1, const char *p2, 
167                           const char *p3, const char **list)
168 {
169     const char *p, *from;
170
171     while (*cmds) {
172         *args = into;
173         args++;
174
175         from = *cmds;
176         cmds++;
177         *into = '\0';
178
179         /* See if it has a '$' anywhere - if not, just copy */
180         if ((p = strchr(from, '$'))) {
181             strncpy(into, from, p - from);
182             from = p+2;
183             p++;
184             switch (*p) {
185             case '1':
186                 if (p1)
187                     strcat(into, p1);
188                 break;
189             case '2':
190                 if (p2)
191                     strcat(into, p2);
192                 break;
193             case '3':
194                 if (p3)
195                     strcat(into, p3);
196                 break;
197             case 'l': {
198                 const char **tmp = list;
199                 if (tmp) {
200                     while (*tmp) {
201                         strcpy(into, *tmp);
202                         into += strlen(into)+1;
203                         *args = into;
204                         args++;
205                         tmp++;
206                     }
207                 }
208                 break;
209             }
210             default:
211                 assert(0);
212             }
213         }
214         strcat(into, from);
215         if (strlen(into) == 0)
216             args--;
217         into += strlen(into)+1;
218     }
219     *args = NULL;
220 }
221
222 /*-----------------------------------------------------------------*/
223 /* printVersionInfo - prints the version info                      */
224 /*-----------------------------------------------------------------*/
225 void    printVersionInfo ()
226 {
227     int i;
228     
229     fprintf (stderr,
230              "SDCC : ");
231     for (i=0; i<NUM_PORTS; i++)
232         fprintf(stderr, "%s%s", i==0 ? "" : "/", _ports[i]->target);
233
234     fprintf(stderr, " %s `"
235 #ifdef __CYGWIN32__
236                 " (CYGWIN32)\n"
237 #else
238 # ifdef __DJGPP__
239                 " (DJGPP) \n"
240 # else
241                 " (UNIX) \n"
242 # endif
243 #endif
244             , VersionString
245             );
246 }
247
248 /*-----------------------------------------------------------------*/
249 /* printUsage - prints command line syntax                         */
250 /*-----------------------------------------------------------------*/
251 void    printUsage ()
252 {
253         printVersionInfo ();
254         fprintf (stderr,
255                  "Usage : [options] filename\n"
256                  "Options :-\n"
257                  "\t-m<proc>             -     Target processor <proc>.  Default %s\n"
258                  "\t                           Try --version for supported values of <proc>\n"
259                  "\t--model-large        -     Large Model\n"
260                  "\t--model-small        -     Small Model (default)\n"
261                  "\t--stack-auto         -     Stack automatic variables\n"
262                  "\t--xstack             -     Use external stack\n"
263                  "\t--xram-loc <nnnn>    -     External Ram start location\n"
264                  "\t--xstack-loc <nnnn>  -     Xternal Stack Location\n"
265                  "\t--code-loc <nnnn>    -     Code Segment Location\n"
266                  "\t--stack-loc <nnnn>   -     Stack pointer initial value\n"
267                  "\t--data-loc <nnnn>    -     Direct data start location\n"
268                  "\t--idata-loc <nnnn>   -     Indirect data start location\n"
269                  "\t--iram-size <nnnn>   -     Internal Ram size\n"
270                  "\t--nojtbound          -     Don't generate boundary check for jump tables\n"
271                  "\t--generic            -     All unqualified ptrs converted to '_generic'\n"
272                  "PreProcessor Options :-\n"
273                  "\t-Dmacro             -       Define Macro\n"          
274                  "\t-Ipath              -       Include \"*.h\" path\n"
275                  "Note: this is a complete list of options see docs for details\n",
276                  _ports[0]->target
277                  );             
278         exit (0);
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* parseWithComma - separates string with comma                    */
283 /*-----------------------------------------------------------------*/
284 void parseWithComma (char **dest,char *src)
285 {
286     int i = 0;
287     
288     strtok(src,"\n \t");
289     /* skip the initial white spaces */
290     while (isspace(*src)) src++;
291     dest[i++] = src;
292     while (*src) {
293         if (*src == ',') {
294             *src = '\0';
295             src++;
296             if (*src)
297                 dest[i++] = src;
298             continue ;
299         }
300         src++;
301     }
302 }
303
304 /*-----------------------------------------------------------------*/
305 /* setDefaultOptions - sets the default options                    */
306 /*-----------------------------------------------------------------*/
307 static void setDefaultOptions()
308 {
309     int i ;
310
311     for ( i = 0 ; i < 128 ; i++)
312         preArgv[i] = asmOptions [i] =
313             linkOptions[i] = relFiles[i] = libFiles[i] =
314             libPaths[i] = NULL ;
315
316     /* first the options part */
317     options.stack_loc = 0; /* stack pointer initialised to 0 */
318     options.xstack_loc= 0; /* xternal stack starts at 0 */
319     options.code_loc  = 0; /* code starts at 0 */
320     options.data_loc  = 0x0030; /* data starts at 0x0030 */
321     options.xdata_loc = 0;
322     options.idata_loc = 0x80;
323     options.genericPtr = 1;   /* default on */
324     options.nopeep    = 0;
325
326     /* now for the optimizations */
327     /* turn on the everything */
328     optimize.global_cse = 1;    
329     optimize.label1 = 1;
330     optimize.label2 = 1;
331     optimize.label3 = 1;
332     optimize.label4 = 1;    
333     optimize.loopInvariant = 1;
334     optimize.loopInduction = 1;
335
336     port->setDefaultOptions();
337 }
338
339 /*-----------------------------------------------------------------*/
340 /* processFile - determines the type of file from the extension    */
341 /*-----------------------------------------------------------------*/
342 static void processFile (char *s)
343 {
344     char *fext = NULL;
345     
346     /* get the file extension */
347     fext = s + strlen(s);
348     while ((fext != s) && *fext != '.') fext--;
349     
350     /* now if no '.' then we don't know what the file type is
351        so give a warning and return */
352     if (fext == s) {
353         werror(W_UNKNOWN_FEXT,s);
354         return ;
355     }
356
357     /* otherwise depending on the file type */
358     if (strcmp(fext,".c") == 0 || strcmp(fext,".C") == 0 || options.c1mode) {
359         /* source file name : not if we already have a 
360            source file */
361         if (srcFileName) {
362             werror(W_TOO_MANY_SRC,s);
363             return ;
364         }
365
366         /* the only source file */       
367         if (!(srcFile = fopen((fullSrcFileName = s),"r"))) {
368             werror(E_FILE_OPEN_ERR,s);
369             exit (1);
370         }
371         
372         /* copy the file name into the buffer */
373         strcpy(buffer,s);
374         
375         /* get rid of the "." */
376         strtok(buffer,".");
377         ALLOC_ATOMIC(srcFileName,strlen(buffer)+1);
378         strcpy(srcFileName,buffer);
379
380         /* get rid of any path information 
381            for the module name; do this by going
382            backwards till we get to either '/' or '\' or ':'
383            or start of buffer */
384         fext = buffer + strlen(buffer);
385         while (fext != buffer && 
386                *(fext -1) != '\\'  &&
387                *(fext-1) != '/'   &&
388                *(fext-1) != ':')
389             fext--;
390         ALLOC_ATOMIC(moduleName,strlen(fext)+1);
391         strcpy(moduleName,fext);
392         
393         return ;
394     }
395
396     /* if the extention is type .rel or .r or .REL or .R 
397        addtional object file will be passed to the linker */
398     if (strcmp(fext,".r") == 0 || strcmp(fext,".rel") == 0 ||
399         strcmp(fext,".R") == 0 || strcmp(fext,".REL") == 0) {
400         
401         relFiles[nrelFiles++] = s;
402         return ;
403     }
404
405     /* if .lib or .LIB */
406     if (strcmp(fext,".lib") == 0 || strcmp(fext,".LIB") == 0) {
407         libFiles[nlibFiles++] = s;
408         return;
409     }
410
411     werror(W_UNKNOWN_FEXT,s);
412   
413 }
414
415 static void _processC1Arg(char *s)
416 {
417     if (srcFileName) {
418         if (options.out_name) {
419             werror(W_TOO_MANY_SRC,s);
420             return;
421         }
422         options.out_name = strdup(s);
423     }
424     else {
425         processFile(s);
426     }
427 }
428
429 static void _addToList(const char **list, const char *str)
430 {
431     /* This is the bad way to do things :) */
432     while (*list)
433         list++;
434     *list = strdup(str);
435     if (!*list) {
436         werror(E_OUT_OF_MEM,__FILE__, 0);
437         exit (1);
438     }
439     *(++list) = NULL;
440 }
441
442 /*-----------------------------------------------------------------*/
443 /* parseCmdLine - parses the command line and sets the options     */
444 /*-----------------------------------------------------------------*/
445 int   parseCmdLine ( int argc, char **argv )
446 {
447     int i ;      
448     char cdbfnbuf[50];
449
450     /* go thru all whole command line   */
451     for ( i = 1; i < argc; i++ ) {
452         if ( i >= argc )
453             break ;
454
455         /* options */
456         if (argv[i][0] == '-' && argv[i][1] == '-') {
457             
458             if (strcmp(&argv[i][1],OPTION_HELP) == 0) {
459                 printUsage();
460                 exit(0);
461             }       
462
463             if (strcmp(&argv[i][1],OPTION_XREGS) == 0) {
464                 options.regExtend = 1;
465                 continue;
466             }
467
468             if (strcmp(&argv[i][1],OPTION_LARGE_MODEL) == 0) {
469                 options.model = MODEL_LARGE;
470                 continue;
471             }
472             
473             if (strcmp(&argv[i][1],OPTION_SMALL_MODEL) == 0) {
474                 options.model = MODEL_SMALL;
475                 continue;
476             }
477             
478             if (strcmp(&argv[i][1],OPTION_FLAT24_MODEL) == 0) {
479                 options.model = MODEL_FLAT24;
480                 continue;
481             }
482             
483             if (strcmp(&argv[i][1],OPTION_STACK_10BIT) == 0) {
484                 options.stack10bit = 1;
485                 continue;
486             }
487
488             if (strcmp(&argv[i][1],OPTION_STACK_AUTO) == 0) {
489                 options.stackAuto = 1;
490                 continue;
491             }
492
493             if (strcmp(&argv[i][1],OPTION_DUMP_RAW) == 0) {
494                 options.dump_raw = 1;
495                 continue;
496             }
497
498             if (strcmp(&argv[i][1],OPTION_CYCLOMATIC) == 0) {
499                 options.cyclomatic = 1;
500                 continue;
501             }
502             
503             if (strcmp(&argv[i][1],OPTION_DUMP_GCSE) == 0) {
504                 options.dump_gcse = 1;
505                 continue;
506             }
507             
508             if (strcmp(&argv[i][1],OPTION_DUMP_LOOP) == 0) {
509                 options.dump_loop = 1;
510                 continue;
511             }
512
513             if (strcmp(&argv[i][1],OPTION_DUMP_KILL) == 0) {
514                 options.dump_kill = 1;
515                 continue;
516             }
517
518             if (strcmp(&argv[i][1],OPTION_INTLONG_RENT) == 0) {
519                 options.intlong_rent = 1;
520                 continue;
521             }
522
523             if (strcmp(&argv[i][1],OPTION_FLOAT_RENT) == 0) {
524                 options.float_rent = 1;
525                 continue;
526             }
527
528             if (strcmp(&argv[i][1],OPTION_DUMP_RANGE) == 0) {
529                 options.dump_range = 1;
530                 continue;
531             }
532
533             if (strcmp(&argv[i][1],OPTION_DUMP_PACK) == 0) {
534                 options.dump_pack = 1;
535                 continue;
536             }
537
538             if (strcmp(&argv[i][1],OPTION_DUMP_RASSGN) == 0) {
539                 options.dump_rassgn = 1;
540                 continue;
541             }
542
543             if (strcmp(&argv[i][1],OPTION_OUT_FMT_IHX) == 0) {
544                 options.out_fmt = 0;
545                 continue;
546             }
547
548             if (strcmp(&argv[i][1],OPTION_OUT_FMT_S19) == 0) {
549                 options.out_fmt = 1;
550                 continue;
551             }
552
553             if (strcmp(&argv[i][1],OPTION_NOOVERLAY) == 0) {
554                 options.noOverlay = 1;
555                 continue;
556             }
557
558             if (strcmp(&argv[i][1],OPTION_STKAFTRDATA) == 0) {
559                 options.stackOnData = 1;
560                 continue;
561             }
562
563             if (strcmp(&argv[i][1],OPTION_PREPROC_ONLY) == 0) {
564                 preProcOnly = 1;
565                 continue;
566             }
567
568             if (strcmp(&argv[i][1],OPTION_C1_MODE) == 0) {
569                 options.c1mode = 1;
570                 continue;
571             }
572
573             
574             if (strcmp(&argv[i][1],OPTION_DUMP_ALL) == 0) {
575                 options.dump_rassgn = 
576                 options.dump_pack   =
577                 options.dump_range  = 
578                 options.dump_kill   = 
579                 options.dump_loop   = 
580                 options.dump_gcse   = 
581                 options.dump_raw    = 1;
582                 continue;
583             }
584
585             if (strcmp(&argv[i][1],OPTION_COMP_ONLY) == 0) {
586                 options.cc_only = 1;
587                 continue;
588             }
589    
590             if (strcmp(&argv[i][1],OPTION_GENERIC) == 0) {
591                 options.genericPtr = 1;
592                 continue;
593             }
594             
595             if (strcmp(&argv[i][1],OPTION_NOPEEP) == 0) {
596                 options.nopeep = 1;
597                 continue;
598             }
599
600             if (strcmp(&argv[i][1],OPTION_ASMPEEP) == 0) {
601                 options.asmpeep = 1;
602                 continue;
603             }
604
605             if (strcmp(&argv[i][1],OPTION_DEBUG) == 0) {
606                 options.debug = 1;              
607                 continue;
608             }
609
610             if (strcmp(&argv[i][1],OPTION_NOREGPARMS) == 0) {
611                 options.noregparms = 1;         
612                 continue;
613             }
614             
615             if (strcmp(&argv[i][1],OPTION_PEEP_FILE) == 0) {
616                 if (argv[i][1+strlen(OPTION_PEEP_FILE)]) 
617                     options.peep_file = 
618                         &argv[i][1+strlen(OPTION_PEEP_FILE)];
619                 else
620                     options.peep_file = argv[++i];
621                 continue ;
622             }
623
624             if (strcmp(&argv[i][1],OPTION_LIB_PATH) == 0) {
625                 if (argv[i][1+strlen(OPTION_LIB_PATH)]) 
626                     libPaths[nlibPaths++] = 
627                         &argv[i][1+strlen(OPTION_PEEP_FILE)];
628                 else
629                     libPaths[nlibPaths++] = argv[++i];
630                 continue ;
631             }
632
633             if (strcmp(&argv[i][1],OPTION_XSTACK_LOC) == 0) {
634                 
635                 if (argv[i][1+strlen(OPTION_XSTACK_LOC)])
636                     options.xstack_loc = 
637                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_XSTACK_LOC)]));
638                     else
639                         options.xstack_loc = 
640                             (int) floatFromVal(constVal(argv[++i]));
641                 continue ;
642             }
643
644             if (strcmp(&argv[i][1],OPTION_XSTACK) == 0) {
645                 options.useXstack = 1;
646                 continue;
647             }
648
649             if (strcmp(&argv[i][1],OPTION_MAINRETURN) == 0) {
650                 options.mainreturn = 1;
651                 continue;
652             }
653
654             if (strcmp(&argv[i][1],OPTION_CALLEE_SAVES) == 0) {
655                 if (argv[i][1+strlen(OPTION_CALLEE_SAVES)])
656                     parseWithComma(options.calleeSaves
657                                    ,&argv[i][1+strlen(OPTION_CALLEE_SAVES)]);
658                 else
659                     parseWithComma(options.calleeSaves,argv[++i]);
660                 continue;
661             }
662             
663             if (strcmp(&argv[i][1],OPTION_STACK_LOC) == 0) {
664                 
665                 if (argv[i][1+strlen(OPTION_STACK_LOC)])
666                     options.stack_loc = 
667                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_STACK_LOC)]));
668                     else
669                         options.stack_loc = 
670                             (int) floatFromVal(constVal(argv[++i]));
671                 continue;
672             }
673
674             if (strcmp(&argv[i][1],OPTION_XRAM_LOC) == 0) {
675                 
676                 if (argv[i][1+strlen(OPTION_XRAM_LOC)])
677                     options.xdata_loc = 
678                         (unsigned int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_XRAM_LOC)]));
679                     else
680                         options.xdata_loc = 
681                             (unsigned int) floatFromVal(constVal(argv[++i]));
682                 continue;
683             }
684
685             if (strcmp(&argv[i][1],OPTION_IRAM_SIZE) == 0) {
686                 
687                 if (argv[i][1+strlen(OPTION_IRAM_SIZE)])
688                     options.iram_size = 
689                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_IRAM_SIZE)]));
690                     else
691                         options.iram_size = 
692                             (int) floatFromVal(constVal(argv[++i]));
693                 continue;
694             }
695
696             if (strcmp(&argv[i][1],OPTION_VERSION) == 0) {              
697                 printVersionInfo();
698                 exit(0);
699                 continue;
700             }
701
702             if (strcmp(&argv[i][1],OPTION_DATA_LOC) == 0) {
703                 
704                 if (argv[i][1+strlen(OPTION_DATA_LOC)])
705                     options.data_loc = 
706                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_DATA_LOC)]));
707                     else
708                         options.data_loc = 
709                             (int) floatFromVal(constVal(argv[++i]));
710                 continue;
711             }
712
713             if (strcmp(&argv[i][1],OPTION_IDATA_LOC) == 0) {
714                 
715                 if (argv[i][1+strlen(OPTION_IDATA_LOC)])
716                     options.idata_loc = 
717                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_IDATA_LOC)]));
718                     else
719                         options.idata_loc = 
720                             (int) floatFromVal(constVal(argv[++i]));
721                 continue;
722             }
723
724             if (strcmp(&argv[i][1],OPTION_CODE_LOC) == 0) {
725                 
726                 if (argv[i][1+strlen(OPTION_CODE_LOC)])
727                     options.code_loc = 
728                         (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_CODE_LOC)]));
729                     else
730                         options.code_loc = 
731                             (int) floatFromVal(constVal(argv[++i]));
732                 continue;
733             }
734
735             
736             if (strcmp(&argv[i][1],OPTION_NO_JTBOUND) == 0) {
737                 optimize.noJTabBoundary = 1;
738                 continue;
739             }
740  
741             if (strcmp(&argv[i][1],OPTION_NO_GCSE) == 0) {
742                 optimize.global_cse = 0;
743                 continue;
744             }
745
746             if (strcmp(&argv[i][1],OPTION_NO_LOOP_INV) == 0) {
747                 optimize.loopInvariant = 0;
748                 continue;
749             }
750
751             if (strcmp(&argv[i][1],OPTION_NO_LOOP_IND) == 0) {
752                 optimize.loopInduction = 0;
753                 continue;
754             }
755
756             if (strcmp(&argv[i][1],OPTION_NO_LOOPREV) == 0) {
757                 optimize.noLoopReverse = 1;
758                 continue;
759             }
760
761             if (!port->parseOption(&argc, argv, &i))
762             {
763                 werror(W_UNKNOWN_OPTION,argv[i]);
764             }
765             else
766             {
767                 continue;
768             }
769         }      
770
771         /* these are undocumented options */
772         /* if preceded by '/' then turn off certain optmizations, used
773            for debugging only these are also the legacy options from
774            version 1.xx will be removed gradually.
775            It may be an absolute filename.
776         */
777         if ( *argv[i] == '/' && strlen(argv[i]) < 3) {
778             switch (argv[i][1]) {
779                 
780             case 'p':
781                 optimize.ptrArithmetic=0;
782                 break;
783
784             case 'L':
785                 switch (argv[i][2]) {
786                 case '\0':
787                     optimize.label1 = 
788                         optimize.label2 =
789                         optimize.label3 = 
790                         optimize.label4 = 0 ;
791                     break;
792                 case '1':
793                     optimize.label1 = 0;
794                     break;
795                 case '2':
796                     optimize.label2 = 0;
797                     break;
798                 case '3':
799                     optimize.label3 = 0;
800                     break;
801                 case '4':
802                     optimize.label4 = 0;
803                     break;
804                 }
805                 break;
806                 
807             case 'l' :
808                 switch (argv[i][2]) {               
809                 case 'i' :
810                     optimize.loopInvariant = 0;
811                     break;
812                 case 'n' :
813                     optimize.loopInduction = 0;
814                     break;
815
816
817                 }
818                 break ;
819             case 'g' :
820                 optimize.global_cse = 0;
821                 break;
822
823             }
824             continue ;
825         }
826
827         /* if preceded by  '-' then option */
828         if ( *argv[i] == '-' ) {
829             switch (argv[i][1]) {
830             case 'h'    :
831                 printUsage();
832                 exit(0);
833                 break;
834                 
835             case 'E':
836                 preProcOnly = 1;
837                 break;
838
839             case 'm':
840                 /* Used to select the port */
841                 if (_setPort(argv[i] + 2)) {
842                     werror(W_UNSUPP_OPTION,"-m","Unrecognised processor");
843                 }
844                 break;
845             
846             case 'a'    : 
847                 werror(W_UNSUPP_OPTION,"-a","use --stack-auto instead");
848                 break ;
849                 
850             case 'g'    :
851                 werror(W_UNSUPP_OPTION,"-g","use --generic instead");
852                 break;
853                                 
854             case 'X'    :       /* use external stack           */
855                 werror(W_UNSUPP_OPTION,"-X","use --xstack-loc instead");
856                 break ;
857                 
858             case 'x'    :
859                 werror(W_UNSUPP_OPTION,"-x","use --xstack instead");
860                 break;
861                 
862             case 'p'    :       /* stack pointer intial value */
863             case 'P'    :
864                 werror(W_UNSUPP_OPTION,"-p","use --stack-loc instead");
865                 break ;
866                                 
867             case 'i'    :
868                 werror(W_UNSUPP_OPTION,"-i","use --idata-loc instead");
869                 break ;
870                 
871             case 'r'    :
872                 werror(W_UNSUPP_OPTION,"-r","use --xdata-loc instead");
873                 break ;
874                 
875             case 's'    :
876                 werror(W_UNSUPP_OPTION,"-s","use --code-loc instead");
877                 break ;         
878                                 
879             case 'c':      
880                 options.cc_only = 1;
881                 break;  
882
883             case 'Y':
884                 werror(W_UNSUPP_OPTION,"-Y","use -I instead");
885                 break;
886                 
887             case 'L' :
888                 if (argv[i][2])
889                     libPaths[nlibPaths++] = &argv[i][2];
890                 else
891                     libPaths[nlibPaths++] = argv[++i];
892                 break;
893                 
894             case 'W':
895                 /* linker options */
896                 if (argv[i][2] == 'l') {
897                     if (argv[i][3])
898                         parseWithComma(linkOptions,&argv[i][3]);
899                     else
900                         parseWithComma(linkOptions,argv[++i]);
901                 } else {
902                     /* assembler options */
903                     if (argv[i][2] == 'a') {
904                         if (argv[i][3])
905                             parseWithComma((char **)asmOptions,&argv[i][3]);
906                         else
907                             parseWithComma((char **)asmOptions,argv[++i]);
908                         
909                     } else {
910                         werror(W_UNKNOWN_OPTION,argv[i]);                      
911                     }
912                 }
913                 break;
914             case 'S':
915                 noAssemble = 1;
916                 break;
917
918             case 'v':
919 #if FEATURE_VERBOSE_EXEC
920                 verboseExec = TRUE;
921 #else
922                 printVersionInfo();
923                 exit(0);
924 #endif
925                 break;
926
927                 /* preprocessor options */              
928             case 'd':
929             case 'D':
930             case 'I':
931             case 'M':
932             case 'C':
933             case 'A':
934             case 'U':
935                 {
936                     char sOpt = argv[i][1] ;
937                     char *rest ;
938                     
939                     if ( argv[i][2] == ' ' || argv[i][2] == '\0') {
940                         i++ ;
941                         rest = argv[i] ;
942                     }
943                     else
944                         rest = &argv[i][2] ;
945                     
946                     if ( argv[i][1] == 'Y' )
947                         argv[i][1] = 'I';
948                     if (argv[i][1] == 'M')
949                         preProcOnly = 1;
950
951                     sprintf(buffer, "-%c%s", sOpt, rest);
952                     _addToList(preArgv, buffer);
953                 }
954                 break ;
955
956             default:
957                 if (!port->parseOption(&argc, argv, &i))
958                     werror(W_UNKNOWN_OPTION,argv[i]);
959             }
960             continue ;
961         }
962
963         if (!port->parseOption(&argc, argv, &i)) {
964             /* no option must be a filename */
965             if (options.c1mode)
966                 _processC1Arg(argv[i]);
967             else
968                 processFile(argv[i]);
969         }
970     }   
971
972     /* set up external stack location if not explicitly specified */
973     if ( !options.xstack_loc )
974         options.xstack_loc = options.xdata_loc ;
975
976     /* if debug option is set the open the cdbFile */
977     if (/* options.debug && */ srcFileName) {
978         sprintf(cdbfnbuf,"%s.cdb",srcFileName);
979         if ((cdbFile = fopen(cdbfnbuf,"w")) == NULL)
980             werror(E_FILE_OPEN_ERR,cdbfnbuf);
981         else {
982             /* add a module record */
983             fprintf(cdbFile,"M:%s\n",moduleName);
984         }
985     }
986     return 0;
987 }
988
989 /*-----------------------------------------------------------------*/
990 /* my_system - will call a program with arguments                  */
991 /*-----------------------------------------------------------------*/
992 char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
993 int my_system (const char *cmd, char **cmd_argv)
994 {    
995     char *dir, *got= NULL; int i= 0;
996
997     while (!got && try_dir[i])
998     {
999         dir= (char*)malloc(strlen(try_dir[i])+strlen(cmd)+10);
1000         strcpy(dir, try_dir[i]);
1001         strcat(dir, "/");
1002         strcat(dir, cmd);
1003
1004 #if NATIVE_WIN32
1005         strcat(dir, ".exe");
1006
1007         /* Mung slashes into backslashes to keep WIndoze happy. */
1008         {
1009             char *r;
1010             r = dir;
1011             
1012             while (*r)
1013                 {
1014                     if (*r == '/')
1015                         {
1016                             *r = '\\';
1017                         }
1018                     r++;
1019                 }
1020         }
1021 #endif
1022
1023         if (access(dir, X_OK) == 0)
1024         {
1025             got= strdup(dir);
1026         }
1027         free(dir);
1028         i++;
1029     }
1030 #if FEATURE_VERBOSE_EXEC
1031     if (verboseExec) {
1032         char **pCmd = cmd_argv;
1033         while (*pCmd) {
1034             printf("%s ", *pCmd);
1035             pCmd++;
1036         }
1037         printf("\n");
1038     }
1039 #endif
1040     if (got)
1041       i= spawnv(P_WAIT,got,cmd_argv) == -1;
1042     else
1043       i= spawnvp(P_WAIT,cmd,cmd_argv) == -1;
1044     if (i) {
1045         perror("Cannot exec process ");
1046         return -1;
1047     }
1048     
1049     return 0;
1050 }
1051
1052 /*-----------------------------------------------------------------*/
1053 /* linkEdit : - calls the linkage editor  with options             */
1054 /*-----------------------------------------------------------------*/
1055 static void linkEdit (char **envp)
1056 {
1057     FILE *lnkfile ;
1058     char *argv[128];
1059     char *segName, *c;
1060
1061     int i;
1062     if (!srcFileName)
1063         srcFileName = "temp";
1064
1065     /* first we need to create the <filename>.lnk file */
1066     sprintf(buffer,"%s.lnk",srcFileName);
1067     if (!(lnkfile = fopen(buffer,"w"))) {
1068         werror(E_FILE_OPEN_ERR,buffer);
1069         exit(1);
1070     }
1071
1072     /* now write the options */
1073     fprintf(lnkfile,"-mux%c\n", (options.out_fmt ? 's' : 'i'));
1074
1075     /* if iram size specified */
1076     if (options.iram_size)
1077         fprintf(lnkfile,"-a 0x%04x\n",options.iram_size);
1078     
1079     /*if (options.debug) */
1080     fprintf(lnkfile,"-z\n");
1081
1082 #define WRITE_SEG_LOC(N, L) \
1083     segName = strdup(N); \
1084     c = strtok(segName, " \t"); \
1085     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1086     if (segName) { free(segName); } 
1087     
1088     /* code segment start */
1089     WRITE_SEG_LOC(CODE_NAME, options.code_loc);
1090     
1091      /* data segment start */
1092      WRITE_SEG_LOC(DATA_NAME, options.data_loc);
1093                  
1094     /* xdata start */
1095     WRITE_SEG_LOC(XDATA_NAME, options. xdata_loc);
1096
1097     /* indirect data */
1098     WRITE_SEG_LOC(IDATA_NAME, options.idata_loc);
1099
1100     /* bit segment start */
1101     WRITE_SEG_LOC(BIT_NAME, 0);
1102     
1103     /* add the extra linker options */
1104     for (i=0; linkOptions[i] ; i++)
1105         fprintf(lnkfile,"%s\n",linkOptions[i]);
1106
1107     /* standard library path */
1108     switch(options.model)
1109     {
1110         case MODEL_SMALL:
1111             c = "small";
1112             break;
1113         case MODEL_LARGE:
1114             c = "large";
1115             break;
1116         case MODEL_FLAT24:
1117             c = "flat24";
1118             break;
1119         default:
1120             werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
1121             c = "unknown";
1122             break;
1123     }
1124     fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
1125             
1126     /* other library paths if specified */
1127     for (i = 0 ; i < nlibPaths ; i++ )
1128         fprintf (lnkfile,"-k %s\n",libPaths[i]);
1129         
1130     /* standard library files */
1131     fprintf (lnkfile,"-l %s\n",STD_LIB);
1132     fprintf (lnkfile,"-l %s\n",STD_INT_LIB);
1133     fprintf (lnkfile,"-l %s\n",STD_LONG_LIB);
1134     fprintf (lnkfile,"-l %s\n",STD_FP_LIB);
1135
1136     /* additional libraries if any */
1137     for (i = 0 ; i < nlibFiles; i++)
1138         fprintf (lnkfile,"-l %s\n",libFiles[i]);
1139
1140     /* put in the object files */
1141     if (strcmp(srcFileName,"temp"))
1142         fprintf (lnkfile,"%s ",srcFileName);
1143
1144     for (i = 0 ; i < nrelFiles ; i++ )
1145         fprintf (lnkfile,"%s\n",relFiles[i]);
1146
1147     fprintf (lnkfile,"\n-e\n");
1148     fclose(lnkfile);
1149
1150     _buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1151
1152     /* call the linker */
1153     if (my_system(argv[0], argv)) {
1154         perror("Cannot exec linker");
1155         exit(1);
1156     }
1157
1158     if (strcmp(srcFileName,"temp") == 0) {
1159         /* rename "temp.cdb" to "firstRelFile.cdb" */
1160         char *f = strtok(strdup(relFiles[0]),".");
1161         f = strcat(f,".cdb");
1162         rename("temp.cdb",f);       
1163         srcFileName = NULL;
1164     }
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* assemble - spawns the assembler with arguments                  */
1169 /*-----------------------------------------------------------------*/
1170 static void assemble (char **envp)
1171 {
1172     char *argv[128];  /* assembler arguments */
1173
1174     _buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1175
1176     if (my_system(argv[0], argv)) {
1177         perror("Cannot exec assember");
1178         exit(1);
1179     }
1180 }
1181
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* preProcess - spawns the preprocessor with arguments             */
1186 /*-----------------------------------------------------------------*/
1187 static int preProcess (char **envp)
1188 {
1189     char *argv[128];
1190     char procDef[128];
1191
1192     preOutName = NULL;
1193
1194     if (!options.c1mode) {
1195         /* if using external stack define the macro */
1196         if ( options.useXstack )
1197             _addToList(preArgv, "-DSDCC_USE_XSTACK");
1198         
1199         /* set the macro for stack autos        */
1200         if ( options.stackAuto )
1201             _addToList(preArgv, "-DSDCC_STACK_AUTO");
1202             
1203         /* set the macro for stack autos        */
1204         if ( options.stack10bit )
1205             _addToList(preArgv, "-DSDCC_STACK_TENBIT"); 
1206     
1207         /* set the macro for large model        */
1208         switch(options.model)
1209             {
1210             case MODEL_LARGE:
1211                 _addToList(preArgv, "-DSDCC_MODEL_LARGE");
1212                 break;
1213             case MODEL_SMALL:
1214                 _addToList(preArgv, "-DSDCC_MODEL_SMALL");
1215                 break;
1216             case MODEL_FLAT24:
1217                 _addToList(preArgv, "-DSDCC_MODEL_FLAT24");
1218                 break;
1219             default:
1220                 werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
1221                 break;
1222             }       
1223             
1224     
1225         /* add port (processor information to processor */
1226         sprintf(procDef,"-DSDCC_%s",port->target);
1227         _addToList(preArgv,procDef);
1228
1229         if (!preProcOnly)
1230             preOutName = strdup(tmpnam(NULL));
1231
1232         _buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
1233                       preOutName, srcFileName, preArgv);
1234
1235         if (my_system(argv[0], argv)) {
1236             unlink (preOutName);
1237             perror("Cannot exec Preprocessor");
1238             exit(1);
1239         }
1240
1241         if (preProcOnly)
1242             exit(0);
1243     }
1244     else {
1245         preOutName = fullSrcFileName;
1246     }
1247
1248     yyin = fopen(preOutName, "r");
1249     if (yyin == NULL) {
1250         perror("Preproc file not found\n");
1251         exit(1);
1252     }
1253     
1254     return 0;
1255 }
1256
1257 static void _findPort(int argc, char **argv)
1258 {
1259     argc--;
1260     while (argc) {
1261         if (!strncmp(*argv, "-m", 2)) {
1262             _setPort(*argv + 2);
1263             return;
1264         }
1265         argv++;
1266         argc--;
1267     }
1268     /* Use the first in the list */
1269     port = _ports[0];
1270 }
1271
1272 /* 
1273  * main routine
1274  * initialises and calls the parser
1275  */
1276
1277 int main ( int argc, char **argv , char **envp)
1278 {
1279     /* turn all optimizations off by default */
1280     memset(&optimize,0,sizeof(struct optimize));
1281     
1282     /*printVersionInfo ();*/
1283
1284     _findPort(argc, argv);
1285     /* Initalise the port. */
1286     if (port->init)
1287         port->init();
1288
1289     setDefaultOptions();
1290     parseCmdLine(argc,argv);
1291
1292     initMem();
1293
1294     port->finaliseOptions();
1295
1296     /* if no input then printUsage & exit */
1297     if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name)) {
1298         printUsage();
1299         exit(0);
1300     }
1301
1302         
1303     if (srcFileName)
1304         preProcess(envp) ;
1305
1306     if (srcFileName) {
1307
1308         initSymt();
1309         initiCode();
1310         initCSupport ();
1311         initPeepHole();
1312         yyparse();
1313
1314         if (!fatalError) {
1315             glue();
1316             if (!options.c1mode)
1317                 assemble(envp);
1318         } else {
1319             exit(-1);
1320         }
1321         
1322     }
1323     
1324     if (cdbFile)
1325         fclose(cdbFile);
1326
1327     if (!options.cc_only && 
1328         !fatalError      &&
1329         !noAssemble      &&
1330         !options.c1mode  &&
1331         (srcFileName || nrelFiles))
1332         linkEdit (envp);
1333
1334     if (yyin && yyin != stdin)
1335         fclose(yyin);
1336
1337     if (preOutName && !options.c1mode) {
1338         unlink(preOutName);
1339         free(preOutName);
1340     }
1341     return 0;
1342     
1343 }