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