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