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