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