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