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