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