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