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