3becb08b915e34005430c518b5f8cc8ec6f91b7f
[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 'd':
976             case 'D':
977             case 'I':
978             case 'M':
979             case 'C':
980             case 'A':
981             case 'U':
982                 {
983                     char sOpt = argv[i][1] ;
984                     char *rest ;
985                     
986                     if ( argv[i][2] == ' ' || argv[i][2] == '\0') {
987                         i++ ;
988                         rest = argv[i] ;
989                     }
990                     else
991                         rest = &argv[i][2] ;
992                     
993                     if ( argv[i][1] == 'Y' )
994                         argv[i][1] = 'I';
995                     if (argv[i][1] == 'M')
996                         preProcOnly = 1;
997
998                     sprintf(buffer, "-%c%s", sOpt, rest);
999                     _addToList(preArgv, buffer);
1000                 }
1001                 break ;
1002
1003             default:
1004                 if (!port->parseOption(&argc, argv, &i))
1005                     werror(W_UNKNOWN_OPTION,argv[i]);
1006             }
1007             continue ;
1008         }
1009
1010         if (!port->parseOption(&argc, argv, &i)) {
1011             /* no option must be a filename */
1012             if (options.c1mode)
1013                 _processC1Arg(argv[i]);
1014             else
1015                 processFile(argv[i]);
1016         }
1017     }   
1018
1019     /* set up external stack location if not explicitly specified */
1020     if ( !options.xstack_loc )
1021         options.xstack_loc = options.xdata_loc ;
1022
1023     /* if debug option is set the open the cdbFile */
1024     if (/* options.debug && */ srcFileName) {
1025         sprintf(cdbfnbuf,"%s.cdb",srcFileName);
1026         if ((cdbFile = fopen(cdbfnbuf,"w")) == NULL)
1027             werror(E_FILE_OPEN_ERR,cdbfnbuf);
1028         else {
1029             /* add a module record */
1030             fprintf(cdbFile,"M:%s\n",moduleName);
1031         }
1032     }
1033     return 0;
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* my_system - will call a program with arguments                  */
1038 /*-----------------------------------------------------------------*/
1039 char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
1040 int my_system (const char *cmd, char **cmd_argv)
1041 {    
1042     char *dir, *got= NULL; int i= 0;
1043
1044     while (!got && try_dir[i])
1045     {
1046         dir= (char*)malloc(strlen(try_dir[i])+strlen(cmd)+10);
1047         strcpy(dir, try_dir[i]);
1048         strcat(dir, "/");
1049         strcat(dir, cmd);
1050
1051 #if NATIVE_WIN32
1052         strcat(dir, ".exe");
1053
1054         /* Mung slashes into backslashes to keep WIndoze happy. */
1055         {
1056             char *r;
1057             r = dir;
1058             
1059             while (*r)
1060                 {
1061                     if (*r == '/')
1062                         {
1063                             *r = '\\';
1064                         }
1065                     r++;
1066                 }
1067         }
1068 #endif
1069
1070         if (access(dir, X_OK) == 0)
1071         {
1072             got= strdup(dir);
1073         }
1074         free(dir);
1075         i++;
1076     }
1077 #if FEATURE_VERBOSE_EXEC
1078     if (verboseExec) {
1079         char **pCmd = cmd_argv;
1080         while (*pCmd) {
1081             printf("%s ", *pCmd);
1082             pCmd++;
1083         }
1084         printf("\n");
1085     }
1086 #endif
1087     if (got)
1088       i= spawnv(P_WAIT,got,cmd_argv) == -1;
1089     else
1090       i= spawnvp(P_WAIT,cmd,cmd_argv) == -1;
1091     if (i) {
1092         perror("Cannot exec process ");
1093         return -1;
1094     }
1095     
1096     return 0;
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* linkEdit : - calls the linkage editor  with options             */
1101 /*-----------------------------------------------------------------*/
1102 static void linkEdit (char **envp)
1103 {
1104     FILE *lnkfile ;
1105     char *argv[128];
1106     char *segName, *c;
1107
1108     int i;
1109     if (!srcFileName)
1110         srcFileName = "temp";
1111
1112     /* first we need to create the <filename>.lnk file */
1113     sprintf(buffer,"%s.lnk",srcFileName);
1114     if (!(lnkfile = fopen(buffer,"w"))) {
1115         werror(E_FILE_OPEN_ERR,buffer);
1116         exit(1);
1117     }
1118
1119     /* now write the options */
1120     fprintf(lnkfile,"-mux%c\n", (options.out_fmt ? 's' : 'i'));
1121
1122     /* if iram size specified */
1123     if (options.iram_size)
1124         fprintf(lnkfile,"-a 0x%04x\n",options.iram_size);
1125     
1126     /*if (options.debug) */
1127     fprintf(lnkfile,"-z\n");
1128
1129 #define WRITE_SEG_LOC(N, L) \
1130     segName = strdup(N); \
1131     c = strtok(segName, " \t"); \
1132     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
1133     if (segName) { free(segName); } 
1134     
1135     /* code segment start */
1136     WRITE_SEG_LOC(CODE_NAME, options.code_loc);
1137     
1138      /* data segment start */
1139      WRITE_SEG_LOC(DATA_NAME, options.data_loc);
1140                  
1141     /* xdata start */
1142     WRITE_SEG_LOC(XDATA_NAME, options. xdata_loc);
1143
1144     /* indirect data */
1145     WRITE_SEG_LOC(IDATA_NAME, options.idata_loc);
1146
1147     /* bit segment start */
1148     WRITE_SEG_LOC(BIT_NAME, 0);
1149     
1150     /* add the extra linker options */
1151     for (i=0; linkOptions[i] ; i++)
1152         fprintf(lnkfile,"%s\n",linkOptions[i]);
1153
1154     /* standard library path */
1155     switch(options.model)
1156     {
1157         case MODEL_SMALL:
1158             c = "small";
1159             break;
1160         case MODEL_LARGE:
1161             c = "large";
1162             break;
1163         case MODEL_FLAT24:
1164             c = "flat24";
1165             break;
1166         default:
1167             werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
1168             c = "unknown";
1169             break;
1170     }
1171     fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
1172             
1173     /* other library paths if specified */
1174     for (i = 0 ; i < nlibPaths ; i++ )
1175         fprintf (lnkfile,"-k %s\n",libPaths[i]);
1176         
1177     /* standard library files */
1178     fprintf (lnkfile,"-l %s\n",STD_LIB);
1179     fprintf (lnkfile,"-l %s\n",STD_INT_LIB);
1180     fprintf (lnkfile,"-l %s\n",STD_LONG_LIB);
1181     fprintf (lnkfile,"-l %s\n",STD_FP_LIB);
1182
1183     /* additional libraries if any */
1184     for (i = 0 ; i < nlibFiles; i++)
1185         fprintf (lnkfile,"-l %s\n",libFiles[i]);
1186
1187     /* put in the object files */
1188     if (strcmp(srcFileName,"temp"))
1189         fprintf (lnkfile,"%s ",srcFileName);
1190
1191     for (i = 0 ; i < nrelFiles ; i++ )
1192         fprintf (lnkfile,"%s\n",relFiles[i]);
1193
1194     fprintf (lnkfile,"\n-e\n");
1195     fclose(lnkfile);
1196
1197     buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
1198
1199     /* call the linker */
1200     if (my_system(argv[0], argv)) {
1201         perror("Cannot exec linker");
1202         exit(1);
1203     }
1204
1205     if (strcmp(srcFileName,"temp") == 0) {
1206         /* rename "temp.cdb" to "firstRelFile.cdb" */
1207         char *f = strtok(strdup(relFiles[0]),".");
1208         f = strcat(f,".cdb");
1209         rename("temp.cdb",f);       
1210         srcFileName = NULL;
1211     }
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* assemble - spawns the assembler with arguments                  */
1216 /*-----------------------------------------------------------------*/
1217 static void assemble (char **envp)
1218 {
1219     char *argv[128];  /* assembler arguments */
1220
1221     buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
1222
1223     if (my_system(argv[0], argv)) {
1224         perror("Cannot exec assember");
1225         exit(1);
1226     }
1227 }
1228
1229
1230
1231 /*-----------------------------------------------------------------*/
1232 /* preProcess - spawns the preprocessor with arguments             */
1233 /*-----------------------------------------------------------------*/
1234 static int preProcess (char **envp)
1235 {
1236     char *argv[128];
1237     char procDef[128];
1238
1239     preOutName = NULL;
1240
1241     if (!options.c1mode) {
1242         /* if using external stack define the macro */
1243         if ( options.useXstack )
1244             _addToList(preArgv, "-DSDCC_USE_XSTACK");
1245         
1246         /* set the macro for stack autos        */
1247         if ( options.stackAuto )
1248             _addToList(preArgv, "-DSDCC_STACK_AUTO");
1249             
1250         /* set the macro for stack autos        */
1251         if ( options.stack10bit )
1252             _addToList(preArgv, "-DSDCC_STACK_TENBIT"); 
1253     
1254         /* set the macro for large model        */
1255         switch(options.model)
1256             {
1257             case MODEL_LARGE:
1258                 _addToList(preArgv, "-DSDCC_MODEL_LARGE");
1259                 break;
1260             case MODEL_SMALL:
1261                 _addToList(preArgv, "-DSDCC_MODEL_SMALL");
1262                 break;
1263             case MODEL_COMPACT:
1264                 _addToList(preArgv, "-DSDCC_MODEL_COMPACT");
1265                 break;
1266             case MODEL_MEDIUM:
1267                 _addToList(preArgv, "-DSDCC_MODEL_MEDIUM");
1268                 break;
1269             case MODEL_FLAT24:
1270                 _addToList(preArgv, "-DSDCC_MODEL_FLAT24");
1271                 break;
1272             default:
1273                 werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
1274                 break;
1275             }       
1276             
1277     
1278         /* add port (processor information to processor */
1279         sprintf(procDef,"-DSDCC_%s",port->target);
1280         _addToList(preArgv,procDef);
1281
1282         if (!preProcOnly)
1283             preOutName = strdup(tmpnam(NULL));
1284
1285         buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
1286                       preOutName, srcFileName, preArgv);
1287
1288         if (my_system(argv[0], argv)) {
1289             unlink (preOutName);
1290             perror("Cannot exec Preprocessor");
1291             exit(1);
1292         }
1293
1294         if (preProcOnly)
1295             exit(0);
1296     }
1297     else {
1298         preOutName = fullSrcFileName;
1299     }
1300
1301     yyin = fopen(preOutName, "r");
1302     if (yyin == NULL) {
1303         perror("Preproc file not found\n");
1304         exit(1);
1305     }
1306     
1307     return 0;
1308 }
1309
1310 static void _findPort(int argc, char **argv)
1311 {
1312     argc--;
1313     while (argc) {
1314         if (!strncmp(*argv, "-m", 2)) {
1315             _setPort(*argv + 2);
1316             return;
1317         }
1318         argv++;
1319         argc--;
1320     }
1321     /* Use the first in the list */
1322     port = _ports[0];
1323 }
1324
1325 /* 
1326  * main routine
1327  * initialises and calls the parser
1328  */
1329
1330 int main ( int argc, char **argv , char **envp)
1331 {
1332     /* turn all optimizations off by default */
1333     memset(&optimize,0,sizeof(struct optimize));
1334     
1335     /*printVersionInfo ();*/
1336
1337     _findPort(argc, argv);
1338     /* Initalise the port. */
1339     if (port->init)
1340         port->init();
1341
1342     setDefaultOptions();
1343     parseCmdLine(argc,argv);
1344
1345     initMem();
1346
1347     port->finaliseOptions();
1348
1349     /* if no input then printUsage & exit */
1350     if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name)) {
1351         printUsage();
1352         exit(0);
1353     }
1354         
1355     if (srcFileName)
1356         preProcess(envp) ;
1357
1358     if (srcFileName) {
1359
1360         initSymt();
1361         initiCode();
1362         initCSupport ();
1363         initPeepHole();
1364         yyparse();
1365
1366         if (!fatalError) {
1367             glue();
1368             if (!options.c1mode)
1369                 assemble(envp);
1370         } else {
1371             return 1;
1372         }
1373         
1374     }
1375     
1376     if (cdbFile)
1377         fclose(cdbFile);
1378
1379     if (!options.cc_only && 
1380         !fatalError      &&
1381         !noAssemble      &&
1382         !options.c1mode  &&
1383         (srcFileName || nrelFiles)) {
1384         if (port->linker.do_link)
1385             port->linker.do_link();
1386         else
1387             linkEdit (envp);
1388     }
1389
1390     if (yyin && yyin != stdin)
1391         fclose(yyin);
1392
1393     if (preOutName && !options.c1mode) {
1394         unlink(preOutName);
1395         free(preOutName);
1396     }
1397
1398     return 0;
1399     
1400 }