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