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