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