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