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