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